diff --git a/js/src/jsfun.cpp b/js/src/jsfun.cpp index 304700da2..ef5aea768 100644 --- a/js/src/jsfun.cpp +++ b/js/src/jsfun.cpp @@ -129,6 +129,11 @@ IsFunctionInStrictMode(JSFunction* fun) return IsAsmJSStrictModeModuleOrFunction(fun); } +static bool +IsNewerTypeFunction(JSFunction* fun) { + return fun->isArrow() || fun->isGenerator() || fun->isAsync() || fun->isMethod(); +} + // Beware: this function can be invoked on *any* function! That includes // natives, strict mode functions, bound functions, arrow functions, // self-hosted functions and constructors, asm.js functions, functions with @@ -142,7 +147,9 @@ ArgumentsRestrictions(JSContext* cx, HandleFunction fun) // a strict mode function, or a bound function. // TODO (bug 1057208): ensure semantics are correct for all possible // pairings of callee/caller. - if (fun->isBuiltin() || IsFunctionInStrictMode(fun) || fun->isBoundFunction()) { + if (fun->isBuiltin() || IsFunctionInStrictMode(fun) || + fun->isBoundFunction() || IsNewerTypeFunction(fun)) + { ThrowTypeErrorBehavior(cx); return false; } @@ -229,7 +236,9 @@ CallerRestrictions(JSContext* cx, HandleFunction fun) // a strict mode function, or a bound function. // TODO (bug 1057208): ensure semantics are correct for all possible // pairings of callee/caller. - if (fun->isBuiltin() || IsFunctionInStrictMode(fun) || fun->isBoundFunction()) { + if (fun->isBuiltin() || IsFunctionInStrictMode(fun) || + fun->isBoundFunction() || IsNewerTypeFunction(fun)) + { ThrowTypeErrorBehavior(cx); return false; } diff --git a/js/src/tests/ecma_6/extensions/newer-type-functions-caller-arguments.js b/js/src/tests/ecma_6/extensions/newer-type-functions-caller-arguments.js new file mode 100644 index 000000000..7fed18037 --- /dev/null +++ b/js/src/tests/ecma_6/extensions/newer-type-functions-caller-arguments.js @@ -0,0 +1,43 @@ +// Tests that newer-type functions (i.e. anything not defined by regular function declarations and +// expressions) throw when accessing their 'arguments' and 'caller' properties. + +// 9.2.7 (AddRestrictedFunctionProperties) defines accessors on Function.prototype which throw on +// every 'get' and 'set' of 'caller' and 'arguments'. +// Additionally, 16.2 (Forbidden Extensions) forbids adding properties to all non-"legacy" function +// declarations and expressions. This creates the effect that all newer-style functions act like +// strict-mode functions when accessing their 'caller' and 'arguments' properties. + +const container = { + async asyncMethod() {}, + *genMethod() {}, + method() {} +}; + +[ + async function(){}, + function*(){}, + () => {}, + async () => {}, + + container.asyncMethod, + container.genMethod, + container.method +].forEach(f => { + checkArgumentsAccess(f); + checkCallerAccess(f); +}); + +function checkArgumentsAccess(f) { + assertThrowsInstanceOf(() => f.arguments, TypeError, + `Expected 'arguments' property access to throw on ${f}`); +} + +function checkCallerAccess(f) { + assertThrowsInstanceOf(() => f.caller, TypeError, + `Expected 'caller' property access to throw on ${f}`); +} + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("Tests complete");