From 8a29a8f8cdfd3a3ac6439e2843483a0a4d0d6240 Mon Sep 17 00:00:00 2001 From: Ari Prakash Date: Thu, 12 Jun 2025 16:22:02 -0400 Subject: [PATCH 1/4] basic skeleton for sending --- src/web/js/trove/world.js | 38 +++++++++++++++++++++++++++++++++----- 1 file changed, 33 insertions(+), 5 deletions(-) diff --git a/src/web/js/trove/world.js b/src/web/js/trove/world.js index 3909b94a..7b87d9f0 100644 --- a/src/web/js/trove/world.js +++ b/src/web/js/trove/world.js @@ -3,7 +3,8 @@ { "import-type": "builtin", "name": "image-lib" }, { "import-type": "builtin", "name": "world-lib" }, { "import-type": "builtin", "name": "valueskeleton" }, - { "import-type": "builtin", "name": "reactors" } + { "import-type": "builtin", "name": "reactors" }, + { "import-type": "builtin", "name": "reactor-events" }, ], nativeRequires: ["pyret-base/js/js-numbers"], provides: { @@ -52,7 +53,7 @@ "WorldConfigOption": ["data", "WorldConfigOption", ["a"], [], {}] } }, - theModule: function(runtime, namespace, uri, imageLibraryLib, rawJsworld, VSlib, reactors, jsnums) { + theModule: function(runtime, namespace, uri, imageLibraryLib, rawJsworld, VSlib, reactors, reactorEvents, jsnums) { var imageLibrary = runtime.getField(imageLibraryLib, "internal"); var isImage = imageLibrary.isImage; var VS = runtime.getField(VSlib, "values"); @@ -153,7 +154,7 @@ }); } - function bigBangFromDict(init, dict, tracer) { + function bigBangFromDict(init, dict, tracer, connector) { var handlers = []; function add(k, constr) { if(dict.hasOwnProperty(k)) { @@ -174,6 +175,11 @@ handlers.push(runtime.makeOpaque(new OnTick(dict["on-tick"], DEFAULT_TICK_DELAY * 1000))); } } + + if (dict.hasOwnProperty["on-recieve-send"]) { + handlers.push(runtime.makeOpaque(new OnRecieveSend(dict["on-recieve-send"], connector))); + } + add("on-mouse", OnMouse); add("on-key", OnKey); add("on-raw-key", OnRawKey); @@ -293,7 +299,7 @@ // NOTE(joe): This expects there to be no active run for runtime // (it should be paused). The run gets paused by pauseStack() in the // call to bigBang, so these runs will all be fresh - var adaptWorldFunction = function(worldFunction) { + var adaptWorldFunction = function(worldFunction, connector) { return function() { // Consumes any number of arguments. var success = arguments[arguments.length - 1]; @@ -312,7 +318,13 @@ { sync: false }, function(result) { if(runtime.isSuccessResult(result)) { - success(result.result); + runtime.ffi.cases(runtime.getField(reactorEvents, "is-SendingHandlerResult"), "SendingHandlerResult", result.result, { + update: success, + send(newState, toSend) { + runtime.getField(connector, "handle-message-return").app(toSend); + success(newState); + } + }); } else { return rawJsworld.shutdown({errorShutdown: result.exn}); @@ -464,6 +476,22 @@ }); }; + class OnRecieveSend extends WorldConfigOption { + constructor(handler, connector) { + super("on-recieve-send"); + this.handler = handler; + this.connector = connector; + } + + toRawHandler(topLevelNode) { + const worldFunction = adaptWorldFunction(this.handler, this.connector); + return rawJsworld.on_message( + (w, message, success) => + worldFunction(w, message, success) + ); + } + } + From 125a60a8a41ee8aabd767eb38e6496ece8b52348 Mon Sep 17 00:00:00 2001 From: Ari Prakash Date: Wed, 23 Jul 2025 11:45:42 -0400 Subject: [PATCH 2/4] handle returned messages from reactor --- src/web/js/trove/world.js | 49 ++++++++++++++++++++++++--------------- 1 file changed, 30 insertions(+), 19 deletions(-) diff --git a/src/web/js/trove/world.js b/src/web/js/trove/world.js index 7b87d9f0..d67ff1e1 100644 --- a/src/web/js/trove/world.js +++ b/src/web/js/trove/world.js @@ -54,6 +54,9 @@ } }, theModule: function(runtime, namespace, uri, imageLibraryLib, rawJsworld, VSlib, reactors, reactorEvents, jsnums) { + var gf = runtime.getField; + var gmf = function(m, f) { return gf(runtime.getField(m, "values"), f); } + var imageLibrary = runtime.getField(imageLibraryLib, "internal"); var isImage = imageLibrary.isImage; var VS = runtime.getField(VSlib, "values"); @@ -315,21 +318,21 @@ return result; }, "big-bang"); }, runtime.namespace, - { sync: false }, - function(result) { - if(runtime.isSuccessResult(result)) { - runtime.ffi.cases(runtime.getField(reactorEvents, "is-SendingHandlerResult"), "SendingHandlerResult", result.result, { - update: success, - send(newState, toSend) { - runtime.getField(connector, "handle-message-return").app(toSend); - success(newState); - } - }); - } - else { - return rawJsworld.shutdown({errorShutdown: result.exn}); - } - }); + { sync: false }, + function(result) { + if(runtime.isSuccessResult(result)) { + runtime.ffi.cases(gmf(reactorEvents, "is-SendingHandlerResult"), "SendingHandlerResult", result.result, { + update: success, + send(newState, toSend) { + runtime.getField(connector, "handle-message-return").app(toSend); + success(newState); + } + }); + } + else { + return rawJsworld.shutdown({errorShutdown: result.exn}); + } + }); }; }; @@ -485,10 +488,18 @@ toRawHandler(topLevelNode) { const worldFunction = adaptWorldFunction(this.handler, this.connector); - return rawJsworld.on_message( - (w, message, success) => - worldFunction(w, message, success) - ); + return { + onRegister(_) { + runtime.safeCall( + runtime.getField(this.connector, "reconnect"), + (_) => + runtime.getField(this.connector, "register-on-message").app(worldFunction) + ) + }, + onUnregister(_) { + runtime.getField(this.connector, "dispose").app(); + }, + }; } } From f8373bce842dedd8bd86269516d1fb0f1b0edcc7 Mon Sep 17 00:00:00 2001 From: Ari Prakash Date: Wed, 23 Jul 2025 11:46:03 -0400 Subject: [PATCH 3/4] update dev server port --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 50386eed..7dfac5ba 100644 --- a/README.md +++ b/README.md @@ -39,7 +39,7 @@ it doesn't need to be terminated across builds), run: $ npm start ``` -The editor will be served from `http://localhost:5000/editor`. +The editor will be served from `http://localhost:4999/editor`. If you edit JavaScript or HTML files in `src/web`, run From 442daba8ebdc76b56f1fdce6381dced783468fec Mon Sep 17 00:00:00 2001 From: Ari Prakash Date: Thu, 24 Jul 2025 20:46:38 -0400 Subject: [PATCH 4/4] move success handing into continuation --- src/web/js/trove/world.js | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/src/web/js/trove/world.js b/src/web/js/trove/world.js index d67ff1e1..7b60e099 100644 --- a/src/web/js/trove/world.js +++ b/src/web/js/trove/world.js @@ -179,8 +179,8 @@ } } - if (dict.hasOwnProperty["on-recieve-send"]) { - handlers.push(runtime.makeOpaque(new OnRecieveSend(dict["on-recieve-send"], connector))); + if (dict.hasOwnProperty["on-receive-send"]) { + handlers.push(runtime.makeOpaque(new OnReceiveSend(dict["on-receive-send"], connector))); } add("on-mouse", OnMouse); @@ -315,22 +315,23 @@ return runtime.safeCall(function() { return worldFunction.app.apply(null, pyretArgs); }, function(result) { - return result; + return runtime.ffi.cases(gmf(reactorEvents, "is-SendingHandlerResult"), "SendingHandlerResult", result.result, { + update: (newState) => newState, + send(newState, toSend) { + return runtime.safeCall( + () => runtime.getField(connector, "handle-message-return").app(toSend), + () => newState + ); + } + }); }, "big-bang"); }, runtime.namespace, { sync: false }, function(result) { - if(runtime.isSuccessResult(result)) { - runtime.ffi.cases(gmf(reactorEvents, "is-SendingHandlerResult"), "SendingHandlerResult", result.result, { - update: success, - send(newState, toSend) { - runtime.getField(connector, "handle-message-return").app(toSend); - success(newState); - } - }); - } - else { + if(!runtime.isSuccessResult(result)) { return rawJsworld.shutdown({errorShutdown: result.exn}); + } else { + return success(result.result); } }); }; @@ -479,9 +480,9 @@ }); }; - class OnRecieveSend extends WorldConfigOption { + class OnReceiveSend extends WorldConfigOption { constructor(handler, connector) { - super("on-recieve-send"); + super("on-receive-send"); this.handler = handler; this.connector = connector; }