diff --git a/lib/agents/graaljs.js b/lib/agents/graaljs.js index 1f57418..1ecfdb2 100644 --- a/lib/agents/graaljs.js +++ b/lib/agents/graaljs.js @@ -5,7 +5,8 @@ const runtimePath = require('../runtime-path'); const ConsoleAgent = require('../ConsoleAgent'); const ErrorParser = require('../parse-error.js'); -const errorRe = /(.*?): (.+?) (.+)(\n(\s*)at (.+))*/; +const errorexp = /(.*?): (.*)(\n(\s*)at (.+))*/gm; +const customexp = /^(\w+):? ?(.*)$/gm; class GraalJSAgent extends ConsoleAgent { constructor(options) { @@ -14,12 +15,12 @@ class GraalJSAgent extends ConsoleAgent { this.args.unshift( '--js.test262-mode=true', '--js.intl-402=true', - '--js.ecmascript-version=2020', + '--js.ecmascript-version=2022', '--experimental-options' ); } - evalScript(code, options = {}) { + async evalScript(code, options = {}) { if (options.module && this.args[0] !== '--module') { this.args.unshift('--module'); } @@ -32,35 +33,44 @@ class GraalJSAgent extends ConsoleAgent { } parseError(str) { - const match = str.match(errorRe); - if(!match) { + errorexp.lastIndex = -1; + customexp.lastIndex = -1; + + const ematch = errorexp.exec(str); + const cmatch = customexp.exec(str); + + // If the full error expression has a match with a stack, + // use that as the match object. + const hasStack = ematch && (ematch[3] && ematch[3].trim() !== ''); + const match = hasStack + ? ematch + : cmatch; + + if (!match) { return null; } - const stackStr = match[4] || ''; + + const stackStr = match[3] || ''; let stack; - if (stackStr.trim().length > 0) { - stack = ErrorParser.parseStack(stackStr); + if (hasStack) { + stack = ErrorParser.parseStack(stackStr.trim()); } else { - stack = [{ - source: match[0], - fileName: match[1], - lineNumber: match[2] - }]; + stack = []; } return { name: match[1], - message: match[3], + message: match[2], stack: stack, }; } normalizeResult(result) { - const match = result.stdout.match(errorRe); + const match = result.stdout.match(errorexp); if (match) { - result.stdout = result.stdout.replace(errorRe, ''); + result.stdout = result.stdout.replace(errorexp, ''); result.stderr = match[0]; } diff --git a/runtimes/graaljs.js b/runtimes/graaljs.js index 16b6652..e0c45d9 100644 --- a/runtimes/graaljs.js +++ b/runtimes/graaljs.js @@ -1,21 +1,12 @@ -// No need to create $262 object as it is provided -// behind --experimental-options --js.test262-mode=true flags -$262.createRealm = function(options) { - options = options || {}; - options.globals = options.globals || {}; - var realm = loadWithNewGlobal({ script: 'this', name: 'createRealm' }); - realm.eval(this.source); - realm.$262.source = this.source; - realm.$262.destroy = function () { - if (options.destroy) { - options.destroy(); - } - }; - for(var glob in options.globals) { - realm.$262.global[glob] = options.globals[glob]; - } - return realm.$262; -}; +// $262 object is provided, however the shortName options +// requires redefinition to prevent regeference error. +// (behind --experimental-options --js.test262-mode=true flags) +const graaljs = globalThis["\x24262"]; +const DollarCreateRealm = graaljs.createRealm; +const DollarEvalScript = graaljs.evalScript; +const $262 = Object.assign({}, graaljs); + +$262.global = globalThis; $262.gc = function() { throw new Test262Error('gc() not yet supported.'); }; @@ -28,3 +19,29 @@ $262.setGlobal = function(name, value) { $262.destroy = function () { /* noop */ }; $262.IsHTMLDDA = function() { return {}; }; $262.source = $SOURCE; + +$262.evalScript = function(code) { + try { + DollarEvalScript(code); + return { type: 'normal', value: undefined }; + } catch (e) { + return { type: 'throw', value: e }; + } +}; +$262.createRealm = function (options = {}) { + const realm = DollarCreateRealm(options); + realm.evalScript($262.source); + realm.source = $262.source; + realm.getGlobal = $262.getGlobal; + realm.setGlobal = $262.setGlobal; + realm.destroy = () => { + if (options.destroy) { + options.destroy(); + } + }; + const globals = options.globals || {}; + for (let glob in options.globals) { + realm.global[glob] = options.globals[glob]; + } + return realm; +}; \ No newline at end of file