jseption 0.0.6 → 0.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -200,7 +200,9 @@ const data = fromGuest(ctx, value); // guest object graph -> plain ho
200
200
  ```
201
201
 
202
202
  Primitives cross unchanged. `toGuest` copies objects, arrays, Date, RegExp, Map, Set,
203
- typed arrays and Errors into guest equivalents, wraps host functions in guest functions
203
+ typed arrays and Errors into guest equivalents (a `SharedArrayBuffer`, or any buffer with
204
+ `{ liveBuffers: true }`, is handed over as the host memory itself, so a WebAssembly
205
+ module's memory can be read and written from the guest), wraps host functions in guest functions
204
206
  (host exceptions become guest errors, returned promises are bridged, guest promise jobs
205
207
  run when they settle) and preserves shared references and cycles. `fromGuest` does the
206
208
  reverse, turning guest functions into host functions that call into the guest. See
@@ -224,7 +226,8 @@ exposeLive(ctx, 'store', store, { writable: true, allow: (target, key) => key !=
224
226
  ```
225
227
 
226
228
  Primitives cross as values, host arrays as snapshot guest arrays, `Date`/`RegExp`/typed
227
- arrays/errors as copies, promises as guest promises; guest arguments are copied
229
+ arrays/errors as copies (shared memory, and any buffer under a `liveBuffers` policy, as
230
+ the memory itself), promises as guest promises; guest arguments are copied
228
231
  (`fromGuest`), a proxy passed back is unwrapped to its host object, and guest callbacks
229
232
  become host functions. The sandbox rules are always on: host intrinsics (`Function`,
230
233
  `eval`, `globalThis`, `Object`, `Reflect`, `Proxy`, the intrinsic prototypes, ...) never
@@ -4,8 +4,10 @@ export declare class JSArrayBufferData extends JSArrayBuffer {
4
4
  max_byte_length: number;
5
5
  dv: DataView | null;
6
6
  dv_data: Uint8Array | null;
7
- constructor(len: number, shared: boolean, max_len: number);
7
+ constructor(len: number, shared: boolean, max_len: number, existing?: ArrayBuffer | SharedArrayBuffer);
8
8
  }
9
+ export declare function isSharedArrayBuffer(v: unknown): v is SharedArrayBuffer;
10
+ export declare function JS_NewArrayBufferFrom(ctx: JSContext, buffer: ArrayBuffer | SharedArrayBuffer): JSValue;
9
11
  export declare function JS_NewArrayBufferCopy(ctx: JSContext, buf: Uint8Array): JSValue;
10
12
  export declare function JS_DetachArrayBuffer(ctx: JSContext, obj: JSValue): void;
11
13
  export declare function is_typed_array_class(class_id: JSClassID): boolean;
@@ -44,16 +44,21 @@ export function typed_array_class_available(class_id) {
44
44
  --------------------------------------------------------------------- */
45
45
  /* array buffer data with the resizable extension. The host buffer is
46
46
  resizable (growable when shared) when max_len >= 0; 'data' is a length
47
- tracking view over it. */
47
+ tracking view over it. With 'existing', the guest buffer is that host
48
+ buffer itself (JS_NewArrayBufferFrom): the two sides share the bytes. */
48
49
  export class JSArrayBufferData extends JSArrayBuffer {
49
50
  /* maximum byte length for resizable buffers, -1 otherwise */
50
51
  max_byte_length = -1;
51
52
  /* cached host DataView over 'data' */
52
53
  dv = null;
53
54
  dv_data = null;
54
- constructor(len, shared, max_len) {
55
+ constructor(len, shared, max_len, existing) {
55
56
  let buffer;
56
- if (shared)
57
+ if (existing) {
58
+ buffer = existing;
59
+ max_len = (shared ? existing.growable : existing.resizable) ? existing.maxByteLength : -1;
60
+ }
61
+ else if (shared)
57
62
  buffer = max_len >= 0 ? new SharedArrayBuffer(len, { maxByteLength: max_len }) : new SharedArrayBuffer(len);
58
63
  else
59
64
  buffer = max_len >= 0 ? new ArrayBuffer(len, { maxByteLength: max_len }) : new ArrayBuffer(len);
@@ -61,6 +66,10 @@ export class JSArrayBufferData extends JSArrayBuffer {
61
66
  this.max_byte_length = max_len;
62
67
  }
63
68
  }
69
+ /* a host SharedArrayBuffer, where the host has one */
70
+ export function isSharedArrayBuffer(v) {
71
+ return typeof SharedArrayBuffer === 'function' && v instanceof SharedArrayBuffer;
72
+ }
64
73
  function array_buffer_get_dv(abuf) {
65
74
  const a = abuf;
66
75
  if (a.dv === null || a.dv_data !== abuf.data) {
@@ -87,7 +96,7 @@ function JS_ThrowTypeErrorArrayBufferOOB(ctx) {
87
96
  }
88
97
  /* XXX: we are currently limited to 2 GB */
89
98
  const ARRAY_BUFFER_MAX_LENGTH = 0x7fffffff;
90
- function js_array_buffer_constructor3(ctx, new_target, len, max_len, class_id, buf) {
99
+ function js_array_buffer_constructor3(ctx, new_target, len, max_len, class_id, buf, existing) {
91
100
  const obj = js_create_from_ctor(ctx, new_target, class_id);
92
101
  if (JS_IsException(obj))
93
102
  return obj;
@@ -95,12 +104,21 @@ function js_array_buffer_constructor3(ctx, new_target, len, max_len, class_id, b
95
104
  return JS_ThrowRangeError(ctx, 'invalid array buffer length');
96
105
  if (max_len > ARRAY_BUFFER_MAX_LENGTH)
97
106
  return JS_ThrowRangeError(ctx, 'invalid array buffer maximum length');
98
- const abuf = new JSArrayBufferData(len, class_id === 20 /* JSClassID.SHARED_ARRAY_BUFFER */, max_len);
107
+ const abuf = new JSArrayBufferData(len, class_id === 20 /* JSClassID.SHARED_ARRAY_BUFFER */, max_len, existing);
99
108
  if (buf)
100
109
  abuf.data.set(buf.subarray(0, len));
101
110
  Q.JS_SetOpaque(obj, abuf);
102
111
  return obj;
103
112
  }
113
+ /* a guest ArrayBuffer (or SharedArrayBuffer) over the host buffer itself, not a
114
+ copy: what the guest writes the host sees, and the other way round. A
115
+ buffer is bytes: it reaches no host object, so sharing it keeps the
116
+ sandbox rules (its guest prototype is the guest's). The guest cannot
117
+ detach, resize or transfer it beyond what the host buffer allows. */
118
+ export function JS_NewArrayBufferFrom(ctx, buffer) {
119
+ const shared = isSharedArrayBuffer(buffer);
120
+ return js_array_buffer_constructor3(ctx, undefined, buffer.byteLength, -1, shared ? 20 /* JSClassID.SHARED_ARRAY_BUFFER */ : 19 /* JSClassID.ARRAY_BUFFER */, null, buffer);
121
+ }
104
122
  function js_array_buffer_constructor2(ctx, new_target, len, class_id) {
105
123
  return js_array_buffer_constructor3(ctx, new_target, len, -1, class_id, null);
106
124
  }