externref-boxing-struct.js (2947B)
1 // Moving a JS value through a wasm externref is a pair of boxing/unboxing 2 // conversions that leaves the value unchanged. There are many cases, 3 // along these axes: 4 // 5 // - global variables, see externref-boxing.js 6 // - tables, see externref-boxing.js 7 // - function parameters and returns, see externref-boxing.js 8 // - struct fields [for the gc feature], this file 9 // - WasmGcObject fields when we construct with the externref type; this file 10 11 // Struct fields of externref type can receive their value in these ways: 12 // 13 // - the struct.new and struct.set instructions 14 // - storing into mutable fields from JS 15 // - from a constructor called from JS 16 // 17 // Struct fields can be read in these ways: 18 // 19 // - the struct.get instruction 20 // - reading the field from JS 21 // 22 // We're especially interested in two cases: where JS stores a non-object value 23 // into a field, in this case there should be boxing; and where JS reads a 24 // non-pointer value from a field, in this case there should be unboxing. 25 26 // Write with struct.new, read with the JS getter 27 28 for (let v of WasmExternrefValues) 29 { 30 let ins = wasmEvalText( 31 `(module 32 (type $S (struct (field $S.x (mut externref)))) 33 (func (export "make") (param $v externref) (result eqref) 34 (struct.new $S (local.get $v))))`); 35 let x = ins.exports.make(v); 36 assertEq(wasmGcReadField(x, 0), v); 37 } 38 39 // Try to make sure externrefs are properly traced 40 41 { 42 let fields = iota(10).map(() => `(field externref)`).join(' '); 43 let params = iota(10).map((i) => `(param $${i} externref)`).join(' '); 44 let args = iota(10).map((i) => `(local.get $${i})`).join(' '); 45 let txt = `(module 46 (type $S (struct ${fields})) 47 (func (export "make") ${params} (result eqref) 48 (struct.new $S ${args})))`; 49 let ins = wasmEvalText(txt); 50 let x = ins.exports.make({x:0}, {x:1}, {x:2}, {x:3}, {x:4}, {x:5}, {x:6}, {x:7}, {x:8}, {x:9}) 51 gc('shrinking'); 52 assertEq(typeof wasmGcReadField(x, 0), "object"); 53 assertEq(wasmGcReadField(x, 0).x, 0); 54 assertEq(typeof wasmGcReadField(x, 1), "object"); 55 assertEq(wasmGcReadField(x, 1).x, 1); 56 assertEq(typeof wasmGcReadField(x, 2), "object"); 57 assertEq(wasmGcReadField(x, 2).x, 2); 58 assertEq(typeof wasmGcReadField(x, 3), "object"); 59 assertEq(wasmGcReadField(x, 3).x, 3); 60 assertEq(typeof wasmGcReadField(x, 4), "object"); 61 assertEq(wasmGcReadField(x, 4).x, 4); 62 assertEq(typeof wasmGcReadField(x, 5), "object"); 63 assertEq(wasmGcReadField(x, 5).x, 5); 64 assertEq(typeof wasmGcReadField(x, 6), "object"); 65 assertEq(wasmGcReadField(x, 6).x, 6); 66 assertEq(typeof wasmGcReadField(x, 7), "object"); 67 assertEq(wasmGcReadField(x, 7).x, 7); 68 assertEq(typeof wasmGcReadField(x, 8), "object"); 69 assertEq(wasmGcReadField(x, 8).x, 8); 70 assertEq(typeof wasmGcReadField(x, 9), "object"); 71 assertEq(wasmGcReadField(x, 9).x, 9); 72 }