Allow whitelist after patch
MODIFY
packages/intrinsics-whitelist/src/whitelist.js
packages/intrinsics-whitelist/src/whitelist.js
@@ -281,7 +281,7 @@ export default {
// 19.2.3.3 Function.prototype.call
call: fn,
// 19.2.3.4 Function.prototype.constructor
- constructor: 'Function',
+ constructor: 'FunctionPrototypeConstructor', //TODO test
// 19.2.3.5 Function.prototype.toString
toString: fn,
// 19.2.3.6 Function.prototype [ @@hasInstance ]
@@ -1341,7 +1341,7 @@ export default {
GeneratorFunction: {
// 25.2.2 Properties of the GeneratorFunction Constructor
- '**proto**': 'Function',
+ '**proto**': 'FunctionPrototypeConstructor',
name: 'string',
// 25.2.2.1 GeneratorFunction.length
length: 'number',
@@ -1360,7 +1360,7 @@ export default {
AsyncGeneratorFunction: {
// 25.3.2 Properties of the AsyncGeneratorFunction Constructor
- '**proto**': 'Function',
+ '**proto**': 'FunctionPrototypeConstructor',
name: 'string',
// 25.3.2.1 AsyncGeneratorFunction.length
length: 'number',
@@ -1444,7 +1444,7 @@ export default {
AsyncFunction: {
// 25.7.2 Properties of the AsyncFunction Constructor
- '**proto**': 'Function',
+ '**proto**': 'FunctionPrototypeConstructor',
name: 'string',
// 25.7.2.1 AsyncFunction.length
length: 'number',
@@ -1512,6 +1512,13 @@ export default {
// ESNext
+ // New intrinsic.
+ 'FunctionPrototypeConstructor': {
+ '**proto**': 'FunctionPrototype',
+ length: 'number',
+ prototype: 'FunctionPrototype',
+ },
+
Constructor: {
'**proto**': 'FunctionPrototype',
prototype: 'ConstructorPrototype',

MODIFY
packages/intrinsics/src/main.js
packages/intrinsics/src/main.js
@@ -157,6 +157,7 @@ const intrinsicNames = [
'unescape',
// ESNext
+ 'FunctionPrototypeConstructor',
'Compartment',
'CompartmentPrototype',
'harden',
@@ -169,6 +170,7 @@ const intrinsicNames = [
*/
function validateAnonIntrinsics(intrinsics) {
const {
+ FunctionPrototypeConstructor,
ArrayIteratorPrototype,
AsyncFunction,
AsyncGenerator,
@@ -261,7 +263,8 @@ function validateAnonIntrinsics(intrinsics) {
// 25.2.2 Properties of the GeneratorFunction Constructor
- if (getPrototypeOf(GeneratorFunction) !== Function) {
+ // Use Function.prototype.constructor in case Function has been tamed
+ if (getPrototypeOf(GeneratorFunction) !== FunctionPrototypeConstructor) {
throw new Error('GeneratorFunction.__proto__ should be Function');
}
if (GeneratorFunction.name !== 'GeneratorFunction') {
@@ -276,7 +279,8 @@ function validateAnonIntrinsics(intrinsics) {
// 25.3.1 The AsyncGeneratorFunction Constructor
- if (getPrototypeOf(AsyncGeneratorFunction) !== Function) {
+ // Use Function.prototype.constructor in case Function has been tamed
+ if (getPrototypeOf(AsyncGeneratorFunction) !== FunctionPrototypeConstructor) {
throw new TypeError('AsyncGeneratorFunction.__proto__ should be Function');
}
if (AsyncGeneratorFunction.name !== 'AsyncGeneratorFunction') {
@@ -301,7 +305,8 @@ function validateAnonIntrinsics(intrinsics) {
// 25.7.1 The AsyncFunction Constructor
- if (getPrototypeOf(AsyncFunction) !== Function) {
+ // Use Function.prototype.constructor in case Function has been tamed
+ if (getPrototypeOf(AsyncFunction) !== FunctionPrototypeConstructor) {
throw new TypeError('AsyncFunction.__proto__ should be Function');
}
if (AsyncFunction.name !== 'AsyncFunction') {
@@ -315,6 +320,9 @@ function validateAnonIntrinsics(intrinsics) {
* traversal from the global object.
*/
function getAnonymousIntrinsics() {
+
+ const FunctionPrototypeConstructor = Function.prototype.constructor;
+
const SymbolIterator = (typeof Symbol && Symbol.iterator) || '@@iterator';
const SymbolMatchAll = (typeof Symbol && Symbol.matchAll) || '@@matchAll';
@@ -388,6 +396,7 @@ function getAnonymousIntrinsics() {
// VALIDATION
const intrinsics = {
+ FunctionPrototypeConstructor,
ArrayIteratorPrototype,
AsyncFunction,
AsyncGenerator,

MODIFY
packages/intrinsics/test/getIntrinsics.test.js
packages/intrinsics/test/getIntrinsics.test.js
@@ -3,6 +3,10 @@ import { getIntrinsics } from '../src/main.js';
const { test } = tap;
+function ObjectHasOwnProperty(obj, prop) {
+ return Object.prototype.hasOwnProperty.call(obj, prop);
+}
+
// TODO Module
// eslint-disable-next-line no-eval
if (!eval.toString().includes('native code')) {
@@ -12,6 +16,8 @@ if (!eval.toString().includes('native code')) {
const { getPrototypeOf } = Object;
function getAnonIntrinsics() {
+ const FunctionPrototypeConstructor = Function.prototype.constructor;
+
// eslint-disable-next-line no-new-wrappers
const StringIteratorObject = new String()[Symbol.iterator]();
const StringIteratorPrototype = getPrototypeOf(StringIteratorObject);
@@ -65,6 +71,7 @@ function getAnonIntrinsics() {
})();
return {
+ FunctionPrototypeConstructor,
StringIteratorPrototype,
RegExpStringIteratorPrototype,
ArrayIteratorPrototype,
@@ -91,15 +98,15 @@ test('intrinsics - getIntrinsics', t => {
const anonIntrinsics = getAnonIntrinsics();
for (const name of Object.keys(instrinsics)) {
- if (Object.prototype.hasOwnProperty.call(anonIntrinsics, name)) {
+ if (ObjectHasOwnProperty(anonIntrinsics, name)) {
t.equal(instrinsics[name], anonIntrinsics[name], name);
- } else if (Object.prototype.hasOwnProperty.call(global, name)) {
+ } else if (ObjectHasOwnProperty(global, name)) {
t.equal(instrinsics[name], global[name], name);
} else if (name.endsWith('Prototype')) {
const base = name.slice(0, -9);
- if (Object.prototype.hasOwnProperty.call(anonIntrinsics, base)) {
+ if (ObjectHasOwnProperty(anonIntrinsics, base)) {
t.equal(instrinsics[name], anonIntrinsics[base].prototype, name);
- } else if (Object.prototype.hasOwnProperty.call(global, base)) {
+ } else if (ObjectHasOwnProperty(global, base)) {
t.equal(instrinsics[name], global[base].prototype, name);
} else {
t.skip(name);

Allow whitelist after patch