Files
ask262/engine262/src/intrinsics/NativeError.mts
T

89 lines
3.1 KiB
TypeScript

import {
surroundingAgent,
} from '../host-defined/engine.mts';
import {
Descriptor,
UndefinedValue,
Value,
type Arguments,
type FunctionCallContext,
} from '../value.mts';
import { Q, X, type ValueEvaluator } from '../completion.mts';
import { captureStack, callSiteToErrorString } from '../helpers.mts';
import { bootstrapConstructor, bootstrapPrototype } from './bootstrap.mts';
import type { ErrorObject } from './Error.mts';
import {
DefinePropertyOrThrow,
OrdinaryCreateFromConstructor,
InstallErrorCause,
ToString,
Realm,
type FunctionObject,
} from '#self';
const nativeErrorNames = [
'EvalError',
'RangeError',
'ReferenceError',
'SyntaxError',
'TypeError',
'URIError',
] as const;
export type NativeErrorNames = typeof nativeErrorNames[number];
export function bootstrapNativeError(realmRec: Realm) {
for (const name of nativeErrorNames) {
const proto = bootstrapPrototype(realmRec, [
['name', Value(name)],
['message', Value('')],
], realmRec.Intrinsics['%Error.prototype%']);
/** https://tc39.es/ecma262/#sec-nativeerror */
const Constructor = function* Constructor([message = Value.undefined, options = Value.undefined]: Arguments, { NewTarget }: FunctionCallContext): ValueEvaluator {
// 1. If NewTarget is undefined, let newTarget be the active function object; else let newTarget be NewTarget.
let newTarget;
if (NewTarget instanceof UndefinedValue) {
newTarget = surroundingAgent.activeFunctionObject;
} else {
newTarget = NewTarget;
}
// 2. Let O be ? OrdinaryCreateFromConstructor(newTarget, "%NativeError.prototype%", « [[ErrorData]] »).
const O = Q(yield* OrdinaryCreateFromConstructor(newTarget as FunctionObject, `%${name}.prototype%`, [
'ErrorData',
'HostDefinedErrorStack',
])) as ErrorObject;
// 3. If message is not undefined, then
if (message !== Value.undefined) {
// a. Let msg be ? ToString(message).
const msg = Q(yield* ToString(message));
// b. Let msgDesc be the PropertyDescriptor { [[Value]]: msg, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true }.
const msgDesc = Descriptor({
Value: msg,
Writable: Value.true,
Enumerable: Value.false,
Configurable: Value.true,
});
// c. Perform ! DefinePropertyOrThrow(O, "message", msgDesc).
X(DefinePropertyOrThrow(O, Value('message'), msgDesc));
}
// 4. Perform ? InstallErrorCause(O, options).
Q(yield* InstallErrorCause(O, options));
// NON-SPEC
const S = captureStack();
O.HostDefinedErrorStack = S.stack;
O.ErrorData = X(callSiteToErrorString(O, S.stack, S.nativeStack));
// 5. Return O.
return O;
};
Object.defineProperty(Constructor, 'name', {
value: `${name}Constructor`,
configurable: true,
});
const cons = bootstrapConstructor(realmRec, Constructor, name, 1, proto, []);
cons.Prototype = realmRec.Intrinsics['%Error%'];
realmRec.Intrinsics[`%${name}.prototype%`] = proto;
realmRec.Intrinsics[`%${name}%`] = cons;
}
}