154 lines
4.4 KiB
JavaScript
154 lines
4.4 KiB
JavaScript
/* Any copyright is dedicated to the Public Domain.
|
|
http://creativecommons.org/publicdomain/zero/1.0/ */
|
|
|
|
"use strict";
|
|
|
|
Services.prefs.setBoolPref("security.allow_eval_with_system_principal", true);
|
|
registerCleanupFunction(() => {
|
|
Services.prefs.clearUserPref("security.allow_eval_with_system_principal");
|
|
});
|
|
|
|
add_task(
|
|
threadFrontTest(async ({ commands, threadFront, debuggee }) => {
|
|
const packet = await executeOnNextTickAndWaitForPause(
|
|
() => evalCode(debuggee),
|
|
threadFront
|
|
);
|
|
|
|
const arg1 = packet.frame.arguments[0];
|
|
Assert.equal(arg1.class, "Object");
|
|
|
|
const objectFront = threadFront.pauseGrip(arg1);
|
|
|
|
const obj1 = (
|
|
await objectFront.getPropertyValue("obj1", null)
|
|
).value.return.getGrip();
|
|
const obj2 = (
|
|
await objectFront.getPropertyValue("obj2", null)
|
|
).value.return.getGrip();
|
|
|
|
info(`Retrieve "context" function reference`);
|
|
const context = (await objectFront.getPropertyValue("context", null)).value
|
|
.return;
|
|
info(`Retrieve "sum" function reference`);
|
|
const sum = (await objectFront.getPropertyValue("sum", null)).value.return;
|
|
info(`Retrieve "error" function reference`);
|
|
const error = (await objectFront.getPropertyValue("error", null)).value
|
|
.return;
|
|
const notCallable = (
|
|
await objectFront.getPropertyValue("notCallable", null)
|
|
).value.return;
|
|
|
|
assert_response(await context.apply(obj1, [obj1]), {
|
|
return: "correct context",
|
|
});
|
|
assert_response(await context.apply(obj2, [obj2]), {
|
|
return: "correct context",
|
|
});
|
|
assert_response(await context.apply(obj1, [obj2]), {
|
|
return: "wrong context",
|
|
});
|
|
assert_response(await context.apply(obj2, [obj1]), {
|
|
return: "wrong context",
|
|
});
|
|
// eslint-disable-next-line no-useless-call
|
|
assert_response(await sum.apply(null, [1, 2, 3, 4, 5, 6, 7]), {
|
|
return: 1 + 2 + 3 + 4 + 5 + 6 + 7,
|
|
});
|
|
// eslint-disable-next-line no-useless-call
|
|
assert_response(await error.apply(null, []), {
|
|
throw: "an error",
|
|
});
|
|
|
|
try {
|
|
await notCallable.apply(obj1, []);
|
|
Assert.ok(false, "expected exception");
|
|
} catch (err) {
|
|
Assert.ok(!!err.message.match(/debugee object is not callable/));
|
|
}
|
|
|
|
await resume(threadFront);
|
|
|
|
// In order to cover pausing from getPropertyValue we have to first resume
|
|
// as pausing while already paused will be ignored.
|
|
// So we have to have the pausingProp in a global object and access it while not paused.
|
|
const { result: secondObjectFront } =
|
|
await commands.scriptCommand.execute("obj");
|
|
|
|
const onPropertyResumed = secondObjectFront.getPropertyValue(
|
|
"pausingProp",
|
|
null
|
|
);
|
|
|
|
// Ensure that we actually paused at the `debugger;` line.
|
|
const packet2 = await waitForPause(threadFront);
|
|
Assert.equal(packet2.frame.where.line, 18);
|
|
Assert.equal(packet2.frame.where.column, 8);
|
|
|
|
await threadFront.resume();
|
|
await onPropertyResumed;
|
|
})
|
|
);
|
|
|
|
function evalCode(debuggee) {
|
|
debuggee.eval(
|
|
// These arguments are tested.
|
|
// eslint-disable-next-line no-unused-vars
|
|
function stopMe(arg1) {
|
|
debugger;
|
|
}.toString()
|
|
);
|
|
|
|
debuggee.eval(`
|
|
stopMe({
|
|
obj1: {},
|
|
obj2: {},
|
|
context(arg) {
|
|
return this === arg ? "correct context" : "wrong context";
|
|
},
|
|
sum(...parts) {
|
|
return parts.reduce((acc, v) => acc + v, 0);
|
|
},
|
|
error() {
|
|
throw "an error";
|
|
},
|
|
notCallable: {},
|
|
});
|
|
var obj = {
|
|
get pausingProp() {
|
|
debugger;
|
|
},
|
|
};
|
|
`);
|
|
}
|
|
|
|
function assert_response({ value }, expected) {
|
|
assert_completion(value, expected);
|
|
}
|
|
|
|
function assert_completion(value, expected) {
|
|
if (expected && "return" in expected) {
|
|
assert_value(value.return, expected.return);
|
|
}
|
|
if (expected && "throw" in expected) {
|
|
assert_value(value.throw, expected.throw);
|
|
}
|
|
if (!expected) {
|
|
assert_value(value, expected);
|
|
}
|
|
}
|
|
|
|
function assert_value(actual, expected) {
|
|
Assert.equal(typeof actual, typeof expected);
|
|
|
|
if (typeof expected === "object") {
|
|
// Note: We aren't using deepEqual here because we're only doing a cursory
|
|
// check of a few properties, not a full comparison of the result, since
|
|
// the full outputs includes stuff like preview info that we don't need.
|
|
for (const key of Object.keys(expected)) {
|
|
assert_value(actual[key], expected[key]);
|
|
}
|
|
} else {
|
|
Assert.equal(actual, expected);
|
|
}
|
|
}
|