aran
Version:
JavaScript instrumenter
1,655 lines (1,617 loc) • 48.5 kB
JavaScript
import { BINARY_OPERATOR_RECORD, UNARY_OPERATOR_RECORD } from "estree-sentry";
import { getIntrinsicFunctionName } from "../lang/index.mjs";
import { listKey, map } from "../util/index.mjs";
import { AranTypeError } from "../error.mjs";
import { makeReadDependencyExpression } from "./dependency.mjs";
import { global_object_parameter } from "./global.mjs";
const BINARY_OPERATOR_ENUM = listKey(BINARY_OPERATOR_RECORD);
const UNARY_OPERATOR_ENUM = listKey(UNARY_OPERATOR_RECORD);
/**
* @type {(
* layout: {
* name: keyof import("../lang/naming.d.ts").IntrinsicFunctionNaming,
* dependencies: import("../util/tree.d.ts").Tree<import("./layout.d.ts").Dependency>,
* setup: import("../util/tree.d.ts").Tree<import("estree-sentry").Statement<{}>>,
* head: import("estree-sentry").RestablePattern<{}>[],
* body: (
* | import("estree-sentry").Expression<{}>
* | import("estree-sentry").BlockStatement<{}>
* ),
* },
* ) => import("./layout.d.ts").Layout}
*/
export const toArrowLayout = ({ name, dependencies, setup, head, body }) => ({
name,
dependencies,
setup: [
setup,
{
type: "VariableDeclaration",
kind: "const",
declarations: [
{
type: "VariableDeclarator",
id: {
type: "Identifier",
name: getIntrinsicFunctionName(name),
},
init:
body.type === "BlockStatement"
? {
type: "ArrowFunctionExpression",
id: null,
generator: false,
expression: false,
async: false,
params: head,
body,
}
: {
type: "ArrowFunctionExpression",
id: null,
generator: false,
expression: true,
async: false,
params: head,
body,
},
},
],
},
],
value: {
type: "Identifier",
name: getIntrinsicFunctionName(name),
},
});
/**
* @type {(
* name: string,
* ) => import("estree-sentry").VariableIdentifier<{}>}
*/
const makeVariableIdentifier = (name) => ({
type: "Identifier",
// eslint-disable-next-line object-shorthand
name: /** @type {import("estree-sentry").VariableName} */ (name),
});
/**
* @type {(
* name: string,
* ) => import("estree-sentry").PublicKeyIdentifier<{}>}
*/
const makePublicKeyIdentifier = (name) => ({
type: "Identifier",
// eslint-disable-next-line object-shorthand
name: /** @type {import("estree-sentry").PublicKeyName} */ (name),
});
/**
* @type {(
* value: null | boolean | number | string,
* ) => import("estree-sentry").Literal<{}>}
*/
const makeSimpleLiteral = (value) => {
if (value === null) {
return {
type: "Literal",
value,
raw: null,
bigint: null,
regex: null,
};
} else if (typeof value === "boolean") {
return {
type: "Literal",
value,
raw: null,
bigint: null,
regex: null,
};
} else if (typeof value === "number") {
return {
type: "Literal",
value,
raw: null,
bigint: null,
regex: null,
};
} else if (typeof value === "string") {
return {
type: "Literal",
// eslint-disable-next-line object-shorthand
value: /** @type {import("estree-sentry").StringValue} */ (value),
raw: null,
bigint: null,
regex: null,
};
} else {
throw new AranTypeError(value);
}
};
/**
* @type {(
* argument: import("estree-sentry").Pattern<{}>,
* ) => import("estree-sentry").RestElement<{}>}
*/
const makeRestElement = (argument) => ({
type: "RestElement",
argument,
});
/**
* @type {(
* test: import("estree-sentry").Expression<{}>,
* body: import("estree-sentry").Statement<{}>,
* ) => import("estree-sentry").WhileStatement<{}>}
*/
const makeWhileStatement = (test, body) => ({
type: "WhileStatement",
test,
body,
});
/**
* @type {(
* test: import("estree-sentry").Expression<{}>,
* consequent: import("estree-sentry").Statement<{}>,
* alternate: import("estree-sentry").Statement<{}> | null,
* ) => import("estree-sentry").IfStatement<{}>}
*/
const makeIfStatement = (test, consequent, alternate) => ({
type: "IfStatement",
test,
consequent,
alternate,
});
/**
* @type {(
* test: import("estree-sentry").Expression<{}>,
* consequent: import("estree-sentry").Expression<{}>,
* alternate: import("estree-sentry").Expression<{}>,
* ) => import("estree-sentry").ConditionalExpression<{}>}
*/
const makeConditionalExpression = (test, consequent, alternate) => ({
type: "ConditionalExpression",
test,
consequent,
alternate,
});
/**
* @type {(
* expressions: import("estree-sentry").Expression<{}>[],
* ) => import("estree-sentry").SequenceExpression<{}>}
*/
const makeSequenceExpression = (expressions) => ({
type: "SequenceExpression",
expressions,
});
/**
* @type {(
* left: (
* | import("estree-sentry").Pattern<{}>
* | import("estree-sentry").VariableDeclaration<{}>
* ),
* right: import("estree-sentry").Expression<{}>,
* body: import("estree-sentry").Statement<{}>,
* ) => import("estree-sentry").ForInStatement<{}>}
*/
const makeForInStatement = (left, right, body) => ({
type: "ForInStatement",
left,
right,
body,
});
/**
* @type {(
* elements: import("estree-sentry").Expression<{}>[],
* ) => import("estree-sentry").ArrayExpression<{}>}
*/
const makeArrayExpression = (elements) => ({
type: "ArrayExpression",
elements,
});
/**
* @type {(
* expression: import("estree-sentry").Expression<{}>,
* ) => import("estree-sentry").ExpressionStatement<{}>}
*/
const makeExpressionStatement = (expression) => ({
type: "ExpressionStatement",
directive: null,
expression,
});
/**
* @type {(
* kind: import("estree-sentry").VariableKind,
* id: import("estree-sentry").Pattern<{}>,
* init: null | import("estree-sentry").Expression<{}>,
* ) => import("estree-sentry").VariableDeclaration<{}>}
*/
const makeVariableDeclaration = (kind, id, init) => ({
type: "VariableDeclaration",
kind,
declarations: [
{
type: "VariableDeclarator",
id,
init,
},
],
});
/**
* @type {(
* left: import("estree-sentry").Pattern<{}>,
* right: import("estree-sentry").Expression<{}>,
* ) => import("estree-sentry").AssignmentExpression<{}>}
*/
const makeAssignmentExpression = (left, right) => ({
type: "AssignmentExpression",
operator: "=",
left,
right,
});
/**
* @type {(
* param: null | import("estree-sentry").Pattern<{}>,
* body: import("estree-sentry").BlockStatement<{}>,
* ) => import("estree-sentry").CatchClause<{}>}
*/
const makeCatchClause = (param, body) => ({
type: "CatchClause",
param,
body,
});
/**
* @type {(
* block: import("estree-sentry").BlockStatement<{}>,
* handler: null | import("estree-sentry").CatchClause<{}>,
* finalizer: null | import("estree-sentry").BlockStatement<{}>,
* ) => import("estree-sentry").TryStatement<{}>}
*/
const makeTryStatement = (block, handler, finalizer) => ({
type: "TryStatement",
block,
handler,
finalizer,
});
/**
* @type {(
* prefix: boolean,
* operator: import("estree-sentry").UpdateOperator,
* argument: import("estree-sentry").UpdatePattern<{}>,
* ) => import("estree-sentry").UpdateExpression<{}>}
*/
const makeUpdateExpression = (prefix, operator, argument) => ({
type: "UpdateExpression",
prefix,
operator,
argument,
});
/**
* @type {(
* argument: import("estree-sentry").Expression<{}>,
* ) => import("estree-sentry").SpreadElement<{}>}
*/
const makeSpreadElement = (argument) => ({
type: "SpreadElement",
argument,
});
/**
* @type {(
* argument: import("estree-sentry").Expression<{}>,
* ) => import("estree-sentry").ThrowStatement<{}>}
*/
const makeThrowStatement = (argument) => ({
type: "ThrowStatement",
argument,
});
/**
* @type {(
* operator: import("estree-sentry").UnaryOperator,
* argument: import("estree-sentry").Expression<{}>,
* ) => import("estree-sentry").UnaryExpression<{}>}
*/
const makeUnaryExpression = (operator, argument) => ({
type: "UnaryExpression",
operator,
prefix: true,
argument,
});
/**
* @type {(
* operator: import("estree-sentry").BinaryOperator,
* left: import("estree-sentry").Expression<{}>,
* right: import("estree-sentry").Expression<{}>,
* ) => import("estree-sentry").BinaryExpression<{}>}
*/
const makeBinaryExpression = (operator, left, right) => ({
type: "BinaryExpression",
operator,
left,
right,
});
/* eslint-disable local/no-impure */
/**
* @type {(
* operator: import("estree-sentry").BinaryOperator,
* terms: [
* import("estree-sentry").Expression<{}>,
* ... import("estree-sentry").Expression<{}>[]
* ],
* ) => import("estree-sentry").Expression<{}>}
*/
const makeConcatExpression = (operation, terms) => {
let result = terms[0];
for (let index = 0; index < terms.length - 1; index += 1) {
result = makeBinaryExpression(operation, result, terms[index + 1]);
}
return result;
};
/* eslint-enable local/no-impure */
/**
* @type {(
* body: import("estree-sentry").Statement<{}>[],
* ) => import("estree-sentry").BlockStatement<{}>}
*/
const makeBlockStatement = (body) => ({
type: "BlockStatement",
body,
});
/**
* @type {(
* argument: import("estree-sentry").Expression<{}>,
* ) => import("estree-sentry").ReturnStatement<{}>}
*/
const makeReturnStatement = (argument) => ({
type: "ReturnStatement",
argument,
});
/**
* @type {(
* test: import("estree-sentry").Expression<{}>,
* consequent: import("estree-sentry").Statement<{}>[],
* ) => import("estree-sentry").SwitchCase<{}>}
*/
const makeSwitchCase = (test, consequent) => ({
type: "SwitchCase",
test,
consequent,
});
/**
* @type {(
* discriminant: import("estree-sentry").Expression<{}>,
* cases: import("estree-sentry").SwitchCase<{}>[],
* ) => import("estree-sentry").SwitchStatement<{}>}
*/
const makeSwitchStatement = (discriminant, cases) => ({
type: "SwitchStatement",
discriminant,
cases,
});
/**
* @type {(
* operator: import("estree-sentry").LogicalOperator,
* left: import("estree-sentry").Expression<{}>,
* right: import("estree-sentry").Expression<{}>,
* ) => import("estree-sentry").Expression<{}>}
*/
const makeLogicalExpression = (operator, left, right) => ({
type: "LogicalExpression",
operator,
left,
right,
});
/**
* @type {(... [computed, key, value]: [
* true,
* import("estree-sentry").Expression<{}>,
* import("estree-sentry").Expression<{}>,
* ] | [
* false,
* (
* | import("estree-sentry").PublicKeyIdentifier<{}>
* | import("estree-sentry").PublicKeyLiteral<{}>
* ),
* import("estree-sentry").Expression<{}>,
* ]) => import("estree-sentry").ObjectProperty<{}>}
*/
const makeProperty = (computed, key, value) => {
if (computed) {
return {
type: "Property",
kind: "init",
method: false,
computed,
shorthand: false,
key,
value,
};
} else {
return {
type: "Property",
kind: "init",
method: false,
computed,
shorthand: false,
key,
value,
};
}
};
/**
* @type {(
* properties: (
* | import("estree-sentry").ObjectProperty<{}>
* | import("estree-sentry").SpreadElement<{}>
* )[],
* ) => import("estree-sentry").ObjectExpression<{}>}
*/
const makeObjectExpression = (properties) => ({
type: "ObjectExpression",
properties,
});
/**
* @type {(
* name: null | string,
* kind: {
* asynchronous: boolean,
* generator: boolean,
* },
* parameters: import("estree-sentry").Pattern<{}>[],
* body: import("estree-sentry").BlockStatement<{}>,
* ) => import("estree-sentry").FunctionExpression<{}>}
*/
const makeFunctionExpression = (
name,
{ asynchronous, generator },
parameters,
body,
) => ({
type: "FunctionExpression",
async: asynchronous,
generator,
params: parameters,
id: name === null ? null : makeVariableIdentifier(name),
body,
});
/**
* @type {(... [computed, object, property]: ([
* true,
* import("estree-sentry").Expression<{}>,
* import("estree-sentry").Expression<{}>,
* ] | [
* false,
* import("estree-sentry").Expression<{}>,
* import("estree-sentry").PublicKeyIdentifier<{}>,
* ])
* ) => import("estree-sentry").MemberExpression<{}>}
*/
const makeMemberExpression = (computed, object, property) => {
if (computed) {
return {
type: "MemberExpression",
computed,
optional: false,
object,
property,
};
} else {
return {
type: "MemberExpression",
computed,
optional: false,
object,
property,
};
}
};
/**
* @type {(
* callee: import("estree-sentry").Expression<{}>,
* arguments_: import("estree-sentry").Expression<{}>[],
* ) => import("estree-sentry").CallExpression<{}>}
*/
const makeCallExpression = (callee, arguments_) => ({
type: "CallExpression",
optional: false,
callee,
arguments: arguments_,
});
/**
* @type {(
* callee: import("estree-sentry").Expression<{}>,
* arguments_: import("estree-sentry").Expression<{}>[],
* ) => import("estree-sentry").NewExpression<{}>}
*/
const makeNewExpression = (callee, arguments_) => ({
type: "NewExpression",
callee,
arguments: arguments_,
});
/**
* @type {(
* name: keyof import("../lang/naming.d.ts").IntrinsicFunctionNaming,
* makeCodeExpression: (
* variable: string,
* ) => import("estree-sentry").Expression<{}>
* ) => import("./layout.d.ts").Layout}
*/
const makeAccessLayout = (name, makeCodeExpression) =>
toArrowLayout({
name,
dependencies: ["eval"],
setup: [
makeVariableDeclaration(
"const",
makeVariableIdentifier(`${getIntrinsicFunctionName(name)}_cache`),
makeObjectExpression([
makeProperty(
false,
makePublicKeyIdentifier("__proto__"),
makeSimpleLiteral(null),
),
]),
),
],
head: [
makeVariableIdentifier("variable"),
makeVariableIdentifier("additional"),
makeVariableIdentifier("optimization"),
],
body: makeConditionalExpression(
makeVariableIdentifier("optimization"),
makeAssignmentExpression(
makeMemberExpression(
true,
makeVariableIdentifier(`${getIntrinsicFunctionName(name)}_cache`),
makeVariableIdentifier("variable"),
),
makeVariableIdentifier("optimization"),
),
makeCallExpression(
makeLogicalExpression(
"??",
makeMemberExpression(
true,
makeVariableIdentifier(`${getIntrinsicFunctionName(name)}_cache`),
makeVariableIdentifier("variable"),
),
makeAssignmentExpression(
makeMemberExpression(
true,
makeVariableIdentifier(`${getIntrinsicFunctionName(name)}_cache`),
makeVariableIdentifier("variable"),
),
makeCallExpression(makeReadDependencyExpression("eval"), [
makeCodeExpression("variable"),
]),
),
),
[makeVariableIdentifier("additional")],
),
),
});
/**
* @type {(
* name: import("../lang/syntax.d.ts").AranIntrinsic,
* ) => import("./layout.d.ts").Layout}
*/
export const makeExtraLayout = (name) => {
switch (name) {
case "aran.global_object": {
return {
name,
dependencies: [],
setup: [],
value: makeVariableIdentifier(global_object_parameter),
};
}
case "aran.global_declarative_record": {
return {
name,
dependencies: [],
setup: [],
value: makeObjectExpression([
makeProperty(
false,
makePublicKeyIdentifier("__proto__"),
makeSimpleLiteral(null),
),
]),
};
}
case "aran.deadzone_symbol": {
return {
name,
dependencies: ["Symbol"],
setup: [],
value: makeCallExpression(makeReadDependencyExpression("Symbol"), [
makeSimpleLiteral("deadzone"),
]),
};
}
case "aran.throwException": {
return toArrowLayout({
name,
dependencies: [],
setup: [],
head: [makeVariableIdentifier("error")],
body: makeBlockStatement([
makeThrowStatement(makeVariableIdentifier("error")),
]),
});
}
case "aran.AsyncGeneratorFunction.prototype.prototype": {
return {
name,
dependencies: ["Reflect_getPrototypeOf"],
setup: [],
value: makeCallExpression(
makeReadDependencyExpression("Reflect_getPrototypeOf"),
[
makeMemberExpression(
false,
makeFunctionExpression(
null,
{ asynchronous: true, generator: true },
[],
makeBlockStatement([]),
),
makePublicKeyIdentifier("prototype"),
),
],
),
};
}
case "aran.GeneratorFunction.prototype.prototype": {
return {
name,
dependencies: ["Reflect_getPrototypeOf"],
setup: [],
value: makeCallExpression(
makeReadDependencyExpression("Reflect_getPrototypeOf"),
[
makeMemberExpression(
false,
makeFunctionExpression(
null,
{ asynchronous: false, generator: true },
[],
makeBlockStatement([]),
),
makePublicKeyIdentifier("prototype"),
),
],
),
};
}
case "aran.getValueProperty": {
return toArrowLayout({
name,
dependencies: [],
setup: [],
head: [makeVariableIdentifier("object"), makeVariableIdentifier("key")],
body: makeMemberExpression(
true,
makeVariableIdentifier("object"),
makeVariableIdentifier("key"),
),
});
}
case "aran.performUnaryOperation": {
return toArrowLayout({
name,
dependencies: [],
setup: [],
head: [
makeVariableIdentifier("operator"),
makeVariableIdentifier("argument"),
],
body: makeBlockStatement([
makeSwitchStatement(
makeVariableIdentifier("operator"),
map(UNARY_OPERATOR_ENUM, (operator) =>
makeSwitchCase(makeSimpleLiteral(operator), [
makeReturnStatement(
operator === "delete"
? makeSimpleLiteral(true)
: makeUnaryExpression(
operator,
makeVariableIdentifier("argument"),
),
),
]),
),
),
]),
});
}
case "aran.performBinaryOperation": {
return toArrowLayout({
name,
dependencies: [],
setup: [],
head: [
makeVariableIdentifier("operator"),
makeVariableIdentifier("left"),
makeVariableIdentifier("right"),
],
body: makeBlockStatement([
makeSwitchStatement(
makeVariableIdentifier("operator"),
map(BINARY_OPERATOR_ENUM, (operator) =>
makeSwitchCase(makeSimpleLiteral(operator), [
makeReturnStatement(
makeBinaryExpression(
operator,
makeVariableIdentifier("left"),
makeVariableIdentifier("right"),
),
),
]),
),
),
]),
});
}
case "aran.isConstructor": {
return toArrowLayout({
name,
dependencies: ["Boolean", "Reflect_construct"],
setup: [],
head: [makeVariableIdentifier("value")],
body: makeBlockStatement([
makeTryStatement(
makeBlockStatement([
makeExpressionStatement(
makeCallExpression(
makeReadDependencyExpression("Reflect_construct"),
[
makeReadDependencyExpression("Boolean"),
makeObjectExpression([]),
makeVariableIdentifier("value"),
],
),
),
makeReturnStatement(makeSimpleLiteral(true)),
]),
makeCatchClause(
null,
makeBlockStatement([
makeReturnStatement(makeSimpleLiteral(false)),
]),
),
null,
),
]),
});
}
case "aran.sliceObject": {
return toArrowLayout({
name,
dependencies: [
"Object_hasOwn",
"Reflect_getOwnPropertyDescriptor",
"Reflect_defineProperty",
"Reflect_ownKeys",
],
setup: [],
head: [
makeVariableIdentifier("object"),
makeVariableIdentifier("exclusion"),
],
body: makeBlockStatement([
makeVariableDeclaration(
"const",
makeVariableIdentifier("descriptor"),
makeObjectExpression([
makeProperty(
false,
makePublicKeyIdentifier("__proto__"),
makeSimpleLiteral(null),
),
makeProperty(
false,
makePublicKeyIdentifier("value"),
makeSimpleLiteral(null),
),
makeProperty(
false,
makePublicKeyIdentifier("writable"),
makeSimpleLiteral(true),
),
makeProperty(
false,
makePublicKeyIdentifier("enumerable"),
makeSimpleLiteral(true),
),
makeProperty(
false,
makePublicKeyIdentifier("configurable"),
makeSimpleLiteral(true),
),
]),
),
makeVariableDeclaration(
"const",
makeVariableIdentifier("keys"),
makeCallExpression(
makeReadDependencyExpression("Reflect_ownKeys"),
[makeVariableIdentifier("object")],
),
),
makeVariableDeclaration(
"const",
makeVariableIdentifier("length"),
makeMemberExpression(
false,
makeVariableIdentifier("keys"),
makePublicKeyIdentifier("length"),
),
),
makeVariableDeclaration(
"const",
makeVariableIdentifier("copy"),
makeObjectExpression([]),
),
makeVariableDeclaration(
"let",
makeVariableIdentifier("index"),
makeSimpleLiteral(0),
),
makeWhileStatement(
makeBinaryExpression(
"<",
makeVariableIdentifier("index"),
makeVariableIdentifier("length"),
),
makeBlockStatement([
makeVariableDeclaration(
"const",
makeVariableIdentifier("key"),
makeMemberExpression(
true,
makeVariableIdentifier("keys"),
makeVariableIdentifier("index"),
),
),
makeIfStatement(
makeLogicalExpression(
"&&",
makeUnaryExpression(
"!",
makeCallExpression(
makeReadDependencyExpression("Object_hasOwn"),
[
makeVariableIdentifier("exclusion"),
makeVariableIdentifier("key"),
],
),
),
makeMemberExpression(
false,
makeLogicalExpression(
"??",
makeCallExpression(
makeReadDependencyExpression(
"Reflect_getOwnPropertyDescriptor",
),
[
makeVariableIdentifier("object"),
makeVariableIdentifier("key"),
],
),
makeObjectExpression([
makeProperty(
false,
makePublicKeyIdentifier("enumerable"),
makeSimpleLiteral(false),
),
]),
),
makePublicKeyIdentifier("enumerable"),
),
),
makeBlockStatement([
makeExpressionStatement(
makeCallExpression(
makeReadDependencyExpression("Reflect_defineProperty"),
[
makeVariableIdentifier("copy"),
makeVariableIdentifier("key"),
makeSequenceExpression([
makeAssignmentExpression(
makeMemberExpression(
false,
makeVariableIdentifier("descriptor"),
makePublicKeyIdentifier("value"),
),
makeMemberExpression(
true,
makeVariableIdentifier("object"),
makeVariableIdentifier("key"),
),
),
makeVariableIdentifier("descriptor"),
]),
],
),
),
]),
null,
),
makeExpressionStatement(
makeAssignmentExpression(
makeVariableIdentifier("index"),
makeBinaryExpression(
"+",
makeVariableIdentifier("index"),
makeSimpleLiteral(1),
),
),
),
]),
),
makeReturnStatement(makeVariableIdentifier("copy")),
]),
});
}
case "aran.toArgumentList": {
return toArrowLayout({
name,
dependencies: [
"Reflect_defineProperty",
"Array_prototype_values",
"Function_prototype",
"Symbol_iterator",
"Symbol_toStringTag",
],
setup: [
makeVariableDeclaration(
"const",
makeVariableIdentifier("default_callee_descriptor"),
makeObjectExpression([
makeProperty(
false,
makePublicKeyIdentifier("__proto__"),
makeSimpleLiteral(null),
),
makeSpreadElement(
makeCallExpression(
makeReadDependencyExpression(
"Reflect_getOwnPropertyDescriptor",
),
[
makeReadDependencyExpression("Function_prototype"),
makeSimpleLiteral("arguments"),
],
),
),
makeProperty(
false,
makePublicKeyIdentifier("configurable"),
makeSimpleLiteral(false),
),
]),
),
],
head: [
makeVariableIdentifier("array"),
makeVariableIdentifier("callee"),
],
body: makeBlockStatement([
makeVariableDeclaration(
"const",
makeVariableIdentifier("descriptor"),
makeObjectExpression([
makeProperty(
false,
makePublicKeyIdentifier("__proto__"),
makeSimpleLiteral(null),
),
makeProperty(
false,
makePublicKeyIdentifier("value"),
makeSimpleLiteral(null),
),
makeProperty(
false,
makePublicKeyIdentifier("writable"),
makeSimpleLiteral(true),
),
makeProperty(
false,
makePublicKeyIdentifier("enumerable"),
makeSimpleLiteral(true),
),
makeProperty(
false,
makePublicKeyIdentifier("configurable"),
makeSimpleLiteral(true),
),
]),
),
makeVariableDeclaration(
"const",
makeVariableIdentifier("list"),
makeObjectExpression([]),
),
makeVariableDeclaration(
"const",
makeVariableIdentifier("length"),
makeMemberExpression(
false,
makeVariableIdentifier("array"),
makePublicKeyIdentifier("length"),
),
),
makeVariableDeclaration(
"let",
makeVariableIdentifier("index"),
makeSimpleLiteral(0),
),
makeWhileStatement(
makeBinaryExpression(
"<",
makeVariableIdentifier("index"),
makeVariableIdentifier("length"),
),
makeBlockStatement([
makeExpressionStatement(
makeCallExpression(
makeReadDependencyExpression("Reflect_defineProperty"),
[
makeVariableIdentifier("list"),
makeVariableIdentifier("index"),
makeSequenceExpression([
makeAssignmentExpression(
makeMemberExpression(
false,
makeVariableIdentifier("descriptor"),
makePublicKeyIdentifier("value"),
),
makeMemberExpression(
true,
makeVariableIdentifier("array"),
makeVariableIdentifier("index"),
),
),
makeVariableIdentifier("descriptor"),
]),
],
),
),
makeExpressionStatement(
makeAssignmentExpression(
makeVariableIdentifier("index"),
makeBinaryExpression(
"+",
makeVariableIdentifier("index"),
makeSimpleLiteral(1),
),
),
),
]),
),
makeExpressionStatement(
makeAssignmentExpression(
makeMemberExpression(
false,
makeVariableIdentifier("descriptor"),
makePublicKeyIdentifier("enumerable"),
),
makeSimpleLiteral(false),
),
),
makeExpressionStatement(
makeCallExpression(
makeReadDependencyExpression("Reflect_defineProperty"),
[
makeVariableIdentifier("list"),
makeSimpleLiteral("length"),
makeSequenceExpression([
makeAssignmentExpression(
makeMemberExpression(
false,
makeVariableIdentifier("descriptor"),
makePublicKeyIdentifier("value"),
),
makeVariableIdentifier("length"),
),
makeVariableIdentifier("descriptor"),
]),
],
),
),
makeExpressionStatement(
makeCallExpression(
makeReadDependencyExpression("Reflect_defineProperty"),
[
makeVariableIdentifier("list"),
makeSimpleLiteral("callee"),
makeConditionalExpression(
makeVariableIdentifier("callee"),
makeSequenceExpression([
makeAssignmentExpression(
makeMemberExpression(
false,
makeVariableIdentifier("descriptor"),
makePublicKeyIdentifier("value"),
),
makeVariableIdentifier("callee"),
),
makeVariableIdentifier("descriptor"),
]),
makeVariableIdentifier("default_callee_descriptor"),
),
],
),
),
makeExpressionStatement(
makeCallExpression(
makeReadDependencyExpression("Reflect_defineProperty"),
[
makeVariableIdentifier("list"),
makeReadDependencyExpression("Symbol_iterator"),
makeSequenceExpression([
makeAssignmentExpression(
makeMemberExpression(
false,
makeVariableIdentifier("descriptor"),
makePublicKeyIdentifier("value"),
),
makeReadDependencyExpression("Array_prototype_values"),
),
makeVariableIdentifier("descriptor"),
]),
],
),
),
makeExpressionStatement(
makeCallExpression(
makeReadDependencyExpression("Reflect_defineProperty"),
[
makeVariableIdentifier("list"),
makeReadDependencyExpression("Symbol_toStringTag"),
makeSequenceExpression([
makeAssignmentExpression(
makeMemberExpression(
false,
makeVariableIdentifier("descriptor"),
makePublicKeyIdentifier("value"),
),
makeSimpleLiteral("Arguments"),
),
makeVariableIdentifier("descriptor"),
]),
],
),
),
makeReturnStatement(makeVariableIdentifier("list")),
]),
});
}
case "aran.listForInKey": {
return toArrowLayout({
name,
dependencies: [],
setup: [],
head: [makeVariableIdentifier("target")],
body: makeBlockStatement([
makeVariableDeclaration(
"let",
makeVariableIdentifier("length"),
makeSimpleLiteral(0),
),
// Use {__proto__: null} instead of [] to avoid the prototype chain
makeVariableDeclaration(
"const",
makeVariableIdentifier("keys"),
makeObjectExpression([
makeProperty(
false,
makePublicKeyIdentifier("__proto__"),
makeSimpleLiteral(null),
),
]),
),
makeForInStatement(
makeVariableDeclaration(
"const",
makeVariableIdentifier("key"),
null,
),
makeVariableIdentifier("target"),
makeExpressionStatement(
makeAssignmentExpression(
makeMemberExpression(
true,
makeVariableIdentifier("keys"),
makeUpdateExpression(
false,
"++",
makeVariableIdentifier("length"),
),
),
makeVariableIdentifier("key"),
),
),
),
makeExpressionStatement(
makeAssignmentExpression(
makeMemberExpression(
false,
makeVariableIdentifier("keys"),
makePublicKeyIdentifier("length"),
),
makeVariableIdentifier("length"),
),
),
makeReturnStatement(makeVariableIdentifier("keys")),
]),
});
}
case "aran.listIteratorRest": {
return toArrowLayout({
name,
dependencies: ["Reflect_apply"],
setup: [],
head: [
makeVariableIdentifier("iterator"),
makeVariableIdentifier("next"),
],
body: makeBlockStatement([
makeVariableDeclaration(
"const",
makeVariableIdentifier("rest"),
makeArrayExpression([]),
),
makeVariableDeclaration(
"let",
makeVariableIdentifier("step"),
makeCallExpression(makeReadDependencyExpression("Reflect_apply"), [
makeVariableIdentifier("next"),
makeVariableIdentifier("iterator"),
makeArrayExpression([]),
]),
),
makeVariableDeclaration(
"let",
makeVariableIdentifier("index"),
makeSimpleLiteral(0),
),
makeWhileStatement(
makeUnaryExpression(
"!",
makeMemberExpression(
false,
makeVariableIdentifier("step"),
makePublicKeyIdentifier("done"),
),
),
makeBlockStatement([
makeExpressionStatement(
makeAssignmentExpression(
makeMemberExpression(
true,
makeVariableIdentifier("rest"),
makeVariableIdentifier("index"),
),
makeMemberExpression(
false,
makeVariableIdentifier("step"),
makePublicKeyIdentifier("value"),
),
),
),
makeExpressionStatement(
makeAssignmentExpression(
makeVariableIdentifier("index"),
makeBinaryExpression(
"+",
makeVariableIdentifier("index"),
makeSimpleLiteral(1),
),
),
),
makeExpressionStatement(
makeAssignmentExpression(
makeVariableIdentifier("step"),
makeCallExpression(
makeReadDependencyExpression("Reflect_apply"),
[
makeVariableIdentifier("next"),
makeVariableIdentifier("iterator"),
makeArrayExpression([]),
],
),
),
),
]),
),
makeReturnStatement(makeVariableIdentifier("rest")),
]),
});
}
case "aran.toPropertyKey": {
return toArrowLayout({
name,
dependencies: ["Reflect_ownKeys"],
setup: [],
head: [makeVariableIdentifier("key")],
body: makeMemberExpression(
true,
makeCallExpression(makeReadDependencyExpression("Reflect_ownKeys"), [
makeObjectExpression([
makeProperty(
false,
makePublicKeyIdentifier("__proto__"),
makeSimpleLiteral(null),
),
makeProperty(
true,
makeVariableIdentifier("key"),
makeSimpleLiteral(null),
),
]),
]),
makeSimpleLiteral(0),
),
});
}
case "aran.createObject": {
return toArrowLayout({
name,
dependencies: ["Reflect_defineProperty"],
setup: [],
head: [
makeVariableIdentifier("prototype"),
makeRestElement(makeVariableIdentifier("entries")),
],
body: makeBlockStatement([
makeVariableDeclaration(
"const",
makeVariableIdentifier("descriptor"),
makeObjectExpression([
makeProperty(
false,
makePublicKeyIdentifier("__proto__"),
makeSimpleLiteral(null),
),
makeProperty(
false,
makePublicKeyIdentifier("value"),
makeSimpleLiteral(null),
),
makeProperty(
false,
makePublicKeyIdentifier("writable"),
makeSimpleLiteral(true),
),
makeProperty(
false,
makePublicKeyIdentifier("enumerable"),
makeSimpleLiteral(true),
),
makeProperty(
false,
makePublicKeyIdentifier("configurable"),
makeSimpleLiteral(true),
),
]),
),
makeVariableDeclaration(
"const",
makeVariableIdentifier("object"),
makeObjectExpression([
makeProperty(
false,
makePublicKeyIdentifier("__proto__"),
makeVariableIdentifier("prototype"),
),
]),
),
makeVariableDeclaration(
"const",
makeVariableIdentifier("length"),
makeMemberExpression(
false,
makeVariableIdentifier("entries"),
makePublicKeyIdentifier("length"),
),
),
makeVariableDeclaration(
"let",
makeVariableIdentifier("index"),
makeSimpleLiteral(0),
),
makeWhileStatement(
makeBinaryExpression(
"<",
makeVariableIdentifier("index"),
makeVariableIdentifier("length"),
),
makeBlockStatement([
makeExpressionStatement(
makeAssignmentExpression(
makeMemberExpression(
false,
makeVariableIdentifier("descriptor"),
makePublicKeyIdentifier("value"),
),
makeMemberExpression(
true,
makeVariableIdentifier("entries"),
makeBinaryExpression(
"+",
makeVariableIdentifier("index"),
makeSimpleLiteral(1),
),
),
),
),
makeExpressionStatement(
makeCallExpression(
makeReadDependencyExpression("Reflect_defineProperty"),
[
makeVariableIdentifier("object"),
makeMemberExpression(
true,
makeVariableIdentifier("entries"),
makeVariableIdentifier("index"),
),
makeVariableIdentifier("descriptor"),
],
),
),
makeExpressionStatement(
makeAssignmentExpression(
makeVariableIdentifier("index"),
makeBinaryExpression(
"+",
makeVariableIdentifier("index"),
makeSimpleLiteral(2),
),
),
),
]),
),
makeReturnStatement(makeVariableIdentifier("object")),
]),
});
}
case "aran.declareGlobalVariable": {
return toArrowLayout({
name,
dependencies: ["eval"],
setup: [],
head: [makeVariableIdentifier("variables")],
body: makeCallExpression(makeReadDependencyExpression("eval"), [
makeConcatExpression("+", [
makeSimpleLiteral("var "),
makeVariableIdentifier("variables"),
makeSimpleLiteral(";"),
]),
]),
});
}
case "aran.readGlobalVariable": {
return makeAccessLayout(name, (variable) =>
makeConcatExpression("+", [
makeSimpleLiteral("(() => "),
makeVariableIdentifier(variable),
makeSimpleLiteral(");"),
]),
);
}
case "aran.typeofGlobalVariable": {
return makeAccessLayout(name, (variable) =>
makeConcatExpression("+", [
makeSimpleLiteral("(() => typeof "),
makeVariableIdentifier(variable),
makeSimpleLiteral(");"),
]),
);
}
case "aran.discardGlobalVariable": {
return makeAccessLayout(name, (variable) =>
makeConcatExpression("+", [
makeSimpleLiteral("(() => delete "),
makeVariableIdentifier(variable),
makeSimpleLiteral(");"),
]),
);
}
case "aran.writeGlobalVariableSloppy": {
return makeAccessLayout(name, (variable) =>
makeConcatExpression("+", [
makeSimpleLiteral("(("),
makeConditionalExpression(
makeBinaryExpression(
"===",
makeVariableIdentifier(variable),
makeSimpleLiteral("VALUE"),
),
makeSimpleLiteral("$VALUE) => { "),
makeSimpleLiteral("VALUE) => { "),
),
makeVariableIdentifier(variable),
makeSimpleLiteral(" = "),
makeConditionalExpression(
makeBinaryExpression(
"===",
makeVariableIdentifier(variable),
makeSimpleLiteral("VALUE"),
),
makeSimpleLiteral("$VALUE; });"),
makeSimpleLiteral("VALUE; });"),
),
]),
);
}
case "aran.writeGlobalVariableStrict": {
return makeAccessLayout(name, (variable) =>
makeConcatExpression("+", [
makeSimpleLiteral("'use strict'; (("),
makeConditionalExpression(
makeBinaryExpression(
"===",
makeVariableIdentifier(variable),
makeSimpleLiteral("VALUE"),
),
makeSimpleLiteral("$VALUE) => { "),
makeSimpleLiteral("VALUE) => { "),
),
makeVariableIdentifier(variable),
makeSimpleLiteral(" = "),
makeConditionalExpression(
makeBinaryExpression(
"===",
makeVariableIdentifier(variable),
makeSimpleLiteral("VALUE"),
),
makeSimpleLiteral("$VALUE; });"),
makeSimpleLiteral("VALUE; });"),
),
]),
);
}
case "aran.transpileEvalCode": {
return toArrowLayout({
name,
dependencies: ["SyntaxError"],
setup: [],
head: [
makeVariableIdentifier("_code"),
makeVariableIdentifier("_situ"),
],
body: makeBlockStatement([
makeThrowStatement(
makeNewExpression(makeReadDependencyExpression("SyntaxError"), [
makeSimpleLiteral(
"aran.transpileEvalCode must be overriden to support direct eval calls",
),
]),
),
]),
});
}
case "aran.retropileEvalCode": {
return toArrowLayout({
name,
dependencies: ["SyntaxError"],
setup: [],
head: [makeVariableIdentifier("_aran")],
body: makeBlockStatement([
makeThrowStatement(
makeNewExpression(makeReadDependencyExpression("SyntaxError"), [
makeSimpleLiteral(
"aran.retropileEvalCode must be overriden to support direct eval calls",
),
]),
),
]),
});
}
default: {
throw new AranTypeError(name);
}
}
};