feat: implement new API with source maps

This commit is contained in:
TopchetoEU 2023-11-28 21:40:37 +02:00
parent 124341969c
commit 73345062ca
Signed by: topchetoeu
GPG Key ID: 6531B8583E5F6ED4
3 changed files with 44 additions and 40 deletions

View File

@ -1,7 +1,6 @@
(function (_arguments) { (function (ts, env, libs) {
var ts = _arguments[0];
var src = '', version = 0; var src = '', version = 0;
var lib = _arguments[2].concat([ var lib = libs.concat([
'declare const exit: never;', 'declare const exit: never;',
'declare const go: any;', 'declare const go: any;',
'declare function getTsDeclarations(): string[];' 'declare function getTsDeclarations(): string[];'
@ -57,6 +56,8 @@
service.getEmitOutput("/lib.d.ts"); service.getEmitOutput("/lib.d.ts");
log("Loaded libraries!"); log("Loaded libraries!");
var oldCompile = env.compile;
function compile(code, filename, env) { function compile(code, filename, env) {
src = code; src = code;
version++; version++;
@ -88,23 +89,19 @@
var result = emit.outputFiles[1].text; var result = emit.outputFiles[1].text;
var declaration = emit.outputFiles[2].text; var declaration = emit.outputFiles[2].text;
var compiled = oldCompile(result, filename, env);
return { return {
source: result, function: function () {
map: log(JSON.stringify({ var val = compiled.function.apply(this, arguments);
version: 3, if (declaration !== '') declSnapshots.push(ts.ScriptSnapshot.fromString(declaration));
sources: [ filename ], return val;
},
mapChain: compiled.mapChain.concat(JSON.stringify({
file: filename, file: filename,
mappings: map.mappings sources: [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;
}
}
}; };
} }
@ -115,5 +112,5 @@
} }
} }
apply(_arguments[1]); apply(env);
})(arguments); })(arguments[0], arguments[1], arguments[2]);

View File

@ -9,11 +9,11 @@ import java.util.TreeSet;
import me.topchetoeu.jscript.Filename; import me.topchetoeu.jscript.Filename;
import me.topchetoeu.jscript.Location; import me.topchetoeu.jscript.Location;
import me.topchetoeu.jscript.engine.frame.CodeFrame; 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.FunctionValue;
import me.topchetoeu.jscript.engine.values.ObjectValue;
import me.topchetoeu.jscript.engine.values.Values; import me.topchetoeu.jscript.engine.values.Values;
import me.topchetoeu.jscript.exceptions.EngineException; import me.topchetoeu.jscript.exceptions.EngineException;
import me.topchetoeu.jscript.parsing.Parsing; import me.topchetoeu.jscript.mapping.SourceMap;
public class Context { public class Context {
private final Stack<Environment> env = new Stack<>(); private final Stack<Environment> env = new Stack<>();
@ -34,24 +34,17 @@ public class Context {
public FunctionValue compile(Filename filename, String raw) { public FunctionValue compile(Filename filename, String raw) {
var env = environment(); var env = environment();
var transpiled = env.compile.call(this, null, raw, filename.toString(), env); var result = env.compile.call(this, null, raw, filename.toString(), env);
String source = null;
FunctionValue runner = null;
if (transpiled instanceof ObjectValue) { var function = (FunctionValue)Values.getMember(this, result, "function");
source = Values.toString(this, Values.getMember(this, transpiled, "source")); var rawMapChain = ((ArrayValue)Values.getMember(this, result, "mapChain")).toArray();
var _runner = Values.getMember(this, transpiled, "runner"); var maps = new SourceMap[rawMapChain.length];
if (_runner instanceof FunctionValue) runner = (FunctionValue)_runner; for (var i = 0; i < maps.length; i++) maps[i] = SourceMap.parse((String)rawMapChain[i]);
} var map = SourceMap.chain(maps);
else source = Values.toString(this, transpiled);
var breakpoints = new TreeSet<Location>(); engine.onSource(filename, raw, new TreeSet<>(), map);
FunctionValue res = Parsing.compile(Engine.functions, breakpoints, env, filename, source);
engine.onSource(filename, source, breakpoints);
if (runner != null) res = (FunctionValue)runner.call(this, null, res); return function;
return res;
} }

View File

@ -1,18 +1,23 @@
package me.topchetoeu.jscript.engine; package me.topchetoeu.jscript.engine;
import java.util.HashMap; 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.scope.GlobalScope;
import me.topchetoeu.jscript.engine.values.ArrayValue;
import me.topchetoeu.jscript.engine.values.FunctionValue; import me.topchetoeu.jscript.engine.values.FunctionValue;
import me.topchetoeu.jscript.engine.values.NativeFunction; import me.topchetoeu.jscript.engine.values.NativeFunction;
import me.topchetoeu.jscript.engine.values.ObjectValue; import me.topchetoeu.jscript.engine.values.ObjectValue;
import me.topchetoeu.jscript.engine.values.Symbol; import me.topchetoeu.jscript.engine.values.Symbol;
import me.topchetoeu.jscript.engine.values.Values;
import me.topchetoeu.jscript.exceptions.EngineException; import me.topchetoeu.jscript.exceptions.EngineException;
import me.topchetoeu.jscript.filesystem.RootFilesystem; import me.topchetoeu.jscript.filesystem.RootFilesystem;
import me.topchetoeu.jscript.interop.Native; import me.topchetoeu.jscript.interop.Native;
import me.topchetoeu.jscript.interop.NativeGetter; import me.topchetoeu.jscript.interop.NativeGetter;
import me.topchetoeu.jscript.interop.NativeSetter; import me.topchetoeu.jscript.interop.NativeSetter;
import me.topchetoeu.jscript.interop.NativeWrapperProvider; import me.topchetoeu.jscript.interop.NativeWrapperProvider;
import me.topchetoeu.jscript.parsing.Parsing;
import me.topchetoeu.jscript.permissions.Permission; import me.topchetoeu.jscript.permissions.Permission;
import me.topchetoeu.jscript.permissions.PermissionsProvider; import me.topchetoeu.jscript.permissions.PermissionsProvider;
@ -31,7 +36,17 @@ public class Environment implements PermissionsProvider {
@Native public int id = ++nextId; @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) -> { @Native public FunctionValue regexConstructor = new NativeFunction("RegExp", (ctx, thisArg, args) -> {
throw EngineException.ofError("Regular expressions not supported.").setCtx(ctx.environment(), ctx.engine); 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) { 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 (nativeConverter == null) nativeConverter = new NativeWrapperProvider(this);
if (global == null) global = new GlobalScope(); if (global == null) global = new GlobalScope();
this.wrappers = nativeConverter; this.wrappers = nativeConverter;
this.compile = compile;
this.global = global; this.global = global;
} }
} }