From bef35ebb1bc9a4e31d0db53fac6abb33e591b734 Mon Sep 17 00:00:00 2001 From: TopchetoEU <36534413+TopchetoEU@users.noreply.github.com> Date: Fri, 25 Aug 2023 11:53:27 +0300 Subject: [PATCH] fix: include JSON.stringify in polyfills --- src/me/topchetoeu/jscript/Main.java | 2 +- src/me/topchetoeu/jscript/js/bootstrap.js | 2 +- src/me/topchetoeu/jscript/json/JSON.java | 28 +++------- .../topchetoeu/jscript/json/JSONElement.java | 2 +- src/me/topchetoeu/jscript/polyfills/JSON.java | 54 +++++++++++++++++-- 5 files changed, 60 insertions(+), 28 deletions(-) diff --git a/src/me/topchetoeu/jscript/Main.java b/src/me/topchetoeu/jscript/Main.java index aa92604..34a2426 100644 --- a/src/me/topchetoeu/jscript/Main.java +++ b/src/me/topchetoeu/jscript/Main.java @@ -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]; diff --git a/src/me/topchetoeu/jscript/js/bootstrap.js b/src/me/topchetoeu/jscript/js/bootstrap.js index 2cf9d29..3d87c49 100644 --- a/src/me/topchetoeu/jscript/js/bootstrap.js +++ b/src/me/topchetoeu/jscript/js/bootstrap.js @@ -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 = { diff --git a/src/me/topchetoeu/jscript/json/JSON.java b/src/me/topchetoeu/jscript/json/JSON.java index 3edfe7c..0df53d5 100644 --- a/src/me/topchetoeu/jscript/json/JSON.java +++ b/src/me/topchetoeu/jscript/json/JSON.java @@ -10,31 +10,17 @@ import me.topchetoeu.jscript.parsing.Token; public class JSON { public static ParseRes parseIdentifier(List 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 parseString(String filename, List 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 parseNumber(String filename, List 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 parseBool(String filename, List tokens, int i) { var id = parseIdentifier(tokens, i); diff --git a/src/me/topchetoeu/jscript/json/JSONElement.java b/src/me/topchetoeu/jscript/json/JSONElement.java index 16aef1b..e26aa3a 100644 --- a/src/me/topchetoeu/jscript/json/JSONElement.java +++ b/src/me/topchetoeu/jscript/json/JSONElement.java @@ -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); diff --git a/src/me/topchetoeu/jscript/polyfills/JSON.java b/src/me/topchetoeu/jscript/polyfills/JSON.java index 953e17c..34fcdd1 100644 --- a/src/me/topchetoeu/jscript/polyfills/JSON.java +++ b/src/me/topchetoeu/jscript/polyfills/JSON.java @@ -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 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("", val)); + return toJS(me.topchetoeu.jscript.json.JSON.parse("", 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<>())); + } }