diff --git a/test/built-ins/Function/prototype/arguments/prop-desc.js b/test/built-ins/Function/prototype/arguments/prop-desc.js new file mode 100644 index 00000000000..9f411825948 --- /dev/null +++ b/test/built-ins/Function/prototype/arguments/prop-desc.js @@ -0,0 +1,43 @@ +// Copyright (C) 2024 Justin Dorfman. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-addrestrictedfunctionproperties +description: > + Function.prototype.arguments is an accessor property whose set and get + functions are both %ThrowTypeError%. +info: | + 2. Let _thrower_ be _realm_.[[Intrinsics]].[[%ThrowTypeError%]]. + 3. Perform ! DefinePropertyOrThrow(_F_, *"caller"*, PropertyDescriptor { [[Get]]: _thrower_, [[Set]]: _thrower_, [[Enumerable]]: *false*, [[Configurable]]: *true* }). + 4. Perform ! DefinePropertyOrThrow(_F_, *"arguments"*, PropertyDescriptor { [[Get]]: _thrower_, [[Set]]: _thrower_, [[Enumerable]]: *false*, [[Configurable]]: *true* }). +includes: [propertyHelper.js] +---*/ + +const argumentsDesc = Object.getOwnPropertyDescriptor(Function.prototype, 'arguments'); + +verifyProperty(Function.prototype, "arguments", { + enumerable: false, + configurable: true +}); + +assert.sameValue(typeof argumentsDesc.get, "function", + "Function.prototype.arguments has function getter"); +assert.sameValue(typeof argumentsDesc.set, "function", + "Function.prototype.arguments has function setter"); +assert.sameValue(argumentsDesc.get, argumentsDesc.set, + "Function.prototype.arguments property getter/setter are the same function"); + +var throwTypeError; +WellKnownIntrinsicObjects.forEach(function(record) { + if (record.name === "%ThrowTypeError%") { + throwTypeError = record.value; + } +}); +if (throwTypeError) { + assert.sameValue(descriptor.set, throwTypeError, "Function.prototype.arguments getter is %ThrowTypeError%"); +} +assert.throws(TypeError, function() { + return Function.prototype.arguments; +}); +assert.throws(TypeError, function() { + Function.prototype.arguments = {}; +}); diff --git a/test/built-ins/Function/prototype/caller-arguments/accessor-properties.js b/test/built-ins/Function/prototype/caller-arguments/accessor-properties.js new file mode 100644 index 00000000000..7803fa06d31 --- /dev/null +++ b/test/built-ins/Function/prototype/caller-arguments/accessor-properties.js @@ -0,0 +1,20 @@ +/*--- +esid: sec-addrestrictedfunctionproperties +description: > + Function.prototype.arguments and Function.prototype.arguments are both + accessor properties whose set and get functions are both %ThrowTypeError%. +info: | + 2. Let _thrower_ be _realm_.[[Intrinsics]].[[%ThrowTypeError%]]. + 3. Perform ! DefinePropertyOrThrow(_F_, *"caller"*, PropertyDescriptor { [[Get]]: _thrower_, [[Set]]: _thrower_, [[Enumerable]]: *false*, [[Configurable]]: *true* }). + 4. Perform ! DefinePropertyOrThrow(_F_, *"arguments"*, PropertyDescriptor { [[Get]]: _thrower_, [[Set]]: _thrower_, [[Enumerable]]: *false*, [[Configurable]]: *true* }). +---*/ + +const callerDesc = Object.getOwnPropertyDescriptor(Function.prototype, "caller"); +const argumentsDesc = Object.getOwnPropertyDescriptor(Function.prototype, "arguments"); + +// Other tests at ../{arguments,caller}/prop-desc.js already assert that each +// getter/setter pair use a single function (and when possible, that the +// function is %ThrowTypeError%), so this test only needs to assert equality +// *across* the pairs. +assert.sameValue(callerDesc.get, argumentsDesc.get, + "Function.prototype.arguments and Function.prototype.caller accessor functions should match (%ThrowTypeError%)"); diff --git a/test/built-ins/Function/prototype/caller-arguments/cross-realm-behavior.js b/test/built-ins/Function/prototype/caller-arguments/cross-realm-behavior.js new file mode 100644 index 00000000000..925ea5e4866 --- /dev/null +++ b/test/built-ins/Function/prototype/caller-arguments/cross-realm-behavior.js @@ -0,0 +1,13 @@ +/*--- +description: Function.prototype caller and arguments properties use the same ThrowTypeError across realms +features: [cross-realm] +---*/ + +const otherRealm = $262.createRealm(); +const otherFunctionProto = otherRealm.evaluate('Function.prototype'); + +const mainCallerDesc = Object.getOwnPropertyDescriptor(Function.prototype, "caller"); +const otherCallerDesc = Object.getOwnPropertyDescriptor(otherFunctionProto, "caller"); + +assert.sameValue(mainCallerDesc.get, otherCallerDesc.get, "caller getter should be same across realms"); +assert.sameValue(mainCallerDesc.set, otherCallerDesc.set, "caller setter should be same across realms"); diff --git a/test/built-ins/Function/prototype/caller-arguments/module-context.js b/test/built-ins/Function/prototype/caller-arguments/module-context.js new file mode 100644 index 00000000000..18944c3c3d3 --- /dev/null +++ b/test/built-ins/Function/prototype/caller-arguments/module-context.js @@ -0,0 +1,12 @@ +/*--- +description: Function properties behave consistently in module context +flags: [module] +---*/ + +function normalFunc() {} +function strictFunc() { } + +assert(!Object.hasOwnProperty.call(normalFunc, "caller"), "normal function should not have caller"); +assert(!Object.hasOwnProperty.call(strictFunc, "caller"), "strict function should not have caller"); +assert(!Object.hasOwnProperty.call(normalFunc, "arguments"), "normal function should not have arguments"); +assert(!Object.hasOwnProperty.call(strictFunc, "arguments"), "strict function should not have arguments"); diff --git a/test/built-ins/Function/prototype/caller-arguments/strict-vs-nonstrict.js b/test/built-ins/Function/prototype/caller-arguments/strict-vs-nonstrict.js new file mode 100644 index 00000000000..e9c99b400a5 --- /dev/null +++ b/test/built-ins/Function/prototype/caller-arguments/strict-vs-nonstrict.js @@ -0,0 +1,18 @@ +/*--- +description: Function properties behavior in strict vs non-strict contexts +flags: [noStrict] +---*/ + +function nonStrictFunc() { + return nonStrictFunc.caller; +} + +function strictFunc() { + return strictFunc.caller; +} + +assert(!Object.hasOwnProperty.call(nonStrictFunc, "caller"), "non-strict function should not have own caller property"); +assert(!Object.hasOwnProperty.call(strictFunc, "caller"), "strict function should not have own caller property"); + +assert.throws(TypeError, () => nonStrictFunc(), "accessing caller should throw"); +assert.throws(TypeError, () => strictFunc(), "accessing caller should throw in strict mode"); diff --git a/test/built-ins/Function/prototype/caller/prop-desc.js b/test/built-ins/Function/prototype/caller/prop-desc.js new file mode 100644 index 00000000000..3ab9a02780e --- /dev/null +++ b/test/built-ins/Function/prototype/caller/prop-desc.js @@ -0,0 +1,25 @@ +// Copyright (C) 2024 Justin Dorfman. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-function.prototype.caller +description: > + Function.prototype.caller property descriptor +info: | + Function.prototype.caller is an accessor property whose set and get + accessor functions are both %ThrowTypeError%. +includes: [propertyHelper.js] +---*/ + +const callerDesc = Object.getOwnPropertyDescriptor(Function.prototype, 'caller'); + +verifyProperty(Function.prototype, "caller", { + enumerable: false, + configurable: true +}); + +assert.sameValue(typeof callerDesc.get, "function", + "Function.prototype.caller has function getter"); +assert.sameValue(typeof callerDesc.set, "function", + "Function.prototype.caller has function setter"); +assert.sameValue(callerDesc.get, callerDesc.set, + "Caller property getter/setter are the same function");