forked from mirrors/gecko-dev
		
	Differential Revision: https://phabricator.services.mozilla.com/D65509 --HG-- extra : moz-landing-system : lando
		
			
				
	
	
		
			175 lines
		
	
	
	
		
			5.2 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			175 lines
		
	
	
	
		
			5.2 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
/*
 | 
						|
 * This file is meant to provide common infrastructure for several consumers.
 | 
						|
 * The consumer is expected to define the following things:
 | 
						|
 *
 | 
						|
 * 1) An verifyPromiseGlobal function which does whatever test the consumer
 | 
						|
 *    wants.
 | 
						|
 * 2) An isXrayArgumentTest global boolean, because some of these tests act
 | 
						|
 *    differenly based on that boolean.
 | 
						|
 * 3) A function named getPromise.  This function is given a global object and a
 | 
						|
 *    single argument to use for getting the promise.  The getPromise function
 | 
						|
 *    is expected to trigger the canonical Promise.resolve for the given global
 | 
						|
 *    with the given argument in some way that depends on the test, and return
 | 
						|
 *    the result.
 | 
						|
 * 4) A subframe (frames[0]) which can be used as a second global for creating
 | 
						|
 *    promises.
 | 
						|
 */
 | 
						|
 | 
						|
/* global verifyPromiseGlobal, getPromise, isXrayArgumentTest */
 | 
						|
 | 
						|
var label = "parent";
 | 
						|
 | 
						|
function passBasicPromise() {
 | 
						|
  var p1 = Promise.resolve();
 | 
						|
  verifyPromiseGlobal(p1, window, "Promise.resolve return value 1");
 | 
						|
  var p2 = getPromise(window, p1);
 | 
						|
  is(p1, p2, "Basic promise should just pass on through");
 | 
						|
  return p2;
 | 
						|
}
 | 
						|
 | 
						|
function passPrimitive(global) {
 | 
						|
  var p = getPromise(global, 5);
 | 
						|
  verifyPromiseGlobal(p, global, "Promise wrapping primitive");
 | 
						|
  return p.then(function(arg) {
 | 
						|
    is(arg, 5, "Should have the arg we passed in");
 | 
						|
  });
 | 
						|
}
 | 
						|
 | 
						|
function passThenable(global) {
 | 
						|
  var called = false;
 | 
						|
  var thenable = {
 | 
						|
    then(f) {
 | 
						|
      called = true;
 | 
						|
      f(7);
 | 
						|
    },
 | 
						|
  };
 | 
						|
  var p = getPromise(global, thenable);
 | 
						|
  verifyPromiseGlobal(p, global, "Promise wrapping thenable");
 | 
						|
  return p.then(function(arg) {
 | 
						|
    ok(called, "Thenable should have been called");
 | 
						|
    is(arg, 7, "Should have the arg our thenable passed in");
 | 
						|
  });
 | 
						|
}
 | 
						|
 | 
						|
function passWrongPromiseWithMatchingConstructor() {
 | 
						|
  var p1 = Promise.resolve();
 | 
						|
  verifyPromiseGlobal(p1, window, "Promise.resolve() return value 2");
 | 
						|
  p1.constructor = frames[0].Promise;
 | 
						|
  var p2 = getPromise(frames[0], p1);
 | 
						|
  // The behavior here will depend on whether we're touching frames[0] via Xrays
 | 
						|
  // or not.  If we are not, the current compartment while getting our promise
 | 
						|
  // will be that of frames[0].  If we are, it will be our window's compartment.
 | 
						|
  if (isXrayArgumentTest) {
 | 
						|
    isnot(
 | 
						|
      p1,
 | 
						|
      p2,
 | 
						|
      "Should have wrapped the Promise in a new promise, because its constructor is not matching the current-compartment Promise constructor"
 | 
						|
    );
 | 
						|
    verifyPromiseGlobal(
 | 
						|
      p2,
 | 
						|
      window,
 | 
						|
      "Promise wrapping xrayed promise with therefore non-matching constructor"
 | 
						|
    );
 | 
						|
  } else {
 | 
						|
    is(
 | 
						|
      p1,
 | 
						|
      p2,
 | 
						|
      "Should have left the Promise alone because its constructor matched"
 | 
						|
    );
 | 
						|
  }
 | 
						|
  return p2;
 | 
						|
}
 | 
						|
 | 
						|
