mirror of
https://github.com/bendtherules/ask262.git
synced 2026-08-18 21:31:46 +00:00
178 lines
4.2 KiB
TypeScript
178 lines
4.2 KiB
TypeScript
import fs from 'node:fs';
|
|
import { loadImportedModuleSync } from '../lib-src/node/module.mts';
|
|
import { supportColor, type SkipReason } from './tui.mts';
|
|
import {
|
|
Agent, ManagedRealm, type OrdinaryObject, SourceTextModuleRecord, OrdinaryObjectCreate, createTest262Intrinsics,
|
|
Value,
|
|
} from '#self';
|
|
|
|
export interface Attrs {
|
|
description: string;
|
|
features?: string[];
|
|
includes: string[];
|
|
flags: {
|
|
async?: boolean;
|
|
module?: boolean;
|
|
onlyStrict?: boolean;
|
|
noStrict?: boolean;
|
|
raw?: boolean;
|
|
};
|
|
negative: {
|
|
type: string;
|
|
phase: string;
|
|
};
|
|
}
|
|
|
|
export class Test {
|
|
constructor(file: string, specifier: string, engineFeatures: readonly string[], attrs: Attrs, currentRunFlags: string, contents: string) {
|
|
this.file = file;
|
|
this.specifier = specifier;
|
|
this.engineFeatures = engineFeatures;
|
|
this.attrs = attrs;
|
|
this.content = contents;
|
|
this.currentTestFlag = currentRunFlags;
|
|
}
|
|
|
|
startTime: number | null = null;
|
|
|
|
endTime: number | null = null;
|
|
|
|
getRuntimeSeconds(): number {
|
|
if (this.startTime === null) {
|
|
return 0;
|
|
}
|
|
return ~~((Date.now() - this.startTime) / 1000);
|
|
}
|
|
|
|
id = Math.random();
|
|
|
|
file: string;
|
|
|
|
specifier: string;
|
|
|
|
attrs: Attrs;
|
|
|
|
engineFeatures: readonly string[];
|
|
|
|
content: string;
|
|
|
|
currentTestFlag: string;
|
|
|
|
status: 'pending' | 'skipped' | 'running' | 'passed' | 'failed' = 'pending';
|
|
|
|
skipReason: SkipReason | null = null;
|
|
|
|
skipFeature: string | null = null;
|
|
|
|
withDifferentTestFlag(newFlag: string, newContent = this.content) {
|
|
return new Test(this.file, this.specifier, this.engineFeatures, this.attrs, newFlag, newContent);
|
|
}
|
|
}
|
|
|
|
export type SupervisorToWorker = Exclude<Test, 'withDifferentTestFlag'>
|
|
export type WorkerToSupervisor_Running = {
|
|
status: 'RUNNING';
|
|
testId: number;
|
|
};
|
|
|
|
export type WorkerToSupervisor_Pass = {
|
|
status: 'PASS';
|
|
file: string;
|
|
flags: string;
|
|
testId: number;
|
|
};
|
|
|
|
export interface Stack {
|
|
specifier?: string | null | undefined;
|
|
source?: string;
|
|
line: number;
|
|
column: number;
|
|
}
|
|
|
|
export type WorkerToSupervisor_Failed = {
|
|
status: 'FAIL';
|
|
file: string;
|
|
flags: string;
|
|
testId: number;
|
|
description: string;
|
|
error: string;
|
|
stack: Stack[]
|
|
};
|
|
|
|
export type WorkerToSupervisor =
|
|
| WorkerToSupervisor_Running
|
|
| WorkerToSupervisor_Pass
|
|
| WorkerToSupervisor_Failed
|
|
|
|
export function readList(path: string | URL) {
|
|
const source = fs.readFileSync(path, 'utf8');
|
|
return source
|
|
.split('\n')
|
|
.filter((line) => line && !line.startsWith('#') && !line.startsWith(';'))
|
|
.map((line) => line.split('#')[0].split(';')[0].trim());
|
|
}
|
|
|
|
export interface CreateAgentOptions {
|
|
features?: readonly string[];
|
|
}
|
|
|
|
export function createAgent({ features = [] }: CreateAgentOptions) {
|
|
const agent = new Agent({
|
|
features,
|
|
supportedImportAttributes: ['type'],
|
|
loadImportedModule: loadImportedModuleSync,
|
|
onDebugger() {
|
|
// attach an empty debugger to make sure our debugger infrastructure does not break the engine
|
|
agent.resumeEvaluate({ noBreakpoint: true });
|
|
},
|
|
});
|
|
return agent;
|
|
}
|
|
|
|
export interface Test262CreateRealm {
|
|
realm: ManagedRealm;
|
|
$262: OrdinaryObject;
|
|
resolverCache: Map<string, SourceTextModuleRecord>;
|
|
setPrintHandle: (callback: ((str: string, value: Value) => void) | undefined) => void;
|
|
}
|
|
export interface CreateRealmOptions {
|
|
printCompatMode?: boolean;
|
|
specifier?: string;
|
|
}
|
|
|
|
export function createRealm({ printCompatMode = false, specifier }: CreateRealmOptions = {}): Test262CreateRealm {
|
|
const resolverCache = new Map();
|
|
|
|
const realm = new ManagedRealm({
|
|
resolverCache,
|
|
specifier,
|
|
});
|
|
|
|
return realm.scope(() => {
|
|
const $262 = OrdinaryObjectCreate(realm.Intrinsics['%Object.prototype%']);
|
|
const { setPrintHandle } = createTest262Intrinsics(realm, printCompatMode);
|
|
return {
|
|
realm,
|
|
$262,
|
|
resolverCache,
|
|
setPrintHandle,
|
|
};
|
|
});
|
|
}
|
|
|
|
export function fatal_exit(message: string): never {
|
|
// eslint-disable-next-line no-console
|
|
console.error(message);
|
|
process.exit(1);
|
|
}
|
|
|
|
export function link(text: string, url: string | URL) {
|
|
if (supportColor) {
|
|
const OSC = '\u001B]';
|
|
const BEL = '\u0007';
|
|
return `${OSC}8;;${url}${BEL}${text}${OSC}8;;${BEL}`;
|
|
} else {
|
|
return text;
|
|
}
|
|
}
|