diff --git a/src/me/topchetoeu/jscript/Main.java b/src/me/topchetoeu/jscript/Main.java index a603117..8a7edf4 100644 --- a/src/me/topchetoeu/jscript/Main.java +++ b/src/me/topchetoeu/jscript/Main.java @@ -125,7 +125,7 @@ public class Main { engineTask = engine.start(); debugTask = debugServer.start(new InetSocketAddress("127.0.0.1", 9229), true); } - private static void initTypescript() { + private static void initTypescript() throws IOException { var tsEnv = Internals.apply(new Environment()); var bsEnv = Internals.apply(new Environment()); diff --git a/src/me/topchetoeu/jscript/Reading.java b/src/me/topchetoeu/jscript/Reading.java index 7665ffb..7a26cc5 100644 --- a/src/me/topchetoeu/jscript/Reading.java +++ b/src/me/topchetoeu/jscript/Reading.java @@ -4,8 +4,7 @@ import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; - -import me.topchetoeu.jscript.exceptions.UncheckedException; +import java.io.UncheckedIOException; public class Reading { private static final BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); @@ -14,9 +13,16 @@ public class Reading { return reader.readLine(); } + /** + * Reads the given stream to a string + * @param in + * @return + */ public static String streamToString(InputStream in) { - try { return new String(in.readAllBytes()); } - catch (Throwable e) { throw new UncheckedException(e); } + try { + return new String(in.readAllBytes()); + } + catch (IOException e) { throw new UncheckedIOException(e); } } public static InputStream resourceToStream(String name) { return Reading.class.getResourceAsStream("/" + name); diff --git a/src/me/topchetoeu/jscript/engine/debug/DebugHandler.java b/src/me/topchetoeu/jscript/engine/debug/DebugHandler.java index a2ed59f..7ff2b9e 100644 --- a/src/me/topchetoeu/jscript/engine/debug/DebugHandler.java +++ b/src/me/topchetoeu/jscript/engine/debug/DebugHandler.java @@ -1,31 +1,33 @@ package me.topchetoeu.jscript.engine.debug; +import java.io.IOException; + public interface DebugHandler { - void enable(V8Message msg); - void disable(V8Message msg); + void enable(V8Message msg) throws IOException; + void disable(V8Message msg) throws IOException; - void setBreakpointByUrl(V8Message msg); - void removeBreakpoint(V8Message msg); - void continueToLocation(V8Message msg); + void setBreakpointByUrl(V8Message msg) throws IOException; + void removeBreakpoint(V8Message msg) throws IOException; + void continueToLocation(V8Message msg) throws IOException; - void getScriptSource(V8Message msg); - void getPossibleBreakpoints(V8Message msg); + void getScriptSource(V8Message msg) throws IOException; + void getPossibleBreakpoints(V8Message msg) throws IOException; - void resume(V8Message msg); - void pause(V8Message msg); + void resume(V8Message msg) throws IOException; + void pause(V8Message msg) throws IOException; - void stepInto(V8Message msg); - void stepOut(V8Message msg); - void stepOver(V8Message msg); + void stepInto(V8Message msg) throws IOException; + void stepOut(V8Message msg) throws IOException; + void stepOver(V8Message msg) throws IOException; - void setPauseOnExceptions(V8Message msg); + void setPauseOnExceptions(V8Message msg) throws IOException; - void evaluateOnCallFrame(V8Message msg); + void evaluateOnCallFrame(V8Message msg) throws IOException; - void getProperties(V8Message msg); - void releaseObjectGroup(V8Message msg); - void releaseObject(V8Message msg); - void callFunctionOn(V8Message msg); + void getProperties(V8Message msg) throws IOException; + void releaseObjectGroup(V8Message msg) throws IOException; + void releaseObject(V8Message msg) throws IOException; + void callFunctionOn(V8Message msg) throws IOException; - void runtimeEnable(V8Message msg); + void runtimeEnable(V8Message msg) throws IOException; } diff --git a/src/me/topchetoeu/jscript/engine/debug/DebugServer.java b/src/me/topchetoeu/jscript/engine/debug/DebugServer.java index 65247c7..016c1b0 100644 --- a/src/me/topchetoeu/jscript/engine/debug/DebugServer.java +++ b/src/me/topchetoeu/jscript/engine/debug/DebugServer.java @@ -1,6 +1,7 @@ package me.topchetoeu.jscript.engine.debug; import java.io.IOException; +import java.io.UncheckedIOException; import java.net.InetSocketAddress; import java.net.ServerSocket; import java.net.Socket; @@ -13,8 +14,6 @@ import me.topchetoeu.jscript.Reading; import me.topchetoeu.jscript.engine.debug.WebSocketMessage.Type; import me.topchetoeu.jscript.events.Notifier; import me.topchetoeu.jscript.exceptions.SyntaxException; -import me.topchetoeu.jscript.exceptions.UncheckedException; -import me.topchetoeu.jscript.exceptions.UncheckedIOException; import me.topchetoeu.jscript.json.JSON; import me.topchetoeu.jscript.json.JSONList; import me.topchetoeu.jscript.json.JSONMap; @@ -36,8 +35,7 @@ public class DebugServer { try { return MessageDigest.getInstance("sha1"); } - catch (Throwable e) { throw new UncheckedException(e); } - + catch (Throwable e) { throw new RuntimeException(e); } } private static Thread runAsync(Runnable func, String name) { @@ -47,7 +45,7 @@ public class DebugServer { return res; } - private void handle(WebSocket ws, Debugger debugger) { + private void handle(WebSocket ws, Debugger debugger) throws IOException { WebSocketMessage raw; while ((raw = ws.receive()) != null) { @@ -66,53 +64,47 @@ public class DebugServer { return; } - try { - switch (msg.name) { - case "Debugger.enable": - connNotifier.next(); - debugger.enable(msg); - continue; - case "Debugger.disable": debugger.close(); continue; + switch (msg.name) { + case "Debugger.enable": + connNotifier.next(); + debugger.enable(msg); + continue; + case "Debugger.disable": debugger.close(); continue; - case "Debugger.setBreakpointByUrl": debugger.setBreakpointByUrl(msg); continue; - case "Debugger.removeBreakpoint": debugger.removeBreakpoint(msg); continue; - case "Debugger.continueToLocation": debugger.continueToLocation(msg); continue; + case "Debugger.setBreakpointByUrl": debugger.setBreakpointByUrl(msg); continue; + case "Debugger.removeBreakpoint": debugger.removeBreakpoint(msg); continue; + case "Debugger.continueToLocation": debugger.continueToLocation(msg); continue; - case "Debugger.getScriptSource": debugger.getScriptSource(msg); continue; - case "Debugger.getPossibleBreakpoints": debugger.getPossibleBreakpoints(msg); continue; + case "Debugger.getScriptSource": debugger.getScriptSource(msg); continue; + case "Debugger.getPossibleBreakpoints": debugger.getPossibleBreakpoints(msg); continue; - case "Debugger.resume": debugger.resume(msg); continue; - case "Debugger.pause": debugger.pause(msg); continue; + case "Debugger.resume": debugger.resume(msg); continue; + case "Debugger.pause": debugger.pause(msg); continue; - case "Debugger.stepInto": debugger.stepInto(msg); continue; - case "Debugger.stepOut": debugger.stepOut(msg); continue; - case "Debugger.stepOver": debugger.stepOver(msg); continue; + case "Debugger.stepInto": debugger.stepInto(msg); continue; + case "Debugger.stepOut": debugger.stepOut(msg); continue; + case "Debugger.stepOver": debugger.stepOver(msg); continue; - case "Debugger.setPauseOnExceptions": debugger.setPauseOnExceptions(msg); continue; - case "Debugger.evaluateOnCallFrame": debugger.evaluateOnCallFrame(msg); continue; + case "Debugger.setPauseOnExceptions": debugger.setPauseOnExceptions(msg); continue; + case "Debugger.evaluateOnCallFrame": debugger.evaluateOnCallFrame(msg); continue; - case "Runtime.releaseObjectGroup": debugger.releaseObjectGroup(msg); continue; - case "Runtime.releaseObject": debugger.releaseObject(msg); continue; - case "Runtime.getProperties": debugger.getProperties(msg); continue; - case "Runtime.callFunctionOn": debugger.callFunctionOn(msg); continue; - // case "NodeWorker.enable": debugger.nodeWorkerEnable(msg); continue; - case "Runtime.enable": debugger.runtimeEnable(msg); continue; - } - - if ( - msg.name.startsWith("DOM.") || - msg.name.startsWith("DOMDebugger.") || - msg.name.startsWith("Emulation.") || - msg.name.startsWith("Input.") || - msg.name.startsWith("Network.") || - msg.name.startsWith("Page.") - ) ws.send(new V8Error("This isn't a browser...")); - else ws.send(new V8Error("This API is not supported yet.")); - } - catch (Throwable e) { - e.printStackTrace(); - throw new UncheckedException(e); + case "Runtime.releaseObjectGroup": debugger.releaseObjectGroup(msg); continue; + case "Runtime.releaseObject": debugger.releaseObject(msg); continue; + case "Runtime.getProperties": debugger.getProperties(msg); continue; + case "Runtime.callFunctionOn": debugger.callFunctionOn(msg); continue; + // case "NodeWorker.enable": debugger.nodeWorkerEnable(msg); continue; + case "Runtime.enable": debugger.runtimeEnable(msg); continue; } + + if ( + msg.name.startsWith("DOM.") || + msg.name.startsWith("DOMDebugger.") || + msg.name.startsWith("Emulation.") || + msg.name.startsWith("Input.") || + msg.name.startsWith("Network.") || + msg.name.startsWith("Page.") + ) ws.send(new V8Error("This isn't a browser...")); + else ws.send(new V8Error("This API is not supported yet.")); } debugger.close(); @@ -147,8 +139,11 @@ public class DebugServer { runAsync(() -> { try { handle(ws, debugger); } - catch (RuntimeException e) { - ws.send(new V8Error(e.getMessage())); + catch (RuntimeException | IOException e) { + try { + ws.send(new V8Error(e.getMessage())); + } + catch (IOException e2) { /* Shit outta luck */ } } finally { ws.close(); debugger.close(); } }, "Debug Handler"); @@ -239,6 +234,8 @@ public class DebugServer { .replace("${AUTHOR}", Metadata.author()) .getBytes(); } - catch (IOException e) { throw new UncheckedIOException(e); } + catch (IOException e) { + throw new UncheckedIOException(e); + } } } diff --git a/src/me/topchetoeu/jscript/engine/debug/SimpleDebugger.java b/src/me/topchetoeu/jscript/engine/debug/SimpleDebugger.java index 7abefa5..f3e860d 100644 --- a/src/me/topchetoeu/jscript/engine/debug/SimpleDebugger.java +++ b/src/me/topchetoeu/jscript/engine/debug/SimpleDebugger.java @@ -1,5 +1,6 @@ package me.topchetoeu.jscript.engine.debug; +import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; @@ -453,44 +454,74 @@ public class SimpleDebugger implements Debugger { } private void resume(State state) { - this.state = state; - ws.send(new V8Event("Debugger.resumed", new JSONMap())); - updateNotifier.next(); + try { + this.state = state; + ws.send(new V8Event("Debugger.resumed", new JSONMap())); + updateNotifier.next(); + } + catch (IOException e) { + ws.close(); + close(); + } } private void pauseDebug(Context ctx, Breakpoint bp) { - state = State.PAUSED_NORMAL; - var map = new JSONMap() - .set("callFrames", serializeFrames(ctx)) - .set("reason", "debugCommand"); + try { + state = State.PAUSED_NORMAL; + var map = new JSONMap() + .set("callFrames", serializeFrames(ctx)) + .set("reason", "debugCommand"); - if (bp != null) map.set("hitBreakpoints", new JSONList().add(bp.id + "")); - ws.send(new V8Event("Debugger.paused", map)); + if (bp != null) map.set("hitBreakpoints", new JSONList().add(bp.id + "")); + ws.send(new V8Event("Debugger.paused", map)); + } + catch (IOException e) { + ws.close(); + close(); + } } private void pauseException(Context ctx) { - state = State.PAUSED_EXCEPTION; - var map = new JSONMap() - .set("callFrames", serializeFrames(ctx)) - .set("reason", "exception"); + try { + state = State.PAUSED_EXCEPTION; + var map = new JSONMap() + .set("callFrames", serializeFrames(ctx)) + .set("reason", "exception"); - ws.send(new V8Event("Debugger.paused", map)); + ws.send(new V8Event("Debugger.paused", map)); + } + catch (IOException e) { + ws.close(); + close(); + } } - private void sendSource(Source src) { - ws.send(new V8Event("Debugger.scriptParsed", new JSONMap() - .set("scriptId", src.id + "") - .set("hash", src.source.hashCode()) - .set("url", src.filename + "") - )); + private void sendSource(Source src){ + try { + ws.send(new V8Event("Debugger.scriptParsed", new JSONMap() + .set("scriptId", src.id + "") + .set("hash", src.source.hashCode()) + .set("url", src.filename + "") + )); + } + catch (IOException e) { + ws.close(); + close(); + } } private void addBreakpoint(Breakpoint bpt) { - idToBreakpoint.put(bpt.id, bpt); - locToBreakpoint.put(bpt.location, bpt); + try { + idToBreakpoint.put(bpt.id, bpt); + locToBreakpoint.put(bpt.location, bpt); - ws.send(new V8Event("Debugger.breakpointResolved", new JSONMap() - .set("breakpointId", bpt.id) - .set("location", serializeLocation(bpt.location)) - )); + ws.send(new V8Event("Debugger.breakpointResolved", new JSONMap() + .set("breakpointId", bpt.id) + .set("location", serializeLocation(bpt.location)) + )); + } + catch (IOException e) { + ws.close(); + close(); + } } private RunResult run(Frame codeFrame, String code) { @@ -582,7 +613,7 @@ public class SimpleDebugger implements Debugger { return resObj; } - @Override public synchronized void enable(V8Message msg) { + @Override public synchronized void enable(V8Message msg) throws IOException { enabled = true; ws.send(msg.respond()); @@ -591,7 +622,7 @@ public class SimpleDebugger implements Debugger { updateNotifier.next(); } - @Override public synchronized void disable(V8Message msg) { + @Override public synchronized void disable(V8Message msg) throws IOException { close(); ws.send(msg.respond()); } @@ -625,11 +656,11 @@ public class SimpleDebugger implements Debugger { updateNotifier.next(); } - @Override public synchronized void getScriptSource(V8Message msg) { + @Override public synchronized void getScriptSource(V8Message msg) throws IOException { int id = Integer.parseInt(msg.params.string("scriptId")); ws.send(msg.respond(new JSONMap().set("scriptSource", idToSource.get(id).source))); } - @Override public synchronized void getPossibleBreakpoints(V8Message msg) { + @Override public synchronized void getPossibleBreakpoints(V8Message msg) throws IOException { var src = idToSource.get(Integer.parseInt(msg.params.map("start").string("scriptId"))); var start = deserializeLocation(msg.params.get("start"), false); var end = msg.params.isMap("end") ? deserializeLocation(msg.params.get("end"), false) : null; @@ -644,16 +675,16 @@ public class SimpleDebugger implements Debugger { ws.send(msg.respond(new JSONMap().set("locations", res))); } - @Override public synchronized void pause(V8Message msg) { + @Override public synchronized void pause(V8Message msg) throws IOException { pendingPause = true; ws.send(msg.respond()); } - @Override public synchronized void resume(V8Message msg) { + @Override public synchronized void resume(V8Message msg) throws IOException { resume(State.RESUMED); ws.send(msg.respond(new JSONMap())); } - @Override public synchronized void setBreakpointByUrl(V8Message msg) { + @Override public synchronized void setBreakpointByUrl(V8Message msg) throws IOException { var line = (int)msg.params.number("lineNumber") + 1; var col = (int)msg.params.number("columnNumber", 0) + 1; var cond = msg.params.string("condition", "").trim(); @@ -688,7 +719,7 @@ public class SimpleDebugger implements Debugger { .set("locations", locs) )); } - @Override public synchronized void removeBreakpoint(V8Message msg) { + @Override public synchronized void removeBreakpoint(V8Message msg) throws IOException { var id = Integer.parseInt(msg.params.string("breakpointId")); if (idToBptCand.containsKey(id)) { @@ -705,7 +736,7 @@ public class SimpleDebugger implements Debugger { } ws.send(msg.respond()); } - @Override public synchronized void continueToLocation(V8Message msg) { + @Override public synchronized void continueToLocation(V8Message msg) throws IOException { var loc = deserializeLocation(msg.params.get("location"), true); tmpBreakpts.add(loc); @@ -714,7 +745,7 @@ public class SimpleDebugger implements Debugger { ws.send(msg.respond()); } - @Override public synchronized void setPauseOnExceptions(V8Message msg) { + @Override public synchronized void setPauseOnExceptions(V8Message msg) throws IOException { switch (msg.params.string("state")) { case "none": execptionType = CatchType.NONE; break; case "all": execptionType = CatchType.ALL; break; @@ -727,7 +758,7 @@ public class SimpleDebugger implements Debugger { ws.send(msg.respond()); } - @Override public synchronized void stepInto(V8Message msg) { + @Override public synchronized void stepInto(V8Message msg) throws IOException { if (state == State.RESUMED) ws.send(new V8Error("Debugger is resumed.")); else { stepOutFrame = currFrame; @@ -736,7 +767,7 @@ public class SimpleDebugger implements Debugger { ws.send(msg.respond()); } } - @Override public synchronized void stepOut(V8Message msg) { + @Override public synchronized void stepOut(V8Message msg) throws IOException { if (state == State.RESUMED) ws.send(new V8Error("Debugger is resumed.")); else { stepOutFrame = currFrame; @@ -745,7 +776,7 @@ public class SimpleDebugger implements Debugger { ws.send(msg.respond()); } } - @Override public synchronized void stepOver(V8Message msg) { + @Override public synchronized void stepOver(V8Message msg) throws IOException { if (state == State.RESUMED) ws.send(new V8Error("Debugger is resumed.")); else { stepOutFrame = currFrame; @@ -755,7 +786,7 @@ public class SimpleDebugger implements Debugger { } } - @Override public synchronized void evaluateOnCallFrame(V8Message msg) { + @Override public synchronized void evaluateOnCallFrame(V8Message msg) throws IOException { var cfId = Integer.parseInt(msg.params.string("callFrameId")); var expr = msg.params.string("expression"); var group = msg.params.string("objectGroup", null); @@ -769,12 +800,12 @@ public class SimpleDebugger implements Debugger { else ws.send(msg.respond(new JSONMap().set("result", serializeObj(res.ctx, res.result)))); } - @Override public synchronized void releaseObjectGroup(V8Message msg) { + @Override public synchronized void releaseObjectGroup(V8Message msg) throws IOException { var group = msg.params.string("objectGroup"); releaseGroup(group); ws.send(msg.respond()); } - @Override public synchronized void releaseObject(V8Message msg) { + @Override public synchronized void releaseObject(V8Message msg) throws IOException { var id = Integer.parseInt(msg.params.string("objectId")); var ref = idToObject.get(id); ref.held = false; @@ -786,7 +817,7 @@ public class SimpleDebugger implements Debugger { ws.send(msg.respond()); } - @Override public synchronized void getProperties(V8Message msg) { + @Override public synchronized void getProperties(V8Message msg) throws IOException { var ref = idToObject.get(Integer.parseInt(msg.params.string("objectId"))); var obj = ref.obj; @@ -833,7 +864,7 @@ public class SimpleDebugger implements Debugger { ws.send(msg.respond(new JSONMap().set("result", res))); } - @Override public synchronized void callFunctionOn(V8Message msg) { + @Override public synchronized void callFunctionOn(V8Message msg) throws IOException { var src = msg.params.string("functionDeclaration"); var args = msg.params .list("arguments", new JSONList()) @@ -881,7 +912,7 @@ public class SimpleDebugger implements Debugger { catch (EngineException e) { ws.send(msg.respond(new JSONMap().set("exceptionDetails", serializeException(ctx, e)))); } } - @Override public synchronized void runtimeEnable(V8Message msg) { + @Override public synchronized void runtimeEnable(V8Message msg) throws IOException { ws.send(msg.respond()); } @@ -921,7 +952,11 @@ public class SimpleDebugger implements Debugger { if (error != null && (execptionType == CatchType.ALL || execptionType == CatchType.UNCAUGHT && !caught)) { pauseException(ctx); } - else if (loc != null && (state == State.STEPPING_IN || state == State.STEPPING_OVER) && returnVal != Values.NO_RETURN && stepOutFrame == frame) { + else if ( + loc != null && + (state == State.STEPPING_IN || state == State.STEPPING_OVER) && + returnVal != Values.NO_RETURN && stepOutFrame == frame + ) { pauseDebug(ctx, null); } else if (isBreakpointable && locToBreakpoint.containsKey(loc)) { diff --git a/src/me/topchetoeu/jscript/engine/debug/WebSocket.java b/src/me/topchetoeu/jscript/engine/debug/WebSocket.java index ea1eaef..c29e3ae 100644 --- a/src/me/topchetoeu/jscript/engine/debug/WebSocket.java +++ b/src/me/topchetoeu/jscript/engine/debug/WebSocket.java @@ -7,7 +7,6 @@ import java.io.OutputStream; import java.net.Socket; import me.topchetoeu.jscript.engine.debug.WebSocketMessage.Type; -import me.topchetoeu.jscript.exceptions.UncheckedIOException; public class WebSocket implements AutoCloseable { public long maxLength = 1 << 20; @@ -15,109 +14,95 @@ public class WebSocket implements AutoCloseable { private Socket socket; private boolean closed = false; - private OutputStream out() { - try { return socket.getOutputStream(); } - catch (IOException e) { throw new UncheckedIOException(e); } + private OutputStream out() throws IOException { + return socket.getOutputStream(); } - private InputStream in() { - try { return socket.getInputStream(); } - catch (IOException e) { throw new UncheckedIOException(e); } + private InputStream in() throws IOException { + return socket.getInputStream(); } - private long readLen(int byteLen) { + private long readLen(int byteLen) throws IOException { long res = 0; - try { - if (byteLen == 126) { - res |= in().read() << 8; - res |= in().read(); - return res; - } - else if (byteLen == 127) { - res |= in().read() << 56; - res |= in().read() << 48; - res |= in().read() << 40; - res |= in().read() << 32; - res |= in().read() << 24; - res |= in().read() << 16; - res |= in().read() << 8; - res |= in().read(); - return res; - } - else return byteLen; + if (byteLen == 126) { + res |= in().read() << 8; + res |= in().read(); + return res; } - catch (IOException e) { throw new UncheckedIOException(e); } + else if (byteLen == 127) { + res |= in().read() << 56; + res |= in().read() << 48; + res |= in().read() << 40; + res |= in().read() << 32; + res |= in().read() << 24; + res |= in().read() << 16; + res |= in().read() << 8; + res |= in().read(); + return res; + } + else return byteLen; } - private byte[] readMask(boolean has) { + private byte[] readMask(boolean has) throws IOException { if (has) { - try { return new byte[] { + return new byte[] { (byte)in().read(), (byte)in().read(), (byte)in().read(), (byte)in().read() - }; } - catch (IOException e) { throw new UncheckedIOException(e); } + }; } else return new byte[4]; } - private void writeLength(int len) { - try { - if (len < 126) { - out().write((int)len); - } - else if (len <= 0xFFFF) { - out().write(126); - out().write((int)(len >> 8) & 0xFF); - out().write((int)len & 0xFF); - } - else { - out().write(127); - out().write((len >> 56) & 0xFF); - out().write((len >> 48) & 0xFF); - out().write((len >> 40) & 0xFF); - out().write((len >> 32) & 0xFF); - out().write((len >> 24) & 0xFF); - out().write((len >> 16) & 0xFF); - out().write((len >> 8) & 0xFF); - out().write(len & 0xFF); - } + private void writeLength(int len) throws IOException { + if (len < 126) { + out().write((int)len); } - catch (IOException e) { throw new UncheckedIOException(e); } - } - private synchronized void write(int type, byte[] data) { - try { - int i; - - for (i = 0; i < data.length / 0xFFFF; i++) { - out().write(type); - writeLength(0xFFFF); - out().write(data, i * 0xFFFF, 0xFFFF); - type = 0; - } - - out().write(type | 0x80); - writeLength(data.length % 0xFFFF); - out().write(data, i * 0xFFFF, data.length % 0xFFFF); + else if (len <= 0xFFFF) { + out().write(126); + out().write((int)(len >> 8) & 0xFF); + out().write((int)len & 0xFF); } - catch (IOException e) { - throw new UncheckedIOException(e); + else { + out().write(127); + out().write((len >> 56) & 0xFF); + out().write((len >> 48) & 0xFF); + out().write((len >> 40) & 0xFF); + out().write((len >> 32) & 0xFF); + out().write((len >> 24) & 0xFF); + out().write((len >> 16) & 0xFF); + out().write((len >> 8) & 0xFF); + out().write(len & 0xFF); } } + private synchronized void write(int type, byte[] data) throws IOException { + int i; - public void send(String data) { + for (i = 0; i < data.length / 0xFFFF; i++) { + out().write(type); + writeLength(0xFFFF); + out().write(data, i * 0xFFFF, 0xFFFF); + type = 0; + } + + out().write(type | 0x80); + writeLength(data.length % 0xFFFF); + out().write(data, i * 0xFFFF, data.length % 0xFFFF); + } + + public void send(String data) throws IOException { if (closed) throw new IllegalStateException("Object is closed."); write(1, data.getBytes()); } - public void send(byte[] data) { + public void send(byte[] data) throws IOException { if (closed) throw new IllegalStateException("Object is closed."); write(2, data); } - public void send(WebSocketMessage msg) { + public void send(WebSocketMessage msg) throws IOException { if (msg.type == Type.Binary) send(msg.binaryData()); else send(msg.textData()); } - public void send(Object data) { + public void send(Object data) throws IOException { if (closed) throw new IllegalStateException("Object is closed."); write(1, data.toString().getBytes()); } @@ -144,67 +129,59 @@ public class WebSocket implements AutoCloseable { return null; } - private byte[] readData() { - try { - var maskLen = in().read(); - var hasMask = (maskLen & 0x80) != 0; - var len = (int)readLen(maskLen & 0x7F); - var mask = readMask(hasMask); - - if (len > maxLength) fail("WebSocket Error: client exceeded configured max message size"); - else { - var buff = new byte[len]; - - if (in().read(buff) < len) fail("WebSocket Error: payload too short"); - else { - for (int i = 0; i < len; i++) { - buff[i] ^= mask[(int)(i % 4)]; - } - return buff; - } - } + private byte[] readData() throws IOException { + var maskLen = in().read(); + var hasMask = (maskLen & 0x80) != 0; + var len = (int)readLen(maskLen & 0x7F); + var mask = readMask(hasMask); - return null; + if (len > maxLength) fail("WebSocket Error: client exceeded configured max message size"); + else { + var buff = new byte[len]; + + if (in().read(buff) < len) fail("WebSocket Error: payload too short"); + else { + for (int i = 0; i < len; i++) { + buff[i] ^= mask[(int)(i % 4)]; + } + return buff; + } } - catch (IOException e) { throw new UncheckedIOException(e); } + + return null; } - public WebSocketMessage receive() { - try { - var data = new ByteArrayOutputStream(); - var type = 0; + public WebSocketMessage receive() throws IOException { + var data = new ByteArrayOutputStream(); + var type = 0; - while (socket != null && !closed) { - var finId = in().read(); - if (finId < 0) break; - var fin = (finId & 0x80) != 0; - int id = finId & 0x0F; + while (socket != null && !closed) { + var finId = in().read(); + if (finId < 0) break; + var fin = (finId & 0x80) != 0; + int id = finId & 0x0F; - if (id == 0x8) { close(); return null; } - if (id >= 0x8) { - if (!fin) return fail("WebSocket Error: client-sent control frame was fragmented"); - if (id == 0x9) write(0xA, data.toByteArray()); - continue; - } - - if (type == 0) type = id; - if (type == 0) return fail("WebSocket Error: client used opcode 0x00 for first fragment"); - - var buff = readData(); - if (buff == null) break; - - if (data.size() + buff.length > maxLength) return fail("WebSocket Error: client exceeded configured max message size"); - data.write(buff); - - if (!fin) continue; - var raw = data.toByteArray(); - - if (type == 1) return new WebSocketMessage(new String(raw)); - else return new WebSocketMessage(raw); + if (id == 0x8) { close(); return null; } + if (id >= 0x8) { + if (!fin) return fail("WebSocket Error: client-sent control frame was fragmented"); + if (id == 0x9) write(0xA, data.toByteArray()); + continue; } - } - catch (IOException e) { - close(); + + if (type == 0) type = id; + if (type == 0) return fail("WebSocket Error: client used opcode 0x00 for first fragment"); + + var buff = readData(); + if (buff == null) break; + + if (data.size() + buff.length > maxLength) return fail("WebSocket Error: client exceeded configured max message size"); + data.write(buff); + + if (!fin) continue; + var raw = data.toByteArray(); + + if (type == 1) return new WebSocketMessage(new String(raw)); + else return new WebSocketMessage(raw); } return null; diff --git a/src/me/topchetoeu/jscript/engine/values/Values.java b/src/me/topchetoeu/jscript/engine/values/Values.java index a6b3790..5b06a04 100644 --- a/src/me/topchetoeu/jscript/engine/values/Values.java +++ b/src/me/topchetoeu/jscript/engine/values/Values.java @@ -17,7 +17,6 @@ import me.topchetoeu.jscript.engine.frame.ConvertHint; import me.topchetoeu.jscript.exceptions.ConvertException; import me.topchetoeu.jscript.exceptions.EngineException; import me.topchetoeu.jscript.exceptions.SyntaxException; -import me.topchetoeu.jscript.exceptions.UncheckedException; import me.topchetoeu.jscript.lib.PromiseLib; public class Values { @@ -135,7 +134,6 @@ public class Values { if (val instanceof String) { try { return Double.parseDouble((String)val); } catch (NumberFormatException e) { return Double.NaN; } - catch (Throwable e) { throw new UncheckedException(e); } } return Double.NaN; } diff --git a/src/me/topchetoeu/jscript/events/DataNotifier.java b/src/me/topchetoeu/jscript/events/DataNotifier.java index 63f1376..d671ba5 100644 --- a/src/me/topchetoeu/jscript/events/DataNotifier.java +++ b/src/me/topchetoeu/jscript/events/DataNotifier.java @@ -11,9 +11,6 @@ public class DataNotifier implements Awaitable { isErr = true; notifier.next(); } - public void error(Throwable t) { - error(new RuntimeException(t)); - } public void next(T val) { this.val = val; isErr = false; diff --git a/src/me/topchetoeu/jscript/exceptions/UncheckedException.java b/src/me/topchetoeu/jscript/exceptions/UncheckedException.java deleted file mode 100644 index 4e730e7..0000000 --- a/src/me/topchetoeu/jscript/exceptions/UncheckedException.java +++ /dev/null @@ -1,7 +0,0 @@ -package me.topchetoeu.jscript.exceptions; - -public class UncheckedException extends RuntimeException { - public UncheckedException(Throwable err) { - super(err); - } -} diff --git a/src/me/topchetoeu/jscript/exceptions/UncheckedIOException.java b/src/me/topchetoeu/jscript/exceptions/UncheckedIOException.java deleted file mode 100644 index fae7e82..0000000 --- a/src/me/topchetoeu/jscript/exceptions/UncheckedIOException.java +++ /dev/null @@ -1,9 +0,0 @@ -package me.topchetoeu.jscript.exceptions; - -import java.io.IOException; - -public class UncheckedIOException extends RuntimeException { - public UncheckedIOException(IOException e) { - super(e); - } -}