@@ -353,7 +353,85 @@ C |- br_on_cast_rtt_fail l rt_1 rt_2 : t* rt_1 (ref null exact_1 y) -> t* rt_2
353
353
354
354
## JS Prototypes
355
355
356
- TODO
356
+ In JS engines,
357
+ WebAssembly RTTs correspond to JS shape descriptors.
358
+ Custom RTTs act as first-class handles to the engine-managed RTTs,
359
+ so they can serve as extension points for the JS reflection of the Wasm objects they describe.
360
+
361
+ We introduce a new ` WebAssembly.setDescriptorPrototype() ` API
362
+ that takes a custom RTT instance and a prototype object.
363
+ The provided prototype will be attached to the custom RTT
364
+ and will become the prototype for the JS reflection
365
+ of all Wasm objects the custom RTT describes.
366
+
367
+ The following is a full example that uses ` WebAssembly.setDescriptorPrototype() `
368
+ to allow JS to call ` get() ` and ` inc() ` methods on counter objects implemented in
369
+ WebAssembly.
370
+
371
+ > Note: If there is demand for it,
372
+ > a similar API could configure property names that JS could use to access fields
373
+ > of the described WebAssembly objects.
374
+
375
+ ``` wasm
376
+ ;; counter.wasm
377
+ (module
378
+ (rec
379
+ (type $counter (struct (descriptor $counter.vtable (field $val i32))))
380
+ (type $counter.vtable (struct
381
+ (describes $counter)
382
+ (field $get (ref $get_t))
383
+ (field $inc (ref $inc_t))
384
+ ))
385
+ (type $get_t (func (param (ref null $counter)) (result i32)))
386
+ (type $inc_t (func (param (ref null $counter))))
387
+ )
388
+
389
+ (elem declare func $counter.get $counter.inc)
390
+
391
+ (global $counter.vtable (export "counter.vtable") (ref exact $counter.vtable)
392
+ (struct.new $counter.vtable
393
+ (ref.func $counter.get)
394
+ (ref.func $counter.inc)
395
+ )
396
+ )
397
+
398
+ (global $counter (export "counter") (ref $counter)
399
+ (struct.new_default $counter
400
+ (global.get $counter.vtable)
401
+ )
402
+ )
403
+
404
+ (func $counter.get (export "counter.get") (type $get_t) (param (ref null $counter)) (result i32)
405
+ (struct.get $counter $val (local.get 0))
406
+ )
407
+
408
+ (func $counter.inc (export "counter.inc") (type $inc_t) (param (ref null $counter))
409
+ (struct.set $counter $val
410
+ (local.get 0)
411
+ (i32.add
412
+ (struct.get $counter $val (local.get 0))
413
+ (i32.const 1)
414
+ )
415
+ )
416
+ )
417
+ )
418
+ ```
419
+
420
+ ``` js
421
+ // counter.js
422
+ var {module , instance} = await WebAssembly .instantiateStreaming (fetch (' counter.wasm' ));
423
+
424
+ WebAssembly .setDescriptorPrototype (instance .exports [' counter.vtable' ], {
425
+ get : function () { instance .exports [' counter.get' ](this ); },
426
+ inc : function () { return instance .exports [' counter.get' ](this ); }
427
+ });
428
+
429
+ var counter = instance .exports [' counter' ];
430
+
431
+ console .log (counter .get ()); // 0
432
+ counter .inc ();
433
+ console .log (counter .get ()); // 1
434
+ ```
357
435
358
436
## Declarative Prototype Initialization
359
437
0 commit comments