Clone engine262 in /engine262

This commit is contained in:
2020-09-07 10:19:00 +05:30
parent 7688de2e5c
commit 66c1aeb9e0
313 changed files with 46014 additions and 0 deletions
+217
View File
@@ -0,0 +1,217 @@
#!/usr/bin/env node
'use strict';
/* eslint-disable import/order */
try {
require('@snek/source-map-support/register');
} catch {
// empty
}
const repl = require('repl');
const fs = require('fs');
const path = require('path');
const util = require('util');
const packageJson = require('../package.json');
const snekparse = require('./snekparse');
const {
Agent,
setSurroundingAgent,
FEATURES,
inspect,
Value,
CreateDataProperty,
OrdinaryObjectCreate,
Type,
Completion,
AbruptCompletion,
Throw,
} = require('..');
const { createRealm } = require('./test262_realm');
const execArgv = [];
let entry;
const programArgv = [];
{
let target = execArgv;
process.argv.slice(2).forEach((a) => {
if (a.startsWith('--')) {
target.push(a);
} else if (!entry) {
entry = a;
target = programArgv;
} else {
target.push(a);
}
});
}
const help = `
engine262 v${require('../package.json').version}
Usage:
engine262 [options]
engine262 [options] [input file]
engine262 [input file]
Options:
-h, --help Show help (this screen)
-m, --module Evaluate contents of input-file as a module.
Must be followed by input-file
--features=... A comma separated list of features. If no features
are provided, the available features are listed.
`;
const argv = snekparse(execArgv);
if (argv.h || argv.help) {
process.stdout.write(help);
process.exit(0);
} else if (argv.features === true) {
let nameLength = 0;
let flagLength = 0;
FEATURES.forEach((f) => {
if (f.name.length > nameLength) {
nameLength = f.name.length;
}
if (f.flag.length > flagLength) {
flagLength = f.flag.length;
}
});
const log = (n, f, u) => {
process.stdout.write(`${n.padEnd(nameLength, ' ')} ${f.padEnd(flagLength, ' ')} ${u}\n`);
};
log('name', 'flag', 'url');
log('----', '----', '---');
FEATURES.forEach((f) => {
log(f.name, f.flag, f.url);
});
process.exit(0);
}
let features;
if (argv.features === 'all') {
features = FEATURES.map((f) => f.flag);
} else if (argv.features) {
features = argv.features.split(',');
} else {
features = [];
}
const agent = new Agent({ features });
setSurroundingAgent(agent);
const { realm, resolverCache } = createRealm({ printCompatMode: true });
realm.scope(() => {
const console = OrdinaryObjectCreate(realm.Intrinsics['%Object.prototype%']);
CreateDataProperty(realm.GlobalObject, new Value('console'), console);
const format = (args) => args.map((a, i) => {
if (i === 0 && Type(a) === 'String') {
return a.stringValue();
}
return inspect(a);
}).join(' ');
const log = new Value((args) => {
process.stdout.write(`${format(args)}\n`);
return Value.undefined;
});
CreateDataProperty(console, new Value('log'), log);
const error = new Value((args) => {
process.stderr.write(`${format(args)}\n`);
return Value.undefined;
});
CreateDataProperty(console, new Value('error'), error);
const debug = new Value((args) => {
process.stderr.write(`${util.format(...args)}\n`);
return Value.undefined;
});
CreateDataProperty(console, new Value('debug'), debug);
});
if (argv.inspector) {
const inspector = require('../inspector');
inspector.attachRealm(realm);
}
function oneShotEval(source, filename) {
realm.scope(() => {
let result;
if (argv.m || argv.module || filename.endsWith('.mjs')) {
result = realm.createSourceTextModule(filename, source);
if (!(result instanceof AbruptCompletion)) {
const module = result;
resolverCache.set(filename, result);
result = module.Link();
if (!(result instanceof AbruptCompletion)) {
result = module.Evaluate();
}
if (!(result instanceof AbruptCompletion)) {
if (result.PromiseState === 'rejected') {
result = Throw(result.PromiseResult);
}
}
}
} else {
result = realm.evaluateScript(source, { specifier: filename });
}
if (result instanceof AbruptCompletion) {
const inspected = inspect(result);
process.stderr.write(`${inspected}\n`);
process.exit(1);
}
});
}
if (entry) {
const source = fs.readFileSync(entry, 'utf8');
oneShotEval(source, path.resolve(entry));
} else if (!process.stdin.isTTY) {
process.stdin.setEncoding('utf8');
let source = '';
process.stdin.on('data', (data) => {
source += data;
});
process.stdin.once('end', () => {
oneShotEval(source, process.cwd());
});
} else {
process.stdout.write(`${packageJson.name} v${packageJson.version}
Please report bugs to ${packageJson.bugs.url}
`);
repl.start({
prompt: '> ',
eval: (cmd, context, filename, callback) => {
try {
const result = realm.evaluateScript(cmd, { specifier: '(engine262)' });
callback(null, result);
} catch (e) {
callback(e, null);
}
},
preview: false,
completer: () => [],
writer: (o) => realm.scope(() => {
if (o instanceof Value || o instanceof Completion) {
return inspect(o);
}
return util.inspect(o);
}),
});
}
+76
View File
@@ -0,0 +1,76 @@
'use strict';
function snekparse(args) {
if (typeof args === 'string') {
args = args.split(' ');
}
const argv = [];
for (let i = 0; i < args.length; i += 1) {
const arg = args[i];
if (/^--.+=/.test(arg)) {
const match = arg.match(/^--([^=]+)=([\s\S]*)$/);
argv[match[1]] = match[2];
} else if (/^--no-.+/.test(arg)) {
argv[arg.match(/^--no-(.+)/)[1]] = false;
} else if (/^--.+/.test(arg)) {
const key = arg.match(/^--(.+)/)[1];
const next = args[i + 1];
if (typeof next !== 'undefined' && !/^-/.test(next)) {
argv[key] = next;
} else if (/^(true|false)$/.test(next)) {
argv[key] = next === 'true';
} else {
argv[key] = true;
}
} else if (/^-[^-]+/.test(arg)) {
const letters = arg.slice(1, -1).split('');
let broken = false;
for (const j of letters) {
const next = arg.slice(j + 2);
if (next === '-') {
argv[letters[j]] = next;
continue;
}
if (/[A-Za-z]/.test(letters[j]) && /=/.test(next)) {
argv[letters[j]] = next.split('=')[1];
broken = true;
break;
}
if (/[A-Za-z]/.test(letters[j])
&& /-?\d+(\.\d*)?(e-?\d+)?$/.test(next)) {
argv[letters[j]] = next;
broken = true;
break;
}
if (letters[j + 1] && letters[j + 1].match(/\W/)) {
argv[letters[j]] = arg.slice(j + 2);
broken = true;
break;
} else {
argv[letters[j]] = true;
}
}
const key = arg.slice(-1)[0];
if (!broken && key !== '-') {
if (args[i + 1] && !/^(-|--)[^-]/.test(args[i + 1])) {
argv[key] = args[i + 1];
} else if (args[i + 1] && /true|false/.test(args[i + 1])) {
argv[key] = args[i + 1] === 'true';
} else {
argv[key] = true;
}
}
} else {
argv.push(arg);
}
}
return argv;
}
module.exports = snekparse;
+129
View File
@@ -0,0 +1,129 @@
'use strict';
const path = require('path');
const fs = require('fs');
const {
Value,
CreateDataProperty,
DetachArrayBuffer,
OrdinaryObjectCreate,
ToString,
Type,
Throw,
AbruptCompletion,
ManagedRealm,
inspect,
gc,
} = require('..');
const createRealm = ({ printCompatMode = false } = {}) => {
const resolverCache = new Map();
const trackedPromises = new Set();
const realm = new ManagedRealm({
promiseRejectionTracker(promise, operation) {
switch (operation) {
case 'reject':
trackedPromises.add(promise);
break;
case 'handle':
trackedPromises.delete(promise);
break;
/* istanbul ignore next */
default:
throw new RangeError('promiseRejectionTracker', operation);
}
},
resolveImportedModule(referencingScriptOrModule, specifier) {
try {
const base = path.dirname(referencingScriptOrModule.HostDefined.specifier);
const resolved = path.resolve(base, specifier);
if (resolverCache.has(resolved)) {
return resolverCache.get(resolved);
}
const source = fs.readFileSync(resolved, 'utf8');
const m = realm.createSourceTextModule(resolved, source);
resolverCache.set(resolved, m);
return m;
} catch (e) {
return Throw(e.name, 'Raw', e.message);
}
},
});
return realm.scope(() => {
const $262 = OrdinaryObjectCreate(realm.Intrinsics['%Object.prototype%']);
let printHandle;
const setPrintHandle = (f) => {
printHandle = f;
};
CreateDataProperty(realm.GlobalObject, new Value('print'), new Value((args) => {
/* istanbul ignore next */
if (printHandle !== undefined) {
printHandle(...args);
} else {
if (printCompatMode) {
for (let i = 0; i < args.length; i += 1) {
const arg = args[i];
const s = ToString(arg);
if (s instanceof AbruptCompletion) {
return s;
}
process.stdout.write(s.stringValue());
if (i !== args.length - 1) {
process.stdout.write(' ');
}
}
process.stdout.write('\n');
return Value.undefined;
} else {
const formatted = args.map((a, i) => {
if (i === 0 && Type(a) === 'String') {
return a.stringValue();
}
return inspect(a, realm);
}).join(' ');
console.log(formatted); // eslint-disable-line no-console
}
}
return Value.undefined;
}));
[
['global', realm.GlobalObject],
['createRealm', () => {
const info = createRealm();
return info.$262;
}],
['evalScript', ([sourceText]) => realm.evaluateScript(sourceText.stringValue())],
['detachArrayBuffer', ([arrayBuffer]) => DetachArrayBuffer(arrayBuffer)],
['gc', () => {
gc();
return Value.undefined;
}],
['spec', ([v]) => {
if (v.nativeFunction && v.nativeFunction.section) {
return new Value(v.nativeFunction.section);
}
return Value.undefined;
}],
].forEach(([name, value]) => {
const v = value instanceof Value ? value : new Value(value);
CreateDataProperty($262, new Value(name), v);
});
CreateDataProperty(realm.GlobalObject, new Value('$262'), $262);
CreateDataProperty(realm.GlobalObject, new Value('$'), $262);
return {
realm,
$262,
resolverCache,
trackedPromises,
setPrintHandle,
};
});
};
module.exports = { createRealm };