Bug 1732543 - Part 1: Call onNativeCall for Function.prototype.{call,apply} inside self-hosted JS. r=jandem

Differential Revision: https://phabricator.services.mozilla.com/D152349
This commit is contained in:
Tooru Fujisawa 2022-07-26 02:37:51 +00:00
Родитель b3c8ed8937
Коммит c7684cf7c3
4 изменённых файлов: 48 добавлений и 5 удалений

Просмотреть файл

@ -965,14 +965,19 @@ NativeResumeMode DebugAPI::slowPathOnNativeCall(JSContext* cx,
// The onNativeCall hook is fired when self hosted functions are called,
// and any other self hosted function or C++ native that is directly called
// by the self hosted function is considered to be part of the same
// native call, except for callContentFunction and constructContentFunction,
// which uses CallReason::CallContent.
// native call, except for the following 2 cases:
//
// * callContentFunction and constructContentFunction,
// which uses CallReason::CallContent
// * Function.prototype.call and Function.prototype.apply,
// which uses CallReason::FunCall
//
// We check this only after checking that debuggerList has items in order
// to avoid unnecessary calls to cx->currentScript(), which can be expensive
// when the top frame is in jitcode.
JSScript* script = cx->currentScript();
if (script && script->selfHosted() && reason != CallReason::CallContent) {
if (script && script->selfHosted() && reason != CallReason::CallContent &&
reason != CallReason::FunCall) {
return NativeResumeMode::Continue;
}
@ -2304,6 +2309,9 @@ bool Debugger::fireNativeCall(JSContext* cx, const CallArgs& args,
case CallReason::CallContent:
reasonAtom = cx->names().call;
break;
case CallReason::FunCall:
reasonAtom = cx->names().call;
break;
case CallReason::Getter:
reasonAtom = cx->names().get;
break;

Просмотреть файл

@ -0,0 +1,33 @@
// Test that the onNativeCall hook is called when native function is
// called inside self-hosted JS with Function.prototype.{call,apply}.
load(libdir + 'eqArrayHelper.js');
var g = newGlobal({ newCompartment: true });
var dbg = new Debugger();
var gdbg = dbg.addDebuggee(g);
const rv = [];
dbg.onNativeCall = (callee, reason) => {
rv.push(callee.name);
};
gdbg.executeInGlobal(`
// Directly call.
dateNow.call();
dateNow.apply();
// Call via bind.
Function.prototype.call.bind(Function.prototype.call)(dateNow);
Function.prototype.apply.bind(Function.prototype.apply)(dateNow);
// Call via std_Function_apply
Reflect.apply(dateNow, null, []);
`);
assertEqArray(rv, [
"call", "dateNow",
"apply", "dateNow",
"bind", "call", "call", "call", "dateNow",
"bind", "apply", "apply", "apply", "dateNow",
"apply", "dateNow",
]);

Просмотреть файл

@ -55,6 +55,8 @@ enum class CallReason {
Call,
// callContentFunction or constructContentFunction in self-hosted JS.
CallContent,
// Function.prototype.call or Function.prototype.apply.
FunCall,
Getter,
Setter,
};

Просмотреть файл

@ -979,7 +979,7 @@ bool js::fun_call(JSContext* cx, unsigned argc, Value* vp) {
iargs[i].set(args[i + 1]);
}
return Call(cx, func, args.get(0), iargs, args.rval());
return Call(cx, func, args.get(0), iargs, args.rval(), CallReason::FunCall);
}
// ES5 15.3.4.3
@ -1031,7 +1031,7 @@ bool js::fun_apply(JSContext* cx, unsigned argc, Value* vp) {
}
// Step 9.
return Call(cx, fval, args[0], args2, args.rval());
return Call(cx, fval, args[0], args2, args.rval(), CallReason::FunCall);
}
static const JSFunctionSpec function_methods[] = {