test_objectgrips-fn-apply-01.js (4513B)
1 /* Any copyright is dedicated to the Public Domain. 2 http://creativecommons.org/publicdomain/zero/1.0/ */ 3 4 "use strict"; 5 6 Services.prefs.setBoolPref("security.allow_eval_with_system_principal", true); 7 registerCleanupFunction(() => { 8 Services.prefs.clearUserPref("security.allow_eval_with_system_principal"); 9 }); 10 11 add_task( 12 threadFrontTest(async ({ commands, threadFront, debuggee }) => { 13 const packet = await executeOnNextTickAndWaitForPause( 14 () => evalCode(debuggee), 15 threadFront 16 ); 17 18 const arg1 = packet.frame.arguments[0]; 19 Assert.equal(arg1.class, "Object"); 20 21 const objectFront = threadFront.pauseGrip(arg1); 22 23 const obj1 = ( 24 await objectFront.getPropertyValue("obj1", null) 25 ).value.return.getGrip(); 26 const obj2 = ( 27 await objectFront.getPropertyValue("obj2", null) 28 ).value.return.getGrip(); 29 30 info(`Retrieve "context" function reference`); 31 const context = (await objectFront.getPropertyValue("context", null)).value 32 .return; 33 info(`Retrieve "sum" function reference`); 34 const sum = (await objectFront.getPropertyValue("sum", null)).value.return; 35 info(`Retrieve "error" function reference`); 36 const error = (await objectFront.getPropertyValue("error", null)).value 37 .return; 38 const notCallable = ( 39 await objectFront.getPropertyValue("notCallable", null) 40 ).value.return; 41 42 assert_response(await context.apply(obj1, [obj1]), { 43 return: "correct context", 44 }); 45 assert_response(await context.apply(obj2, [obj2]), { 46 return: "correct context", 47 }); 48 assert_response(await context.apply(obj1, [obj2]), { 49 return: "wrong context", 50 }); 51 assert_response(await context.apply(obj2, [obj1]), { 52 return: "wrong context", 53 }); 54 // eslint-disable-next-line no-useless-call 55 assert_response(await sum.apply(null, [1, 2, 3, 4, 5, 6, 7]), { 56 return: 1 + 2 + 3 + 4 + 5 + 6 + 7, 57 }); 58 // eslint-disable-next-line no-useless-call 59 assert_response(await error.apply(null, []), { 60 throw: "an error", 61 }); 62 63 try { 64 await notCallable.apply(obj1, []); 65 Assert.ok(false, "expected exception"); 66 } catch (err) { 67 Assert.ok(!!err.message.match(/debugee object is not callable/)); 68 } 69 70 await resume(threadFront); 71 72 // In order to cover pausing from getPropertyValue we have to first resume 73 // as pausing while already paused will be ignored. 74 // So we have to have the pausingProp in a global object and access it while not paused. 75 const { result: secondObjectFront } = 76 await commands.scriptCommand.execute("obj"); 77 78 const onPropertyResumed = secondObjectFront.getPropertyValue( 79 "pausingProp", 80 null 81 ); 82 83 // Ensure that we actually paused at the `debugger;` line. 84 const packet2 = await waitForPause(threadFront); 85 Assert.equal(packet2.frame.where.line, 18); 86 Assert.equal(packet2.frame.where.column, 8); 87 88 await threadFront.resume(); 89 await onPropertyResumed; 90 }) 91 ); 92 93 function evalCode(debuggee) { 94 debuggee.eval( 95 // These arguments are tested. 96 // eslint-disable-next-line no-unused-vars 97 function stopMe(arg1) { 98 debugger; 99 }.toString() 100 ); 101 102 debuggee.eval(` 103 stopMe({ 104 obj1: {}, 105 obj2: {}, 106 context(arg) { 107 return this === arg ? "correct context" : "wrong context"; 108 }, 109 sum(...parts) { 110 return parts.reduce((acc, v) => acc + v, 0); 111 }, 112 error() { 113 throw "an error"; 114 }, 115 notCallable: {}, 116 }); 117 var obj = { 118 get pausingProp() { 119 debugger; 120 }, 121 }; 122 `); 123 } 124 125 function assert_response({ value }, expected) { 126 assert_completion(value, expected); 127 } 128 129 function assert_completion(value, expected) { 130 if (expected && "return" in expected) { 131 assert_value(value.return, expected.return); 132 } 133 if (expected && "throw" in expected) { 134 assert_value(value.throw, expected.throw); 135 } 136 if (!expected) { 137 assert_value(value, expected); 138 } 139 } 140 141 function assert_value(actual, expected) { 142 Assert.equal(typeof actual, typeof expected); 143 144 if (typeof expected === "object") { 145 // Note: We aren't using deepEqual here because we're only doing a cursory 146 // check of a few properties, not a full comparison of the result, since 147 // the full outputs includes stuff like preview info that we don't need. 148 for (const key of Object.keys(expected)) { 149 assert_value(actual[key], expected[key]); 150 } 151 } else { 152 Assert.equal(actual, expected); 153 } 154 }