fix: include JSON.stringify in polyfills

This commit is contained in:
2023-08-25 11:53:27 +03:00
parent b8b000ddf0
commit bef35ebb1b
5 changed files with 60 additions and 28 deletions

View File

@@ -54,7 +54,7 @@ public class Main {
public static void main(String args[]) {
var in = new BufferedReader(new InputStreamReader(System.in));
engine = new PolyfillEngine(new File("."));
engine = new TypescriptEngine(new File("."));
var scope = engine.global().globalChild();
var exited = new boolean[1];

View File

@@ -2,7 +2,7 @@
var ts = require('./ts__');
log("Loaded typescript!");
var src = '', lib = libs.join(''), decls = '', version = 0;
var src = '', lib = libs.concat([ 'declare const exit: never;' ]).join(''), decls = '', version = 0;
var libSnapshot = ts.ScriptSnapshot.fromString(lib);
var settings = {

View File

@@ -10,31 +10,17 @@ import me.topchetoeu.jscript.parsing.Token;
public class JSON {
public static ParseRes<String> parseIdentifier(List<Token> tokens, int i) {
try {
if (tokens.get(i).isIdentifier()) return ParseRes.res(tokens.get(i).identifier(), 1);
else return ParseRes.failed();
}
catch (IndexOutOfBoundsException e) {
return ParseRes.failed();
}
return Parsing.parseIdentifier(tokens, i);
}
public static ParseRes<String> parseString(String filename, List<Token> tokens, int i) {
try {
if (tokens.get(i).isString()) return ParseRes.res(tokens.get(i).string(), 1);
else return ParseRes.failed();
}
catch (IndexOutOfBoundsException e) {
return ParseRes.failed();
}
var res = Parsing.parseString(filename, tokens, i);
if (res.isSuccess()) return ParseRes.res((String)res.result.value, res.n);
else return res.transform();
}
public static ParseRes<Double> parseNumber(String filename, List<Token> tokens, int i) {
try {
if (tokens.get(i).isNumber()) return ParseRes.res(tokens.get(i).number(), 1);
else return ParseRes.failed();
}
catch (IndexOutOfBoundsException e) {
return ParseRes.failed();
}
var res = Parsing.parseNumber(filename, tokens, i);
if (res.isSuccess()) return ParseRes.res((Double)res.result.value, res.n);
else return res.transform();
}
public static ParseRes<Boolean> parseBool(String filename, List<Token> tokens, int i) {
var id = parseIdentifier(tokens, i);

View File

@@ -10,7 +10,7 @@ public class JSONElement {
MAP,
}
public static JSONElement NULL = new JSONElement(Type.NULL, null);
public static final JSONElement NULL = new JSONElement(Type.NULL, null);
public static JSONElement map(JSONMap val) {
return new JSONElement(Type.MAP, val);

View File

@@ -1,5 +1,7 @@
package me.topchetoeu.jscript.polyfills;
import java.util.HashSet;
import me.topchetoeu.jscript.engine.CallContext;
import me.topchetoeu.jscript.engine.values.ArrayValue;
import me.topchetoeu.jscript.engine.values.ObjectValue;
@@ -8,31 +10,75 @@ import me.topchetoeu.jscript.exceptions.EngineException;
import me.topchetoeu.jscript.exceptions.SyntaxException;
import me.topchetoeu.jscript.interop.Native;
import me.topchetoeu.jscript.json.JSONElement;
import me.topchetoeu.jscript.json.JSONList;
import me.topchetoeu.jscript.json.JSONMap;
public class JSON {
private static Object convert(JSONElement val) {
private static Object toJS(JSONElement val) {
if (val.isBoolean()) return val.bool();
if (val.isString()) return val.string();
if (val.isNumber()) return val.number();
if (val.isList()) return ArrayValue.of(val.list().stream().map(JSON::convert).toList());
if (val.isList()) return ArrayValue.of(val.list().stream().map(JSON::toJS).toList());
if (val.isMap()) {
var res = new ObjectValue();
for (var el : val.map().entrySet()) {
res.defineProperty(el.getKey(), convert(el.getValue()));
res.defineProperty(el.getKey(), toJS(el.getValue()));
}
return res;
}
if (val.isNull()) return Values.NULL;
return null;
}
private static JSONElement toJSON(CallContext ctx, Object val, HashSet<Object> prev) throws InterruptedException {
if (val instanceof Boolean) return JSONElement.bool((boolean)val);
if (val instanceof Number) return JSONElement.number(((Number)val).doubleValue());
if (val instanceof String) return JSONElement.string((String)val);
if (val == Values.NULL) return JSONElement.NULL;
if (val instanceof ObjectValue) {
if (prev.contains(val)) throw new EngineException("Circular dependency in JSON.");
prev.add(val);
var res = new JSONMap();
for (var el : ((ObjectValue)val).keys(false)) {
var jsonEl = toJSON(ctx, ((ObjectValue)val).getMember(ctx, el), prev);
if (jsonEl == null) continue;
if (el instanceof String || el instanceof Number) res.put(el.toString(), jsonEl);
}
prev.remove(val);
return JSONElement.of(res);
}
if (val instanceof ArrayValue) {
if (prev.contains(val)) throw new EngineException("Circular dependency in JSON.");
prev.add(val);
var res = new JSONList();
for (var el : ((ArrayValue)val).toArray()) {
var jsonEl = toJSON(ctx, el, prev);
if (jsonEl == null) jsonEl = JSONElement.NULL;
res.add(jsonEl);
}
prev.remove(val);
return JSONElement.of(res);
}
if (val == null) return null;
return null;
}
@Native
public static Object parse(CallContext ctx, String val) throws InterruptedException {
try {
return convert(me.topchetoeu.jscript.json.JSON.parse("<value>", val));
return toJS(me.topchetoeu.jscript.json.JSON.parse("<value>", val));
}
catch (SyntaxException e) {
throw EngineException.ofSyntax(e.msg);
}
}
@Native
public static String stringify(CallContext ctx, Object val) throws InterruptedException {
return me.topchetoeu.jscript.json.JSON.stringify(toJSON(ctx, val, new HashSet<>()));
}
}