diff --git a/CMakeLists.txt b/CMakeLists.txt index 4fbd0e3..4b756f9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -313,6 +313,7 @@ link_bare_module(bare bare-hrtime) link_bare_module(bare bare-inspect) link_bare_module(bare bare-module) link_bare_module(bare bare-os) +link_bare_module(bare bare-structured-clone) link_bare_module(bare bare-timers) link_bare_module(bare bare-url) diff --git a/README.md b/README.md index 76431ae..4a5b765 100644 --- a/README.md +++ b/README.md @@ -180,7 +180,7 @@ Options include: ```js { // Optional data to pass to the thread - data: Buffer | ArrayBuffer | SharedArrayBuffer | External, + data: null, // Optional file source, will be read from `filename` if neither `source` nor `callback` are provided source: string | Buffer, // Optional source encoding if `source` is a string diff --git a/package-lock.json b/package-lock.json index 80b4a58..3614c89 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17,6 +17,7 @@ "bare-os": "^2.0.0", "bare-path": "^2.0.0", "bare-repl": "^1.0.0", + "bare-structured-clone": "^1.0.1", "bare-timers": "^2.0.0", "bare-tty": "^3.0.0", "bare-url": "^1.0.0", @@ -558,6 +559,16 @@ "streamx": "^2.15.0" } }, + "node_modules/bare-structured-clone": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/bare-structured-clone/-/bare-structured-clone-1.0.1.tgz", + "integrity": "sha512-12J7XJXbgwMHQyAxOHqEU0orVKcasew0V5Puaz7nSciJpFDu900FEu6eogaYZ2VJPFfzvOtE9idMu44i2V9PAQ==", + "dependencies": { + "bits-to-bytes": "^1.3.0", + "compact-encoding": "^2.15.0", + "compact-encoding-bitfield": "^1.0.0" + } + }, "node_modules/bare-timers": { "version": "2.0.9", "resolved": "https://registry.npmjs.org/bare-timers/-/bare-timers-2.0.9.tgz", @@ -584,6 +595,14 @@ "safety-catch": "^1.0.2" } }, + "node_modules/bits-to-bytes": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/bits-to-bytes/-/bits-to-bytes-1.3.0.tgz", + "integrity": "sha512-OJoHTpFXS9bXHBCekGTByf3MqM8CGblBDIduKQeeVVeiU9dDWywSSirXIBYGgg3d1zbVuvnMa1vD4r6PA0kOKg==", + "dependencies": { + "b4a": "^1.5.0" + } + }, "node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -685,6 +704,22 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, + "node_modules/compact-encoding": { + "version": "2.15.0", + "resolved": "https://registry.npmjs.org/compact-encoding/-/compact-encoding-2.15.0.tgz", + "integrity": "sha512-af/NomxL9Mo0lqCk++rxLLDZI+lJqeBrPt4dK6FbjxTCEhfC9yQAIoO6yq9ixyCirce0luQwErkwJrhem6clxA==", + "dependencies": { + "b4a": "^1.3.0" + } + }, + "node_modules/compact-encoding-bitfield": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/compact-encoding-bitfield/-/compact-encoding-bitfield-1.0.0.tgz", + "integrity": "sha512-3nMVKUg+PF72UHfainmCL8uKvyWfxsjqOtUY+HiMPGLPCTjnwzoKfFAMo1Ad7nwTPdjBqtGK5b3BOFTFW4EBTg==", + "dependencies": { + "compact-encoding": "^2.4.1" + } + }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", diff --git a/package.json b/package.json index 064290e..55dd031 100644 --- a/package.json +++ b/package.json @@ -26,6 +26,7 @@ "bare-os": "^2.0.0", "bare-path": "^2.0.0", "bare-repl": "^1.0.0", + "bare-structured-clone": "^1.0.1", "bare-timers": "^2.0.0", "bare-tty": "^3.0.0", "bare-url": "^1.0.0", diff --git a/src/bare.js b/src/bare.js index 5e102db..d691b88 100644 --- a/src/bare.js +++ b/src/bare.js @@ -17,25 +17,28 @@ bare.addon = function addon (specifier) { // statically resolvable to allow them to be included by the bundler. switch (specifier) { case '/node_modules/bare-buffer/': - pkg = require('bare-buffer/package.json') + pkg = require('bare-buffer/package') break case '/node_modules/bare-timers/': - pkg = require('bare-timers/package.json') + pkg = require('bare-timers/package') break case '/node_modules/bare-inspect/': - pkg = require('bare-inspect/package.json') + pkg = require('bare-inspect/package') break case '/node_modules/bare-hrtime/': - pkg = require('bare-hrtime/package.json') + pkg = require('bare-hrtime/package') break case '/node_modules/bare-os/': - pkg = require('bare-os/package.json') + pkg = require('bare-os/package') + break + case '/node_modules/bare-structured-clone/': + pkg = require('bare-structured-clone/package') break case '/node_modules/bare-url/': - pkg = require('bare-url/package.json') + pkg = require('bare-url/package') break case '/node_modules/bare-module/': - pkg = require('bare-module/package.json') + pkg = require('bare-module/package') break default: throw new Error(`Unknown addon '${specifier}'`) @@ -177,6 +180,10 @@ class Bare extends EventEmitter { this.emit('resume') } + _onthread (data) { + exports.Thread.self._ondata(data) + } + [Symbol.for('bare.inspect')] () { return { __proto__: { constructor: Bare }, @@ -243,6 +250,7 @@ bare.onteardown = exports._onteardown.bind(exports) bare.onsuspend = exports._onsuspend.bind(exports) bare.onidle = exports._onidle.bind(exports) bare.onresume = exports._onresume.bind(exports) +bare.onthread = exports._onthread.bind(exports) /** * Step 8: diff --git a/src/runtime.c b/src/runtime.c index 592dd19..2c93dca 100644 --- a/src/runtime.c +++ b/src/runtime.c @@ -151,17 +151,11 @@ bare_runtime_on_before_exit (bare_runtime_t *runtime) { err = js_get_named_property(env, exports, "onbeforeexit", &fn); assert(err == 0); - bool is_set; - err = js_is_function(env, fn, &is_set); + js_value_t *global; + err = js_get_global(env, &global); assert(err == 0); - if (is_set) { - js_value_t *global; - err = js_get_global(env, &global); - assert(err == 0); - - js_call_function(env, global, fn, 0, NULL, NULL); - } + js_call_function(env, global, fn, 0, NULL, NULL); err = js_close_handle_scope(env, scope); assert(err == 0); @@ -193,17 +187,11 @@ bare_runtime_on_exit (bare_runtime_t *runtime) { err = js_get_named_property(env, exports, "onexit", &fn); assert(err == 0); - bool is_set; - err = js_is_function(env, fn, &is_set); + js_value_t *global; + err = js_get_global(env, &global); assert(err == 0); - if (is_set) { - js_value_t *global; - err = js_get_global(env, &global); - assert(err == 0); - - js_call_function(env, global, fn, 0, NULL, NULL); - } + js_call_function(env, global, fn, 0, NULL, NULL); err = js_close_handle_scope(env, scope); assert(err == 0); @@ -235,17 +223,11 @@ bare_runtime_on_teardown (bare_runtime_t *runtime, int *exit_code) { err = js_get_named_property(env, exports, "onteardown", &fn); assert(err == 0); - bool is_set; - err = js_is_function(env, fn, &is_set); + js_value_t *global; + err = js_get_global(env, &global); assert(err == 0); - if (is_set) { - js_value_t *global; - err = js_get_global(env, &global); - assert(err == 0); - - js_call_function(env, global, fn, 0, NULL, NULL); - } + js_call_function(env, global, fn, 0, NULL, NULL); if (exit_code) { js_value_t *val; @@ -284,17 +266,11 @@ bare_runtime_on_suspend (bare_runtime_t *runtime) { err = js_get_named_property(env, exports, "onsuspend", &fn); assert(err == 0); - bool is_set; - err = js_is_function(env, fn, &is_set); + js_value_t *global; + err = js_get_global(env, &global); assert(err == 0); - if (is_set) { - js_value_t *global; - err = js_get_global(env, &global); - assert(err == 0); - - js_call_function(env, global, fn, 0, NULL, NULL); - } + js_call_function(env, global, fn, 0, NULL, NULL); err = js_close_handle_scope(env, scope); assert(err == 0); @@ -335,17 +311,11 @@ bare_runtime_on_idle (bare_runtime_t *runtime) { err = js_get_named_property(env, exports, "onidle", &fn); assert(err == 0); - bool is_set; - err = js_is_function(env, fn, &is_set); + js_value_t *global; + err = js_get_global(env, &global); assert(err == 0); - if (is_set) { - js_value_t *global; - err = js_get_global(env, &global); - assert(err == 0); - - js_call_function(env, global, fn, 0, NULL, NULL); - } + js_call_function(env, global, fn, 0, NULL, NULL); err = js_close_handle_scope(env, scope); assert(err == 0); @@ -375,17 +345,11 @@ bare_runtime_on_resume (bare_runtime_t *runtime) { err = js_get_named_property(env, exports, "onresume", &fn); assert(err == 0); - bool is_set; - err = js_is_function(env, fn, &is_set); + js_value_t *global; + err = js_get_global(env, &global); assert(err == 0); - if (is_set) { - js_value_t *global; - err = js_get_global(env, &global); - assert(err == 0); - - js_call_function(env, global, fn, 0, NULL, NULL); - } + js_call_function(env, global, fn, 0, NULL, NULL); err = js_close_handle_scope(env, scope); assert(err == 0); @@ -781,36 +745,6 @@ bare_runtime_setup_thread (js_env_t *env, js_callback_info_t *info) { assert(err == 0); data.type = bare_thread_data_buffer; - } else { - err = js_is_arraybuffer(env, argv[2], &has_data); - assert(err == 0); - - if (has_data) { - err = js_get_arraybuffer_info(env, argv[2], (void **) &data.buffer.base, (size_t *) &data.buffer.len); - assert(err == 0); - - data.type = bare_thread_data_arraybuffer; - } else { - err = js_is_sharedarraybuffer(env, argv[2], &has_data); - assert(err == 0); - - if (has_data) { - err = js_get_sharedarraybuffer_backing_store(env, argv[2], &data.backing_store); - assert(err == 0); - - data.type = bare_thread_data_sharedarraybuffer; - } else { - err = js_is_external(env, argv[2], &has_data); - assert(err == 0); - - if (has_data) { - err = js_get_value_external(env, argv[2], &data.external); - assert(err == 0); - - data.type = bare_thread_data_external; - } - } - } } uint32_t stack_size; diff --git a/src/thread.c b/src/thread.c index e412ed9..8d257a0 100644 --- a/src/thread.c +++ b/src/thread.c @@ -83,37 +83,22 @@ bare_thread_entry (void *data) { assert(err == 0); break; } - - case bare_thread_data_arraybuffer: { - void *data; - err = js_create_arraybuffer(runtime->env, thread->data.buffer.len, &data, &thread_data); - assert(err == 0); - - memcpy(data, thread->data.buffer.base, thread->data.buffer.len); - break; - } - - case bare_thread_data_sharedarraybuffer: - err = js_create_sharedarraybuffer_with_backing_store(runtime->env, thread->data.backing_store, NULL, NULL, &thread_data); - assert(err == 0); - - err = js_release_arraybuffer_backing_store(runtime->env, thread->data.backing_store); - assert(err == 0); - break; - - case bare_thread_data_external: - err = js_create_external(runtime->env, thread->data.external, NULL, NULL, &thread_data); - assert(err == 0); - break; } js_value_t *exports; err = js_get_reference_value(env, runtime->exports, &exports); assert(err == 0); - err = js_set_named_property(runtime->env, exports, "threadData", thread_data); + js_value_t *fn; + err = js_get_named_property(env, exports, "onthread", &fn); + assert(err == 0); + + js_value_t *global; + err = js_get_global(env, &global); assert(err == 0); + js_call_function(env, global, fn, 1, (js_value_t *[]){thread_data}, NULL); + err = js_close_handle_scope(env, scope); assert(err == 0); diff --git a/src/thread.js b/src/thread.js index 967cdc9..6818fa4 100644 --- a/src/thread.js +++ b/src/thread.js @@ -1,4 +1,5 @@ /* global bare, Bare */ +const structuredClone = require('bare-structured-clone') module.exports = exports = class Thread { constructor (filename, opts, callback) { @@ -32,6 +33,18 @@ module.exports = exports = class Thread { if (typeof source === 'string') source = Buffer.from(source, encoding) + if (data !== null) { + const serialized = structuredClone.serialize(data) + + const state = { start: 0, end: 0, buffer: null } + structuredClone.preencode(state, serialized) + + state.buffer = Buffer.allocUnsafe(state.end) + structuredClone.encode(state, serialized) + + data = state.buffer + } + this._handle = bare.setupThread(filename, source, data, stackSize) Thread._threads.add(this) @@ -78,8 +91,16 @@ module.exports = exports = class Thread { } class ThreadProxy { - get data () { - return ArrayBuffer.isView(bare.threadData) ? Buffer.coerce(bare.threadData) : bare.threadData + constructor () { + this.data = null + } + + _ondata (data) { + if (data === null) return + + const state = { start: 0, end: data.byteLength, buffer: data } + + this.data = structuredClone.deserialize(structuredClone.decode(state)) } [Symbol.for('bare.inspect')] () { diff --git a/src/types.h b/src/types.h index 5e13087..9d269e3 100644 --- a/src/types.h +++ b/src/types.h @@ -82,15 +82,10 @@ struct bare_thread_data_s { enum { bare_thread_data_none, bare_thread_data_buffer, - bare_thread_data_arraybuffer, - bare_thread_data_sharedarraybuffer, - bare_thread_data_external, } type; union { uv_buf_t buffer; - js_arraybuffer_backing_store_t *backing_store; - void *external; }; };