Progress report!Here's what works so far:All Sphere v1 and v2 APIsCellES6 syntax, no transpilation requiredES6 built-ins, no polyfill requiredES6 modules!ES2017 async functions (!!)require() can load ES modulesSTILL backward compatible with Sphere 1.x games Here's what doesn't:File and line information on the error screen. SpheRun does show a stack trace after a crash, however.SSj and SSj BlueLinux support; it crashes under VirtualBox at leastGetting require() to be able to load modules was important, as without that ability, transpiled code doesn't work, and backward compatibility is lost. Both Babel and TypeScript transpile import statements to require() calls.
Thread 12 Crashed:0 libsystem_c.dylib 0x00007fffb5df5b52 strlen + 181 spheredev.miniSphere 0x0000000106c6aaf7 jsal_push_new_error_va + 16 (jsal.c:1000)2 spheredev.miniSphere 0x0000000106c5b048 jsal_error_blame + 160 (api.c:308)3 spheredev.miniSphere 0x0000000106c8a39d js_RequireScript + 77 (vanilla.c:5054)4 spheredev.miniSphere 0x0000000106c6bbcc do_native_call + 447 (jsal.c:1820)5 spheredev.miniSphere 0x00000001073d01c7 Js::JavascriptExternalFunction::StdCallExternalFunctionThunk(Js::RecyclableObject*, Js::CallInfo, ...) + 1996 spheredev.miniSphere 0x00000001075257ae amd64_CallFunction + 787 spheredev.miniSphere 0x00000001072eb130 void Js::InterpreterStackFrame::OP_CallCommon<Js::OpLayoutT_CallIFlags<Js::LayoutSizePolicy<(Js::LayoutSize)0> > >(Js::OpLayoutT_CallIFlags<Js::LayoutSizePolicy<(Js::LayoutSize)0> > const*, Js::RecyclableObject*, unsigned int, Js::AuxArray<unsigned int> const*) + 3048 spheredev.miniSphere 0x000000010728e58d Js::InterpreterStackFrame::ProcessUnprofiled() + 135659 spheredev.miniSphere 0x000000010727f28f Js::InterpreterStackFrame::Process() + 46310 spheredev.miniSphere 0x000000010727e912 Js::InterpreterStackFrame::InterpreterHelper(Js::ScriptFunction*, Js::ArgumentReader, void*, void*, Js::InterpreterStackFrame::AsmJsReturnStruct*) + 113811 spheredev.miniSphere 0x000000010727e48d Js::InterpreterStackFrame::InterpreterThunk(Js::JavascriptCallStackLayout*) + 9312 ??? 0x000000010f740132 0 + 455422801813 spheredev.miniSphere 0x00000001075257ae amd64_CallFunction + 7814 spheredev.miniSphere 0x00000001073d2c1b Js::JavascriptFunction::CallRootFunction(Js::Arguments, Js::ScriptContext*, bool) + 2715 spheredev.miniSphere 0x0000000106eb674f JsCallFunction + 73516 spheredev.miniSphere 0x0000000106c6a4ca jsal_call_method + 166 (jsal.c:199)17 spheredev.miniSphere 0x0000000106c6a39a jsal_call + 53 (jsal.c:178)18 spheredev.miniSphere 0x0000000106c6cb9e jsal_try_call + 74 (jsal.c:1525)19 spheredev.miniSphere 0x0000000106c7c764 script_eval + 215 (script.c:99)20 spheredev.miniSphere 0x0000000106c6d82a _al_mangled_main + 2505 (main.c:274)21 spheredev.miniSphere 0x0000000106de4326 +[AllegroAppDelegate app_main:] + 2322 com.apple.Foundation 0x00007fffa20628ad __NSThread__start__ + 124323 libsystem_pthread.dylib 0x00007fffb5fd893b _pthread_body + 18024 libsystem_pthread.dylib 0x00007fffb5fd8887 _pthread_start + 28625 libsystem_pthread.dylib 0x00007fffb5fd808d thread_start + 13
The problem is that there's seemingly no access to the module's exports from the native side--so there's nothing to latch onto.
With Chakra included this Sphere is no longer mini, the app I've just built is 42mb. (I note it's probably possible to optimise it down a bit for size but I don't know how much and I wonder if the CC enabled version may end up needing a different name...)
There's no way to do it natively via some kind of shim? This seems like it would be a definite deal breaker
import * as Module from "<module filename>"global.___exports = Module;
4205 malloc.c: No such file or directory.(gdb) backtrace#0 malloc_consolidate (av=av@entry=0x7ffff64a7b00 <main_arena>) at malloc.c:4205#1 0x00007ffff6186dca in _int_malloc (av=av@entry=0x7ffff64a7b00 <main_arena>, bytes=bytes@entry=4096) at malloc.c:3488#2 0x00007ffff6188f34 in __GI___libc_malloc (bytes=4096) at malloc.c:2928#3 0x00007ffff6c9d5d1 in ?? () from /usr/lib/x86_64-linux-gnu/liballegro.so.5.2#4 0x00007ffff6c9e212 in al_create_bitmap () from /usr/lib/x86_64-linux-gnu/liballegro.so.5.2#5 0x00007ffff6c9eb35 in al_clone_bitmap () from /usr/lib/x86_64-linux-gnu/liballegro.so.5.2#6 0x00007ffff6ca2cc8 in al_convert_bitmap () from /usr/lib/x86_64-linux-gnu/liballegro.so.5.2#7 0x00007ffff6ca321b in _al_convert_to_memory_bitmap () from /usr/lib/x86_64-linux-gnu/liballegro.so.5.2#8 0x00007ffff6d08c80 in ?? () from /usr/lib/x86_64-linux-gnu/liballegro.so.5.2#9 0x00005555555d969e in screen_free (it=0x555555913ea0) at src/minisphere/screen.c:146#10 0x0000555555568327 in shutdown_engine () at src/minisphere/main.c:484#11 0x000055555555e4c8 in main (argc=<optimized out>, argv=<optimized out>) at src/minisphere/main.c:167
*** Error in `/usr/bin/minisphere': corrupted size vs. prev_size: 0x00005555564aec5f ***
export default const Module = require("<filename>");
I can't understand the benefit of an ES17 async functions - possibly as I've never written web javascript.I similarly don't understand the benefit of promises, unless they're to do with working with working in a browser event loop?
async function downloadHugeFile(url){ SSj.log(`starting to download ${url}...`); await downloadFile(url); // yields to event loop SSj.log("download complete!");}
Quote from: Rhuan on August 30, 2017, 05:41:54 pmI can't understand the benefit of an ES17 async functions - possibly as I've never written web javascript.I similarly don't understand the benefit of promises, unless they're to do with working with working in a browser event loop?They're not too useful in Sphere--yet. They can be very useful if you have APIs that do stuff in the background, though, for example downloading files. Suppose you have an operation that needs to download a file but can't do anything until the file is complete, however you want your game to continue running as normal. You could implement that as an async function:Code: (javascript) [Select]async function downloadHugeFile(url){ SSj.log(`starting to download ${url}...`); await downloadFile(url); // yields to event loop SSj.log("download complete!");}The hypothetical downloadFile() function would return a promise that it resolves when the download is complete, after which point execution continues right after the await.Notes:async () => 812 is shorthand for: () => Promise.resolve(812);await x() is shorthand for: x().then(retval => { /*everything after the await*/ })Sphere has an event loop as well; in Sphere v1 you invoke it manually by calling FlipScreen(). Sphere v2 has a real, Node-like event loop that runs as long as there's something in the Dispatch queue.
initializing Allegro 5.2.2.0initializing Dyad 0.2.0initializing JavaScriptinitializing dispatch managerinitializing Galileo subsysteminitializing audio subsysteminitializing input subsystemopening kevfile #0 `#/miniSphere.conf` `#/miniSphere.conf` doesn't existreading key `keymap_Player1_MENU` from kevfile #0SNIP - removed numerous lines about loading keysreading key `keymap_Player4_Y` from kevfile #0disposing kevfile #0 no longer in useinitializing sockets subsystem Dyad.c 0.2.0initializing spriteset managerinitializing map engine subsystemcreating new mixer #1 at 44 kHz format: 2ch 44100 Hz, 16-bitinitializing JS script managerinitializing legacy support moduleopening kevfile #1 `#/system.ini`reading key `Font` from kevfile #1loading font #0 as `#/system.rfn`creating image #0 at 128x192creating image #1 as 8x12 subimage of image #0SNIP - removed numerous lines about creating subimages of image #0creating image #256 as 8x12 subimage of image #0reading key `WindowStyle` from kevfile #1reading 16x16 image #257 from open filereading 16x16 image #258 from open filereading 16x16 image #259 from open filereading 16x16 image #260 from open filereading 16x16 image #261 from open filereading 16x16 image #262 from open filereading 16x16 image #263 from open filereading 16x16 image #264 from open filereading 16x16 image #265 from open filereading key `Arrow` from kevfile #1loading image #266 as `#/pointer.png`reading key `UpArrow` from kevfile #1loading image #267 as `#/up_arrow.png`reading key `DownArrow` from kevfile #1loading image #268 as `#/down_arrow.png`disposing kevfile #1 no longer in usesetting up jump points for longjmpsearching for a game to launchopening `/Xdevelopment/startup/game.sgm` from game #1opening package #1 `/Xdevelopment/startup/game.sgm`failed to open package #1opening kevfile #2 `@/game.sgm`parsing SGM manifest for game #1reading key `name` from kevfile #2reading key `author` from kevfile #2reading key `description` from kevfile #2reading key `screen_width` from kevfile #2reading key `screen_height` from kevfile #2reading key `script` from kevfile #2disposing kevfile #2 no longer in use title: Startup author: tunginobi resolution: 320x240 save ID: (null)loading image #269 as `@/icon.png` failed to load image #269loading image #270 as `#/icon.png`initializing render context at 320x240creating image #271 at 320x240cloning image #272 from source image #2702017-08-31 18:17:17.628 minisphere[22798:1702920] void * _Nullable NSMapGet(NSMapTable * _Nonnull, const void * _Nullable): map table argument is NULLactivating legacy shadersopening kevfile #3 `@/keymap.conf` `@/keymap.conf` doesn't existreading key `keymap_Player1_MENU` from kevfile #3SNIP - removed numerous lines about reading keysreading key `keymap_Player4_Y` from kevfile #3disposing kevfile #3 no longer in useinitializing Sphere v1 API (v2.0)creating new mixer #2 at 44 kHz format: 2ch 44100 Hz, 16-bitinitializing Sphere v2 L0 APIcreating new mixer #3 at 44 kHz format: 2ch 44100 Hz, 16-bitloading system default fontGAME CRASH: uncaught JavaScript exception.)
If I understand this correctly, the downloadFile function would be run in a seperate thread and the second SSj.log call would take place in the event loop when the second thread reported that the file was downloaded?In other words this allows you to make non-blocking api calls and have specific functions pause until the api call is complete then resume BUT other JS execution continues during the pause?I can't really think of anything in the Sphere v1 or v2 apis that would benefit from being called in that way, if I could call another JS function with await in front of it rather than an api funciton that could be amazing but based on my reading of it it doesn't work that way.
import { Pact } from 'sphere-runtime';var pact = new Pact();var downloads = [];function downloadFile(){ let socket = new Socket(url, 80); let promise = pact.promise(); downloads.push({ socket, promise }); return promise;}Dispatch.onUpdate(() => { for (let dl of downloads) { allData += dl.socket.read(dl.socket.bytesPending); if (downloadIsFinished) { // whatever criteria for when a download is done pact.resolve(dl.promise, allData); } }});
async function loadInBackground(){ SSj.log("loading..."); let downloadedData = await downloadFile("whatever"); SSj.log("finished loading!");}