Use defineProperties to get throwing behavior.
MODIFY
shim/src/commons.js
shim/src/commons.js
export const {
assign,
create,
- defineProperties,
- defineProperty,
freeze,
+ defineProperties, // Object.defineProperty is allowed to fail silentlty, use Object.defineProperties instead.
getOwnPropertyDescriptor,
getOwnPropertyDescriptors,
getOwnPropertyNames,

MODIFY
shim/src/evaluators.js
shim/src/evaluators.js
@@ -6,7 +6,7 @@ import {
arrayJoin,
arrayPop,
create,
- defineProperty,
+ defineProperties,
getOwnPropertyDescriptors,
getPrototypeOf,
setPrototypeOf,
@@ -127,11 +127,13 @@ export function createSafeEvaluatorFactory(unsafeRec, safeGlobal) {
// note: be careful to not leak our primal Function.prototype by setting
// this to a plain arrow function. Now that we have safeEval, use it.
- defineProperty(safeEval, 'toString', {
+ defineProperties(safeEval, {
+ toString: {
value: safeEval("() => 'function eval() { [shim code] }'"),
writable: false,
enumerable: false,
configurable: true
+ }
});
return safeEval;
@@ -200,17 +202,19 @@ export function createFunctionEvaluator(unsafeRec, safeEval) {
assert(getPrototypeOf(safeFunction).constructor !== Function, 'hide Function');
assert(getPrototypeOf(safeFunction).constructor !== unsafeFunction, 'hide unsafeFunction');
+ defineProperties(safeFunction, {
// Ensure that any function created in any compartment in a root realm is an
// instance of Function in any compartment of the same root ralm.
- defineProperty(safeFunction, 'prototype', { value: unsafeFunction.prototype });
+ prototype: { value: unsafeFunction.prototype },
// Provide a custom output without overwriting the Function.prototype.toString
// which is called by some third-party libraries.
- defineProperty(safeFunction, 'toString', {
+ toString: {
value: safeEval("() => 'function Function() { [shim code] }'"),
writable: false,
enumerable: false,
configurable: true
+ }
});
return safeFunction;

MODIFY
shim/src/realmFacade.js
shim/src/realmFacade.js
@@ -12,7 +12,7 @@ export function buildChildRealm(unsafeRec, BaseRealm) {
// *after* user code has had a chance to pollute its environment, or it
// could be used to gain access to BaseRealm and primal-realm Error
// objects.
- const { create, defineProperty } = Object;
+ const { create, defineProperties } = Object;
const errorConstructors = new Map([
['EvalError', EvalError],
@@ -112,18 +112,22 @@ export function buildChildRealm(unsafeRec, BaseRealm) {
}
}
- defineProperty(Realm, 'toString', {
+ defineProperties(Realm, {
+ toString: {
value: () => 'function Realm() { [shim code] }',
writable: false,
enumerable: false,
configurable: true
+ }
});
- defineProperty(Realm.prototype, 'toString', {
+ defineProperties(Realm.prototype, {
+ toString: {
value: () => '[object Realm]',
writable: false,
enumerable: false,
configurable: true
+ }
});
return Realm;

MODIFY
shim/src/repair/functions.js
shim/src/repair/functions.js
// todo: this file should be moved out to a separate repo and npm module.
export function repairFunctions() {
- const { defineProperty, getPrototypeOf, setPrototypeOf } = Object;
+ const { defineProperties, getPrototypeOf, setPrototypeOf } = Object;
/**
* The process to repair constructors:
@@ -48,7 +48,7 @@ export function repairFunctions() {
// Prevents the evaluation of source when calling constructor on the prototype of functions.
// eslint-disable-next-line no-new-func
const TamedFunction = Function('throw new TypeError("Not available");');
- defineProperty(TamedFunction, 'name', { value: name });
+ defineProperties(TamedFunction, { name: { value: name } });
// (new Error()).constructors does not inherit from Function, because Error
// was defined before ES6 classes. So we don't need to repair it too.
@@ -62,11 +62,11 @@ export function repairFunctions() {
// This line replaces the original constructor in the prototype chain
// with the tamed one. No copy of the original is peserved.
- defineProperty(FunctionPrototype, 'constructor', { value: TamedFunction });
+ defineProperties(FunctionPrototype, { constructor: { value: TamedFunction } });
// This line sets the tamed constructor's prototype data property to
// the original one.
- defineProperty(TamedFunction, 'prototype', { value: FunctionPrototype });
+ defineProperties(TamedFunction, { prototype: { value: FunctionPrototype } });
if (TamedFunction !== Function.prototype.constructor) {
// Ensures that all functions meet "instanceof Function" in a realm.

Use defineProperties to get throwing behavior.