mirror of
https://github.com/bendtherules/ask262.git
synced 2026-08-18 13:21:55 +00:00
342 lines
9.8 KiB
TypeScript
342 lines
9.8 KiB
TypeScript
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
/* eslint-disable no-await-in-loop */
|
|
import { expect, test } from 'vitest';
|
|
import type Protocol from 'devtools-protocol';
|
|
import { TestInspector } from './utils.mts';
|
|
import { Agent, ManagedRealm, setSurroundingAgent } from '#self';
|
|
|
|
test('primitive values', async () => {
|
|
const agent = new Agent();
|
|
setSurroundingAgent(agent);
|
|
const inspector = new TestInspector();
|
|
const realm = new ManagedRealm();
|
|
inspector.attachAgent(agent, [realm]);
|
|
|
|
for (const value of [
|
|
'undefined',
|
|
'null',
|
|
'false',
|
|
'true',
|
|
'42',
|
|
'-42',
|
|
'42n',
|
|
'-42n',
|
|
'0',
|
|
'-0',
|
|
'Infinity',
|
|
'-Infinity',
|
|
'NaN',
|
|
'"engine262"',
|
|
'Symbol()',
|
|
'Symbol("desc")',
|
|
'Symbol.for("symbol")',
|
|
'Symbol.iterator',
|
|
]) {
|
|
// eslint-disable-next-line no-await-in-loop
|
|
expect(await inspector.eval(value)).toMatchSnapshot(value);
|
|
}
|
|
});
|
|
|
|
test('functions', async () => {
|
|
const agent = new Agent();
|
|
setSurroundingAgent(agent);
|
|
const inspector = new TestInspector();
|
|
const realm = new ManagedRealm();
|
|
inspector.attachAgent(agent, [realm]);
|
|
|
|
for (const value of [
|
|
// function declaration
|
|
'function f() { /* comment */ }; f',
|
|
'function* f() { /* comment */ }; f',
|
|
'function *f() { /* comment */ }; f',
|
|
'async function f() { /* comment */ }; f',
|
|
'async function* f() { /* comment */ }; f',
|
|
'async function *f() { /* comment */ }; f',
|
|
// function expression
|
|
'(function f() { /* comment */ })',
|
|
'(function* f() { /* comment */ })',
|
|
'(function *f() { /* comment */ })',
|
|
'(async function f() { /* comment */ })',
|
|
'(async function* f() { /* comment */ })',
|
|
'(async function *f() { /* comment */ })',
|
|
// arrow expression
|
|
'(() => { /* comment */ })',
|
|
'(() => 42)',
|
|
'(async () => { /* comment */ })',
|
|
'(async () => 42)',
|
|
// computed function name
|
|
'var a = 1; ({ [a]() {} })[a]',
|
|
'({ *[Symbol.iterator]() {} })[Symbol.iterator]',
|
|
// getter & setter
|
|
'var o = { get f() { /* comment */ } }; Reflect.getOwnPropertyDescriptor(o, "f").get',
|
|
'var o = { set f(v) { /* comment */ } }; Reflect.getOwnPropertyDescriptor(o, "f").set',
|
|
// getter & setter with computed name
|
|
'var o = { get [Symbol.iterator]() { /* comment */ } }; Reflect.getOwnPropertyDescriptor(o, Symbol.iterator).get',
|
|
'var o = { set [Symbol.iterator](v) { /* comment */ } }; Reflect.getOwnPropertyDescriptor(o, Symbol.iterator).set',
|
|
// built-in function
|
|
'Array.prototype.map',
|
|
// built-in getter
|
|
'Reflect.getOwnPropertyDescriptor(Function.prototype, "caller").get',
|
|
// method
|
|
'class C { static method() {} }; C.method',
|
|
'class C { constructor() {}; #f }; C.prototype.constructor',
|
|
]) {
|
|
// eslint-disable-next-line no-await-in-loop
|
|
expect(await inspector.eval(value), value).toMatchSnapshot(value);
|
|
}
|
|
});
|
|
|
|
async function snapshotObject(inspector: TestInspector, value: string) {
|
|
const result = await inspector.eval(value);
|
|
expect(result).toMatchSnapshot(value);
|
|
const properties = await inspector.runtime.getProperties({ objectId: (result as any).objectId!, ownProperties: true, generatePreview: true }) as Protocol.Protocol.Runtime.GetPropertiesResponse;
|
|
properties.internalProperties = properties.internalProperties?.filter((prop) => prop.name !== '[[Prototype]]');
|
|
expect(properties).toMatchSnapshot(`${value} properties`);
|
|
}
|
|
|
|
test('array', async () => {
|
|
const agent = new Agent();
|
|
setSurroundingAgent(agent);
|
|
const inspector = new TestInspector();
|
|
const realm = new ManagedRealm();
|
|
inspector.attachAgent(agent, [realm]);
|
|
|
|
for (const value of [
|
|
'[]',
|
|
'[1]',
|
|
'Array(10)',
|
|
'[,,,]',
|
|
'var a = [1,,2]; a.x = 1; a',
|
|
]) {
|
|
await snapshotObject(inspector, value);
|
|
}
|
|
});
|
|
|
|
test('regex', async () => {
|
|
const agent = new Agent();
|
|
setSurroundingAgent(agent);
|
|
const inspector = new TestInspector();
|
|
const realm = new ManagedRealm();
|
|
inspector.attachAgent(agent, [realm]);
|
|
|
|
for (const value of [
|
|
'/cat/',
|
|
'/cat/g',
|
|
'/cat/i',
|
|
'var a = /cat/; a.lastIndex = 1; a',
|
|
]) {
|
|
expect(await inspector.eval(value)).toMatchSnapshot(value);
|
|
}
|
|
});
|
|
|
|
test('date', async () => {
|
|
const agent = new Agent();
|
|
setSurroundingAgent(agent);
|
|
const inspector = new TestInspector();
|
|
const realm = new ManagedRealm();
|
|
inspector.attachAgent(agent, [realm]);
|
|
|
|
for (const value of [
|
|
'new Date(0)',
|
|
'new Date(NaN)',
|
|
'new Date(-1)',
|
|
'new Date(9999999999999)',
|
|
]) {
|
|
expect(await inspector.eval(value)).toMatchSnapshot(value);
|
|
}
|
|
});
|
|
|
|
test('map and set', async () => {
|
|
const agent = new Agent();
|
|
setSurroundingAgent(agent);
|
|
const inspector = new TestInspector();
|
|
const realm = new ManagedRealm();
|
|
inspector.attachAgent(agent, [realm]);
|
|
|
|
for (const value of [
|
|
'new Map',
|
|
'new Map([["a", 1], ["b", 2]])',
|
|
'var x = new Map([["a", 1], ["b", 2]]); x.x = 1; x',
|
|
'new Set',
|
|
'new Set(["a", 1, "b", 2])',
|
|
'var x = new Set(["a", 1, "b", 2]); x.x = 1; x',
|
|
'new WeakMap',
|
|
'new WeakMap([[{}, 1], [{}, 2]])',
|
|
'var x = new WeakMap([[{}, 1], [{}, 2]]); x.x = 1; x',
|
|
'new WeakSet',
|
|
'new WeakSet([{}, {}])',
|
|
'var x = new WeakSet([{}, {}]); x.x = 1; x',
|
|
]) {
|
|
await snapshotObject(inspector, value);
|
|
}
|
|
});
|
|
|
|
// TODO: generator
|
|
|
|
test('error', async () => {
|
|
const agent = new Agent();
|
|
setSurroundingAgent(agent);
|
|
const inspector = new TestInspector();
|
|
const realm = new ManagedRealm();
|
|
inspector.attachAgent(agent, [realm]);
|
|
|
|
for (const value of [
|
|
'new Error()',
|
|
'new Error("message")',
|
|
'new Error("message", { cause: new Error("cause") })',
|
|
'new RangeError()',
|
|
'new (class MyError extends Error {})()',
|
|
// TODO: className should not be syntaxError
|
|
'new (class MyError extends Error { constructor() { super(); this.message = "hello" } })()',
|
|
]) {
|
|
expect(await inspector.eval(value)).toMatchSnapshot(value);
|
|
}
|
|
});
|
|
|
|
test('proxy', async () => {
|
|
const agent = new Agent();
|
|
setSurroundingAgent(agent);
|
|
const inspector = new TestInspector();
|
|
const realm = new ManagedRealm();
|
|
inspector.attachAgent(agent, [realm]);
|
|
|
|
for (const value of [
|
|
'new Proxy({}, {})',
|
|
'new Proxy({}, { get: () => {} })',
|
|
'new Proxy({ a: 1 }, {})',
|
|
'new Proxy(Function, {})',
|
|
'new Proxy(() => {}, {})',
|
|
'var a = Proxy.revocable({}, {}); a.revoke(); a.proxy',
|
|
]) {
|
|
await snapshotObject(inspector, value);
|
|
}
|
|
});
|
|
|
|
test('promise', async () => {
|
|
const agent = new Agent();
|
|
setSurroundingAgent(agent);
|
|
const inspector = new TestInspector();
|
|
const realm = new ManagedRealm();
|
|
inspector.attachAgent(agent, [realm]);
|
|
|
|
for (const value of [
|
|
'new Promise(() => {})',
|
|
'var a = new Promise(() => {}); a.x = 1; a',
|
|
'Promise.resolve()',
|
|
'Promise.resolve(42)',
|
|
'Promise.reject()',
|
|
'Promise.reject(42)',
|
|
]) {
|
|
await snapshotObject(inspector, value);
|
|
}
|
|
});
|
|
|
|
test('typed array', async () => {
|
|
const agent = new Agent();
|
|
setSurroundingAgent(agent);
|
|
const inspector = new TestInspector();
|
|
const realm = new ManagedRealm();
|
|
inspector.attachAgent(agent, [realm]);
|
|
|
|
for (const value of [
|
|
'new Uint8Array()',
|
|
'new Uint8Array(10)',
|
|
'new Uint8Array([1, 2, 3])',
|
|
'var x = new Uint8Array(10); x.a = 1; x',
|
|
'new Int32Array()',
|
|
'new Int32Array(10)',
|
|
'new Int32Array([1, 2, 3])',
|
|
// TODO: test with detached arraybuffer
|
|
]) {
|
|
await snapshotObject(inspector, value);
|
|
}
|
|
});
|
|
|
|
test('array buffer', async () => {
|
|
const agent = new Agent();
|
|
setSurroundingAgent(agent);
|
|
const inspector = new TestInspector();
|
|
const realm = new ManagedRealm();
|
|
inspector.attachAgent(agent, [realm]);
|
|
|
|
for (const value of [
|
|
'new ArrayBuffer(0)',
|
|
'new ArrayBuffer(10)',
|
|
'var x = new ArrayBuffer(10); x.a = 1; x',
|
|
// TODO: test with detached arraybuffer
|
|
]) {
|
|
await snapshotObject(inspector, value);
|
|
}
|
|
});
|
|
|
|
test('data view', async () => {
|
|
const agent = new Agent();
|
|
setSurroundingAgent(agent);
|
|
const inspector = new TestInspector();
|
|
const realm = new ManagedRealm();
|
|
inspector.attachAgent(agent, [realm]);
|
|
|
|
for (const value of [
|
|
'new DataView(new ArrayBuffer(0))',
|
|
'new DataView(new ArrayBuffer(10))',
|
|
'var x = new DataView(new ArrayBuffer(10), 0); x.a = 1; x',
|
|
]) {
|
|
await snapshotObject(inspector, value);
|
|
}
|
|
});
|
|
|
|
test('module namespace', async () => {
|
|
const agent = new Agent();
|
|
setSurroundingAgent(agent);
|
|
const inspector = new TestInspector();
|
|
const realm = new ManagedRealm();
|
|
inspector.attachAgent(agent, [realm]);
|
|
await inspector.debugger.engine262_setEvaluateMode({ mode: 'module' });
|
|
|
|
for (const value of [
|
|
// Note: our inspector will return the module namespace object after evaluation
|
|
'',
|
|
'export const a = 1',
|
|
'export const b = 2; export { b as c }',
|
|
'export default 42',
|
|
'export default function() {}',
|
|
]) {
|
|
await snapshotObject(inspector, value);
|
|
}
|
|
});
|
|
|
|
test('shadow realm', async () => {
|
|
const agent = new Agent();
|
|
setSurroundingAgent(agent);
|
|
const inspector = new TestInspector();
|
|
const realm = new ManagedRealm();
|
|
inspector.attachAgent(agent, [realm]);
|
|
|
|
await snapshotObject(inspector, 'new ShadowRealm');
|
|
expect(await inspector.eval('new ShadowRealm().evaluate("(() => {})")')).toMatchSnapshot('ShadowRealm function');
|
|
});
|
|
|
|
test('normal object', async () => {
|
|
const agent = new Agent();
|
|
setSurroundingAgent(agent);
|
|
const inspector = new TestInspector();
|
|
const realm = new ManagedRealm();
|
|
inspector.attachAgent(agent, [realm]);
|
|
|
|
for (const value of [
|
|
'({})',
|
|
'({ a: 1 })',
|
|
'({ a: 1, b: 2 })',
|
|
'({ __proto__: null })',
|
|
'({ __proto__: { a: 1 } })',
|
|
'({ [Symbol.iterator]: () => {} })',
|
|
'({ f() {} })',
|
|
'({ get f() {}, set f(v) {} })',
|
|
'{ class T { #priv = 1 }; new T }',
|
|
'{ class T { #priv = 1; normal = 2 }; new T }',
|
|
'({ a: 1n, b: undefined, c: null, d: true, e: Symbol.iterator, f: [] })',
|
|
]) {
|
|
await snapshotObject(inspector, value);
|
|
}
|
|
});
|