Files

1613 lines
52 KiB
JavaScript

/*!
* engine262 0.0.1 3748e24ce7e55e3eaeef4f1949b7a0c2570ba720
*
* Copyright (c) 2018 engine262 Contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
import { Value, surroundingAgent, evalQ, ObjectValue, skipDebugger, Get, ToString, R, DateProto_toISOString, ValueOfNormalCompletion, TemporalInstantToString, TemporalDurationToString, TemporalDateToString, ISODateTimeToString, TemporalMonthDayToString, TimeRecordToString, TemporalYearMonthToString, TemporalZonedDateTimeToString, IsCallable, JSStringValue, PrivateName, SymbolDescriptiveString, isTemporalZonedDateTimeObject, isTemporalPlainYearMonthObject, isTemporalPlainTimeObject, isTemporalPlainMonthDayObject, isTemporalPlainDateTimeObject, isTemporalPlainDateObject, isTemporalDurationObject, isTemporalInstantObject, isShadowRealmObject, isModuleNamespaceObject, isDataViewObject, isArrayBufferObject, isTypedArrayObject, isPromiseObject, isErrorObject, isWeakSetObject, isWeakMapObject, isSetObject, isMapObject, isDateObject, isRegExpObject, isArrayExoticObject, isProxyExoticObject, BigIntValue, NumberValue, SymbolValue, ArrayExoticObjectInternalMethods, Descriptor, F, isIntegerIndex, IntrinsicsFunctionToString, isECMAScriptFunctionObject, DataBlock, MakeTypedArrayWithBufferWitnessRecord, TypedArrayLength, TypedArrayGetElement, UndefinedValue, isWrappedFunctionExoticObject, ManagedRealm, IsAccessorDescriptor, isBuiltinFunctionObject, ThrowCompletion, getHostDefinedErrorStack, EnsureCompletion, getCurrentStack, EnvironmentRecord, DeclarativeEnvironmentRecord, OrdinaryObjectCreate, isArgumentExoticObject, ObjectEnvironmentRecord, GlobalEnvironmentRecord, NullValue, FunctionEnvironmentRecord, ModuleEnvironmentRecord, SourceTextModuleRecord, Call, ParseModule, ParseScript, kInternal, performDevtoolsEval, runJobQueue, Assert, captureStack, DefinePropertyOrThrow, CreateBuiltinFunction, CreateDataProperty } from './engine262.mjs';
/*
Test code: copy this into the inspector console.
primitive: console.log('primitive:', null, undefined, true, false, 0, -0, NaN, Infinity, -Infinity, 1n, 'string', Symbol(), Symbol('text'), Symbol.for('global'), Symbol.iterator);
fn: console.log('builtin:', eval, '\nfunction:', function() { code }, '\ngenerator:', function*() { code }, '\nasync:', async function() { code }, '\nasync generator:', async function*() { code }, '\narrow:', () => { code }, '\narrow async:', async () => { code });
normal: console.log('normal:', {}, new (class T { #a }), globalThis);
arraybuffer: console.log('arraybuffer:', new ArrayBuffer(8));
dataview: console.log('dataview:', new DataView(new ArrayBuffer(8)));
map: console.log('map:', new Map(), new Map([[eval, globalThis], [1, 2]]));
set: console.log('set:', new Set(), new Set([1, globalThis]));
weakmap: console.log('weakmap:', new WeakMap(), new WeakMap([[{}, 1]]));
weakset: console.log('weakset:', new WeakSet(), new WeakSet([{}]));
date: console.log('date:', new Date());
promise: console.log('promise:', new Promise(() => {}), Promise.resolve(globalThis), Promise.reject(globalThis));
proxy: { const x = Proxy.revocable({}, {}); x.revoke(); console.log('proxy:', new Proxy({}, {}), new Proxy(function() {}, {}), x.proxy); }
regexp: console.log('regexp:', /pattern/, new RegExp('pattern', 'g'));
array: console.log('array:', [], [1, 2], Object.assign([1, 2], { a: 1 }), [0, ,,, 3]);
typedarray: console.log('typedarray:', new Int8Array(8), new Int16Array(8), new Int32Array(8), new Uint8Array(8), new Uint16Array(8), new Uint32Array(8), new Uint8ClampedArray(8), new Float32Array(8), new Float64Array(8), new BigInt64Array(8), new BigUint64Array(8));
*/
const Null = {
toRemoteObject: () => ({
type: 'object',
subtype: 'null',
value: null
}),
toObjectPreview: () => ({
type: 'object',
subtype: 'null',
properties: [],
overflow: false
}),
toPropertyPreview: name => ({
name,
type: 'object',
subtype: 'null',
value: 'null'
}),
toDescription: () => ''
};
const Undefined = {
toRemoteObject: () => ({
type: 'undefined'
}),
toObjectPreview: () => ({
type: 'undefined',
properties: [],
overflow: false
}),
toPropertyPreview: name => ({
name,
type: 'undefined',
value: 'undefined'
}),
toDescription: () => 'undefined'
};
const Boolean$1 = {
toRemoteObject: value => ({
type: 'boolean',
value: value.booleanValue()
}),
toPropertyPreview: (name, value) => ({
name,
type: 'boolean',
value: value.booleanValue().toString()
}),
toObjectPreview(value) {
return {
type: 'boolean',
value: value.booleanValue(),
description: value.booleanValue().toString(),
overflow: false,
properties: []
};
},
toDescription: value => value.booleanValue().toString()
};
const Symbol = {
toRemoteObject: (value, getObjectId) => ({
type: 'symbol',
description: SymbolDescriptiveString(value).stringValue(),
objectId: getObjectId(value)
}),
toPropertyPreview: (name, value) => ({
name,
type: 'symbol',
value: SymbolDescriptiveString(value).stringValue()
}),
toObjectPreview: value => ({
type: 'symbol',
description: SymbolDescriptiveString(value).stringValue(),
overflow: false,
properties: []
}),
toDescription: value => SymbolDescriptiveString(value).stringValue()
};
const String$1 = {
toRemoteObject: value => ({
type: 'string',
value: value.stringValue()
}),
toPropertyPreview(name, value) {
return {
name,
type: 'string',
value: value.stringValue()
};
},
toObjectPreview(value) {
return {
type: 'string',
description: value.stringValue(),
overflow: false,
properties: []
};
},
toDescription: value => value.stringValue()
};
const Number = {
toRemoteObject(value) {
const v = R(value);
let description = v.toString();
const isNeg0 = Object.is(v, -0);
// Includes values `-0`, `NaN`, `Infinity`, `-Infinity`, and bigint literals.
if (isNeg0 || !globalThis.Number.isFinite(v)) {
if (typeof v === 'bigint') {
description += 'n';
return {
type: 'bigint',
unserializableValue: description,
description
};
}
return {
type: 'number',
unserializableValue: description,
description: isNeg0 ? '-0' : description
};
}
return {
type: 'number',
value: v,
description
};
},
toPropertyPreview(name, value) {
return {
name,
type: 'number',
value: this.toDescription(value)
};
},
toObjectPreview(value) {
return {
type: 'number',
description: this.toDescription(value),
overflow: false,
properties: []
};
},
toDescription: value => {
const r = R(value);
return value instanceof BigIntValue ? `${r}n` : r.toString();
}
};
function unwrapFunction(value) {
if (isWrappedFunctionExoticObject(value)) {
return unwrapFunction(value.WrappedTargetFunction);
}
return value;
}
const Function = {
toRemoteObject(value, getObjectId) {
value = unwrapFunction(value);
const result = {
type: 'function',
objectId: getObjectId(value)
};
result.description = IntrinsicsFunctionToString(value);
if (isECMAScriptFunctionObject(value) && value.ECMAScriptCode) {
if (value.ECMAScriptCode.type === 'FunctionBody') {
result.className = 'Function';
} else if (value.ECMAScriptCode.type === 'GeneratorBody') {
result.className = 'GeneratorFunction';
} else if (value.ECMAScriptCode.type === 'AsyncBody') {
result.className = 'AsyncFunction';
} else if (value.ECMAScriptCode.type === 'AsyncGeneratorBody') {
result.className = 'AsyncGeneratorFunction';
}
} else {
result.className = 'Function';
}
return result;
},
toPropertyPreview: name => ({
name,
type: 'function',
value: ''
}),
toObjectPreview(value) {
return {
type: 'function',
description: IntrinsicsFunctionToString(value),
overflow: false,
properties: []
};
},
toDescription: () => 'Function'
};
class ObjectInspector {
subtype;
className;
toDescription;
toEntries;
additionalProperties;
internalProperties;
constructor(className, subtype, toDescription, additionalOptions) {
this.className = className;
this.subtype = subtype;
this.toDescription = toDescription;
this.toEntries = additionalOptions?.entries;
this.additionalProperties = additionalOptions?.additionalProperties;
this.internalProperties = additionalOptions?.internalProperties;
}
toRemoteObject(value, getObjectId) {
return {
type: 'object',
subtype: this.subtype,
objectId: getObjectId(value),
className: typeof this.className === 'string' ? this.className : this.className(value),
description: this.toDescription(value),
preview: this.toObjectPreview(value)
};
}
toPropertyPreview(name, value) {
return {
name,
type: 'object',
subtype: this.subtype,
value: this.toDescription(value)
};
}
toInternalProperties(value, getObjectId, generatePreview) {
const internalProperties = [...(this.internalProperties?.(value) || [])];
if (!internalProperties.length) {
return [];
}
return internalProperties.map(([name, val]) => {
let value;
if (val instanceof Value) {
value = getInspector(val).toRemoteObject(val, getObjectId, generatePreview);
} else {
const array = new ObjectValue([]);
array.DefineOwnProperty = ArrayExoticObjectInternalMethods.DefineOwnProperty;
array.properties.set('length', Descriptor({
Value: F(val.length)
}));
for (const [index, item] of val.entries()) {
let value;
if (item instanceof Value) {
value = item;
} else {
if (!item?.Key || !item.Value) {
continue;
}
value = new ObjectValue(['InspectorEntry']);
value.properties.set('key', Descriptor({
Value: item.Key
}));
value.properties.set('value', Descriptor({
Value: item.Value
}));
}
array.properties.set(Value(index.toString()), Descriptor({
Value: value
}));
}
value = Array$1.toRemoteObject(array, getObjectId, generatePreview);
}
return {
name,
value
};
});
}
toObjectPreview(value) {
const e = this.toEntries?.(value);
return {
type: 'object',
subtype: this.subtype,
description: this.toDescription(value),
entries: e?.length ? e : undefined,
...propertiesToPropertyPreview(value, [...(this.internalProperties?.(value) || []), ...(this.additionalProperties?.(value) || [])])
};
}
}
const InspectorEntry = new ObjectInspector('Object', 'internal#entry', value => {
const key = value.properties.get(Value('key')).Value;
const val = value.properties.get(Value('value')).Value;
return `{${getInspector(key).toDescription(key)} => ${getInspector(val).toDescription(val)}}`;
});
const Default = new ObjectInspector('Object', undefined, object => {
const [ctor] = object.ConstructedBy;
if (!ctor) {
return 'Object';
}
return propertyNameToString(ctor.HostInitialName);
});
const ArrayBuffer = new ObjectInspector('ArrayBuffer', 'arraybuffer', value => `ArrayBuffer(${value.ArrayBufferByteLength})`, {});
const DataView = new ObjectInspector('DataView', 'dataview', value => `DataView(${value.ByteLength})`);
const Error$1 = new ObjectInspector('SyntaxError', 'error', value => {
let text = '';
surroundingAgent.debugger_scopePreview(() => {
evalQ(Q => {
if (value instanceof ObjectValue) {
const stack = Q(skipDebugger(Get(value, Value('stack'))));
if (stack !== Value.undefined) {
text += Q(skipDebugger(ToString(stack))).stringValue();
}
}
});
});
return text;
});
const Map$1 = new ObjectInspector('Map', 'map', value => `Map(${value.MapData.filter(x => !!x.Key).length})`, {
additionalProperties: value => [['size', Value(value.MapData.filter(x => !!x.Key).length)]],
internalProperties: value => [['[[Entries]]', value.MapData]],
entries: value => value.MapData.filter(x => x.Key).map(({
Key,
Value
}) => ({
key: getInspector(Key).toObjectPreview(Key),
value: getInspector(Value).toObjectPreview(Value)
}))
});
const Set = new ObjectInspector('Set', 'set', value => `Set(${value.SetData.filter(globalThis.Boolean).length})`, {
additionalProperties: value => [['size', Value(value.SetData.filter(globalThis.Boolean).length)]],
internalProperties: value => [['[[Entries]]', value.SetData]],
entries: value => value.SetData.filter(globalThis.Boolean).map(Value => ({
value: getInspector(Value).toObjectPreview(Value)
}))
});
const WeakMap$1 = new ObjectInspector('WeakMap', 'weakmap', () => 'WeakMap', {
internalProperties: value => [['[[Entries]]', value.WeakMapData]],
entries: value => value.WeakMapData.filter(x => x.Key).map(({
Key,
Value
}) => ({
key: getInspector(Key).toObjectPreview(Key),
value: getInspector(Value).toObjectPreview(Value)
}))
});
const WeakSet = new ObjectInspector('WeakSet', 'weakset', () => 'WeakSet', {
internalProperties: value => [['[[Entries]]', value.WeakSetData]],
entries: value => value.WeakSetData.filter(globalThis.Boolean).map(Value => ({
value: getInspector(Value).toObjectPreview(Value)
}))
});
const Date$1 = new ObjectInspector('Date', 'date', value => {
if (!globalThis.Number.isFinite(R(value.DateValue))) {
return 'Invalid Date';
}
const val = DateProto_toISOString([], {
thisValue: value,
NewTarget: Value.undefined
});
return ValueOfNormalCompletion(val).stringValue();
});
const TemporalInstant = new ObjectInspector('Temporal.Instant', 'date', value => `Temporal.Instant <${TemporalInstantToString(value, undefined, 'auto')}>`);
const TemporalDuration = new ObjectInspector('Temporal.Duration', 'date', value => `Temporal.Duration <${TemporalDurationToString(value, 'auto')}>`);
const TemporalPlainDate = new ObjectInspector('Temporal.PlainDate', 'date', value => `Temporal.PlainDate <${TemporalDateToString(value, 'auto')}>`);
const TemporalPlainDateTime = new ObjectInspector('Temporal.PlainDateTime', 'date', value => `Temporal.PlainDateTime <${ISODateTimeToString(value.ISODateTime, value.Calendar, 'auto', 'auto')}>`);
const TemporalPlainMonthDay = new ObjectInspector('Temporal.PlainMonthDay', 'date', value => `Temporal.PlainMonthDay <${TemporalMonthDayToString(value, 'auto')}>`);
const TemporalPlainTime = new ObjectInspector('Temporal.PlainTime', 'date', value => `Temporal.PlainTime <${TimeRecordToString(value.Time, 'auto')}>`);
const TemporalPlainYearMonth = new ObjectInspector('Temporal.PlainYearMonth', 'date', value => `Temporal.PlainYearMonth <${TemporalYearMonthToString(value, 'auto')}>`);
const TemporalZonedDateTime = new ObjectInspector('Temporal.ZonedDateTime', 'date', value => `Temporal.ZonedDateTime <${TemporalZonedDateTimeToString(value, 'auto', 'auto', 'auto', 'auto')}>`);
const Promise$1 = new ObjectInspector('Promise', 'promise', () => 'Promise', {
internalProperties: value => [['[[PromiseState]]', Value(value.PromiseState)], ['[[PromiseResult]]', value.PromiseResult || Value.undefined]]
});
const Proxy$1 = new ObjectInspector('Proxy', 'proxy', value => {
if (IsCallable(value.ProxyTarget)) {
return 'Proxy(Function)';
}
if (value.ProxyTarget instanceof ObjectValue) {
return 'Proxy(Object)';
}
return 'Proxy';
});
const RegExp = new ObjectInspector('RegExp', 'regexp', value => `/${value.OriginalSource.stringValue()}/${value.OriginalFlags.stringValue()}`);
const Module = new ObjectInspector('Module', undefined, () => 'Module', {});
const ShadowRealm = new ObjectInspector('ShadowRealm', undefined, () => 'ShadowRealm', {
internalProperties: realm => [['[[GlobalObject]]', realm.ShadowRealm.GlobalObject]]
});
const Array$1 = {
toRemoteObject(value, getObjectId) {
return {
type: 'object',
className: 'Array',
subtype: 'array',
objectId: getObjectId(value),
description: getInspector(value).toDescription(value),
preview: this.toObjectPreview?.(value)
};
},
toPropertyPreview(name, value) {
return {
name,
type: 'object',
subtype: 'array',
value: this.toDescription(value)
};
},
toObjectPreview(value) {
const result = {
type: 'object',
subtype: 'array',
overflow: false,
properties: [],
description: this.toDescription(value)
};
const indexProp = [];
const otherProp = [];
for (const [key, desc] of value.properties) {
if (indexProp.length > 100) {
result.overflow = true;
break;
}
if (isIntegerIndex(key)) {
indexProp.push(propertyToPropertyPreview(key, desc));
} else if (!(key instanceof JSStringValue && key.stringValue() === 'length')) {
otherProp.push(propertyToPropertyPreview(key, desc));
}
}
result.properties = indexProp.concat(otherProp).slice(0, 100);
return result;
},
toDescription(value) {
const length = [...value.properties.entries()].find(([key]) => key instanceof JSStringValue && key.stringValue() === 'length');
if (!length || !(length[1].Value instanceof NumberValue)) {
throw new TypeError('Bad ArrayExoticObject');
}
return `Array(${R(length[1].Value)})`;
}
};
const TypedArray = new ObjectInspector('TypedArray', 'typedarray', value => `${value.TypedArrayName.stringValue()}(${value.ArrayLength})`);
function propertyNameToString(value) {
if (value instanceof JSStringValue) {
return value.stringValue();
} else if (value instanceof PrivateName) {
return value.Description.stringValue();
} else {
return SymbolDescriptiveString(value).stringValue();
}
}
function propertyToPropertyPreview(key, desc) {
const name = propertyNameToString(key);
if (desc.Get || desc.Set) {
return {
name,
type: 'accessor'
};
} else {
return getInspector(desc.Value).toPropertyPreview(name, desc.Value);
}
}
function propertiesToPropertyPreview(value, extra, max = 5) {
let overflow = false;
const properties = [];
if (extra) {
for (const [key, value] of extra) {
if (value instanceof Value) {
properties.push(getInspector(value).toPropertyPreview(key, value));
}
// TODO:... handle Value[]
}
}
if (isTypedArrayObject(value) && value.ViewedArrayBuffer instanceof ObjectValue && value.ViewedArrayBuffer.ArrayBufferData instanceof DataBlock) {
const record = MakeTypedArrayWithBufferWitnessRecord(value, 'seq-cst');
const length = TypedArrayLength(record);
for (let index = 0; index < length; index += 1) {
const index_value = TypedArrayGetElement(value, Value(index));
if (index_value instanceof UndefinedValue) {
break;
}
if (properties.length > 100) {
overflow = true;
break;
}
properties.push(getInspector(index_value).toPropertyPreview(index.toString(), index_value));
}
properties.push({
name: 'buffer',
type: 'object',
subtype: 'arraybuffer',
value: `ArrayBuffer(${value.ViewedArrayBuffer.ArrayBufferData.byteLength})`
}, {
name: 'byteLength',
type: 'number',
value: globalThis.String(value.ArrayLength)
}, {
name: 'byteOffset',
type: 'number',
value: globalThis.String(value.ByteOffset)
}, {
name: 'length',
type: 'number',
value: globalThis.String(length)
});
}
for (const [key, desc] of value.properties) {
if (properties.length > max) {
overflow = true;
break;
}
properties.push(propertyToPropertyPreview(key, desc));
}
for (const desc of value.PrivateElements) {
if (properties.length > max) {
overflow = true;
break;
}
properties.push(propertyToPropertyPreview(desc.Key, desc));
}
return {
overflow,
properties
};
}
function getInspector(value) {
switch (true) {
case value === Value.null:
return Null;
case value === Value.undefined:
return Undefined;
case value === Value.true || value === Value.false:
return Boolean$1;
case value instanceof SymbolValue:
return Symbol;
case value instanceof JSStringValue:
return String$1;
case value instanceof NumberValue:
case value instanceof BigIntValue:
return Number;
case isProxyExoticObject(value):
return Proxy$1;
case IsCallable(value):
return Function;
case isArrayExoticObject(value):
return Array$1;
case isRegExpObject(value):
return RegExp;
case isDateObject(value):
return Date$1;
case isMapObject(value):
return Map$1;
case isSetObject(value):
return Set;
case isWeakMapObject(value):
return WeakMap$1;
case isWeakSetObject(value):
return WeakSet;
// generator
case isErrorObject(value):
return Error$1;
case isPromiseObject(value):
return Promise$1;
case isTypedArrayObject(value):
return TypedArray;
case isArrayBufferObject(value):
return ArrayBuffer;
case isDataViewObject(value):
return DataView;
case isModuleNamespaceObject(value):
return Module;
case isShadowRealmObject(value):
return ShadowRealm;
case isTemporalInstantObject(value):
return TemporalInstant;
case isTemporalDurationObject(value):
return TemporalDuration;
case isTemporalPlainDateObject(value):
return TemporalPlainDate;
case isTemporalPlainDateTimeObject(value):
return TemporalPlainDateTime;
case isTemporalPlainMonthDayObject(value):
return TemporalPlainMonthDay;
case isTemporalPlainTimeObject(value):
return TemporalPlainTime;
case isTemporalPlainYearMonthObject(value):
return TemporalPlainYearMonth;
case isTemporalZonedDateTimeObject(value):
return TemporalZonedDateTime;
case value.internalSlotsList.includes('InspectorEntry'):
return InspectorEntry;
default:
return Default;
}
}
class InspectorContext {
#io;
constructor(io) {
this.#io = io;
}
realms = [];
attachRealm(realm, agent) {
const id = this.realms.length;
const descriptor = {
id,
origin: realm.HostDefined.specifier || 'vm://repl',
name: realm.HostDefined.name || 'engine262',
uniqueId: id.toString()
};
this.realms.push({
realm,
descriptor,
agent,
detach: () => {
realm.HostDefined.attachingInspector = oldInspector;
realm.HostDefined.attachingInspectorReportError = function attachingInspectorReportError(realm, error) {
if (this.attachingInspector && realm instanceof ManagedRealm) {
this.attachingInspector.console(realm, 'error', [error]);
}
};
}
});
const oldInspector = realm.HostDefined.attachingInspector;
realm.HostDefined.attachingInspector = this.#io;
const oldPromiseRejectionTracker = realm.HostDefined.promiseRejectionTracker;
realm.HostDefined.promiseRejectionTracker = (promise, operation) => {
oldPromiseRejectionTracker?.(promise, operation);
if (operation === 'reject') {
this.#io.sendEvent['Runtime.exceptionThrown']({
timestamp: Date.now(),
exceptionDetails: this.createExceptionDetails(promise, true)
});
} else {
const id = this.#exceptionMap.get(promise);
if (id) {
this.#io.sendEvent['Runtime.exceptionRevoked']({
reason: 'Handler added to rejected promise',
exceptionId: id
});
}
}
};
this.#io.sendEvent['Runtime.executionContextCreated']({
context: descriptor
});
}
detachAgent(agent) {
for (const realm of this.realms) {
if (realm?.agent === agent) {
this.detachRealm(realm.realm);
}
}
}
detachRealm(realm) {
const index = this.realms.findIndex(c => c?.realm === realm);
if (index === -1) {
return;
}
const {
descriptor
} = this.realms[index];
realm.HostDefined.attachingInspector = undefined;
realm.HostDefined.attachingInspectorReportError = undefined;
this.realms[index] = undefined;
this.#io.sendEvent['Runtime.executionContextDestroyed']({
executionContextId: descriptor.id,
executionContextUniqueId: descriptor.uniqueId
});
}
getRealm(realm) {
if (realm === undefined) {
if (surroundingAgent.runningExecutionContext && surroundingAgent.currentRealmRecord instanceof ManagedRealm) {
realm = surroundingAgent.currentRealmRecord;
} else {
return undefined;
}
}
if (typeof realm === 'string') {
return this.realms.find(c => c?.descriptor.uniqueId === realm);
} else if (typeof realm === 'number') {
return this.realms[realm];
}
return this.realms.find(c => c?.realm === realm);
}
/** @deprecated in this case we are guessing the realm should be using, which may create bad result */
getAnyRealm() {
return this.realms.find(Boolean);
}
#idToObject = new Map();
// id 0 is falsy, skip it
#idToArrayBufferBlock = [undefined];
#objectToId = new Map();
#objectCounter = 1;
#internObject(object, group = 'default') {
if (this.#objectToId.has(object)) {
return this.#objectToId.get(object);
}
const id = `${group}:${this.#objectCounter}`;
this.#objectCounter += 1;
this.#idToObject.set(id, object);
this.#objectToId.set(object, id);
return id;
}
releaseObject(id) {
const object = this.#idToObject.get(id);
if (object) {
this.#idToObject.delete(id);
this.#objectToId.delete(object);
}
}
releaseObjectGroup(group) {
for (const [id, object] of this.#idToObject.entries()) {
if (id.startsWith(group)) {
this.#idToObject.delete(id);
this.#objectToId.delete(object);
}
}
}
getObject(objectId) {
return this.#idToObject.get(objectId);
}
toRemoteObject(value, options) {
return getInspector(value).toRemoteObject(value, val => this.#internObject(val, options.objectGroup), options.generatePreview);
}
getProperties({
objectId,
accessorPropertiesOnly,
generatePreview,
nonIndexedPropertiesOnly,
ownProperties
}) {
const object = this.getObject(objectId);
if (!(object instanceof ObjectValue)) {
return {
result: []
};
}
const wrap = v => this.toRemoteObject(v, {
generatePreview
});
const properties = [];
const internalProperties = [];
const privateProperties = [];
object.PrivateElements.forEach(value => {
privateProperties.push({
name: value.Key.Description.stringValue(),
value: value.Value ? wrap(value.Value) : undefined,
get: value.Get ? wrap(value.Get) : undefined,
set: value.Set ? wrap(value.Set) : undefined
});
});
(() => {
let p = object;
while (p instanceof ObjectValue) {
for (const key of p.properties.keys()) {
if (nonIndexedPropertiesOnly && isIntegerIndex(key)) {
continue;
}
const desc = p.properties.get(key);
if (!desc) {
return;
}
if (accessorPropertiesOnly && !IsAccessorDescriptor(desc)) {
continue;
}
const descriptor = {
name: key instanceof JSStringValue ? key.stringValue() : SymbolDescriptiveString(key).stringValue(),
value: desc.Value && !('HostUninitializedBindingMarkerObject' in desc.Value) ? wrap(desc.Value) : undefined,
writable: desc.Writable === Value.true,
get: desc.Get ? wrap(desc.Get) : undefined,
set: desc.Set ? wrap(desc.Set) : undefined,
configurable: desc.Configurable === Value.true,
enumerable: desc.Enumerable === Value.true,
wasThrown: false,
isOwn: p === object,
symbol: key instanceof SymbolValue ? wrap(key) : undefined
};
properties.push(descriptor);
}
if (ownProperties) {
break;
}
if ('Prototype' in p) {
p = p.Prototype;
} else {
p = Value.null;
}
}
})();
const additionalInternalFields = getInspector(object).toInternalProperties?.(object, val => this.#internObject(val, 'default'), generatePreview);
if (additionalInternalFields) {
internalProperties.push(...additionalInternalFields);
}
if ('Prototype' in object) {
internalProperties.push({
name: '[[Prototype]]',
value: wrap(object.Prototype)
});
}
if (isBuiltinFunctionObject(object) && object.nativeFunction.section) {
internalProperties.push({
name: '[[Section]]',
value: {
type: 'string',
value: object.nativeFunction.section
}
});
}
if (isArrayBufferObject(object) && object.ArrayBufferData instanceof DataBlock) {
internalProperties.push({
name: '[[ArrayBufferByteLength]]',
value: {
type: 'number',
value: object.ArrayBufferByteLength
}
});
this.#idToArrayBufferBlock.push(object.ArrayBufferData.buffer);
internalProperties.push({
name: '[[ArrayBufferData]]',
value: {
type: 'number',
value: this.#idToArrayBufferBlock.length - 1
}
});
}
return {
result: properties,
internalProperties,
privateProperties
};
}
#exceptionMap = new WeakMap();
createExceptionDetails(completion, isPromise) {
const value = completion instanceof ThrowCompletion ? completion.Value : completion;
const stack = getHostDefinedErrorStack(value);
const frames = InspectorContext.callSiteToCallFrame(stack);
const exceptionId = this.#objectCounter;
this.#objectCounter += 1;
this.#exceptionMap.set(value, exceptionId);
return {
text: isPromise ? 'Uncaught (in promise)' : 'Uncaught',
stackTrace: stack ? {
callFrames: frames
} : undefined,
exception: getInspector(value).toRemoteObject(value, val => this.#internObject(val), false),
lineNumber: frames[0]?.lineNumber || 0,
columnNumber: frames[0]?.columnNumber || 0,
exceptionId,
scriptId: frames[0]?.scriptId,
url: frames[0]?.url
};
}
static callSiteToCallFrame(callSite) {
return callSite?.map(call => call.toCallFrame()).filter(Boolean) || [];
}
createEvaluationResult(completion) {
completion = EnsureCompletion(completion);
if (!(completion.Value instanceof Value)) {
throw new RangeError('Invalid completion value');
}
return {
exceptionDetails: completion instanceof ThrowCompletion ? this.createExceptionDetails(completion, false) : undefined,
result: this.toRemoteObject(completion.Value, {})
};
}
getDebuggerCallFrame() {
const stacks = getCurrentStack(false);
const length = surroundingAgent.executionContextStack.length;
return stacks.map((stack, index) => {
if (!stack.getScriptId()) {
return undefined;
}
const scopeChain = [];
let env = stack.context.LexicalEnvironment;
while (env instanceof EnvironmentRecord) {
const result = getDisplayObjectFromEnvironmentRecord(env);
if (result) {
scopeChain.push({
type: result.type,
object: this.toRemoteObject(result.object, {})
});
}
env = env.OuterEnv;
}
return {
callFrameId: String(length - index - 1),
functionName: stack.getFunctionName() || '<anonymous>',
location: {
scriptId: stack.getScriptId(),
lineNumber: (stack.lineNumber || 1) - 1,
columnNumber: (stack.columnNumber || 1) - 1
},
this: this.toRemoteObject(HostGetThisEnvironment(stack.context.LexicalEnvironment), {}),
url: stack.getSpecifier() || '',
canBeRestarted: false,
functionLocation: isECMAScriptFunctionObject(stack.context.Function) ? {
lineNumber: (stack.context.Function.ECMAScriptCode?.location.start.line || 1) - 1,
columnNumber: (stack.context.Function.ECMAScriptCode?.location.start.column || 1) - 1,
scriptId: stack.getScriptId() || ''
} : undefined,
scopeChain
};
}).filter(Boolean);
}
evaluateMode = 'script';
}
function HostGetThisEnvironment(env) {
while (!(env instanceof NullValue)) {
const exists = env.HasThisBinding();
if (exists === Value.true) {
const value = env.GetThisBinding();
if (value instanceof ThrowCompletion) {
return Value.undefined;
}
return value;
}
const outer = env.OuterEnv;
env = outer;
}
throw new ReferenceError('No this environment found');
}
function getDisplayObjectFromEnvironmentRecord(record) {
if (record instanceof DeclarativeEnvironmentRecord) {
const object = OrdinaryObjectCreate(Value.null, ['HostInspectorScopePreview']);
for (const [key, binding] of record.bindings) {
const value = binding.initialized ? binding.value : OrdinaryObjectCreate(Value.null, ['HostUninitializedBindingMarkerObject']);
if (isArgumentExoticObject(value)) {
continue;
}
object.properties.set(key, Descriptor({
Enumerable: isArgumentExoticObject(value) ? Value.false : Value.true,
Value: value,
Writable: binding.mutable ? Value.true : Value.false
}));
}
let type = 'block';
if (record instanceof FunctionEnvironmentRecord) {
type = 'local';
} else if (record instanceof ModuleEnvironmentRecord) {
type = 'module';
}
if (type !== 'local' && !object.properties.size) {
return undefined;
}
return {
type,
object
};
} else if (record instanceof ObjectEnvironmentRecord) {
return {
type: record.IsWithEnvironment === Value.true ? 'with' : 'global',
object: record.BindingObject
};
} else if (record instanceof GlobalEnvironmentRecord) {
return {
type: 'global',
object: record.GlobalThisValue
};
}
throw new TypeError('Unknown environment record');
}
function getParsedEvent(source, id, executionContextId) {
const lines = source.ECMAScriptCode.sourceText.split('\n');
return {
isModule: source instanceof SourceTextModuleRecord,
scriptId: id,
url: source.HostDefined.specifier || `vm:///${id}`,
startLine: 0,
startColumn: 0,
endLine: lines.length,
endColumn: lines.pop().length,
executionContextId,
hash: '',
buildId: ''
};
}
const Debugger = {
enable(_req, {
onDebuggerAttached
}) {
onDebuggerAttached();
return {
debuggerId: 'debugger.0'
};
},
getScriptSource({
scriptId
}) {
const source = surroundingAgent.parsedSources.get(scriptId);
if (!source) {
throw new Error('Not found');
}
return {
scriptSource: source.ECMAScriptCode.sourceText
};
},
setAsyncCallStackDepth() {},
setBlackboxPatterns() {},
setBlackboxExecutionContexts() {},
// #region breakpoints
getPossibleBreakpoints() {
// getPossibleBreakpoints({ start, end, restrictToFunction }) {
return {
locations: []
};
// return { locations: getBreakpointCandidates(start, end, restrictToFunction) };
},
removeBreakpoint({
breakpointId
}) {
surroundingAgent?.removeBreakpoint(breakpointId);
},
// setBreakpoint({ location, condition }) { },
setBreakpointByUrl(req) {
return surroundingAgent?.addBreakpointByUrl(req);
},
// setBreakpointOnFunctionCall({ objectId, condition }) { },
setBreakpointsActive({
active
}) {
surroundingAgent.breakpointsEnabled = active;
},
// setInstrumentationBreakpoint({ instrumentation }) { },
setPauseOnExceptions({
state
}) {
if (surroundingAgent) {
surroundingAgent.pauseOnExceptions = state === 'none' ? undefined : state;
}
},
// #endregion
stepInto(_, {
sendEvent
}) {
sendEvent['Debugger.resumed']();
surroundingAgent.resumeEvaluate({
pauseAt: 'step-in'
});
},
resume(_, {
sendEvent
}) {
sendEvent['Debugger.resumed']();
surroundingAgent.resumeEvaluate();
},
stepOver(_req, {
sendEvent
}) {
sendEvent['Debugger.resumed']();
surroundingAgent.resumeEvaluate({
pauseAt: 'step-over'
});
},
stepOut(_req, {
sendEvent
}) {
sendEvent['Debugger.resumed']();
surroundingAgent.resumeEvaluate({
pauseAt: 'step-out'
});
},
evaluateOnCallFrame(req, context) {
return evaluate({
...req,
uniqueContextId: context.context.getRealm(undefined).descriptor.uniqueId,
evalMode: context.context.evaluateMode
}, context);
},
engine262_setEvaluateMode({
mode
}, {
context
}) {
if (mode === 'module' || mode === 'script' || mode === 'console') {
context.evaluateMode = mode;
}
},
engine262_setFeatures() {
throw new Error('Method should not be implemented here.');
}
};
const Profiler = {
enable() {}
};
const Runtime = {
discardConsoleEntries() {},
enable() {},
compileScript(options, {
context,
sendEvent
}) {
let parsed;
let realm = context.getRealm(options.executionContextId);
if (!realm && !options.persistScript) {
realm = context.getAnyRealm();
}
if (!realm) {
return unsupportedError;
}
realm.realm.scope(() => {
if (context.evaluateMode === 'module') {
parsed = ParseModule(options.expression, realm.realm, {
specifier: options.sourceURL,
doNotTrackScriptId: !options.persistScript
});
} else {
parsed = ParseScript(options.expression, realm.realm, {
specifier: options.sourceURL,
doNotTrackScriptId: !options.persistScript,
[kInternal]: {
allowAllPrivateNames: true
}
});
}
});
if (!parsed) {
throw new Error('No parsed result');
}
if (Array.isArray(parsed)) {
const e = context.createExceptionDetails(ThrowCompletion(parsed[0]), false);
// Note: it has to be this message to trigger devtools' line wrap.
e.exception.description = 'SyntaxError: Unexpected end of input';
return {
exceptionDetails: e
};
}
if (options.persistScript) {
if (realm?.descriptor.id === undefined) {
throw new Error('No realm id found');
}
const event = getParsedEvent(parsed, parsed.HostDefined.scriptId, realm.descriptor.id);
sendEvent['Debugger.scriptParsed'](event);
return {
scriptId: event.scriptId
};
}
return {};
},
callFunctionOn(options, {
context
}) {
const realmDesc = context.getRealm(options.uniqueContextId || options.executionContextId) || context.getAnyRealm();
if (!realmDesc) {
throw new Error('No realm found');
}
const {
Value: F
} = realmDesc.realm.evaluateScript(`(${options.functionDeclaration})`, {
doNotTrackScriptId: true
});
const thisValue = options.objectId ? context.getObject(options.objectId) : Value.undefined;
const args = options.arguments?.map(a => {
// TODO: revisit
if ('value' in a) {
return Value(a.value);
}
if (a.objectId) {
return context.getObject(a.objectId);
}
if ('unserializableValue' in a) {
throw new RangeError();
}
return Value.undefined;
});
return realmDesc.realm.scope(() => {
const completion = evalQ((Q, X) => {
const r = Q(skipDebugger(Call(F, thisValue, args || [])));
if (options.returnByValue) {
const value = X(Call(realmDesc.realm.Intrinsics['%JSON.stringify%'], Value.undefined, [r]));
if (value instanceof JSStringValue) {
const valueRealized = JSON.parse(value.stringValue());
return {
result: {
type: typeof value,
value: valueRealized
}
};
}
}
return context.createEvaluationResult(r);
});
if (completion instanceof ThrowCompletion) {
return {
result: {
type: 'undefined'
},
exceptionDetails: context.createExceptionDetails(completion, false)
};
}
return completion.Value;
});
},
evaluate(options, context) {
return evaluate({
...options,
evalMode: context.context.evaluateMode,
uniqueContextId: options.uniqueContextId
}, context);
},
getExceptionDetails(req, {
context
}) {
const object = context.getObject(req.errorObjectId);
if (object instanceof ObjectValue) {
return {
exceptionDetails: context.createExceptionDetails(ThrowCompletion(object), false)
};
}
return {
exceptionDetails: {
text: 'unsupported',
lineNumber: 0,
columnNumber: 0,
exceptionId: 0
}
};
},
getHeapUsage() {
return {
usedSize: 0,
totalSize: 0,
backingStorageSize: 0,
embedderHeapUsedSize: 0
};
},
getIsolateId() {
return {
id: 'isolate.0'
};
},
getProperties(options, {
context
}) {
return context.getProperties(options);
},
globalLexicalScopeNames({
executionContextId
}, {
context
}) {
const global = context.getRealm(executionContextId)?.realm.GlobalObject;
if (!global) {
return {
names: []
};
}
const keys = skipDebugger(global.OwnPropertyKeys());
if (keys instanceof ThrowCompletion) {
return {
names: []
};
}
return {
names: ValueOfNormalCompletion(keys).map(k => k instanceof JSStringValue ? k.stringValue() : null).filter(Boolean)
};
},
releaseObject(req, {
context
}) {
context.releaseObject(req.objectId);
},
releaseObjectGroup({
objectGroup
}, {
context
}) {
context.releaseObjectGroup(objectGroup);
},
runIfWaitingForDebugger() {}
};
const HeapProfiler = {
enable() {},
collectGarbage() {}
};
const Target = {
setDiscoverTargets() {},
// @ts-expect-error no doc
setRemoteLocations() {}
};
const unsupportedError = {
result: {
type: 'undefined'
},
exceptionDetails: {
text: 'unsupported',
lineNumber: 0,
columnNumber: 0,
exceptionId: 0
}
};
function evaluate(options, _context) {
const {
context
} = _context;
const isPreview = options.throwOnSideEffect;
if (options.awaitPromise) {
return unsupportedError;
}
const realm = context.getRealm(options.uniqueContextId);
if (!realm) {
return unsupportedError;
}
const isCallOnFrame = typeof options.callFrameId === 'string';
let callOnFramePoppedLevel = 0;
const oldExecutionStack = [...surroundingAgent.executionContextStack];
if (isCallOnFrame) {
const frame = surroundingAgent.executionContextStack[options.callFrameId];
if (!frame) {
// eslint-disable-next-line no-console
console.error('Execution context not found: ', options.callFrameId);
return unsupportedError;
}
for (const currentFrame of [...surroundingAgent.executionContextStack].reverse()) {
if (currentFrame === frame) {
break;
}
callOnFramePoppedLevel += 1;
surroundingAgent.executionContextStack.pop(currentFrame);
}
}
const promise = new Promise(resolve => {
let toBeEvaluated;
if (isPreview || options.evalMode === 'console' || isCallOnFrame) {
toBeEvaluated = performDevtoolsEval(options.expression, realm.realm, false, !!(isPreview || isCallOnFrame));
} else {
let parsed;
const realm = context.getRealm(options.uniqueContextId);
realm?.realm.scope(() => {
if (options.evalMode === 'module') {
parsed = ParseModule(options.expression, realm.realm);
} else {
parsed = ParseScript(options.expression, realm.realm);
}
});
if (Array.isArray(parsed)) {
const e = context.createExceptionDetails(ThrowCompletion(parsed[0]), false);
resolve({
exceptionDetails: e,
result: {
type: 'undefined'
}
});
return;
}
toBeEvaluated = parsed;
}
const noDebuggerEvaluate = () => {
if (!('next' in toBeEvaluated)) {
throw new Assert.Error('Unexpected');
}
resolve(context.createEvaluationResult(skipDebugger(toBeEvaluated)));
};
if (isPreview) {
surroundingAgent.debugger_scopePreview(noDebuggerEvaluate);
return;
}
if (isCallOnFrame) {
noDebuggerEvaluate();
return;
}
const completion = realm.realm.evaluate(toBeEvaluated, completion => {
resolve(context.createEvaluationResult(completion));
runJobQueue();
});
if (completion) {
return;
}
surroundingAgent.resumeEvaluate();
});
promise.then(() => {
if (callOnFramePoppedLevel) {
Assert(oldExecutionStack.length - callOnFramePoppedLevel === surroundingAgent.executionContextStack.length);
for (const [newIndex, newStack] of surroundingAgent.executionContextStack.entries()) {
Assert(newStack === oldExecutionStack[newIndex]);
}
surroundingAgent.executionContextStack.length = 0;
for (const stack of oldExecutionStack) {
surroundingAgent.executionContextStack.push(stack);
}
}
}, err => {
const expr = surroundingAgent.runningExecutionContext.callSite.lastNode?.sourceText;
const frame = InspectorContext.callSiteToCallFrame(captureStack().stack);
_context.sendEvent['Runtime.exceptionThrown']({
timestamp: Date.now(),
exceptionDetails: {
stackTrace: frame.length ? {
callFrames: frame
} : undefined,
text: `engine262 error when evaluating the following node:\n\n ${expr}\n\n${err.constructor.name}: ${err.message}\n${err.stack.slice(err.stack.indexOf(err.message) + err.message.length + 1)}\n\nFrom now on, the engine262 VM state is broken, please press the reload button.`,
columnNumber: frame[0]?.columnNumber,
lineNumber: frame[0]?.lineNumber,
scriptId: frame[0]?.scriptId,
url: frame[0]?.url,
exceptionId: 0
}
});
return {
result: {
type: 'undefined'
}
};
});
return promise;
}
var impl = /*#__PURE__*/Object.freeze({
__proto__: null,
Debugger: Debugger,
HeapProfiler: HeapProfiler,
Profiler: Profiler,
Runtime: Runtime,
Target: Target
});
const consoleMethods = ['log', 'debug', 'info', 'error', 'warning', 'dir', 'dirxml', 'table', 'trace', 'clear', 'startGroup', 'startGroupCollapsed', 'endGroup', 'assert', 'profile', 'profileEnd', 'count', 'timeEnd'];
function createConsole(realm, defaultBehaviour) {
realm.scope(() => {
const console = OrdinaryObjectCreate(realm.Intrinsics['%Object.prototype%']);
skipDebugger(DefinePropertyOrThrow(realm.GlobalObject, Value('console'), Descriptor({
Configurable: Value.true,
Enumerable: Value.false,
Writable: Value.true,
Value: console
})));
consoleMethods.forEach(method => {
const f = CreateBuiltinFunction(function* Console(args) {
if (surroundingAgent.debugger_isPreviewing) {
return Value.undefined;
}
let completion;
if (defaultBehaviour[method]) {
completion = defaultBehaviour[method](args);
} else if (defaultBehaviour.default) {
completion = defaultBehaviour.default(method, args);
}
if (completion) {
if (typeof completion === 'object' && 'next' in completion) {
completion = yield* completion;
}
// Do not use Q(host) here. A host may return something invalid like ReturnCompletion.
if (completion instanceof ThrowCompletion) {
return completion;
}
}
if (realm.HostDefined.attachingInspector) {
realm.HostDefined.attachingInspector.console(realm, method, args);
}
return Value.undefined;
}, 1, Value(method), []);
skipDebugger(CreateDataProperty(console, Value(method), f));
});
});
}
const ignoreNamespaces = ['Network'];
const ignoreMethods = [];
class Inspector {
#context = new InspectorContext(this);
#agents = [];
attachAgent(agent, priorRealms) {
const oldOnDebugger = agent.hostDefinedOptions.onDebugger;
agent.hostDefinedOptions.onDebugger = () => {
oldOnDebugger?.();
this.sendEvent['Debugger.paused']({
reason: 'debugCommand',
callFrames: this.#context.getDebuggerCallFrame()
});
};
const oldOnRealmCreated = agent.hostDefinedOptions.onRealmCreated;
agent.hostDefinedOptions.onRealmCreated = realm => {
oldOnRealmCreated?.(realm);
this.#context.attachRealm(realm, agent);
};
const oldOnScriptParsed = agent.hostDefinedOptions.onScriptParsed;
agent.hostDefinedOptions.onScriptParsed = (script, id) => {
oldOnScriptParsed?.(script, id);
const realmId = this.#context.getRealm(script.Realm)?.descriptor.id;
if (realmId === undefined) {
return;
}
this.sendEvent['Debugger.scriptParsed'](getParsedEvent(script, id, realmId));
};
this.#agents.push({
agent,
onDetach: () => {
agent.hostDefinedOptions.onDebugger = oldOnDebugger;
agent.hostDefinedOptions.onRealmCreated = oldOnRealmCreated;
agent.hostDefinedOptions.onScriptParsed = oldOnScriptParsed;
this.#agents = this.#agents.filter(x => x.agent !== agent);
}
});
priorRealms.forEach(realm => {
this.#context.attachRealm(realm, agent);
});
}
detachAgent(agent) {
const record = this.#agents.find(x => x.agent === agent);
record?.onDetach();
this.#context.detachAgent(agent);
}
preference = {
previewDebug: false
};
onMessage(id, methodArg, params) {
if (ignoreMethods.includes(methodArg)) {
return;
}
const [namespace, method] = methodArg.split('.');
if (ignoreNamespaces.includes(namespace)) {
return;
}
if (!(namespace in impl)) {
// eslint-disable-next-line no-console
console.error(`Unknown namespace requested: ${namespace}`);
return;
}
const ns = impl[namespace];
if (!(method in ns)) {
// eslint-disable-next-line no-console
console.error(`Unknown method requested: ${namespace}.${method}`);
return;
}
const f = ns[method];
new Promise(resolve => {
resolve(f(params, this.#debugContext));
}).then((result = {}) => {
this.send({
id,
result
});
});
}
sendEvent = Object.create(new Proxy({}, {
get: (_, key) => {
const f = params => {
this.send({
method: key,
params
});
};
Object.defineProperty(this.sendEvent, key, {
value: f
});
return f;
}
}));
console(realm, type, args) {
const context = this.#context.getRealm(realm);
if (!context) {
return;
}
this.sendEvent['Runtime.consoleAPICalled']({
type,
args: args.map(x => this.#context.toRemoteObject(x, {})),
executionContextId: context.descriptor.id,
timestamp: Date.now()
});
}
#debugContext = {
sendEvent: this.sendEvent,
preference: this.preference,
context: this.#context,
onDebuggerAttached: () => {
this.#context.realms.forEach(realm => {
if (realm) {
this.sendEvent['Runtime.executionContextCreated']({
context: realm.descriptor
});
}
});
}
};
}
export { Inspector, createConsole };
//# sourceMappingURL=inspector.mjs.map