file_promise_argument_tests.js (5376B)
1 /* 2 * This file is meant to provide common infrastructure for several consumers. 3 * The consumer is expected to define the following things: 4 * 5 * 1) An verifyPromiseGlobal function which does whatever test the consumer 6 * wants. 7 * 2) An isXrayArgumentTest global boolean, because some of these tests act 8 * differenly based on that boolean. 9 * 3) A function named getPromise. This function is given a global object and a 10 * single argument to use for getting the promise. The getPromise function 11 * is expected to trigger the canonical Promise.resolve for the given global 12 * with the given argument in some way that depends on the test, and return 13 * the result. 14 * 4) A subframe (frames[0]) which can be used as a second global for creating 15 * promises. 16 */ 17 18 /* global verifyPromiseGlobal, getPromise, isXrayArgumentTest */ 19 20 var label = "parent"; 21 22 function passBasicPromise() { 23 var p1 = Promise.resolve(); 24 verifyPromiseGlobal(p1, window, "Promise.resolve return value 1"); 25 var p2 = getPromise(window, p1); 26 is(p1, p2, "Basic promise should just pass on through"); 27 return p2; 28 } 29 30 function passPrimitive(global) { 31 var p = getPromise(global, 5); 32 verifyPromiseGlobal(p, global, "Promise wrapping primitive"); 33 return p.then(function (arg) { 34 is(arg, 5, "Should have the arg we passed in"); 35 }); 36 } 37 38 function passThenable(global) { 39 var called = false; 40 var thenable = { 41 then(f) { 42 called = true; 43 f(7); 44 }, 45 }; 46 var p = getPromise(global, thenable); 47 verifyPromiseGlobal(p, global, "Promise wrapping thenable"); 48 return p.then(function (arg) { 49 ok(called, "Thenable should have been called"); 50 is(arg, 7, "Should have the arg our thenable passed in"); 51 }); 52 } 53 54 function passWrongPromiseWithMatchingConstructor() { 55 var p1 = Promise.resolve(); 56 verifyPromiseGlobal(p1, window, "Promise.resolve() return value 2"); 57 p1.constructor = frames[0].Promise; 58 var p2 = getPromise(frames[0], p1); 59 // The behavior here will depend on whether we're touching frames[0] via Xrays 60 // or not. If we are not, the current compartment while getting our promise 61 // will be that of frames[0]. If we are, it will be our window's compartment. 62 if (isXrayArgumentTest) { 63 isnot( 64 p1, 65 p2, 66 "Should have wrapped the Promise in a new promise, because its constructor is not matching the current-compartment Promise constructor" 67 ); 68 verifyPromiseGlobal( 69 p2, 70 window, 71 "Promise wrapping xrayed promise with therefore non-matching constructor" 72 ); 73 } else { 74 is( 75 p1, 76 p2, 77 "Should have left the Promise alone because its constructor matched" 78 ); 79 } 80 return p2; 81 } 82 83 function passCorrectPromiseWithMismatchedConstructor() { 84 var p1 = Promise.resolve(9); 85 verifyPromiseGlobal(p1, window, "Promise.resolve() return value 3"); 86 p1.constructor = frames[0].Promise; 87 var p2 = getPromise(window, p1); 88 isnot( 89 p1, 90 p2, 91 "Should have wrapped promise in a new promise, since its .constructor was wrong" 92 ); 93 verifyPromiseGlobal( 94 p2, 95 window, 96 "Promise wrapping passed-in promise with mismatched constructor" 97 ); 98 return p2.then(function (arg) { 99 is(arg, 9, "Should have propagated along our resolution value"); 100 }); 101 } 102 103 function passPromiseToOtherGlobal() { 104 var p1 = Promise.resolve(); 105 verifyPromiseGlobal(p1, window, "Promise.resolve() return value 4"); 106 var p2 = getPromise(frames[0], p1); 107 // The behavior here will depend on whether we're touching frames[0] via Xrays 108 // or not. If we are not, the current compartment while getting our promise 109 // will be that of frames[0]. If we are, it will be our window's compartment. 110 if (isXrayArgumentTest) { 111 is( 112 p1, 113 p2, 114 "Should have left the Promise alone, because its constructor matches the current compartment's constructor" 115 ); 116 } else { 117 isnot( 118 p1, 119 p2, 120 "Should have wrapped promise in a promise from the other global" 121 ); 122 verifyPromiseGlobal( 123 p2, 124 frames[0], 125 "Promise wrapping passed-in basic promise" 126 ); 127 } 128 return p2; 129 } 130 131 function passPromiseSubclass() { 132 class PromiseSubclass extends Promise { 133 constructor(func) { 134 super(func); 135 } 136 } 137 138 var p1 = PromiseSubclass.resolve(11); 139 verifyPromiseGlobal(p1, window, "PromiseSubclass.resolve() return value"); 140 var p2 = getPromise(window, p1); 141 isnot(p1, p2, "Should have wrapped promise subclass in a new promise"); 142 verifyPromiseGlobal( 143 p2, 144 window, 145 "Promise wrapping passed-in promise subclass" 146 ); 147 return p2.then(function (arg) { 148 is( 149 arg, 150 11, 151 "Should have propagated along our resolution value from subclass" 152 ); 153 }); 154 } 155 156 function runPromiseArgumentTests(finishFunc) { 157 Promise.resolve() 158 .then(passBasicPromise) 159 .then(passPrimitive.bind(undefined, window)) 160 .then(passPrimitive.bind(undefined, frames[0])) 161 .then(passThenable.bind(undefined, window)) 162 .then(passThenable.bind(undefined, frames[0])) 163 .then(passWrongPromiseWithMatchingConstructor) 164 .then(passCorrectPromiseWithMismatchedConstructor) 165 .then(passPromiseToOtherGlobal) 166 .then(passPromiseSubclass) 167 .then(finishFunc) 168 .catch(function (e) { 169 ok( 170 false, 171 `Exception thrown: ${e}@${location.pathname}:${e.lineNumber}:${e.columnNumber}` 172 ); 173 finishFunc(); 174 }); 175 }