Skip to content
This repository was archived by the owner on Dec 31, 2024. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
38acc20
refactor: greatly improve Environment API
TopchetoEU Dec 26, 2023
802f2f3
fix: access env via context
TopchetoEU Dec 27, 2023
21534ef
feat: readd FS API via new env API
TopchetoEU Dec 27, 2023
bf38587
feat: readd module API via env API
TopchetoEU Dec 27, 2023
153a1a9
feat: readd permissions API via new env API
TopchetoEU Dec 27, 2023
3343262
fix: main now uses new env API
TopchetoEU Dec 27, 2023
579f09c
fix: pass arguments to regex constructor in LOAD_REGEX
TopchetoEU Dec 27, 2023
aaf9a6f
fix: pass environment to compiler via simple environment wrapper
TopchetoEU Dec 27, 2023
9ea5cd9
refactor: remove old Data API
TopchetoEU Dec 27, 2023
c0b895e
feat: greatly improve Context API
TopchetoEU Dec 27, 2023
d5fd6e6
fix: clean up debugger API
TopchetoEU Dec 27, 2023
d6ee593
refactor: remove unneeded event system
TopchetoEU Dec 27, 2023
c36a0db
refactor: remove more dead code
TopchetoEU Dec 27, 2023
e372941
refactor: generalize Reading class
TopchetoEU Dec 27, 2023
978ee8d
feat: make better native wrapper API
TopchetoEU Dec 28, 2023
a61c6a4
fix: some Argument and Engine API improvements,
TopchetoEU Jan 4, 2024
4fa5f5a
feat: use new wrapper API in libs
TopchetoEU Jan 4, 2024
e575b32
fix: try-catch-finally fix #457846982
TopchetoEU Jan 4, 2024
71f735b
fix: some more libs fixes
TopchetoEU Jan 4, 2024
5f4011a
refactor: move NO_RETURN to Values, remove some casters from Values
TopchetoEU Jan 6, 2024
07a6f18
refactor: some spring cleaning in array lib, fix small issue with join
TopchetoEU Jan 6, 2024
a321fc1
fix: wrong signature of Map.forEach
TopchetoEU Jan 6, 2024
918f262
fix: small issue with sparse arrays
TopchetoEU Jan 6, 2024
4aa757e
fix: Function.bind now passess this argument, instead of the function…
TopchetoEU Jan 6, 2024
2c63477
fix: report proper function name in String.length errors
TopchetoEU Jan 6, 2024
34276d7
fix: remove sparse call arguments
TopchetoEU Jan 6, 2024
45f133c
fix: use Values.call instead of direct calling
TopchetoEU Jan 6, 2024
3173919
fix: implement proper parseInt logic
TopchetoEU Jan 6, 2024
0251c46
fix: use Values to access members in ObjectLib, instead of direct access
TopchetoEU Jan 6, 2024
4572db5
feat: some array tests
TopchetoEU Jan 6, 2024
292ca64
fix: wrong behavior in Number.toString (which somehow broke typescript)
TopchetoEU Jan 6, 2024
c6e6425
fix: bring back ts minification
TopchetoEU Jan 6, 2024
e4c9a87
fix: debugger hanging sometimes
TopchetoEU Jan 6, 2024
d8585a2
refactor: don't require ctx in frame.push
TopchetoEU Jan 6, 2024
72a0d39
fix: make java 11 compatible
TopchetoEU Jan 6, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions build.js
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ async function downloadTypescript(outFile) {
console.log('Minifying typescript...');

const minified = minify((await fs.readFile('tmp/typescript-es5.js')).toString());
// const minified = { code: (await fs.readFile('tmp/typescript-es5.js')).toString() };
if (minified.error) throw minified.error;

// Patch unsupported regex syntax
Expand Down
4 changes: 2 additions & 2 deletions src/assets/js/lib.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -566,7 +566,7 @@ declare class Map<KeyT, ValueT> {

public get size(): number;

public forEach(func: (key: KeyT, val: ValueT, map: Map<KeyT, ValueT>) => void, thisArg?: any): void;
public forEach(func: (val: ValueT, key: KeyT, map: Map<KeyT, ValueT>) => void, thisArg?: any): void;

public constructor();
}
Expand All @@ -585,7 +585,7 @@ declare class Set<T> {

public get size(): number;

public forEach(func: (key: T, set: Set<T>) => void, thisArg?: any): void;
public forEach(func: (key: T, value: T, set: Set<T>) => void, thisArg?: any): void;

public constructor();
}
Expand Down
72 changes: 37 additions & 35 deletions src/me/topchetoeu/jscript/Main.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,42 +8,32 @@
import me.topchetoeu.jscript.engine.Context;
import me.topchetoeu.jscript.engine.Engine;
import me.topchetoeu.jscript.engine.Environment;
import me.topchetoeu.jscript.engine.debug.DebugContext;
import me.topchetoeu.jscript.engine.debug.DebugServer;
import me.topchetoeu.jscript.engine.debug.SimpleDebugger;
import me.topchetoeu.jscript.engine.values.ArrayValue;
import me.topchetoeu.jscript.engine.values.NativeFunction;
import me.topchetoeu.jscript.engine.values.ObjectValue;
import me.topchetoeu.jscript.engine.values.Values;
import me.topchetoeu.jscript.events.Observer;
import me.topchetoeu.jscript.exceptions.EngineException;
import me.topchetoeu.jscript.exceptions.InterruptException;
import me.topchetoeu.jscript.exceptions.SyntaxException;
import me.topchetoeu.jscript.filesystem.Filesystem;
import me.topchetoeu.jscript.filesystem.MemoryFilesystem;
import me.topchetoeu.jscript.filesystem.Mode;
import me.topchetoeu.jscript.filesystem.PhysicalFilesystem;
import me.topchetoeu.jscript.filesystem.RootFilesystem;
import me.topchetoeu.jscript.lib.EnvironmentLib;
import me.topchetoeu.jscript.lib.Internals;
import me.topchetoeu.jscript.modules.ModuleRepo;
import me.topchetoeu.jscript.permissions.PermissionsManager;
import me.topchetoeu.jscript.permissions.PermissionsProvider;

public class Main {
public static class Printer implements Observer<Object> {
public void next(Object data) {
Values.printValue(null, data);
System.out.println();
}

public void error(RuntimeException err) {
Values.printError(err, null);
}

public void finish() {
engineTask.interrupt();
}
}

public class Main {
static Thread engineTask, debugTask;
static Engine engine = new Engine(true);
static Engine engine = new Engine();
static DebugServer debugServer = new DebugServer();
static Environment environment = new Environment(null, null, null);
static Environment environment = new Environment();

static int j = 0;
static boolean exited = false;
Expand All @@ -70,7 +60,7 @@ private static void reader() {
}
for (var i = 0; ; i++) {
try {
var raw = Reading.read();
var raw = Reading.readline();

if (raw == null) break;
var res = engine.pushMsg(
Expand Down Expand Up @@ -104,54 +94,66 @@ private static void reader() {
private static void initEnv() {
environment = Internals.apply(environment);

environment.global.define(false, new NativeFunction("exit", (_ctx, th, args) -> {
environment.global.define(false, new NativeFunction("exit", args -> {
exited = true;
throw new InterruptException();
}));
environment.global.define(false, new NativeFunction("go", (_ctx, th, args) -> {
environment.global.define(false, new NativeFunction("go", args -> {
try {
var f = Path.of("do.js");
var func = _ctx.compile(new Filename("do", "do/" + j++ + ".js"), new String(Files.readAllBytes(f)));
return func.call(_ctx);
var func = args.ctx.compile(new Filename("do", "do/" + j++ + ".js"), new String(Files.readAllBytes(f)));
return func.call(args.ctx);
}
catch (IOException e) {
throw new EngineException("Couldn't open do.js");
}
}));

environment.filesystem.protocols.put("temp", new MemoryFilesystem(Mode.READ_WRITE));
environment.filesystem.protocols.put("file", new PhysicalFilesystem("."));
environment.modules.repos.put("file", ModuleRepo.ofFilesystem(environment.filesystem));
var fs = new RootFilesystem(PermissionsProvider.get(environment));
fs.protocols.put("temp", new MemoryFilesystem(Mode.READ_WRITE));
fs.protocols.put("file", new PhysicalFilesystem("."));

environment.add(PermissionsProvider.ENV_KEY, PermissionsManager.ALL_PERMS);
environment.add(Filesystem.ENV_KEY, fs);
environment.add(ModuleRepo.ENV_KEY, ModuleRepo.ofFilesystem(fs));
}
private static void initEngine() {
debugServer.targets.put("target", (ws, req) -> new SimpleDebugger(ws, engine));
var ctx = new DebugContext();
engine.add(DebugContext.ENV_KEY, ctx);

debugServer.targets.put("target", (ws, req) -> new SimpleDebugger(ws).attach(ctx));
engineTask = engine.start();
debugTask = debugServer.start(new InetSocketAddress("127.0.0.1", 9229), true);
}
private static void initTypescript() {
var tsEnv = Internals.apply(new Environment());
var bsEnv = Internals.apply(new Environment());

try {
var tsEnv = Internals.apply(new Environment(null, null, null));
tsEnv.stackVisible = false;
tsEnv.global.define(null, "module", false, new ObjectValue());
var bsEnv = Internals.apply(new Environment(null, null, null));
bsEnv.stackVisible = false;

engine.pushMsg(
false, tsEnv,
new Filename("jscript", "ts.js"),
Reading.resourceToString("js/ts.js"), null
Reading.resourceToString("assets/js/ts.js"), null
).await();
System.out.println("Loaded typescript!");

var typescript = tsEnv.global.get(new Context(engine, bsEnv), "ts");
var libs = new ArrayValue(null, Reading.resourceToString("assets/js/lib.d.ts"));

engine.pushMsg(
false, bsEnv,
new Filename("jscript", "bootstrap.js"), Reading.resourceToString("js/bootstrap.js"), null,
tsEnv.global.get(new Context(engine, bsEnv), "ts"), environment, new ArrayValue(null, Reading.resourceToString("js/lib.d.ts"))
new Filename("jscript", "bootstrap.js"), Reading.resourceToString("assets/js/bootstrap.js"), null,
typescript, new EnvironmentLib(environment), libs
).await();
}
catch (EngineException e) {
Values.printError(e, "(while initializing TS)");
}

bsEnv.add(Environment.HIDE_STACK, true);
tsEnv.add(Environment.HIDE_STACK, true);
}

public static void main(String args[]) {
Expand Down
6 changes: 0 additions & 6 deletions src/me/topchetoeu/jscript/MessageReceiver.java

This file was deleted.

4 changes: 2 additions & 2 deletions src/me/topchetoeu/jscript/Reading.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
public class Reading {
private static final BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));

public static synchronized String read() throws IOException {
public static synchronized String readline() throws IOException {
return reader.readLine();
}

Expand All @@ -19,7 +19,7 @@ public static String streamToString(InputStream in) {
catch (Throwable e) { throw new UncheckedException(e); }
}
public static InputStream resourceToStream(String name) {
return Reading.class.getResourceAsStream("/assets/" + name);
return Reading.class.getResourceAsStream("/" + name);
}
public static String resourceToString(String name) {
return streamToString(resourceToStream(name));
Expand Down
5 changes: 5 additions & 0 deletions src/me/topchetoeu/jscript/ResultRunnable.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package me.topchetoeu.jscript;

public interface ResultRunnable<T> {
T run();
}
122 changes: 81 additions & 41 deletions src/me/topchetoeu/jscript/engine/Context.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,44 +2,71 @@

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Stack;
import java.util.TreeSet;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;

import me.topchetoeu.jscript.Filename;
import me.topchetoeu.jscript.Location;
import me.topchetoeu.jscript.engine.debug.DebugContext;
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.Symbol;
import me.topchetoeu.jscript.engine.values.Values;
import me.topchetoeu.jscript.exceptions.EngineException;
import me.topchetoeu.jscript.lib.EnvironmentLib;
import me.topchetoeu.jscript.mapping.SourceMap;

public class Context {
private final Stack<Environment> env = new Stack<>();
private final ArrayList<CodeFrame> frames = new ArrayList<>();
public class Context implements Extensions {
public final Context parent;
public final Environment environment;
public final CodeFrame frame;
public final Engine engine;
public final int stackSize;

public Environment environment() {
return env.empty() ? null : env.peek();
@Override public <T> void add(Symbol key, T obj) {
if (environment != null) environment.add(key, obj);
else if (engine != null) engine.add(key, obj);
}
@Override public <T> T get(Symbol key) {
if (environment != null && environment.has(key)) return environment.get(key);
else if (engine != null && engine.has(key)) return engine.get(key);
return null;
}
@Override public boolean has(Symbol key) {
return
environment != null && environment.has(key) ||
engine != null && engine.has(key);
}
@Override public boolean remove(Symbol key) {
var res = false;

if (environment != null) res |= environment.remove(key);
else if (engine != null) res |= engine.remove(key);

private Context pushEnv(Environment env) {
this.env.push(env);
return this;
return res;
}
private void popEnv() {
if (!env.empty()) this.env.pop();
@Override public Iterable<Symbol> keys() {
if (engine == null && environment == null) return List.of();
if (engine == null) return environment.keys();
if (environment == null) return engine.keys();

return () -> Stream.concat(
StreamSupport.stream(engine.keys().spliterator(), false),
StreamSupport.stream(environment.keys().spliterator(), false)
).distinct().iterator();
}

public FunctionValue compile(Filename filename, String raw) {
var env = environment();
var result = env.compile.call(this, null, raw, filename.toString(), env);
var env = environment;
var result = Environment.compileFunc(this).call(this, null, raw, filename.toString(), new EnvironmentLib(env));

var function = (FunctionValue)Values.getMember(this, result, "function");
if (!engine.debugging) return function;
if (!DebugContext.enabled(this)) return function;

var rawMapChain = ((ArrayValue)Values.getMember(this, result, "mapChain")).toArray();
var breakpoints = new TreeSet<>(
Expand All @@ -62,39 +89,41 @@ public FunctionValue compile(Filename filename, String raw) {
breakpoints = newBreakpoints;
}

engine.onSource(filename, raw, breakpoints, map);
DebugContext.get(this).onSource(filename, raw, breakpoints, map);

return function;
}


public void pushFrame(CodeFrame frame) {
frames.add(frame);
if (frames.size() > engine.maxStackFrames) throw EngineException.ofRange("Stack overflow!");
pushEnv(frame.function.environment);
engine.onFramePush(this, frame);
}
public boolean popFrame(CodeFrame frame) {
if (frames.size() == 0) return false;
if (frames.get(frames.size() - 1) != frame) return false;
frames.remove(frames.size() - 1);
popEnv();
engine.onFramePop(this, frame);
return true;
}
public CodeFrame peekFrame() {
if (frames.size() == 0) return null;
return frames.get(frames.size() - 1);
public Context pushFrame(CodeFrame frame) {
var res = new Context(this, frame.function.environment, frame, engine, stackSize + 1);
return res;
}

public List<CodeFrame> frames() {
return Collections.unmodifiableList(frames);
public Iterable<CodeFrame> frames() {
var self = this;
return () -> new Iterator<CodeFrame>() {
private Context curr = self;

private void update() {
while (curr != null && curr.frame == null) curr = curr.parent;
}

@Override public boolean hasNext() {
update();
return curr != null;
}
@Override public CodeFrame next() {
update();
var res = curr.frame;
curr = curr.parent;
return res;
}
};
}
public List<String> stackTrace() {
var res = new ArrayList<String>();

for (var i = frames.size() - 1; i >= 0; i--) {
var el = frames.get(i);
for (var el : frames()) {
var name = el.function.name;
Location loc = null;

Expand All @@ -114,11 +143,22 @@ public List<String> stackTrace() {
return res;
}

public Context(Engine engine) {
private Context(Context parent, Environment environment, CodeFrame frame, Engine engine, int stackSize) {
this.parent = parent;
this.environment = environment;
this.frame = frame;
this.engine = engine;
this.stackSize = stackSize;

if (hasNotNull(Environment.MAX_STACK_COUNT) && stackSize > (int)get(Environment.MAX_STACK_COUNT)) {
throw EngineException.ofRange("Stack overflow!");
}
}

public Context(Engine engine) {
this(null, null, null, engine, 0);
}
public Context(Engine engine, Environment env) {
this(engine);
if (env != null) this.pushEnv(env);
this(null, env, null, engine, 0);
}
}
Loading