From 73345062cae92328f8a3ac2403e96a78102e6f33 Mon Sep 17 00:00:00 2001 From: TopchetoEU <36534413+TopchetoEU@users.noreply.github.com> Date: Tue, 28 Nov 2023 21:40:37 +0200 Subject: [PATCH] feat: implement new API with source maps --- src/assets/js/bootstrap.js | 37 +++++++++---------- src/me/topchetoeu/jscript/engine/Context.java | 27 +++++--------- .../jscript/engine/Environment.java | 20 ++++++++-- 3 files changed, 44 insertions(+), 40 deletions(-) diff --git a/src/assets/js/bootstrap.js b/src/assets/js/bootstrap.js index 65a8e25..791bec7 100644 --- a/src/assets/js/bootstrap.js +++ b/src/assets/js/bootstrap.js @@ -1,7 +1,6 @@ -(function (_arguments) { - var ts = _arguments[0]; +(function (ts, env, libs) { var src = '', version = 0; - var lib = _arguments[2].concat([ + var lib = libs.concat([ 'declare const exit: never;', 'declare const go: any;', 'declare function getTsDeclarations(): string[];' @@ -57,6 +56,8 @@ service.getEmitOutput("/lib.d.ts"); log("Loaded libraries!"); + var oldCompile = env.compile; + function compile(code, filename, env) { src = code; version++; @@ -88,23 +89,19 @@ var result = emit.outputFiles[1].text; var declaration = emit.outputFiles[2].text; + var compiled = oldCompile(result, filename, env); + return { - source: result, - map: log(JSON.stringify({ - version: 3, - sources: [ filename ], + function: function () { + var val = compiled.function.apply(this, arguments); + if (declaration !== '') declSnapshots.push(ts.ScriptSnapshot.fromString(declaration)); + return val; + }, + mapChain: compiled.mapChain.concat(JSON.stringify({ file: filename, - mappings: map.mappings - })), - runner: function(func) { - return function() { - var val = func.apply(this, arguments); - if (declaration !== '') { - declSnapshots.push(ts.ScriptSnapshot.fromString(declaration)); - } - return val; - } - } + sources: [filename], + mappings: map.mappings, + })) }; } @@ -115,5 +112,5 @@ } } - apply(_arguments[1]); -})(arguments); + apply(env); +})(arguments[0], arguments[1], arguments[2]); diff --git a/src/me/topchetoeu/jscript/engine/Context.java b/src/me/topchetoeu/jscript/engine/Context.java index c8246a5..b098330 100644 --- a/src/me/topchetoeu/jscript/engine/Context.java +++ b/src/me/topchetoeu/jscript/engine/Context.java @@ -9,11 +9,11 @@ import java.util.TreeSet; import me.topchetoeu.jscript.Filename; import me.topchetoeu.jscript.Location; import me.topchetoeu.jscript.engine.frame.CodeFrame; +import me.topchetoeu.jscript.engine.values.ArrayValue; import me.topchetoeu.jscript.engine.values.FunctionValue; -import me.topchetoeu.jscript.engine.values.ObjectValue; import me.topchetoeu.jscript.engine.values.Values; import me.topchetoeu.jscript.exceptions.EngineException; -import me.topchetoeu.jscript.parsing.Parsing; +import me.topchetoeu.jscript.mapping.SourceMap; public class Context { private final Stack env = new Stack<>(); @@ -34,24 +34,17 @@ public class Context { public FunctionValue compile(Filename filename, String raw) { var env = environment(); - var transpiled = env.compile.call(this, null, raw, filename.toString(), env); - String source = null; - FunctionValue runner = null; + var result = env.compile.call(this, null, raw, filename.toString(), env); - if (transpiled instanceof ObjectValue) { - source = Values.toString(this, Values.getMember(this, transpiled, "source")); - var _runner = Values.getMember(this, transpiled, "runner"); - if (_runner instanceof FunctionValue) runner = (FunctionValue)_runner; - } - else source = Values.toString(this, transpiled); + var function = (FunctionValue)Values.getMember(this, result, "function"); + var rawMapChain = ((ArrayValue)Values.getMember(this, result, "mapChain")).toArray(); + var maps = new SourceMap[rawMapChain.length]; + for (var i = 0; i < maps.length; i++) maps[i] = SourceMap.parse((String)rawMapChain[i]); + var map = SourceMap.chain(maps); - var breakpoints = new TreeSet(); - FunctionValue res = Parsing.compile(Engine.functions, breakpoints, env, filename, source); - engine.onSource(filename, source, breakpoints); + engine.onSource(filename, raw, new TreeSet<>(), map); - if (runner != null) res = (FunctionValue)runner.call(this, null, res); - - return res; + return function; } diff --git a/src/me/topchetoeu/jscript/engine/Environment.java b/src/me/topchetoeu/jscript/engine/Environment.java index 49d67c5..4d38a8a 100644 --- a/src/me/topchetoeu/jscript/engine/Environment.java +++ b/src/me/topchetoeu/jscript/engine/Environment.java @@ -1,18 +1,23 @@ package me.topchetoeu.jscript.engine; import java.util.HashMap; +import java.util.TreeSet; +import me.topchetoeu.jscript.Filename; import me.topchetoeu.jscript.engine.scope.GlobalScope; +import me.topchetoeu.jscript.engine.values.ArrayValue; import me.topchetoeu.jscript.engine.values.FunctionValue; import me.topchetoeu.jscript.engine.values.NativeFunction; import me.topchetoeu.jscript.engine.values.ObjectValue; import me.topchetoeu.jscript.engine.values.Symbol; +import me.topchetoeu.jscript.engine.values.Values; import me.topchetoeu.jscript.exceptions.EngineException; import me.topchetoeu.jscript.filesystem.RootFilesystem; import me.topchetoeu.jscript.interop.Native; import me.topchetoeu.jscript.interop.NativeGetter; import me.topchetoeu.jscript.interop.NativeSetter; import me.topchetoeu.jscript.interop.NativeWrapperProvider; +import me.topchetoeu.jscript.parsing.Parsing; import me.topchetoeu.jscript.permissions.Permission; import me.topchetoeu.jscript.permissions.PermissionsProvider; @@ -31,7 +36,17 @@ public class Environment implements PermissionsProvider { @Native public int id = ++nextId; - @Native public FunctionValue compile; + @Native public FunctionValue compile = new NativeFunction("compile", (ctx, thisArg, args) -> { + var source = Values.toString(ctx, args[0]); + var filename = Values.toString(ctx, args[1]); + var env = Values.wrapper(args[2], Environment.class); + var res = new ObjectValue(); + + res.defineProperty(ctx, "function", Parsing.compile(Engine.functions, new TreeSet<>(), env, Filename.parse(filename), source)); + res.defineProperty(ctx, "mapChain", new ArrayValue()); + + return res; + }); @Native public FunctionValue regexConstructor = new NativeFunction("RegExp", (ctx, thisArg, args) -> { throw EngineException.ofError("Regular expressions not supported.").setCtx(ctx.environment(), ctx.engine); }); @@ -89,12 +104,11 @@ public class Environment implements PermissionsProvider { } public Environment(FunctionValue compile, WrappersProvider nativeConverter, GlobalScope global) { - if (compile == null) compile = new NativeFunction("compile", (ctx, thisArg, args) -> args.length == 0 ? "" : args[0]); + if (compile != null) this.compile = compile; if (nativeConverter == null) nativeConverter = new NativeWrapperProvider(this); if (global == null) global = new GlobalScope(); this.wrappers = nativeConverter; - this.compile = compile; this.global = global; } }