function passCorrectPromiseWithMismatchedConstructor() {
 | 
						|
  var p1 = Promise.resolve(9);
 | 
						|
  verifyPromiseGlobal(p1, window, "Promise.resolve() return value 3");
 | 
						|
  p1.constructor = frames[0].Promise;
 | 
						|
  var p2 = getPromise(window, p1);
 | 
						|
  isnot(
 | 
						|
    p1,
 | 
						|
    p2,
 | 
						|
    "Should have wrapped promise in a new promise, since its .constructor was wrong"
 | 
						|
  );
 | 
						|
  verifyPromiseGlobal(
 | 
						|
    p2,
 | 
						|
    window,
 | 
						|
    "Promise wrapping passed-in promise with mismatched constructor"
 | 
						|
  );
 | 
						|
  return p2.then(function(arg) {
 | 
						|
    is(arg, 9, "Should have propagated along our resolution value");
 | 
						|
  });
 | 
						|
}
 | 
						|
 | 
						|
function passPromiseToOtherGlobal() {
 | 
						|
  var p1 = Promise.resolve();
 | 
						|
  verifyPromiseGlobal(p1, window, "Promise.resolve() return value 4");
 | 
						|
  var p2 = getPromise(frames[0], p1);
 | 
						|
  // The behavior here will depend on whether we're touching frames[0] via Xrays
 | 
						|
  // or not.  If we are not, the current compartment while getting our promise
 | 
						|
  // will be that of frames[0].  If we are, it will be our window's compartment.
 | 
						|
  if (isXrayArgumentTest) {
 | 
						|
    is(
 | 
						|
      p1,
 | 
						|
      p2,
 | 
						|
      "Should have left the Promise alone, because its constructor matches the current compartment's constructor"
 | 
						|
    );
 | 
						|
  } else {
 | 
						|
    isnot(
 | 
						|
      p1,
 | 
						|
      p2,
 | 
						|
      "Should have wrapped promise in a promise from the other global"
 | 
						|
    );
 | 
						|
    verifyPromiseGlobal(
 | 
						|
      p2,
 | 
						|
      frames[0],
 | 
						|
      "Promise wrapping passed-in basic promise"
 | 
						|
    );
 | 
						|
  }
 | 
						|
  return p2;
 | 
						|
}
 | 
						|
 | 
						|
function passPromiseSubclass() {
 | 
						|
  class PromiseSubclass extends Promise {
 | 
						|
    constructor(func) {
 | 
						|
      super(func);
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  var p1 = PromiseSubclass.resolve(11);
 | 
						|
  verifyPromiseGlobal(p1, window, "PromiseSubclass.resolve() return value");
 | 
						|
  var p2 = getPromise(window, p1);
 | 
						|
  isnot(p1, p2, "Should have wrapped promise subclass in a new promise");
 | 
						|
  verifyPromiseGlobal(
 | 
						|
    p2,
 | 
						|
    window,
 | 
						|
    "Promise wrapping passed-in promise subclass"
 | 
						|
  );
 | 
						|
  return p2.then(function(arg) {
 | 
						|
    is(
 | 
						|
      arg,
 | 
						|
      11,
 | 
						|
      "Should have propagated along our resolution value from subclass"
 | 
						|
    );
 | 
						|
  });
 | 
						|
}
 | 
						|
 | 
						|
function runPromiseArgumentTests(finishFunc) {
 | 
						|
  Promise.resolve()
 | 
						|
    .then(passBasicPromise)
 | 
						|
    .then(passPrimitive.bind(undefined, window))
 | 
						|
    .then(passPrimitive.bind(undefined, frames[0]))
 | 
						|
    .then(passThenable.bind(undefined, window))
 | 
						|
    .then(passThenable.bind(undefined, frames[0]))
 | 
						|
    .then(passWrongPromiseWithMatchingConstructor)
 | 
						|
    .then(passCorrectPromiseWithMismatchedConstructor)
 | 
						|
    .then(passPromiseToOtherGlobal)
 | 
						|
    .then(passPromiseSubclass)
 | 
						|
    .then(finishFunc)
 | 
						|
    .catch(function(e) {
 | 
						|
      ok(
 | 
						|
        false,
 | 
						|
        `Exception thrown: ${e}@${location.pathname}:${e.lineNumber}:${e.columnNumber}`
 | 
						|
      );
 | 
						|
      finishFunc();
 | 
						|
    });
 | 
						|
}
 |