Permissions and filesystems #9

Merged
TopchetoEU merged 36 commits from TopchetoEU/perms-and-fs into master 2023-11-25 18:10:59 +00:00
11 changed files with 75 additions and 107 deletions
Showing only changes of commit b47d1a7576 - Show all commits

View File

@ -1,17 +1,23 @@
package me.topchetoeu.jscript.engine; package me.topchetoeu.jscript.engine;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Stack; import java.util.Stack;
import java.util.TreeSet; 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.values.FunctionValue; import me.topchetoeu.jscript.engine.values.FunctionValue;
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;
import me.topchetoeu.jscript.exceptions.EngineException;
import me.topchetoeu.jscript.parsing.Parsing; import me.topchetoeu.jscript.parsing.Parsing;
public class Context { public class Context {
private final Stack<Environment> env = new Stack<>(); private final Stack<Environment> env = new Stack<>();
private final ArrayList<CodeFrame> frames = new ArrayList<>();
public final Data data; public final Data data;
public final Engine engine; public final Engine engine;
@ -48,16 +54,58 @@ public class Context {
return res; return res;
} }
public Context(Engine engine, Data data) {
this.data = new Data(engine.data); public void pushFrame(CodeFrame frame) {
if (data != null) this.data.addAll(data); frames.add(frame);
if (frames.size() > engine.maxStackFrames) throw EngineException.ofRange("Stack overflow!");
pushEnv(frame.function.environment);
}
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 List<CodeFrame> frames() {
return Collections.unmodifiableList(frames);
}
public List<String> stackTrace() {
var res = new ArrayList<String>();
for (var i = frames.size() - 1; i >= 0; i--) {
var el = frames.get(i);
var name = el.function.name;
Location loc = null;
for (var j = el.codePtr; j >= 0 && loc == null; j--) loc = el.function.body[j].location;
if (loc == null) loc = el.function.loc();
var trace = "";
if (loc != null) trace += "at " + loc.toString() + " ";
if (name != null && !name.equals("")) trace += "in " + name + " ";
trace = trace.trim();
if (!trace.equals("")) res.add(trace);
}
return res;
}
public Context(Engine engine) {
this.data = new Data();
this.engine = engine; this.engine = engine;
} }
public Context(Engine engine) {
this(engine, (Data)null);
}
public Context(Engine engine, Environment env) { public Context(Engine engine, Environment env) {
this(engine, (Data)null); this(engine);
this.pushEnv(env); this.pushEnv(env);
} }

View File

@ -53,17 +53,18 @@ public class Engine implements DebugController {
private static int nextId = 0; private static int nextId = 0;
public static final HashMap<Long, FunctionBody> functions = new HashMap<>(); public static final HashMap<Long, FunctionBody> functions = new HashMap<>();
public final int id = ++nextId;
public final boolean debugging;
public int maxStackFrames = 10000;
private final HashMap<Filename, String> sources = new HashMap<>();
private final HashMap<Filename, TreeSet<Location>> bpts = new HashMap<>();
private DebugController debugger;
private Thread thread; private Thread thread;
private LinkedBlockingDeque<Task> macroTasks = new LinkedBlockingDeque<>(); private LinkedBlockingDeque<Task> macroTasks = new LinkedBlockingDeque<>();
private LinkedBlockingDeque<Task> microTasks = new LinkedBlockingDeque<>(); private LinkedBlockingDeque<Task> microTasks = new LinkedBlockingDeque<>();
public final int id = ++nextId;
public final Data data = new Data().set(StackData.MAX_FRAMES, 10000);
public final boolean debugging;
private final HashMap<Filename, String> sources = new HashMap<>();
private final HashMap<Filename, TreeSet<Location>> bpts = new HashMap<>();
private DebugController debugger;
public boolean attachDebugger(DebugController debugger) { public boolean attachDebugger(DebugController debugger) {
if (!debugging || this.debugger != null) return false; if (!debugging || this.debugger != null) return false;

View File

@ -68,9 +68,6 @@ public class Environment {
return res; return res;
} }
public Context context(Engine engine, Data data) {
return new Context(engine, data).pushEnv(this);
}
public Context context(Engine engine) { public Context context(Engine engine) {
return new Context(engine).pushEnv(this); return new Context(engine).pushEnv(this);
} }

View File

@ -1,66 +0,0 @@
package me.topchetoeu.jscript.engine;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import me.topchetoeu.jscript.Location;
import me.topchetoeu.jscript.engine.debug.Debugger;
import me.topchetoeu.jscript.engine.frame.CodeFrame;
import me.topchetoeu.jscript.exceptions.EngineException;
public class StackData {
public static final DataKey<ArrayList<CodeFrame>> FRAMES = new DataKey<>();
public static final DataKey<Integer> MAX_FRAMES = new DataKey<>();
public static final DataKey<Debugger> DEBUGGER = new DataKey<>();
public static void pushFrame(Context ctx, CodeFrame frame) {
var frames = ctx.data.get(FRAMES, new ArrayList<>());
frames.add(frame);
if (frames.size() > ctx.data.get(MAX_FRAMES, 10000))
throw EngineException.ofRange("Stack overflow!");
ctx.pushEnv(frame.function.environment);
}
public static boolean popFrame(Context ctx, CodeFrame frame) {
var frames = ctx.data.get(FRAMES, new ArrayList<>());
if (frames.size() == 0) return false;
if (frames.get(frames.size() - 1) != frame) return false;
frames.remove(frames.size() - 1);
ctx.popEnv();
ctx.engine.onFramePop(ctx, frame);
return true;
}
public static CodeFrame peekFrame(Context ctx) {
var frames = ctx.data.get(FRAMES, new ArrayList<>());
if (frames.size() == 0) return null;
return frames.get(frames.size() - 1);
}
public static List<CodeFrame> frames(Context ctx) {
return Collections.unmodifiableList(ctx.data.get(FRAMES, new ArrayList<>()));
}
public static List<String> stackTrace(Context ctx) {
var res = new ArrayList<String>();
var frames = frames(ctx);
for (var i = frames.size() - 1; i >= 0; i--) {
var el = frames.get(i);
var name = el.function.name;
Location loc = null;
for (var j = el.codePtr; j >= 0 && loc == null; j--) loc = el.function.body[j].location;
if (loc == null) loc = el.function.loc();
var trace = "";
if (loc != null) trace += "at " + loc.toString() + " ";
if (name != null && !name.equals("")) trace += "in " + name + " ";
trace = trace.trim();
if (!trace.equals("")) res.add(trace);
}
return res;
}
}

View File

@ -15,7 +15,6 @@ import me.topchetoeu.jscript.compilation.Instruction;
import me.topchetoeu.jscript.compilation.Instruction.Type; import me.topchetoeu.jscript.compilation.Instruction.Type;
import me.topchetoeu.jscript.engine.Context; import me.topchetoeu.jscript.engine.Context;
import me.topchetoeu.jscript.engine.Engine; import me.topchetoeu.jscript.engine.Engine;
import me.topchetoeu.jscript.engine.StackData;
import me.topchetoeu.jscript.engine.frame.CodeFrame; import me.topchetoeu.jscript.engine.frame.CodeFrame;
import me.topchetoeu.jscript.engine.frame.Runners; import me.topchetoeu.jscript.engine.frame.Runners;
import me.topchetoeu.jscript.engine.scope.GlobalScope; import me.topchetoeu.jscript.engine.scope.GlobalScope;
@ -187,7 +186,7 @@ public class SimpleDebugger implements Debugger {
} }
private void updateFrames(Context ctx) { private void updateFrames(Context ctx) {
var frame = StackData.peekFrame(ctx); var frame = ctx.peekFrame();
if (frame == null) return; if (frame == null) return;
if (!codeFrameToFrame.containsKey(frame)) { if (!codeFrameToFrame.containsKey(frame)) {
@ -202,7 +201,7 @@ public class SimpleDebugger implements Debugger {
} }
private JSONList serializeFrames(Context ctx) { private JSONList serializeFrames(Context ctx) {
var res = new JSONList(); var res = new JSONList();
var frames = StackData.frames(ctx); var frames = ctx.frames();
for (var i = frames.size() - 1; i >= 0; i--) { for (var i = frames.size() - 1; i >= 0; i--) {
res.add(codeFrameToFrame.get(frames.get(i)).serialized); res.add(codeFrameToFrame.get(frames.get(i)).serialized);
@ -782,7 +781,7 @@ public class SimpleDebugger implements Debugger {
try { idToFrame.remove(codeFrameToFrame.remove(frame).id); } try { idToFrame.remove(codeFrameToFrame.remove(frame).id); }
catch (NullPointerException e) { } catch (NullPointerException e) { }
if (StackData.frames(ctx).size() == 0) resume(State.RESUMED); if (ctx.frames().size() == 0) resume(State.RESUMED);
else if (stepOutFrame != null && stepOutFrame.frame == frame && else if (stepOutFrame != null && stepOutFrame.frame == frame &&
(state == State.STEPPING_OUT || state == State.STEPPING_IN || state == State.STEPPING_OVER) (state == State.STEPPING_OUT || state == State.STEPPING_IN || state == State.STEPPING_OVER)
) { ) {

View File

@ -118,8 +118,6 @@ public class WebSocket implements AutoCloseable {
else send(msg.textData()); else send(msg.textData());
} }
public void send(Object data) { public void send(Object data) {
// TODO: Remove
// System.out.println("SEND: " + data);
if (closed) throw new IllegalStateException("Object is closed."); if (closed) throw new IllegalStateException("Object is closed.");
write(1, data.toString().getBytes()); write(1, data.toString().getBytes());
} }
@ -201,10 +199,6 @@ public class WebSocket implements AutoCloseable {
if (!fin) continue; if (!fin) continue;
var raw = data.toByteArray(); var raw = data.toByteArray();
// TODO: Remove
// System.out.println("RECEIVED: " + new String(raw));
if (type == 1) return new WebSocketMessage(new String(raw)); if (type == 1) return new WebSocketMessage(new String(raw));
else return new WebSocketMessage(raw); else return new WebSocketMessage(raw);
} }

View File

@ -5,7 +5,6 @@ import me.topchetoeu.jscript.compilation.FunctionBody;
import me.topchetoeu.jscript.compilation.Instruction; import me.topchetoeu.jscript.compilation.Instruction;
import me.topchetoeu.jscript.engine.Context; import me.topchetoeu.jscript.engine.Context;
import me.topchetoeu.jscript.engine.Environment; import me.topchetoeu.jscript.engine.Environment;
import me.topchetoeu.jscript.engine.StackData;
import me.topchetoeu.jscript.engine.frame.CodeFrame; import me.topchetoeu.jscript.engine.frame.CodeFrame;
import me.topchetoeu.jscript.engine.frame.Runners; import me.topchetoeu.jscript.engine.frame.Runners;
import me.topchetoeu.jscript.engine.scope.ValueVariable; import me.topchetoeu.jscript.engine.scope.ValueVariable;
@ -35,7 +34,7 @@ public class CodeFunction extends FunctionValue {
public Object call(Context ctx, Object thisArg, Object ...args) { public Object call(Context ctx, Object thisArg, Object ...args) {
var frame = new CodeFrame(ctx, thisArg, args, this); var frame = new CodeFrame(ctx, thisArg, args, this);
try { try {
StackData.pushFrame(ctx, frame); ctx.pushFrame(frame);
while (true) { while (true) {
var res = frame.next(ctx, Runners.NO_RETURN, Runners.NO_RETURN, null); var res = frame.next(ctx, Runners.NO_RETURN, Runners.NO_RETURN, null);
@ -43,7 +42,7 @@ public class CodeFunction extends FunctionValue {
} }
} }
finally { finally {
StackData.popFrame(ctx, frame); ctx.popFrame(frame);
} }
} }

View File

@ -1,7 +1,6 @@
package me.topchetoeu.jscript.lib; package me.topchetoeu.jscript.lib;
import me.topchetoeu.jscript.engine.Context; import me.topchetoeu.jscript.engine.Context;
import me.topchetoeu.jscript.engine.StackData;
import me.topchetoeu.jscript.engine.frame.CodeFrame; import me.topchetoeu.jscript.engine.frame.CodeFrame;
import me.topchetoeu.jscript.engine.frame.Runners; import me.topchetoeu.jscript.engine.frame.Runners;
import me.topchetoeu.jscript.engine.values.CodeFunction; import me.topchetoeu.jscript.engine.values.CodeFunction;
@ -21,7 +20,7 @@ import me.topchetoeu.jscript.interop.Native;
private void next(Context ctx, Object inducedValue, Object inducedError) { private void next(Context ctx, Object inducedValue, Object inducedError) {
Object res = null; Object res = null;
StackData.pushFrame(ctx, frame); ctx.pushFrame(frame);
ctx.pushEnv(frame.function.environment); ctx.pushEnv(frame.function.environment);
awaiting = false; awaiting = false;
@ -40,7 +39,7 @@ import me.topchetoeu.jscript.interop.Native;
} }
} }
StackData.popFrame(ctx, frame); ctx.popFrame(frame);
if (awaiting) { if (awaiting) {
PromiseLib.then(ctx, frame.pop(), new NativeFunction(this::fulfill), new NativeFunction(this::reject)); PromiseLib.then(ctx, frame.pop(), new NativeFunction(this::fulfill), new NativeFunction(this::reject));

View File

@ -3,7 +3,6 @@ package me.topchetoeu.jscript.lib;
import java.util.Map; import java.util.Map;
import me.topchetoeu.jscript.engine.Context; import me.topchetoeu.jscript.engine.Context;
import me.topchetoeu.jscript.engine.StackData;
import me.topchetoeu.jscript.engine.frame.CodeFrame; import me.topchetoeu.jscript.engine.frame.CodeFrame;
import me.topchetoeu.jscript.engine.frame.Runners; import me.topchetoeu.jscript.engine.frame.Runners;
import me.topchetoeu.jscript.engine.values.NativeFunction; import me.topchetoeu.jscript.engine.values.NativeFunction;
@ -29,7 +28,7 @@ import me.topchetoeu.jscript.interop.Native;
} }
Object res = null; Object res = null;
StackData.pushFrame(ctx, frame); ctx.pushFrame(frame);
state = 0; state = 0;
while (state == 0) { while (state == 0) {
@ -50,7 +49,7 @@ import me.topchetoeu.jscript.interop.Native;
} }
} }
StackData.popFrame(ctx, frame); ctx.popFrame(frame);
if (state == 1) { if (state == 1) {
PromiseLib.then(ctx, frame.pop(), new NativeFunction(this::fulfill), new NativeFunction(this::reject)); PromiseLib.then(ctx, frame.pop(), new NativeFunction(this::fulfill), new NativeFunction(this::reject));

View File

@ -2,7 +2,6 @@ package me.topchetoeu.jscript.lib;
import me.topchetoeu.jscript.engine.Context; import me.topchetoeu.jscript.engine.Context;
import me.topchetoeu.jscript.engine.Environment; import me.topchetoeu.jscript.engine.Environment;
import me.topchetoeu.jscript.engine.StackData;
import me.topchetoeu.jscript.engine.values.ArrayValue; import me.topchetoeu.jscript.engine.values.ArrayValue;
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;
@ -51,7 +50,7 @@ import me.topchetoeu.jscript.interop.NativeInit;
var target = new ObjectValue(); var target = new ObjectValue();
if (thisArg instanceof ObjectValue) target = (ObjectValue)thisArg; if (thisArg instanceof ObjectValue) target = (ObjectValue)thisArg;
target.defineProperty(ctx, "stack", ArrayValue.of(ctx, StackData.stackTrace(ctx))); target.defineProperty(ctx, "stack", ArrayValue.of(ctx, ctx.stackTrace()));
target.defineProperty(ctx, "name", "Error"); target.defineProperty(ctx, "name", "Error");
if (message == null) target.defineProperty(ctx, "message", ""); if (message == null) target.defineProperty(ctx, "message", "");
else target.defineProperty(ctx, "message", Values.toString(ctx, message)); else target.defineProperty(ctx, "message", Values.toString(ctx, message));

View File

@ -1,7 +1,6 @@
package me.topchetoeu.jscript.lib; package me.topchetoeu.jscript.lib;
import me.topchetoeu.jscript.engine.Context; import me.topchetoeu.jscript.engine.Context;
import me.topchetoeu.jscript.engine.StackData;
import me.topchetoeu.jscript.engine.frame.CodeFrame; import me.topchetoeu.jscript.engine.frame.CodeFrame;
import me.topchetoeu.jscript.engine.frame.Runners; import me.topchetoeu.jscript.engine.frame.Runners;
import me.topchetoeu.jscript.engine.values.ObjectValue; import me.topchetoeu.jscript.engine.values.ObjectValue;
@ -25,7 +24,7 @@ import me.topchetoeu.jscript.interop.Native;
} }
Object res = null; Object res = null;
StackData.pushFrame(ctx, frame); ctx.pushFrame(frame);
yielding = false; yielding = false;
while (!yielding) { while (!yielding) {
@ -43,7 +42,7 @@ import me.topchetoeu.jscript.interop.Native;
} }
} }
StackData.popFrame(ctx, frame); ctx.popFrame(frame);
if (done) frame = null; if (done) frame = null;
else res = frame.pop(); else res = frame.pop();