const fs = require('fs');
const path = require('path');
function extractMeta(filePath) {
const src = fs.readFileSync(filePath, 'utf8');
const m = src.match(/\/\*---([\s\S]*?)---\*\//);
if (!m) return '';
return m[1];
}
function parseList(meta, key) {
const re = new RegExp(`${key}:\\s*\\[(.*?)\\]`, 's');
const m = meta.match(re);
if (!m) return [];
const inner = m[1];
return inner.split(',').map(s => s.trim().replace(/^['\"]|['\"]$/g, '')).filter(Boolean);
}
function hasFeature(meta, name) {
const arr = parseList(meta, 'features');
return arr.includes(name);
}
function hasFlag(meta, name) {
const re = /flags:\s*\[([\s\S]*?)\]/;
const m = meta.match(re);
if (!m) return false;
return m[1].includes(name);
}
function referencesAssert(filePath) {
const src = fs.readFileSync(filePath, 'utf8');
return /\bassert\b/.test(src);
}
function references262(filePath) {
const src = fs.readFileSync(filePath, 'utf8');
return /\$262\b/.test(src);
}
function ensureArrayDistinct(arr) {
const seen = new Set();
const out = [];
for (const p of arr) {
if (!p) continue;
const b = path.basename(p);
if (!seen.has(b)) {
seen.add(b);
out.push(p);
}
}
return out;
}
function createComposedTarget(testPath) {
const testDir = path.dirname(path.resolve(testPath));
const base = path.basename(testPath, path.extname(testPath));
const ext = path.extname(testPath);
const tmpName = `.test262_composed_${base}${ext}`;
const tmpPath = path.join(testDir, tmpName);
return { tmpDir: testDir, tmpPath };
}
function createModuleBootstrapTarget(testPath) {
const testDir = path.dirname(path.resolve(testPath));
const base = path.basename(testPath, path.extname(testPath));
const ext = path.extname(testPath);
const tmpName = `.test262_bootstrap_${base}${ext}`;
const tmpPath = path.join(testDir, tmpName);
return { tmpDir: testDir, tmpPath };
}
const realmFeatureName = 'cross-realm';
const realmMarker = '// Inject: unified $262 shim - idempotent';
function getAgentBootstrapLines() {
return [
'var __agentGlobal = typeof globalThis !== "undefined" ? globalThis : this;',
'if (!__agentGlobal.$262) { __agentGlobal.$262 = {}; }',
'var $262 = __agentGlobal.$262;',
'if (!$262.agent) { $262.agent = {}; }',
'$262.agent.receiveBroadcast = function(callback) { return __agent_receiveBroadcast(callback); };',
'$262.agent.report = function(value) { return __agent_report(String(value)); };',
'$262.agent.sleep = function(ms) { return __agent_sleep(ms); };',
'$262.agent.monotonicNow = function() { return __agent_monotonicNow(); };',
'$262.agent.leaving = function() { return __agent_leaving(); };',
];
}
function get262StubLines() {
return [
'// Inject: unified $262 shim - idempotent',
'if (typeof $262 === "undefined") {',
' var $262 = (typeof globalThis !== "undefined" && globalThis.$262 && typeof globalThis.$262 === "object") ? globalThis.$262 : {};',
'}',
'if (typeof globalThis !== "undefined" && (typeof globalThis.$262 === "undefined" || globalThis.$262 !== $262)) {',
' globalThis.$262 = $262;',
'}',
'if (typeof $262.AbstractModuleSource === "undefined" && typeof globalThis !== "undefined" && typeof globalThis.__abstract_module_source_ctor === "function") {',
' $262.AbstractModuleSource = globalThis.__abstract_module_source_ctor;',
'}',
'if (typeof $262.global === "undefined") {',
' $262.global = this;',
'}',
'if (typeof $262.evalScript !== "function") {',
' $262.evalScript = function(src) {',
' if (typeof globalThis !== "undefined" && typeof globalThis.__evalScript__ === "function") {',
' return globalThis.__evalScript__(String(src));',
' }',
' return (0, eval)(String(src));',
' };',
'}',
'if (typeof $262.detachArrayBuffer !== "function" && typeof globalThis !== "undefined" && typeof globalThis.__detachArrayBuffer__ === "function") {',
' $262.detachArrayBuffer = function(buffer) {',
' return globalThis.__detachArrayBuffer__(buffer);',
' };',
'}',
'if (typeof $262.IsHTMLDDA === "undefined" && typeof globalThis !== "undefined") {',
' try { var __htmlDDAHook = globalThis.__isHTMLDDA__; if (__htmlDDAHook !== undefined && __htmlDDAHook !== null && (__htmlDDAHook() === null)) $262.IsHTMLDDA = __htmlDDAHook; } catch(e) {}',
'}',
'if (typeof $262.createRealm !== "function") {',
' $262.createRealm = function() {',
' // Delegate to runner-provided native hook when available.',
' if (typeof globalThis.__createRealm__ === "function") {',
' try {',
' var nativeRealm = globalThis.__createRealm__();',
' if (nativeRealm && nativeRealm.global) return nativeRealm;',
' } catch (e) { }',
' }',
'',
' // Fallback: emulate a realm with distinct object intrinsics.',
' var g = Object.create(null);',
' var realmObjectProto = Object.create(null);',
' var realmObjectCtor = function Object(value) {',
' if (value === null || value === undefined) {',
' var o = {};',
' try { Object.setPrototypeOf(o, realmObjectProto); } catch (_) {}',
' return o;',
' }',
' return Object(value);',
' };',
' realmObjectCtor.prototype = realmObjectProto;',
' try { realmObjectProto.constructor = realmObjectCtor; } catch (_) {}',
'',
' var GlobalFunction = Function;',
' var realmFunctionCtor = function RealmFunction() {',
' var args = Array.prototype.slice.call(arguments);',
' var f = Reflect.construct(GlobalFunction, args);',
' try { f.__origin_global = g; } catch (_) {}',
' try {',
' if (f && typeof f === "function" && f.prototype && typeof f.prototype === "object") {',
' Object.setPrototypeOf(f.prototype, realmObjectProto);',
' }',
' } catch (_) {}',
' return f;',
' };',
' try { Object.setPrototypeOf(realmFunctionCtor, GlobalFunction); } catch (_) {}',
' realmFunctionCtor.prototype = GlobalFunction.prototype;',
'',
' g.globalThis = g;',
' g.this = g;',
' g.Object = realmObjectCtor;',
' g.Function = realmFunctionCtor;',
' g.TypeError = TypeError;',
' g.RangeError = RangeError;',
' g.ReferenceError = ReferenceError;',
' g.SyntaxError = SyntaxError;',
' g.Error = Error;',
' g.AggregateError = AggregateError;',
' g.Array = Array;',
' g.ArrayBuffer = ArrayBuffer;',
' g.SharedArrayBuffer = (typeof SharedArrayBuffer !== "undefined") ? SharedArrayBuffer : undefined;',
' g.DataView = DataView;',
' g.Date = Date;',
' g.RegExp = RegExp;',
' g.Int8Array = Int8Array;',
' g.Uint8Array = Uint8Array;',
' g.Uint8ClampedArray = Uint8ClampedArray;',
' g.Int16Array = Int16Array;',
' g.Uint16Array = Uint16Array;',
' g.Int32Array = Int32Array;',
' g.Uint32Array = Uint32Array;',
' g.Float32Array = Float32Array;',
' g.Float64Array = Float64Array;',
' g.BigInt64Array = (typeof BigInt64Array !== "undefined") ? BigInt64Array : undefined;',
' g.BigUint64Array = (typeof BigUint64Array !== "undefined") ? BigUint64Array : undefined;',
' g.Map = Map;',
' g.Set = Set;',
' g.WeakMap = WeakMap;',
' g.WeakSet = WeakSet;',
' g.WeakRef = (typeof WeakRef !== "undefined") ? WeakRef : undefined;',
' g.Proxy = Proxy;',
' g.Reflect = Reflect;',
' g.Math = Math;',
' g.JSON = JSON;',
' g.Promise = Promise;',
' g.Symbol = Symbol;',
' g.Number = Number;',
' g.String = String;',
' g.Boolean = Boolean;',
' g.BigInt = (typeof BigInt !== "undefined") ? BigInt : undefined;',
' g.parseInt = parseInt;',
' g.parseFloat = parseFloat;',
' g.isNaN = isNaN;',
' g.isFinite = isFinite;',
' function __wrapRealmCallable(fn) {',
' if (typeof fn !== "function") return fn;',
' var defaultProto = null;',
' try {',
' if (fn.prototype && typeof fn.prototype === "object") {',
' defaultProto = Object.getPrototypeOf(fn.prototype);',
' }',
' } catch (_) {}',
' var wrapped = function() {',
' var out = fn.apply(this, arguments);',
' try {',
' var ctorProto = wrapped.prototype;',
' var nonObjectProto = (ctorProto === null) || (typeof ctorProto !== "object" && typeof ctorProto !== "function");',
' if (nonObjectProto && out && typeof out === "object" && defaultProto && Object.getPrototypeOf(out) !== defaultProto) {',
' Object.setPrototypeOf(out, defaultProto);',
' }',
' } catch (_) {}',
' return out;',
' };',
' try { Object.setPrototypeOf(wrapped, fn); } catch (_) {}',
' try { wrapped.__origin_global = g; } catch (_) {}',
' try {',
' Object.defineProperty(wrapped, "prototype", {',
' get: function() { return fn.prototype; },',
' set: function(v) { fn.prototype = v; },',
' enumerable: false,',
' configurable: true',
' });',
' } catch (_) {',
' try { wrapped.prototype = fn.prototype; } catch (_) {}',
' }',
' return wrapped;',
' }',
' g.eval = function(src) {',
' src = String(src);',
' var transformed = "";',
' var re = /\\bvar\\s+([^;]+)/g;',
' var lastIndex = 0;',
' var match;',
' while ((match = re.exec(src)) !== null) {',
' transformed += src.slice(lastIndex, match.index);',
' var decls = match[1];',
' var repl = decls.split(",").map(function(p) {',
' var s = p.trim();',
' var mm = s.match(/^([A-Za-z_$][\\w$]*)(\\s*=\\s*[\\s\\S]+)?$/);',
' if (!mm) return "";',
' var name = mm[1];',
' var init = mm[2];',
' if (init) return "this." + name + init;',
' return "this." + name + " = undefined";',
' }).join("; ");',
' transformed += repl;',
' lastIndex = re.lastIndex;',
' }',
' transformed += src.slice(lastIndex);',
' // Execute with `this` bound to the emulated realm global.',
' try {',
' var ret = (new Function("with (this) { return (" + transformed + "); }")).call(g);',
' return __wrapRealmCallable(ret);',
' } catch (e) {',
' var ret2 = (new Function("with (this) { " + transformed + " }")).call(g);',
' return __wrapRealmCallable(ret2);',
' }',
' };',
' return { global: g };',
' };',
'}',
];
}
function inject262Shim(outLines, testPath, meta, prependFiles = [], needsAgent = false) {
let need262Shim = references262(testPath) || hasFeature(meta, realmFeatureName) || needsAgent;
if (!need262Shim) {
for (const p of prependFiles) {
if (p && fs.existsSync(p) && references262(p)) {
need262Shim = true;
break;
}
}
}
if (!need262Shim) return;
if (!outLines.some(l => l.indexOf(realmMarker) !== -1)) {
outLines.push(...get262StubLines());
outLines.push('');
}
}
function verifyComposeStubMarkerCount(testPath, harnessIndex = {}, prependFiles = [], needStrict = true, expected = 1) {
const { tmpPath } = composeTest({ testPath, repoDir: '.', harnessIndex, prependFiles, needStrict });
const src = fs.readFileSync(tmpPath, 'utf8');
const re = new RegExp(realmMarker.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'), 'g');
const count = (src.match(re) || []).length;
return count === expected;
}
function composeTest({ testPath, repoDir, harnessIndex, prependFiles = [], needStrict = true, needsAgent = false, expectedNegative = null }) {
const meta = extractMeta(testPath);
const isRaw = hasFlag(meta, 'raw');
const skipInjects = isRaw || (expectedNegative && expectedNegative.phase && expectedNegative.phase !== 'runtime');
let PREPEND_FILES = prependFiles.slice();
if (referencesAssert(testPath)) {
const assertPath = harnessIndex['assert.js'];
const staPath = harnessIndex['sta.js'];
if (assertPath) {
const fixed = [];
if (staPath) fixed.push(staPath);
fixed.push(assertPath);
for (const p of PREPEND_FILES) {
const b = path.basename(p);
if (!fixed.some(q => path.basename(q) === b)) fixed.push(p);
}
PREPEND_FILES = fixed;
}
}
(function ensureAssertForIncludes() {
const assertPath = harnessIndex['assert.js'];
const staPath = harnessIndex['sta.js'];
if (!assertPath) return;
let needInject = false;
for (const p of PREPEND_FILES) {
if (!p || !fs.existsSync(p)) continue;
const src = fs.readFileSync(p, 'utf8');
const references = /\bassert\b/.test(src);
const definesMeta = parseList(extractMeta(p), 'defines');
const defines = /function\s+assert\b|var\s+assert\b|assert\._isSameValue/.test(src) || definesMeta.includes('assert');
if (references && !defines) { needInject = true; break; }
}
if (needInject) {
const fixed = [];
if (staPath) fixed.push(staPath);
fixed.push(assertPath);
for (const p of PREPEND_FILES) {
const b = path.basename(p);
if (!fixed.some(q => path.basename(q) === b)) fixed.push(p);
}
PREPEND_FILES = fixed;
}
})();
(function ensureTest262Error() {
const src = fs.readFileSync(testPath, 'utf8');
if (/\bTest262Error\b/.test(src)) {
let definesTest262Error = false;
for (const p of PREPEND_FILES) {
if (!p || !fs.existsSync(p)) continue;
const s = fs.readFileSync(p, 'utf8');
if (/function\s+Test262Error\b|Test262Error.prototype/.test(s) ||
/defines:\s*\[[^\]]*\bTest262Error\b/.test(extractMeta(p))) {
definesTest262Error = true;
break;
}
}
if (!definesTest262Error) {
const sta = harnessIndex['sta.js'];
if (sta && fs.existsSync(sta)) {
PREPEND_FILES.unshift(sta);
}
}
}
})();
const composed = createComposedTarget(testPath);
const tmpName = composed.tmpPath;
try { fs.unlinkSync(tmpName); } catch (_) {}
const outLines = [];
if (needStrict) {
outLines.push('"use strict";');
outLines.push('');
}
PREPEND_FILES = ensureArrayDistinct(PREPEND_FILES);
const isModule = hasFlag(meta, 'module');
let moduleBootstrapPath = null;
if (!skipInjects) {
inject262Shim(outLines, testPath, meta, PREPEND_FILES, needsAgent);
if (isModule) {
const bootstrapPrepends = ensureArrayDistinct(
PREPEND_FILES.filter((p) => {
const base = path.basename(p);
return base === 'sta.js' || base === 'assert.js';
})
);
if (bootstrapPrepends.length > 0) {
moduleBootstrapPath = createModuleBootstrapTarget(testPath).tmpPath;
const bootstrapLines = [];
for (const p of bootstrapPrepends) {
const absP = path.resolve(p);
bootstrapLines.push(`// Inject: ${absP}`);
bootstrapLines.push(fs.readFileSync(p, 'utf8'));
bootstrapLines.push('');
}
bootstrapLines.push('// Inject: expose common harness helpers on globalThis for imported modules');
bootstrapLines.push('if (typeof globalThis !== "undefined") {');
bootstrapLines.push(' if (typeof assert !== "undefined" && typeof globalThis.assert === "undefined") globalThis.assert = assert;');
bootstrapLines.push(' if (typeof Test262Error !== "undefined" && typeof globalThis.Test262Error === "undefined") globalThis.Test262Error = Test262Error;');
bootstrapLines.push('}');
bootstrapLines.push('');
fs.writeFileSync(moduleBootstrapPath, bootstrapLines.join('\n'));
}
}
}
if (moduleBootstrapPath) {
outLines.push(`import ${JSON.stringify(`./${path.basename(moduleBootstrapPath)}`)};`);
outLines.push('');
}
if (!skipInjects) {
if (needsAgent) {
const agentBootstrap = JSON.stringify(`${getAgentBootstrapLines().join('\n')}\n`);
outLines.push('// Inject: $262.agent shim for multi-agent tests');
outLines.push('if (!$262.agent) { $262.agent = {}; }');
outLines.push(`var __agentBootstrap = ${agentBootstrap};`);
outLines.push('$262.agent.start = function(script) { __agent_start(__agentBootstrap + String(script)); };');
outLines.push('$262.agent.broadcast = function(sab) {');
outLines.push(' if (sab && sab.buffer) { __agent_broadcast(sab.buffer); }');
outLines.push(' else { __agent_broadcast(sab); }');
outLines.push('};');
outLines.push('$262.agent.getReport = function() { return __agent_getReport(); };');
outLines.push('$262.agent.sleep = function(ms) { __agent_sleep(ms); };');
outLines.push('$262.agent.monotonicNow = function() { return __agent_monotonicNow(); };');
outLines.push('$262.agent.leaving = function() { __agent_leaving(); };');
outLines.push('$262.agent.report = function(val) { __agent_report(String(val)); };');
outLines.push('');
}
for (const p of PREPEND_FILES) {
if (!p) continue;
if (fs.existsSync(p)) {
const absP = path.resolve(p);
outLines.push(`// Inject: ${absP}`);
outLines.push(fs.readFileSync(p, 'utf8'));
outLines.push('');
}
}
outLines.push('// Inject: ensure print is defined for harnesses');
outLines.push('if (typeof print === "undefined") {');
outLines.push(' if (typeof console !== "undefined" && typeof console.log === "function") {');
outLines.push(' var print = function(msg) { console.log(msg); };');
outLines.push(' } else {');
outLines.push(' var print = function() {};');
outLines.push(' }');
outLines.push('}');
outLines.push('');
outLines.push('// Inject: native buildString override for performance');
outLines.push('if (typeof __buildString__ !== "undefined" && typeof buildString !== "undefined") { buildString = __buildString__; }');
outLines.push('');
outLines.push('// Inject: expose common harness helpers on globalThis for imported modules');
outLines.push('if (typeof globalThis !== "undefined") {');
outLines.push(' if (typeof assert !== "undefined" && typeof globalThis.assert === "undefined") globalThis.assert = assert;');
outLines.push(' if (typeof Test262Error !== "undefined" && typeof globalThis.Test262Error === "undefined") globalThis.Test262Error = Test262Error;');
outLines.push(' if (typeof $DONE !== "undefined" && typeof globalThis.$DONE === "undefined") globalThis.$DONE = $DONE;');
outLines.push('}');
outLines.push('');
}
const _test_src = fs.readFileSync(testPath, 'utf8');
const _uses_import = /^\s*import\b/m.test(_test_src) || /\bimport\s*\(/.test(_test_src);
if (_uses_import && !skipInjects) {
outLines.push('// Inject: stabilize __filepath for module resolution (only for tests that use import)');
outLines.push(`globalThis.__filepath = ${JSON.stringify(path.resolve(testPath))};`);
outLines.push('');
}
if (!skipInjects && (testPath.includes('/language/global-code/') || /\$262\.evalScript\b/.test(_test_src))) {
outLines.push('// Inject: enable focused global-code semantics mode');
outLines.push('// __test262_global_code_mode');
outLines.push('');
}
const absTest = path.resolve(testPath);
if (!skipInjects) {
outLines.push(`// Inject: ${absTest}`);
}
outLines.push(fs.readFileSync(testPath, 'utf8'));
fs.writeFileSync(tmpName, outLines.join('\n'));
return { testToRun: tmpName, tmpPath: tmpName, cleanupTmp: true };
}
module.exports = { extractMeta, parseList, hasFlag, hasFeature, get262StubLines, composeTest, referencesAssert, verifyComposeStubMarkerCount };