/* eslint-disable no-await-in-loop */ /* eslint-disable quotes */ import { expect, test } from 'vitest'; import { TestInspector } from './utils.mts'; import { Agent, ManagedRealm, setSurroundingAgent } from '#self'; test('compile script (for invalid code break line)', async () => { const agent = new Agent(); setSurroundingAgent(agent); const inspector = new TestInspector(); const realm = new ManagedRealm(); inspector.attachAgent(agent, [realm]); const result = await inspector.runtime.compileScript({ expression: 'function f() {', persistScript: false, sourceURL: '', executionContextId: 0, }); expect(result).toMatchInlineSnapshot(` { "exceptionDetails": { "columnNumber": 0, "exception": { "className": "SyntaxError", "description": "SyntaxError: Unexpected end of input", "objectId": "default:2", "preview": { "description": " function f() { ^ SyntaxError: Unexpected end of source", "entries": undefined, "overflow": false, "properties": [ { "name": "message", "type": "string", "value": "Unexpected end of source", }, { "name": "stack", "type": "string", "value": " function f() { ^ SyntaxError: Unexpected end of source", }, ], "subtype": "error", "type": "object", }, "subtype": "error", "type": "object", }, "exceptionId": 1, "lineNumber": 0, "scriptId": undefined, "stackTrace": { "callFrames": [], }, "text": "Uncaught", "url": undefined, }, } `); }); test('preview evaluation', async () => { const agent = new Agent(); setSurroundingAgent(agent); const inspector = new TestInspector(); const realm = new ManagedRealm(); inspector.attachAgent(agent, [realm]); for (const code of [ `1`, `[]`, `{ var a = 1; a }`, `{ let a = 1; a }`, `[1, 2, 3].map(x => x + 1)`, `globalThis.x = 1`, ]) { // eslint-disable-next-line @typescript-eslint/no-explicit-any const result: any = await inspector.perview(code); if (result.exceptionDetails?.exception.preview.properties[0].value === 'Preview evaluator cannot evaluate side-effecting code') { expect('side effect').toMatchSnapshot(code); } else { expect(result).toMatchSnapshot(code); } } }); test('get local lexical names', async () => { const agent = new Agent(); setSurroundingAgent(agent); const inspector = new TestInspector(); const realm = new ManagedRealm(); inspector.attachAgent(agent, [realm]); expect(await inspector.runtime.globalLexicalScopeNames({ executionContextId: 0, })).toMatchInlineSnapshot(` { "names": [ "Infinity", "NaN", "undefined", "globalThis", "eval", "isFinite", "isNaN", "parseFloat", "parseInt", "decodeURI", "decodeURIComponent", "encodeURI", "encodeURIComponent", "AggregateError", "Array", "ArrayBuffer", "Boolean", "BigInt", "BigInt64Array", "BigUint64Array", "DataView", "Date", "Error", "EvalError", "FinalizationRegistry", "Float32Array", "Float64Array", "Function", "Int8Array", "Int16Array", "Int32Array", "Iterator", "Map", "Number", "Object", "Promise", "Proxy", "RangeError", "ReferenceError", "RegExp", "Set", "ShadowRealm", "String", "Symbol", "SyntaxError", "TypeError", "Uint8Array", "Uint8ClampedArray", "Uint16Array", "Uint32Array", "URIError", "WeakMap", "WeakRef", "WeakSet", "JSON", "Math", "Reflect", ], } `); }); test('call function on', async () => { const agent = new Agent(); setSurroundingAgent(agent); const inspector = new TestInspector(); const realm = new ManagedRealm(); inspector.attachAgent(agent, [realm]); inspector.flush(); await inspector.eval('const a = { x: 1 }; a'); expect(inspector.flush()).toMatchInlineSnapshot(` [ { "method": "Debugger.scriptParsed", "params": { "buildId": "", "endColumn": 21, "endLine": 1, "executionContextId": 0, "hash": "", "isModule": false, "scriptId": "0", "startColumn": 0, "startLine": 0, "url": "vm:///0", }, }, { "id": 0, "method": "Runtime.evaluate", "params": { "expression": "const a = { x: 1 }; a", "uniqueContextId": "0", }, }, { "id": 0, "result": { "exceptionDetails": undefined, "result": { "className": "Object", "description": "Object", "objectId": "default:1", "preview": { "description": "Object", "entries": undefined, "overflow": false, "properties": [ { "name": "x", "type": "number", "value": "1", }, ], "subtype": undefined, "type": "object", }, "subtype": undefined, "type": "object", }, }, }, ] `); expect(await inspector.runtime.callFunctionOn({ functionDeclaration: 'function (x) { return this.x + x }', arguments: [{ value: 1 }], executionContextId: 0, objectId: 'default:1', })).toMatchInlineSnapshot(` { "description": "2", "type": "number", "value": 2, } `); expect(await inspector.runtime.callFunctionOn({ functionDeclaration: 'function (x) { return [this.x, x, 2, 3] }', arguments: [{ value: 1 }], executionContextId: 0, objectId: 'default:1', returnByValue: true, })).toMatchInlineSnapshot(` { "type": "object", "value": [ 1, 1, 2, 3, ], } `); }); test('private field jailbreak', async () => { const agent = new Agent(); setSurroundingAgent(agent); const inspector = new TestInspector(); const realm = new ManagedRealm(); inspector.attachAgent(agent, [realm]); await inspector.eval('class A { #x = 1; }; globalThis.a = new A();'); await inspector.debugger.engine262_setEvaluateMode({ mode: 'console' }); expect(await inspector.runtime.evaluate({ expression: 'a.#x', uniqueContextId: '0' })).toMatchInlineSnapshot(` { "description": "1", "type": "number", "value": 1, } `); });