Commit c7684cf7 authored by Tooru Fujisawa's avatar Tooru Fujisawa
Browse files

Bug 1732543 - Part 1: Call onNativeCall for Function.prototype.{call,apply}...

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
parent b3c8ed89
Loading
Loading
Loading
Loading
+11 −3
Original line number Diff line number Diff line
@@ -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;
+33 −0
Original line number Diff line number Diff line
// 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",
]);
+2 −0
Original line number Diff line number Diff line
@@ -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,
};
+2 −2
Original line number Diff line number Diff line
@@ -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[] = {