ses
Version:
Hardened JavaScript for Fearless Cooperation
1,731 lines (1,551 loc) • 45.7 kB
JavaScript
/* eslint-disable no-restricted-globals */
/* eslint max-lines: 0 */
import { arrayPush, arrayForEach } from './commons.js';
/** @import {GenericErrorConstructor} from '../types.js' */
/**
* @module Exports {@code permits}, a recursively defined
* JSON record enumerating all intrinsics and their properties
* according to ECMA specs.
*
* @author JF Paradis
* @author Mark S. Miller
*/
/**
* constantProperties
* non-configurable, non-writable data properties of all global objects.
* Must be powerless.
* Maps from property name to the actual value
*/
export const constantProperties = {
// *** Value Properties of the Global Object
Infinity,
NaN,
undefined,
};
/**
* universalPropertyNames
* Properties of all global objects.
* Must be powerless.
* Maps from property name to the intrinsic name in the permits.
*/
export const universalPropertyNames = {
// *** Function Properties of the Global Object
isFinite: 'isFinite',
isNaN: 'isNaN',
parseFloat: 'parseFloat',
parseInt: 'parseInt',
decodeURI: 'decodeURI',
decodeURIComponent: 'decodeURIComponent',
encodeURI: 'encodeURI',
encodeURIComponent: 'encodeURIComponent',
// *** Constructor Properties of the Global Object
Array: 'Array',
ArrayBuffer: 'ArrayBuffer',
BigInt: 'BigInt',
BigInt64Array: 'BigInt64Array',
BigUint64Array: 'BigUint64Array',
Boolean: 'Boolean',
DataView: 'DataView',
EvalError: 'EvalError',
// https://github.com/tc39/proposal-float16array
Float16Array: 'Float16Array',
Float32Array: 'Float32Array',
Float64Array: 'Float64Array',
Int8Array: 'Int8Array',
Int16Array: 'Int16Array',
Int32Array: 'Int32Array',
Map: 'Map',
Number: 'Number',
Object: 'Object',
Promise: 'Promise',
Proxy: 'Proxy',
RangeError: 'RangeError',
ReferenceError: 'ReferenceError',
Set: 'Set',
String: 'String',
SyntaxError: 'SyntaxError',
TypeError: 'TypeError',
Uint8Array: 'Uint8Array',
Uint8ClampedArray: 'Uint8ClampedArray',
Uint16Array: 'Uint16Array',
Uint32Array: 'Uint32Array',
URIError: 'URIError',
WeakMap: 'WeakMap',
WeakSet: 'WeakSet',
// https://github.com/tc39/proposal-iterator-helpers
Iterator: 'Iterator',
// https://github.com/tc39/proposal-async-iterator-helpers
AsyncIterator: 'AsyncIterator',
// https://github.com/endojs/endo/issues/550
AggregateError: 'AggregateError',
// https://github.com/tc39/proposal-explicit-resource-management
// TODO DisposableStack, AsyncDisposableStack
// DisposableStack: 'DisposableStack',
// AsyncDisposableStack: 'AsyncDisposableStack',
// https://tc39.es/proposal-shadowrealm/
// TODO ShadowRealm
// ShadowRealm: 'ShadowRealm',
// *** Other Properties of the Global Object
JSON: 'JSON',
Reflect: 'Reflect',
// *** Annex B
escape: 'escape',
unescape: 'unescape',
// ESNext
// https://github.com/tc39/proposal-source-phase-imports?tab=readme-ov-file#js-module-source
ModuleSource: 'ModuleSource',
lockdown: 'lockdown',
harden: 'harden',
HandledPromise: 'HandledPromise', // TODO: Until Promise.delegate (see below).
};
/**
* initialGlobalPropertyNames
* Those found only on the initial global, i.e., the global of the
* start compartment, as well as any compartments created before lockdown.
* These may provide much of the power provided by the original.
* Maps from property name to the intrinsic name in the permits.
*/
export const initialGlobalPropertyNames = {
// *** Constructor Properties of the Global Object
Date: '%InitialDate%',
Error: '%InitialError%',
RegExp: '%InitialRegExp%',
// Omit `Symbol`, because we want the original to appear on the
// start compartment without passing through the permits mechanism, since
// we want to preserve all its properties, even if we never heard of them.
// Symbol: '%InitialSymbol%',
// *** Other Properties of the Global Object
Math: '%InitialMath%',
// ESNext
// From Error-stack proposal
// Only on initial global. No corresponding
// powerless form for other globals.
getStackString: '%InitialGetStackString%',
// TODO https://github.com/Agoric/SES-shim/issues/551
// Need initial WeakRef and FinalizationGroup in
// start compartment only.
// TODO Temporal
// https://github.com/tc39/proposal-temporal
// Temporal: '%InitialTemporal%' // with Temporal.Now
};
/**
* sharedGlobalPropertyNames
* Those found only on the globals of new compartments created after lockdown,
* which must therefore be powerless.
* Maps from property name to the intrinsic name in the permits.
*/
export const sharedGlobalPropertyNames = {
// *** Constructor Properties of the Global Object
Date: '%SharedDate%',
Error: '%SharedError%',
RegExp: '%SharedRegExp%',
Symbol: '%SharedSymbol%',
// *** Other Properties of the Global Object
Math: '%SharedMath%',
// TODO Temporal
// https://github.com/tc39/proposal-temporal
// Temporal: '%SharedTemporal%' // without Temporal.Now
};
/**
* uniqueGlobalPropertyNames
* Those made separately for each global, including the initial global
* of the start compartment.
* Maps from property name to the intrinsic name in the permits
* (which is currently always the same).
*/
export const uniqueGlobalPropertyNames = {
// *** Value Properties of the Global Object
globalThis: '%UniqueGlobalThis%',
// *** Function Properties of the Global Object
eval: '%UniqueEval%',
// *** Constructor Properties of the Global Object
Function: '%UniqueFunction%',
// *** Other Properties of the Global Object
// ESNext
Compartment: '%UniqueCompartment%',
// According to current agreements, eventually the Realm constructor too.
// 'Realm',
};
// All the "subclasses" of Error. These are collectively represented in the
// ECMAScript spec by the meta variable NativeError.
/** @type {GenericErrorConstructor[]} */
const NativeErrors = [
EvalError,
RangeError,
ReferenceError,
SyntaxError,
TypeError,
URIError,
// https://github.com/endojs/endo/issues/550
// Commented out to accommodate platforms prior to AggregateError.
// Instead, conditional push below.
// AggregateError,
];
if (typeof AggregateError !== 'undefined') {
// Conditional, to accommodate platforms prior to AggregateError
arrayPush(NativeErrors, AggregateError);
}
export { NativeErrors };
/**
* <p>Each JSON record enumerates the disposition of the properties on
* some corresponding intrinsic object.
*
* <p>All records are made of key-value pairs where the key
* is the property to process, and the value is the associated
* dispositions a.k.a. the "permit". Those permits can be:
* <ul>
* <li>The boolean value "false", in which case this property is
* blacklisted and simply removed. Properties not mentioned
* are also considered blacklisted and are removed.
* <li>A string value equal to a primitive ("number", "string", etc),
* in which case the property is permitted if its value property
* is typeof the given type. For example, {@code "Infinity"} leads to
* "number" and property values that fail {@code typeof "number"}.
* are removed.
* <li>A string value equal to an intinsic name ("ObjectPrototype",
* "Array", etc), in which case the property permitted if its
* value property is equal to the value of the corresponfing
* intrinsics. For example, {@code Map.prototype} leads to
* "MapPrototype" and the property is removed if its value is
* not equal to %MapPrototype%
* <li>Another record, in which case this property is simply
* permitted and that next record represents the disposition of
* the object which is its value. For example, {@code "Object"}
* leads to another record explaining what properties {@code
* "Object"} may have and how each such property should be treated.
*
* <p>Notes:
* <li>"[[Proto]]" is used to refer to the "[[Prototype]]" internal
* slot, which says which object this object inherits from.
* <li>"--proto--" is used to refer to the "__proto__" property name,
* which is the name of an accessor property on Object.prototype.
* In practice, it is used to access the [[Proto]] internal slot,
* but is distinct from the internal slot itself. We use
* "--proto--" rather than "__proto__" below because "__proto__"
* in an object literal is special syntax rather than a normal
* property definition.
* <li>"ObjectPrototype" is the default "[[Proto]]" (when not specified).
* <li>Constants "fn" and "getter" are used to keep the structure DRY.
* <li>Symbol properties are listed as follow:
* <li>Well-known symbols use the "@@name" form.
* <li>Registered symbols use the "RegisteredSymbol(key)" form.
* <li>Unique symbols use the "UniqueSymbol(description)" form.
*/
// Function Instances
export const FunctionInstance = {
'[[Proto]]': '%FunctionPrototype%',
length: 'number',
name: 'string',
// Do not specify "prototype" here, since only Function instances that can
// be used as a constructor have a prototype property. For constructors,
// since prototype properties are instance-specific, we define it there.
};
// AsyncFunction Instances
export const AsyncFunctionInstance = {
// This property is not mentioned in ECMA 262, but is present in V8 and
// necessary for lockdown to succeed.
'[[Proto]]': '%AsyncFunctionPrototype%',
};
// Aliases
const fn = FunctionInstance;
const asyncFn = AsyncFunctionInstance;
const getter = {
get: fn,
set: 'undefined',
};
// Possible but not encountered in the specs
// export const setter = {
// get: 'undefined',
// set: fn,
// };
const accessor = {
get: fn,
set: fn,
};
// eslint-disable-next-line func-names
const strict = function () {
'use strict';
};
// TODO Remove this once we no longer support the Hermes that needed this.
arrayForEach(['caller', 'arguments'], prop => {
try {
strict[prop];
} catch (e) {
// https://github.com/facebook/hermes/blob/main/test/hermes/function-non-strict.js
if (e.message === 'Restricted in strict mode') {
// Fixed in Static Hermes: https://github.com/facebook/hermes/issues/1582
FunctionInstance[prop] = accessor;
}
}
});
export const isAccessorPermit = permit => {
return permit === getter || permit === accessor;
};
// NativeError Object Structure
function NativeError(prototype) {
return {
// Properties of the NativeError Constructors
'[[Proto]]': '%SharedError%',
// NativeError.prototype
prototype,
};
}
function NativeErrorPrototype(constructor) {
return {
// Properties of the NativeError Prototype Objects
'[[Proto]]': '%ErrorPrototype%',
constructor,
message: 'string',
name: 'string',
// Redundantly present only on v8. Safe to remove.
toString: false,
// Superfluously present in some versions of V8.
// https://github.com/tc39/notes/blob/master/meetings/2021-10/oct-26.md#:~:text=However%2C%20Chrome%2093,and%20node%2016.11.
cause: false,
};
}
// The TypedArray Constructors
function TypedArray(prototype) {
return {
// Properties of the TypedArray Constructors
'[[Proto]]': '%TypedArray%',
BYTES_PER_ELEMENT: 'number',
prototype,
};
}
function TypedArrayPrototype(constructor) {
return {
// Properties of the TypedArray Prototype Objects
'[[Proto]]': '%TypedArrayPrototype%',
BYTES_PER_ELEMENT: 'number',
constructor,
};
}
// Without Math.random
const CommonMath = {
E: 'number',
LN10: 'number',
LN2: 'number',
LOG10E: 'number',
LOG2E: 'number',
PI: 'number',
SQRT1_2: 'number',
SQRT2: 'number',
'@@toStringTag': 'string',
abs: fn,
acos: fn,
acosh: fn,
asin: fn,
asinh: fn,
atan: fn,
atanh: fn,
atan2: fn,
cbrt: fn,
ceil: fn,
clz32: fn,
cos: fn,
cosh: fn,
exp: fn,
expm1: fn,
floor: fn,
fround: fn,
hypot: fn,
imul: fn,
log: fn,
log1p: fn,
log10: fn,
log2: fn,
max: fn,
min: fn,
pow: fn,
round: fn,
sign: fn,
sin: fn,
sinh: fn,
sqrt: fn,
tan: fn,
tanh: fn,
trunc: fn,
// https://github.com/tc39/proposal-float16array
f16round: fn,
// https://github.com/tc39/proposal-math-sum
sumPrecise: fn,
// See https://github.com/Moddable-OpenSource/moddable/issues/523
idiv: false,
// See https://github.com/Moddable-OpenSource/moddable/issues/523
idivmod: false,
// See https://github.com/Moddable-OpenSource/moddable/issues/523
imod: false,
// See https://github.com/Moddable-OpenSource/moddable/issues/523
imuldiv: false,
// See https://github.com/Moddable-OpenSource/moddable/issues/523
irem: false,
// See https://github.com/Moddable-OpenSource/moddable/issues/523
mod: false,
// See https://github.com/Moddable-OpenSource/moddable/issues/523#issuecomment-1942904505
irandom: false,
};
export const permitted = {
// ECMA https://tc39.es/ecma262
// The intrinsics object has no prototype to avoid conflicts.
'[[Proto]]': null,
// %ThrowTypeError%
'%ThrowTypeError%': fn,
// *** The Global Object
// *** Value Properties of the Global Object
Infinity: 'number',
NaN: 'number',
undefined: 'undefined',
// *** Function Properties of the Global Object
// eval
'%UniqueEval%': fn,
isFinite: fn,
isNaN: fn,
parseFloat: fn,
parseInt: fn,
decodeURI: fn,
decodeURIComponent: fn,
encodeURI: fn,
encodeURIComponent: fn,
// *** Fundamental Objects
Object: {
// Properties of the Object Constructor
'[[Proto]]': '%FunctionPrototype%',
assign: fn,
create: fn,
defineProperties: fn,
defineProperty: fn,
entries: fn,
freeze: fn,
fromEntries: fn,
getOwnPropertyDescriptor: fn,
getOwnPropertyDescriptors: fn,
getOwnPropertyNames: fn,
getOwnPropertySymbols: fn,
getPrototypeOf: fn,
is: fn,
isExtensible: fn,
isFrozen: fn,
isSealed: fn,
keys: fn,
preventExtensions: fn,
prototype: '%ObjectPrototype%',
seal: fn,
setPrototypeOf: fn,
values: fn,
// https://github.com/tc39/proposal-accessible-object-hasownproperty
hasOwn: fn,
// https://github.com/tc39/proposal-array-grouping
groupBy: fn,
// Seen on QuickJS
__getClass: false,
},
'%ObjectPrototype%': {
// Properties of the Object Prototype Object
'[[Proto]]': null,
constructor: 'Object',
hasOwnProperty: fn,
isPrototypeOf: fn,
propertyIsEnumerable: fn,
toLocaleString: fn,
toString: fn,
valueOf: fn,
// Annex B: Additional Properties of the Object.prototype Object
// See note in header about the difference between [[Proto]] and --proto--
// special notations.
'--proto--': accessor,
__defineGetter__: fn,
__defineSetter__: fn,
__lookupGetter__: fn,
__lookupSetter__: fn,
},
'%UniqueFunction%': {
// Properties of the Function Constructor
'[[Proto]]': '%FunctionPrototype%',
prototype: '%FunctionPrototype%',
},
'%InertFunction%': {
'[[Proto]]': '%FunctionPrototype%',
prototype: '%FunctionPrototype%',
},
'%FunctionPrototype%': {
apply: fn,
bind: fn,
call: fn,
constructor: '%InertFunction%',
toString: fn,
'@@hasInstance': fn,
// proposed but not yet std. To be removed if there
caller: false,
// proposed but not yet std. To be removed if there
arguments: false,
// Seen on QuickJS. TODO grab getter for use by console
fileName: false,
// Seen on QuickJS. TODO grab getter for use by console
lineNumber: false,
},
Boolean: {
// Properties of the Boolean Constructor
'[[Proto]]': '%FunctionPrototype%',
prototype: '%BooleanPrototype%',
},
'%BooleanPrototype%': {
constructor: 'Boolean',
toString: fn,
valueOf: fn,
},
'%SharedSymbol%': {
// Properties of the Symbol Constructor
'[[Proto]]': '%FunctionPrototype%',
asyncIterator: 'symbol',
for: fn,
hasInstance: 'symbol',
isConcatSpreadable: 'symbol',
iterator: 'symbol',
keyFor: fn,
match: 'symbol',
matchAll: 'symbol',
prototype: '%SymbolPrototype%',
replace: 'symbol',
search: 'symbol',
species: 'symbol',
split: 'symbol',
toPrimitive: 'symbol',
toStringTag: 'symbol',
unscopables: 'symbol',
// https://github.com/tc39/proposal-explicit-resource-management
asyncDispose: 'symbol',
// https://github.com/tc39/proposal-explicit-resource-management
dispose: 'symbol',
// Seen at core-js https://github.com/zloirock/core-js#ecmascript-symbol
useSimple: false,
// Seen at core-js https://github.com/zloirock/core-js#ecmascript-symbol
useSetter: false,
// Seen on QuickJS
operatorSet: false,
},
'%SymbolPrototype%': {
// Properties of the Symbol Prototype Object
constructor: '%SharedSymbol%',
description: getter,
toString: fn,
valueOf: fn,
'@@toPrimitive': fn,
'@@toStringTag': 'string',
},
'%InitialError%': {
// Properties of the Error Constructor
'[[Proto]]': '%FunctionPrototype%',
prototype: '%ErrorPrototype%',
// Non standard, v8 only, used by tap
captureStackTrace: fn,
// Non standard, v8 only, used by tap, tamed to accessor
stackTraceLimit: accessor,
// Non standard, v8 only, used by several, tamed to accessor
prepareStackTrace: accessor,
// https://github.com/tc39/proposal-is-error
isError: fn,
},
'%SharedError%': {
// Properties of the Error Constructor
'[[Proto]]': '%FunctionPrototype%',
prototype: '%ErrorPrototype%',
// Non standard, v8 only, used by tap
captureStackTrace: fn,
// Non standard, v8 only, used by tap, tamed to accessor
stackTraceLimit: accessor,
// Non standard, v8 only, used by several, tamed to accessor
prepareStackTrace: accessor,
// https://github.com/tc39/proposal-is-error
isError: fn,
},
'%ErrorPrototype%': {
constructor: '%SharedError%',
message: 'string',
name: 'string',
toString: fn,
// proposed de-facto, assumed TODO
// Seen on FF Nightly 88.0a1
at: false,
// Seen on FF and XS
stack: accessor,
// Superfluously present in some versions of V8.
// https://github.com/tc39/notes/blob/master/meetings/2021-10/oct-26.md#:~:text=However%2C%20Chrome%2093,and%20node%2016.11.
cause: false,
},
// NativeError
EvalError: NativeError('%EvalErrorPrototype%'),
RangeError: NativeError('%RangeErrorPrototype%'),
ReferenceError: NativeError('%ReferenceErrorPrototype%'),
SyntaxError: NativeError('%SyntaxErrorPrototype%'),
TypeError: NativeError('%TypeErrorPrototype%'),
URIError: NativeError('%URIErrorPrototype%'),
// https://github.com/endojs/endo/issues/550
AggregateError: NativeError('%AggregateErrorPrototype%'),
// TODO SuppressedError
// https://github.com/tc39/proposal-explicit-resource-management
// SuppressedError: NativeError('%SuppressedErrorPrototype%'),
'%EvalErrorPrototype%': NativeErrorPrototype('EvalError'),
'%RangeErrorPrototype%': NativeErrorPrototype('RangeError'),
'%ReferenceErrorPrototype%': NativeErrorPrototype('ReferenceError'),
'%SyntaxErrorPrototype%': NativeErrorPrototype('SyntaxError'),
'%TypeErrorPrototype%': NativeErrorPrototype('TypeError'),
'%URIErrorPrototype%': NativeErrorPrototype('URIError'),
// https://github.com/endojs/endo/issues/550
'%AggregateErrorPrototype%': NativeErrorPrototype('AggregateError'),
// TODO AggregateError .errors
// TODO SuppressedError
// https://github.com/tc39/proposal-explicit-resource-management
// '%SuppressedErrorPrototype%': NativeErrorPrototype('SuppressedError'),
// TODO SuppressedError .error
// TODO SuppressedError .suppressed
// *** Numbers and Dates
Number: {
// Properties of the Number Constructor
'[[Proto]]': '%FunctionPrototype%',
EPSILON: 'number',
isFinite: fn,
isInteger: fn,
isNaN: fn,
isSafeInteger: fn,
MAX_SAFE_INTEGER: 'number',
MAX_VALUE: 'number',
MIN_SAFE_INTEGER: 'number',
MIN_VALUE: 'number',
NaN: 'number',
NEGATIVE_INFINITY: 'number',
parseFloat: fn,
parseInt: fn,
POSITIVE_INFINITY: 'number',
prototype: '%NumberPrototype%',
},
'%NumberPrototype%': {
// Properties of the Number Prototype Object
constructor: 'Number',
toExponential: fn,
toFixed: fn,
toLocaleString: fn,
toPrecision: fn,
toString: fn,
valueOf: fn,
},
BigInt: {
// Properties of the BigInt Constructor
'[[Proto]]': '%FunctionPrototype%',
asIntN: fn,
asUintN: fn,
prototype: '%BigIntPrototype%',
// See https://github.com/Moddable-OpenSource/moddable/issues/523
bitLength: false,
// See https://github.com/Moddable-OpenSource/moddable/issues/523
fromArrayBuffer: false,
// Seen on QuickJS
tdiv: false,
// Seen on QuickJS
fdiv: false,
// Seen on QuickJS
cdiv: false,
// Seen on QuickJS
ediv: false,
// Seen on QuickJS
tdivrem: false,
// Seen on QuickJS
fdivrem: false,
// Seen on QuickJS
cdivrem: false,
// Seen on QuickJS
edivrem: false,
// Seen on QuickJS
sqrt: false,
// Seen on QuickJS
sqrtrem: false,
// Seen on QuickJS
floorLog2: false,
// Seen on QuickJS
ctz: false,
},
'%BigIntPrototype%': {
constructor: 'BigInt',
toLocaleString: fn,
toString: fn,
valueOf: fn,
'@@toStringTag': 'string',
},
'%InitialMath%': {
...CommonMath,
// `%InitialMath%.random()` has the standard unsafe behavior
random: fn,
},
'%SharedMath%': {
...CommonMath,
// `%SharedMath%.random()` is tamed to always throw
random: fn,
},
'%InitialDate%': {
// Properties of the Date Constructor
'[[Proto]]': '%FunctionPrototype%',
now: fn,
parse: fn,
prototype: '%DatePrototype%',
UTC: fn,
},
'%SharedDate%': {
// Properties of the Date Constructor
'[[Proto]]': '%FunctionPrototype%',
// `%SharedDate%.now()` is tamed to always throw
now: fn,
parse: fn,
prototype: '%DatePrototype%',
UTC: fn,
},
'%DatePrototype%': {
constructor: '%SharedDate%',
getDate: fn,
getDay: fn,
getFullYear: fn,
getHours: fn,
getMilliseconds: fn,
getMinutes: fn,
getMonth: fn,
getSeconds: fn,
getTime: fn,
getTimezoneOffset: fn,
getUTCDate: fn,
getUTCDay: fn,
getUTCFullYear: fn,
getUTCHours: fn,
getUTCMilliseconds: fn,
getUTCMinutes: fn,
getUTCMonth: fn,
getUTCSeconds: fn,
setDate: fn,
setFullYear: fn,
setHours: fn,
setMilliseconds: fn,
setMinutes: fn,
setMonth: fn,
setSeconds: fn,
setTime: fn,
setUTCDate: fn,
setUTCFullYear: fn,
setUTCHours: fn,
setUTCMilliseconds: fn,
setUTCMinutes: fn,
setUTCMonth: fn,
setUTCSeconds: fn,
toDateString: fn,
toISOString: fn,
toJSON: fn,
toLocaleDateString: fn,
toLocaleString: fn,
toLocaleTimeString: fn,
toString: fn,
toTimeString: fn,
toUTCString: fn,
valueOf: fn,
'@@toPrimitive': fn,
// Annex B: Additional Properties of the Date.prototype Object
getYear: fn,
setYear: fn,
toGMTString: fn,
},
// Text Processing
String: {
// Properties of the String Constructor
'[[Proto]]': '%FunctionPrototype%',
fromCharCode: fn,
fromCodePoint: fn,
prototype: '%StringPrototype%',
raw: fn,
// See https://github.com/Moddable-OpenSource/moddable/issues/523
fromArrayBuffer: false,
},
'%StringPrototype%': {
// Properties of the String Prototype Object
length: 'number',
charAt: fn,
charCodeAt: fn,
codePointAt: fn,
concat: fn,
constructor: 'String',
endsWith: fn,
includes: fn,
indexOf: fn,
lastIndexOf: fn,
localeCompare: fn,
match: fn,
matchAll: fn,
normalize: fn,
padEnd: fn,
padStart: fn,
repeat: fn,
replace: fn,
replaceAll: fn, // ES2021
search: fn,
slice: fn,
split: fn,
startsWith: fn,
substring: fn,
toLocaleLowerCase: fn,
toLocaleUpperCase: fn,
toLowerCase: fn,
toString: fn,
toUpperCase: fn,
trim: fn,
trimEnd: fn,
trimStart: fn,
valueOf: fn,
'@@iterator': fn,
// Failed tc39 proposal
// https://github.com/tc39/proposal-relative-indexing-method
at: fn,
// https://github.com/tc39/proposal-is-usv-string
isWellFormed: fn,
toWellFormed: fn,
unicodeSets: fn,
// Annex B: Additional Properties of the String.prototype Object
substr: fn,
anchor: fn,
big: fn,
blink: fn,
bold: fn,
fixed: fn,
fontcolor: fn,
fontsize: fn,
italics: fn,
link: fn,
small: fn,
strike: fn,
sub: fn,
sup: fn,
trimLeft: fn,
trimRight: fn,
// See https://github.com/Moddable-OpenSource/moddable/issues/523
compare: false,
// Seen on QuickJS
__quote: false,
},
'%StringIteratorPrototype%': {
'[[Proto]]': '%IteratorPrototype%',
next: fn,
'@@toStringTag': 'string',
},
'%InitialRegExp%': {
// Properties of the RegExp Constructor
'[[Proto]]': '%FunctionPrototype%',
prototype: '%RegExpPrototype%',
'@@species': getter,
// https://github.com/tc39/proposal-regex-escaping
escape: fn,
// The https://github.com/tc39/proposal-regexp-legacy-features
// are all optional, unsafe, and omitted
input: false,
$_: false,
lastMatch: false,
'$&': false,
lastParen: false,
'$+': false,
leftContext: false,
'$`': false,
rightContext: false,
"$'": false,
$1: false,
$2: false,
$3: false,
$4: false,
$5: false,
$6: false,
$7: false,
$8: false,
$9: false,
},
'%SharedRegExp%': {
// Properties of the RegExp Constructor
'[[Proto]]': '%FunctionPrototype%',
prototype: '%RegExpPrototype%',
'@@species': getter,
// https://github.com/tc39/proposal-regex-escaping
escape: fn,
},
'%RegExpPrototype%': {
// Properties of the RegExp Prototype Object
constructor: '%SharedRegExp%',
exec: fn,
dotAll: getter,
flags: getter,
global: getter,
hasIndices: getter,
ignoreCase: getter,
'@@match': fn,
'@@matchAll': fn,
multiline: getter,
'@@replace': fn,
'@@search': fn,
source: getter,
'@@split': fn,
sticky: getter,
test: fn,
toString: fn,
unicode: getter,
unicodeSets: getter,
// Annex B: Additional Properties of the RegExp.prototype Object
compile: false, // UNSAFE and suppressed.
},
'%RegExpStringIteratorPrototype%': {
// The %RegExpStringIteratorPrototype% Object
'[[Proto]]': '%IteratorPrototype%',
next: fn,
'@@toStringTag': 'string',
},
// Indexed Collections
Array: {
// Properties of the Array Constructor
'[[Proto]]': '%FunctionPrototype%',
from: fn,
isArray: fn,
of: fn,
prototype: '%ArrayPrototype%',
'@@species': getter,
// Failed tc39 proposal
// https://tc39.es/proposal-relative-indexing-method/
at: fn,
// https://tc39.es/proposal-array-from-async/
fromAsync: fn,
},
'%ArrayPrototype%': {
// Properties of the Array Prototype Object
length: 'number',
concat: fn,
constructor: 'Array',
copyWithin: fn,
entries: fn,
every: fn,
fill: fn,
filter: fn,
find: fn,
findIndex: fn,
flat: fn,
flatMap: fn,
forEach: fn,
includes: fn,
indexOf: fn,
join: fn,
keys: fn,
lastIndexOf: fn,
map: fn,
pop: fn,
push: fn,
reduce: fn,
reduceRight: fn,
reverse: fn,
shift: fn,
slice: fn,
some: fn,
sort: fn,
splice: fn,
toLocaleString: fn,
toString: fn,
unshift: fn,
values: fn,
'@@iterator': fn,
'@@unscopables': {
'[[Proto]]': null,
copyWithin: 'boolean',
entries: 'boolean',
fill: 'boolean',
find: 'boolean',
findIndex: 'boolean',
flat: 'boolean',
flatMap: 'boolean',
includes: 'boolean',
keys: 'boolean',
values: 'boolean',
// Failed tc39 proposal
// https://tc39.es/proposal-relative-indexing-method/
// Seen on FF Nightly 88.0a1
at: 'boolean',
// See https://github.com/tc39/proposal-array-find-from-last
findLast: 'boolean',
findLastIndex: 'boolean',
// https://github.com/tc39/proposal-change-array-by-copy
toReversed: 'boolean',
toSorted: 'boolean',
toSpliced: 'boolean',
with: 'boolean',
// https://github.com/tc39/proposal-array-grouping
group: 'boolean',
groupToMap: 'boolean',
groupBy: 'boolean',
},
// See https://github.com/tc39/proposal-array-find-from-last
findLast: fn,
findLastIndex: fn,
// https://github.com/tc39/proposal-change-array-by-copy
toReversed: fn,
toSorted: fn,
toSpliced: fn,
with: fn,
// https://github.com/tc39/proposal-array-grouping
group: fn, // Not in proposal? Where?
groupToMap: fn, // Not in proposal? Where?
groupBy: fn,
// Failed tc39 proposal
// https://tc39.es/proposal-relative-indexing-method/
at: fn,
},
'%ArrayIteratorPrototype%': {
// The %ArrayIteratorPrototype% Object
'[[Proto]]': '%IteratorPrototype%',
next: fn,
'@@toStringTag': 'string',
},
// *** TypedArray Objects
'%TypedArray%': {
// Properties of the %TypedArray% Intrinsic Object
'[[Proto]]': '%FunctionPrototype%',
from: fn,
of: fn,
prototype: '%TypedArrayPrototype%',
'@@species': getter,
},
'%TypedArrayPrototype%': {
buffer: getter,
byteLength: getter,
byteOffset: getter,
constructor: '%TypedArray%',
copyWithin: fn,
entries: fn,
every: fn,
fill: fn,
filter: fn,
find: fn,
findIndex: fn,
forEach: fn,
includes: fn,
indexOf: fn,
join: fn,
keys: fn,
lastIndexOf: fn,
length: getter,
map: fn,
reduce: fn,
reduceRight: fn,
reverse: fn,
set: fn,
slice: fn,
some: fn,
sort: fn,
subarray: fn,
toLocaleString: fn,
toString: fn,
values: fn,
'@@iterator': fn,
'@@toStringTag': getter,
// Failed tc39 proposal
// https://tc39.es/proposal-relative-indexing-method/
at: fn,
// See https://github.com/tc39/proposal-array-find-from-last
findLast: fn,
findLastIndex: fn,
// https://github.com/tc39/proposal-change-array-by-copy
toReversed: fn,
toSorted: fn,
with: fn,
},
// The TypedArray Constructors
BigInt64Array: TypedArray('%BigInt64ArrayPrototype%'),
BigUint64Array: TypedArray('%BigUint64ArrayPrototype%'),
// https://github.com/tc39/proposal-float16array
Float16Array: TypedArray('%Float16ArrayPrototype%'),
Float32Array: TypedArray('%Float32ArrayPrototype%'),
Float64Array: TypedArray('%Float64ArrayPrototype%'),
Int16Array: TypedArray('%Int16ArrayPrototype%'),
Int32Array: TypedArray('%Int32ArrayPrototype%'),
Int8Array: TypedArray('%Int8ArrayPrototype%'),
Uint16Array: TypedArray('%Uint16ArrayPrototype%'),
Uint32Array: TypedArray('%Uint32ArrayPrototype%'),
Uint8ClampedArray: TypedArray('%Uint8ClampedArrayPrototype%'),
Uint8Array: {
...TypedArray('%Uint8ArrayPrototype%'),
// https://github.com/tc39/proposal-arraybuffer-base64
fromBase64: fn,
// https://github.com/tc39/proposal-arraybuffer-base64
fromHex: fn,
},
'%BigInt64ArrayPrototype%': TypedArrayPrototype('BigInt64Array'),
'%BigUint64ArrayPrototype%': TypedArrayPrototype('BigUint64Array'),
// https://github.com/tc39/proposal-float16array
'%Float16ArrayPrototype%': TypedArrayPrototype('Float16Array'),
'%Float32ArrayPrototype%': TypedArrayPrototype('Float32Array'),
'%Float64ArrayPrototype%': TypedArrayPrototype('Float64Array'),
'%Int16ArrayPrototype%': TypedArrayPrototype('Int16Array'),
'%Int32ArrayPrototype%': TypedArrayPrototype('Int32Array'),
'%Int8ArrayPrototype%': TypedArrayPrototype('Int8Array'),
'%Uint16ArrayPrototype%': TypedArrayPrototype('Uint16Array'),
'%Uint32ArrayPrototype%': TypedArrayPrototype('Uint32Array'),
'%Uint8ClampedArrayPrototype%': TypedArrayPrototype('Uint8ClampedArray'),
'%Uint8ArrayPrototype%': {
...TypedArrayPrototype('Uint8Array'),
// https://github.com/tc39/proposal-arraybuffer-base64
setFromBase64: fn,
// https://github.com/tc39/proposal-arraybuffer-base64
setFromHex: fn,
// https://github.com/tc39/proposal-arraybuffer-base64
toBase64: fn,
// https://github.com/tc39/proposal-arraybuffer-base64
toHex: fn,
},
// *** Keyed Collections
Map: {
// Properties of the Map Constructor
'[[Proto]]': '%FunctionPrototype%',
'@@species': getter,
prototype: '%MapPrototype%',
// https://github.com/tc39/proposal-array-grouping
groupBy: fn,
},
'%MapPrototype%': {
clear: fn,
constructor: 'Map',
delete: fn,
entries: fn,
forEach: fn,
get: fn,
has: fn,
keys: fn,
set: fn,
size: getter,
values: fn,
'@@iterator': fn,
'@@toStringTag': 'string',
},
'%MapIteratorPrototype%': {
// The %MapIteratorPrototype% Object
'[[Proto]]': '%IteratorPrototype%',
next: fn,
'@@toStringTag': 'string',
},
Set: {
// Properties of the Set Constructor
'[[Proto]]': '%FunctionPrototype%',
prototype: '%SetPrototype%',
'@@species': getter,
// Seen on QuickJS
groupBy: false,
},
'%SetPrototype%': {
add: fn,
clear: fn,
constructor: 'Set',
delete: fn,
entries: fn,
forEach: fn,
has: fn,
keys: fn,
size: getter,
values: fn,
'@@iterator': fn,
'@@toStringTag': 'string',
// See https://github.com/tc39/proposal-set-methods
intersection: fn,
// See https://github.com/tc39/proposal-set-methods
union: fn,
// See https://github.com/tc39/proposal-set-methods
difference: fn,
// See https://github.com/tc39/proposal-set-methods
symmetricDifference: fn,
// See https://github.com/tc39/proposal-set-methods
isSubsetOf: fn,
// See https://github.com/tc39/proposal-set-methods
isSupersetOf: fn,
// See https://github.com/tc39/proposal-set-methods
isDisjointFrom: fn,
},
'%SetIteratorPrototype%': {
// The %SetIteratorPrototype% Object
'[[Proto]]': '%IteratorPrototype%',
next: fn,
'@@toStringTag': 'string',
},
WeakMap: {
// Properties of the WeakMap Constructor
'[[Proto]]': '%FunctionPrototype%',
prototype: '%WeakMapPrototype%',
},
'%WeakMapPrototype%': {
constructor: 'WeakMap',
delete: fn,
get: fn,
has: fn,
set: fn,
'@@toStringTag': 'string',
},
WeakSet: {
// Properties of the WeakSet Constructor
'[[Proto]]': '%FunctionPrototype%',
prototype: '%WeakSetPrototype%',
},
'%WeakSetPrototype%': {
add: fn,
constructor: 'WeakSet',
delete: fn,
has: fn,
'@@toStringTag': 'string',
},
// *** Structured Data
ArrayBuffer: {
// Properties of the ArrayBuffer Constructor
'[[Proto]]': '%FunctionPrototype%',
isView: fn,
prototype: '%ArrayBufferPrototype%',
'@@species': getter,
// See https://github.com/Moddable-OpenSource/moddable/issues/523
fromString: false,
// See https://github.com/Moddable-OpenSource/moddable/issues/523
fromBigInt: false,
},
'%ArrayBufferPrototype%': {
byteLength: getter,
constructor: 'ArrayBuffer',
slice: fn,
'@@toStringTag': 'string',
// See https://github.com/Moddable-OpenSource/moddable/issues/523
concat: false,
// See https://github.com/tc39/proposal-resizablearraybuffer
transfer: fn,
resize: fn,
resizable: getter,
maxByteLength: getter,
// https://github.com/tc39/proposal-arraybuffer-transfer
transferToFixedLength: fn,
detached: getter,
},
// SharedArrayBuffer Objects
SharedArrayBuffer: false, // UNSAFE and purposely suppressed.
'%SharedArrayBufferPrototype%': false, // UNSAFE and purposely suppressed.
DataView: {
// Properties of the DataView Constructor
'[[Proto]]': '%FunctionPrototype%',
BYTES_PER_ELEMENT: 'number', // Non std but undeletable on Safari.
prototype: '%DataViewPrototype%',
},
'%DataViewPrototype%': {
buffer: getter,
byteLength: getter,
byteOffset: getter,
constructor: 'DataView',
getBigInt64: fn,
getBigUint64: fn,
// https://github.com/tc39/proposal-float16array
getFloat16: fn,
getFloat32: fn,
getFloat64: fn,
getInt8: fn,
getInt16: fn,
getInt32: fn,
getUint8: fn,
getUint16: fn,
getUint32: fn,
setBigInt64: fn,
setBigUint64: fn,
// https://github.com/tc39/proposal-float16array
setFloat16: fn,
setFloat32: fn,
setFloat64: fn,
setInt8: fn,
setInt16: fn,
setInt32: fn,
setUint8: fn,
setUint16: fn,
setUint32: fn,
'@@toStringTag': 'string',
},
// Atomics
Atomics: false, // UNSAFE and suppressed.
JSON: {
parse: fn,
stringify: fn,
'@@toStringTag': 'string',
// https://github.com/tc39/proposal-json-parse-with-source/
rawJSON: fn,
isRawJSON: fn,
},
// *** Control Abstraction Objects
// https://github.com/tc39/proposal-iterator-helpers
Iterator: {
// Properties of the Iterator Constructor
'[[Proto]]': '%FunctionPrototype%',
prototype: '%IteratorPrototype%',
from: fn,
// https://github.com/tc39/proposal-joint-iteration
zip: fn,
zipKeyed: fn,
// https://github.com/tc39/proposal-iterator-sequencing
concat: fn,
},
'%IteratorPrototype%': {
// The %IteratorPrototype% Object
'@@iterator': fn,
// https://github.com/tc39/proposal-iterator-helpers
constructor: 'Iterator',
map: fn,
filter: fn,
take: fn,
drop: fn,
flatMap: fn,
reduce: fn,
toArray: fn,
forEach: fn,
some: fn,
every: fn,
find: fn,
'@@toStringTag': 'string',
// https://github.com/tc39/proposal-async-iterator-helpers
toAsync: fn,
// https://github.com/tc39/proposal-explicit-resource-management
// See https://github.com/Moddable-OpenSource/moddable/issues/523#issuecomment-1942904505
'@@dispose': false,
},
// https://github.com/tc39/proposal-iterator-helpers
'%WrapForValidIteratorPrototype%': {
'[[Proto]]': '%IteratorPrototype%',
next: fn,
return: fn,
},
// https://github.com/tc39/proposal-iterator-helpers
'%IteratorHelperPrototype%': {
'[[Proto]]': '%IteratorPrototype%',
next: fn,
return: fn,
'@@toStringTag': 'string',
},
// https://github.com/tc39/proposal-async-iterator-helpers
AsyncIterator: {
// Properties of the Iterator Constructor
'[[Proto]]': '%FunctionPrototype%',
prototype: '%AsyncIteratorPrototype%',
from: fn,
},
'%AsyncIteratorPrototype%': {
// The %AsyncIteratorPrototype% Object
'@@asyncIterator': fn,
// https://github.com/tc39/proposal-async-iterator-helpers
constructor: 'AsyncIterator',
map: fn,
filter: fn,
take: fn,
drop: fn,
flatMap: fn,
reduce: fn,
toArray: fn,
forEach: fn,
some: fn,
every: fn,
find: fn,
'@@toStringTag': 'string',
// https://github.com/tc39/proposal-explicit-resource-management
// See https://github.com/Moddable-OpenSource/moddable/issues/523#issuecomment-1942904505
'@@asyncDispose': false,
},
// https://github.com/tc39/proposal-async-iterator-helpers
'%WrapForValidAsyncIteratorPrototype%': {
'[[Proto]]': '%AsyncIteratorPrototype%',
next: fn,
return: fn,
},
// https://github.com/tc39/proposal-async-iterator-helpers
'%AsyncIteratorHelperPrototype%': {
'[[Proto]]': '%AsyncIteratorPrototype%',
next: fn,
return: fn,
'@@toStringTag': 'string',
},
'%InertGeneratorFunction%': {
// Properties of the GeneratorFunction Constructor
'[[Proto]]': '%InertFunction%',
prototype: '%Generator%',
},
'%Generator%': {
// Properties of the GeneratorFunction Prototype Object
'[[Proto]]': '%FunctionPrototype%',
constructor: '%InertGeneratorFunction%',
prototype: '%GeneratorPrototype%',
'@@toStringTag': 'string',
},
'%InertAsyncGeneratorFunction%': {
// Properties of the AsyncGeneratorFunction Constructor
'[[Proto]]': '%InertFunction%',
prototype: '%AsyncGenerator%',
},
'%AsyncGenerator%': {
// Properties of the AsyncGeneratorFunction Prototype Object
'[[Proto]]': '%FunctionPrototype%',
constructor: '%InertAsyncGeneratorFunction%',
prototype: '%AsyncGeneratorPrototype%',
// length prop added here for React Native jsc-android
// https://github.com/endojs/endo/issues/660
// https://github.com/react-native-community/jsc-android-buildscripts/issues/181
length: 'number',
'@@toStringTag': 'string',
},
'%GeneratorPrototype%': {
// Properties of the Generator Prototype Object
'[[Proto]]': '%IteratorPrototype%',
constructor: '%Generator%',
next: fn,
return: fn,
throw: fn,
'@@toStringTag': 'string',
},
'%AsyncGeneratorPrototype%': {
// Properties of the AsyncGenerator Prototype Object
'[[Proto]]': '%AsyncIteratorPrototype%',
constructor: '%AsyncGenerator%',
next: fn,
return: fn,
throw: fn,
'@@toStringTag': 'string',
},
// TODO: To be replaced with Promise.delegate
//
// The HandledPromise global variable shimmed by `@agoric/eventual-send/shim`
// implements an initial version of the eventual send specification at:
// https://github.com/tc39/proposal-eventual-send
//
// We will likely change this to add a property to Promise called
// Promise.delegate and put static methods on it, which will necessitate
// another permits change to update to the current proposed standard.
HandledPromise: {
'[[Proto]]': 'Promise',
applyFunction: fn,
applyFunctionSendOnly: fn,
applyMethod: fn,
applyMethodSendOnly: fn,
get: fn,
getSendOnly: fn,
prototype: '%PromisePrototype%',
resolve: fn,
},
// https://github.com/tc39/proposal-source-phase-imports?tab=readme-ov-file#js-module-source
ModuleSource: {
'[[Proto]]': '%AbstractModuleSource%',
prototype: '%ModuleSourcePrototype%',
},
'%ModuleSourcePrototype%': {
'[[Proto]]': '%AbstractModuleSourcePrototype%',
constructor: 'ModuleSource',
'@@toStringTag': 'string',
// https://github.com/tc39/proposal-compartments
bindings: getter,
needsImport: getter,
needsImportMeta: getter,
// @endo/module-source provides a legacy interface
imports: getter,
exports: getter,
reexports: getter,
},
'%AbstractModuleSource%': {
'[[Proto]]': '%FunctionPrototype%',
prototype: '%AbstractModuleSourcePrototype%',
},
'%AbstractModuleSourcePrototype%': {
constructor: '%AbstractModuleSource%',
},
Promise: {
// Properties of the Promise Constructor
'[[Proto]]': '%FunctionPrototype%',
all: fn,
allSettled: fn,
// https://github.com/Agoric/SES-shim/issues/550
any: fn,
prototype: '%PromisePrototype%',
race: fn,
reject: fn,
resolve: fn,
// https://github.com/tc39/proposal-promise-with-resolvers
withResolvers: fn,
'@@species': getter,
// https://github.com/tc39/proposal-promise-try
try: fn,
},
'%PromisePrototype%': {
// Properties of the Promise Prototype Object
catch: fn,
constructor: 'Promise',
finally: fn,
then: fn,
'@@toStringTag': 'string',
// Non-standard, used in node to prevent async_hooks from breaking
'UniqueSymbol(async_id_symbol)': accessor,
'UniqueSymbol(trigger_async_id_symbol)': accessor,
'UniqueSymbol(destroyed)': accessor,
},
'%InertAsyncFunction%': {
// Properties of the AsyncFunction Constructor
'[[Proto]]': '%InertFunction%',
prototype: '%AsyncFunctionPrototype%',
},
'%AsyncFunctionPrototype%': {
// Properties of the AsyncFunction Prototype Object
'[[Proto]]': '%FunctionPrototype%',
constructor: '%InertAsyncFunction%',
// length prop added here for React Native jsc-android
// https://github.com/endojs/endo/issues/660
// https://github.com/react-native-community/jsc-android-buildscripts/issues/181
length: 'number',
'@@toStringTag': 'string',
},
// Reflection
Reflect: {
// The Reflect Object
// Not a function object.
apply: fn,
construct: fn,
defineProperty: fn,
deleteProperty: fn,
get: fn,
getOwnPropertyDescriptor: fn,
getPrototypeOf: fn,
has: fn,
isExtensible: fn,
ownKeys: fn,
preventExtensions: fn,
set: fn,
setPrototypeOf: fn,
'@@toStringTag': 'string',
},
Proxy: {
// Properties of the Proxy Constructor
'[[Proto]]': '%FunctionPrototype%',
revocable: fn,
},
// Appendix B
// Annex B: Additional Properties of the Global Object
escape: fn,
unescape: fn,
// Proposed
'%UniqueCompartment%': {
'[[Proto]]': '%FunctionPrototype%',
prototype: '%CompartmentPrototype%',
toString: fn,
},
'%InertCompartment%': {
'[[Proto]]': '%FunctionPrototype%',
prototype: '%CompartmentPrototype%',
toString: fn,
},
'%CompartmentPrototype%': {
constructor: '%InertCompartment%',
evaluate: fn,
globalThis: getter,
name: getter,
import: asyncFn,
load: asyncFn,
importNow: fn,
module: fn,
'@@toStringTag': 'string',
},
lockdown: fn,
harden: { ...fn, isFake: 'boolean' },
'%InitialGetStackString%': fn,
};