fix: several bug fixes to help with typescript support

This commit is contained in:
TopchetoEU 2023-11-05 12:44:29 +02:00
parent 7df4e3b03f
commit d57044acb7
Signed by: topchetoeu
GPG Key ID: 6531B8583E5F6ED4
8 changed files with 127 additions and 94 deletions

View File

@ -51,6 +51,7 @@ public class Engine implements DebugController {
} }
private static int nextId = 0; private static int nextId = 0;
public static final HashMap<Long, FunctionBody> functions = new HashMap<>();
private Thread thread; private Thread thread;
private LinkedBlockingDeque<Task> macroTasks = new LinkedBlockingDeque<>(); private LinkedBlockingDeque<Task> macroTasks = new LinkedBlockingDeque<>();
@ -58,7 +59,6 @@ public class Engine implements DebugController {
public final int id = ++nextId; public final int id = ++nextId;
public final Data data = new Data().set(StackData.MAX_FRAMES, 200); public final Data data = new Data().set(StackData.MAX_FRAMES, 200);
public final HashMap<Long, FunctionBody> functions = new HashMap<>();
public final boolean debugging; public final boolean debugging;
private final HashMap<Filename, String> sources = new HashMap<>(); private final HashMap<Filename, String> sources = new HashMap<>();
private final HashMap<Filename, TreeSet<Location>> bpts = new HashMap<>(); private final HashMap<Filename, TreeSet<Location>> bpts = new HashMap<>();

View File

@ -473,13 +473,16 @@ public class SimpleDebugger implements Debugger {
@Override public void setBreakpointByUrl(V8Message msg) { @Override public void setBreakpointByUrl(V8Message msg) {
var line = (int)msg.params.number("lineNumber") + 1; var line = (int)msg.params.number("lineNumber") + 1;
var col = (int)msg.params.number("columnNumber", 0) + 1; var col = (int)msg.params.number("columnNumber", 0) + 1;
var cond = msg.params.string("condition", null);
if (cond != null) cond = "(" + cond + ")";
Pattern regex; Pattern regex;
if (msg.params.isString("url")) regex = Pattern.compile(Pattern.quote(msg.params.string("url"))); if (msg.params.isString("url")) regex = Pattern.compile(Pattern.quote(msg.params.string("url")));
else regex = Pattern.compile(msg.params.string("urlRegex")); else regex = Pattern.compile(msg.params.string("urlRegex"));
var bpcd = new BreakpointCandidate(nextId(), regex, line, col, null); var bpcd = new BreakpointCandidate(nextId(), regex, line, col, cond);
idToBptCand.put(bpcd.id, bpcd); idToBptCand.put(bpcd.id, bpcd);
var locs = new JSONList(); var locs = new JSONList();
@ -592,42 +595,44 @@ public class SimpleDebugger implements Debugger {
var res = new JSONList(); var res = new JSONList();
var ctx = objectToCtx.get(obj); var ctx = objectToCtx.get(obj);
for (var key : obj.keys(true)) { if (obj != emptyObject) {
var propDesc = new JSONMap(); for (var key : obj.keys(true)) {
var propDesc = new JSONMap();
if (obj.properties.containsKey(key)) {
var prop = obj.properties.get(key); if (obj.properties.containsKey(key)) {
var prop = obj.properties.get(key);
propDesc.set("name", Values.toString(ctx, key));
if (prop.getter != null) propDesc.set("get", serializeObj(ctx, prop.getter)); propDesc.set("name", Values.toString(ctx, key));
if (prop.setter != null) propDesc.set("set", serializeObj(ctx, prop.setter)); if (prop.getter != null) propDesc.set("get", serializeObj(ctx, prop.getter));
propDesc.set("enumerable", obj.memberEnumerable(key)); if (prop.setter != null) propDesc.set("set", serializeObj(ctx, prop.setter));
propDesc.set("configurable", obj.memberConfigurable(key)); propDesc.set("enumerable", obj.memberEnumerable(key));
propDesc.set("isOwn", true); propDesc.set("configurable", obj.memberConfigurable(key));
res.add(propDesc); propDesc.set("isOwn", true);
} res.add(propDesc);
else { }
propDesc.set("name", Values.toString(ctx, key)); else {
propDesc.set("value", serializeObj(ctx, obj.getMember(ctx, key))); propDesc.set("name", Values.toString(ctx, key));
propDesc.set("writable", obj.memberWritable(key)); propDesc.set("value", serializeObj(ctx, obj.getMember(ctx, key)));
propDesc.set("enumerable", obj.memberEnumerable(key)); propDesc.set("writable", obj.memberWritable(key));
propDesc.set("configurable", obj.memberConfigurable(key)); propDesc.set("enumerable", obj.memberEnumerable(key));
propDesc.set("isOwn", true); propDesc.set("configurable", obj.memberConfigurable(key));
res.add(propDesc); propDesc.set("isOwn", true);
res.add(propDesc);
}
} }
var proto = obj.getPrototype(ctx);
var protoDesc = new JSONMap();
protoDesc.set("name", "__proto__");
protoDesc.set("value", serializeObj(ctx, proto == null ? Values.NULL : proto));
protoDesc.set("writable", true);
protoDesc.set("enumerable", false);
protoDesc.set("configurable", false);
protoDesc.set("isOwn", true);
res.add(protoDesc);
} }
var proto = obj.getPrototype(ctx);
var protoDesc = new JSONMap();
protoDesc.set("name", "__proto__");
protoDesc.set("value", serializeObj(ctx, proto == null ? Values.NULL : proto));
protoDesc.set("writable", true);
protoDesc.set("enumerable", false);
protoDesc.set("configurable", false);
protoDesc.set("isOwn", true);
res.add(protoDesc);
ws.send(msg.respond(new JSONMap().set("result", res))); ws.send(msg.respond(new JSONMap().set("result", res)));
} }
@Override public void callFunctionOn(V8Message msg) { @Override public void callFunctionOn(V8Message msg) {
@ -662,25 +667,25 @@ public class SimpleDebugger implements Debugger {
case VSCODE_STRINGIFY_VAL: case VSCODE_STRINGIFY_VAL:
case VSCODE_STRINGIFY_PROPS: case VSCODE_STRINGIFY_PROPS:
case VSCODE_SHALLOW_COPY: case VSCODE_SHALLOW_COPY:
case VSCODE_SYMBOL_REQUEST:
ws.send(msg.respond(new JSONMap().set("result", serializeObj(ctx, emptyObject)))); ws.send(msg.respond(new JSONMap().set("result", serializeObj(ctx, emptyObject))));
break; break;
case VSCODE_FLATTEN_ARRAY: { case VSCODE_FLATTEN_ARRAY:
ws.send(msg.respond(new JSONMap().set("result", serializeObj(ctx, thisArg)))); ws.send(msg.respond(new JSONMap().set("result", serializeObj(ctx, thisArg))));
break; break;
}
case VSCODE_SYMBOL_REQUEST:
ws.send(msg.respond(new JSONMap().set("result", serializeObj(ctx, new ArrayValue(ctx)))));
break;
case VSCODE_CALL: { case VSCODE_CALL: {
var func = (FunctionValue)(args.size() < 1 ? null : args.get(0)); var func = (FunctionValue)(args.size() < 1 ? null : args.get(0));
ws.send(msg.respond(new JSONMap().set("result", serializeObj(ctx, func.call(ctx, thisArg))))); ws.send(msg.respond(new JSONMap().set("result", serializeObj(ctx, func.call(ctx, thisArg)))));
break; break;
} }
default: { default:
var res = ctx.compile(new Filename("jscript", "eval"), src).call(ctx); ws.send(new V8Error("Please use well-known functions with callFunctionOn"));
if (res instanceof FunctionValue) ((FunctionValue)res).call(ctx, thisArg, args); break;
ws.send(msg.respond(new JSONMap().set("result", serializeObj(ctx, res)))); // default: {
} // var res = ctx.compile(new Filename("jscript", "eval"), src).call(ctx);
// if (res instanceof FunctionValue) ((FunctionValue)res).call(ctx, thisArg, args);
// ws.send(msg.respond(new JSONMap().set("result", serializeObj(ctx, res))));
// }
} }
} }
catch (EngineException e) { ws.send(msg.respond(new JSONMap().set("exceptionDetails", serializeException(ctx, e)))); } catch (EngineException e) { ws.send(msg.respond(new JSONMap().set("exceptionDetails", serializeException(ctx, e)))); }
@ -725,14 +730,15 @@ public class SimpleDebugger implements Debugger {
returnVal != Runners.NO_RETURN returnVal != Runners.NO_RETURN
); );
if (error != null && !caught && StackData.frames(ctx).size() > 1) error = null; // TODO: FIXXXX
// if (error != null && !caught && StackData.frames(ctx).size() > 1) error = null;
if (error != null && (execptionType == CatchType.ALL || execptionType == CatchType.UNCAUGHT && !caught)) { if (error != null && (execptionType == CatchType.ALL || execptionType == CatchType.UNCAUGHT && !caught)) {
pauseException(ctx); pauseException(ctx);
} }
else if (isBreakpointable && locToBreakpoint.containsKey(loc)) { else if (isBreakpointable && locToBreakpoint.containsKey(loc)) {
var bp = locToBreakpoint.get(loc); var bp = locToBreakpoint.get(loc);
var ok = bp.condition == null ? true : Values.toBoolean(run(currFrame, bp.condition)); var ok = bp.condition == null ? true : Values.toBoolean(run(currFrame, bp.condition).result);
if (ok) pauseDebug(ctx, locToBreakpoint.get(loc)); if (ok) pauseDebug(ctx, locToBreakpoint.get(loc));
} }
else if (isBreakpointable && tmpBreakpts.remove(loc)) pauseDebug(ctx, null); else if (isBreakpointable && tmpBreakpts.remove(loc)) pauseDebug(ctx, null);

View File

@ -15,7 +15,7 @@ import me.topchetoeu.jscript.exceptions.EngineException;
import me.topchetoeu.jscript.exceptions.InterruptException; import me.topchetoeu.jscript.exceptions.InterruptException;
public class CodeFrame { public class CodeFrame {
private class TryCtx { public static class TryCtx {
public static final int STATE_TRY = 0; public static final int STATE_TRY = 0;
public static final int STATE_CATCH = 1; public static final int STATE_CATCH = 1;
public static final int STATE_FINALLY_THREW = 2; public static final int STATE_FINALLY_THREW = 2;

View File

@ -42,7 +42,7 @@
service.getEmitOutput('/lib.d.ts'); service.getEmitOutput('/lib.d.ts');
log('Loaded libraries!'); log('Loaded libraries!');
function compile(filename, code) { function compile(code, filename) {
src = code, version++; src = code, version++;
var emit = service.getEmitOutput("/src.ts"); var emit = service.getEmitOutput("/src.ts");

View File

@ -188,13 +188,28 @@ public class JSON {
if (el.isNumber()) return Double.toString(el.number()); if (el.isNumber()) return Double.toString(el.number());
if (el.isBoolean()) return el.bool() ? "true" : "false"; if (el.isBoolean()) return el.bool() ? "true" : "false";
if (el.isNull()) return "null"; if (el.isNull()) return "null";
if (el.isString()) return "\"" + el.string() if (el.isString()) {
.replace("\\", "\\\\") var res = new StringBuilder("\"");
.replace("\n", "\\n") var alphabet = "0123456789ABCDEF".toCharArray();
.replace("\r", "\\r")
.replace("\t", "\\t") for (var c : el.string().toCharArray()) {
.replace("\"", "\\\"") if (c < 32 || c >= 127) {
+ "\""; res
.append("\\u")
.append(alphabet[(c >> 12) & 0xF])
.append(alphabet[(c >> 8) & 0xF])
.append(alphabet[(c >> 4) & 0xF])
.append(alphabet[(c >> 0) & 0xF]);
}
else if (c == '\\')
res.append("\\\\");
else if (c == '"')
res.append("\\\"");
else res.append(c);
}
return res.append('"').toString();
}
if (el.isList()) { if (el.isList()) {
var res = new StringBuilder().append("["); var res = new StringBuilder().append("[");
for (int i = 0; i < el.list().size(); i++) { for (int i = 0; i < el.list().size(); i++) {

View File

@ -93,13 +93,14 @@ import me.topchetoeu.jscript.interop.NativeSetter;
return res; return res;
} }
@Native(thisArg = true) public static void sort(Context ctx, ArrayValue arr, FunctionValue cmp) { @Native(thisArg = true) public static ArrayValue sort(Context ctx, ArrayValue arr, FunctionValue cmp) {
arr.sort((a, b) -> { arr.sort((a, b) -> {
var res = Values.toNumber(ctx, cmp.call(ctx, null, a, b)); var res = Values.toNumber(ctx, cmp.call(ctx, null, a, b));
if (res < 0) return -1; if (res < 0) return -1;
if (res > 0) return 1; if (res > 0) return 1;
return 0; return 0;
}); });
return arr;
} }
private static int normalizeI(int len, int i, boolean clamp) { private static int normalizeI(int len, int i, boolean clamp) {
@ -299,17 +300,14 @@ import me.topchetoeu.jscript.interop.NativeSetter;
return arr.size(); return arr.size();
} }
@Native(thisArg = true) public static ArrayValue slice(Context ctx, ArrayValue arr, int start, int end) { @Native(thisArg = true) public static ArrayValue slice(Context ctx, ArrayValue arr, int start, Object _end) {
start = normalizeI(arr.size(), start, true); start = normalizeI(arr.size(), start, true);
end = normalizeI(arr.size(), end, true); int end = normalizeI(arr.size(), (int)(_end == null ? arr.size() : Values.toNumber(ctx, _end)), true);
var res = new ArrayValue(end - start); var res = new ArrayValue(end - start);
arr.copyTo(ctx, res, start, 0, end - start); arr.copyTo(ctx, res, start, 0, end - start);
return res; return res;
} }
@Native(thisArg = true) public static ArrayValue slice(Context ctx, ArrayValue arr, int start) {
return slice(ctx, arr, start, arr.size());
}
@Native(thisArg = true) public static ArrayValue splice(Context ctx, ArrayValue arr, int start, int deleteCount, Object ...items) { @Native(thisArg = true) public static ArrayValue splice(Context ctx, ArrayValue arr, int start, int deleteCount, Object ...items) {
start = normalizeI(arr.size(), start, true); start = normalizeI(arr.size(), start, true);

View File

@ -2,10 +2,12 @@ package me.topchetoeu.jscript.lib;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Iterator; import java.util.Iterator;
import java.util.function.Function;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import me.topchetoeu.jscript.engine.Context; import me.topchetoeu.jscript.engine.Context;
import me.topchetoeu.jscript.engine.values.ArrayValue; import me.topchetoeu.jscript.engine.values.ArrayValue;
import me.topchetoeu.jscript.engine.values.FunctionValue;
import me.topchetoeu.jscript.engine.values.NativeWrapper; import me.topchetoeu.jscript.engine.values.NativeWrapper;
import me.topchetoeu.jscript.engine.values.ObjectValue; import me.topchetoeu.jscript.engine.values.ObjectValue;
import me.topchetoeu.jscript.engine.values.Values; import me.topchetoeu.jscript.engine.values.Values;
@ -81,7 +83,6 @@ import me.topchetoeu.jscript.interop.NativeGetter;
return res; return res;
} }
@Native public Object exec(String str) { @Native public Object exec(String str) {
var matcher = pattern.matcher(str); var matcher = pattern.matcher(str);
if (lastI > str.length() || !matcher.find(lastI) || sticky && matcher.start() != lastI) { if (lastI > str.length() || !matcher.find(lastI) || sticky && matcher.start() != lastI) {
@ -133,7 +134,7 @@ import me.topchetoeu.jscript.interop.NativeGetter;
return "/" + source + "/" + flags(); return "/" + source + "/" + flags();
} }
@Native("@@Symvol.match") public Object match(Context ctx, String target) { @Native("@@Symbol.match") public Object match(Context ctx, String target) {
if (this.global) { if (this.global) {
var res = new ArrayValue(); var res = new ArrayValue();
Object val; Object val;
@ -150,7 +151,7 @@ import me.topchetoeu.jscript.interop.NativeGetter;
} }
} }
@Native("@@Symvol.matchAll") public Object matchAll(Context ctx, String target) { @Native("@@Symbol.matchAll") public Object matchAll(Context ctx, String target) {
var pattern = new RegExpLib(this.source, this.flags() + "g"); var pattern = new RegExpLib(this.source, this.flags() + "g");
return Values.fromJavaIterator(ctx, new Iterator<Object>() { return Values.fromJavaIterator(ctx, new Iterator<Object>() {
@ -171,8 +172,8 @@ import me.topchetoeu.jscript.interop.NativeGetter;
} }
}); });
} }
@Native("@@Symvol.split") public ArrayValue split(Context ctx, String target, Object limit, boolean sensible) { @Native("@@Symbol.split") public ArrayValue split(Context ctx, String target, Object limit, boolean sensible) {
var pattern = new RegExpLib(this.source, this.flags() + "g"); var pattern = new RegExpLib(this.source, this.flags() + "g");
Object match; Object match;
int lastEnd = 0; int lastEnd = 0;
@ -214,29 +215,41 @@ import me.topchetoeu.jscript.interop.NativeGetter;
} }
return res; return res;
} }
// [Symbol.replace](target, replacement) {
// const pattern = new this.constructor(this, this.flags + "d") as RegExp; @Native("@@Symbol.replace") public String replace(Context ctx, String target, Object replacement) {
// let match: RegExpResult | null; var pattern = new RegExpLib(this.source, this.flags() + "d");
// let lastEnd = 0; Object match;
// const res: string[] = []; var lastEnd = 0;
// // log(pattern.toString()); var res = new StringBuilder();
// while ((match = pattern.exec(target)) !== null) {
// const indices = match.indices![0]; while ((match = pattern.exec(target)) != Values.NULL) {
// res.push(target.substring(lastEnd, indices[0])); var indices = (ArrayValue)((ArrayValue)Values.getMember(ctx, match, "indices")).get(0);
// if (replacement instanceof Function) { var arrMatch = (ArrayValue)match;
// res.push(replacement(target.substring(indices[0], indices[1]), ...match.slice(1), indices[0], target));
// } var start = ((Number)indices.get(0)).intValue();
// else { var end = ((Number)indices.get(1)).intValue();
// res.push(replacement);
// } res.append(target.substring(lastEnd, start));
// lastEnd = indices[1]; if (replacement instanceof FunctionValue) {
// if (!pattern.global) break; var args = new Object[arrMatch.size() + 2];
// } args[0] = target.substring(start, end);
// if (lastEnd < target.length) { arrMatch.copyTo(args, 1, 1, arrMatch.size() - 1);
// res.push(target.substring(lastEnd)); args[args.length - 2] = start;
// } args[args.length - 1] = target;
// return res.join(''); res.append(Values.toString(ctx, ((FunctionValue)replacement).call(ctx, null, args)));
// }, }
else {
res.append(Values.toString(ctx, replacement));
}
lastEnd = end;
if (!pattern.global) break;
}
if (lastEnd < target.length()) {
res.append(target.substring(lastEnd));
}
return res.toString();
}
// [Symbol.search](target, reverse, start) { // [Symbol.search](target, reverse, start) {
// const pattern: RegExp | undefined = new this.constructor(this, this.flags + "g") as RegExp; // const pattern: RegExp | undefined = new this.constructor(this, this.flags + "g") as RegExp;
// if (!reverse) { // if (!reverse) {
@ -258,6 +271,7 @@ import me.topchetoeu.jscript.interop.NativeGetter;
// else return -1; // else return -1;
// } // }
// }, // },
@Native public RegExpLib(Context ctx, Object pattern, Object flags) { @Native public RegExpLib(Context ctx, Object pattern, Object flags) {
this(cleanupPattern(ctx, pattern), cleanupFlags(ctx, flags)); this(cleanupPattern(ctx, pattern), cleanupFlags(ctx, flags));
} }

View File

@ -111,7 +111,7 @@ import me.topchetoeu.jscript.interop.NativeInit;
return lastIndexOf(ctx, passThis(ctx, "includes", thisArg), term, pos) >= 0; return lastIndexOf(ctx, passThis(ctx, "includes", thisArg), term, pos) >= 0;
} }
@Native(thisArg = true) public static String replace(Context ctx, Object thisArg, Object term, String replacement) { @Native(thisArg = true) public static String replace(Context ctx, Object thisArg, Object term, Object replacement) {
var val = passThis(ctx, "replace", thisArg); var val = passThis(ctx, "replace", thisArg);
if (term != null && term != Values.NULL && !(term instanceof String)) { if (term != null && term != Values.NULL && !(term instanceof String)) {
@ -121,9 +121,9 @@ import me.topchetoeu.jscript.interop.NativeInit;
} }
} }
return val.replaceFirst(Pattern.quote(Values.toString(ctx, term)), replacement); return val.replaceFirst(Pattern.quote(Values.toString(ctx, term)), Values.toString(ctx, replacement));
} }
@Native(thisArg = true) public static String replaceAll(Context ctx, Object thisArg, Object term, String replacement) { @Native(thisArg = true) public static String replaceAll(Context ctx, Object thisArg, Object term, Object replacement) {
var val = passThis(ctx, "replaceAll", thisArg); var val = passThis(ctx, "replaceAll", thisArg);
if (term != null && term != Values.NULL && !(term instanceof String)) { if (term != null && term != Values.NULL && !(term instanceof String)) {
@ -133,7 +133,7 @@ import me.topchetoeu.jscript.interop.NativeInit;
} }
} }
return val.replaceFirst(Pattern.quote(Values.toString(ctx, term)), replacement); return val.replaceFirst(Pattern.quote(Values.toString(ctx, term)), Values.toString(ctx, replacement));
} }
@Native(thisArg = true) public static ArrayValue match(Context ctx, Object thisArg, Object term, String replacement) { @Native(thisArg = true) public static ArrayValue match(Context ctx, Object thisArg, Object term, String replacement) {