tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

function-call-bind.js (2593B)


      1 // See "Wasm Function.prototype.call.bind optimization" in WasmInstance.cpp
      2 // for more information.
      3 
      4 function wrapFunc(params, func) {
      5    let funcCallBind = Function.prototype.call.bind(func);
      6 
      7    return wasmEvalText(`(module
      8        (func (import "" "f") (param ${params.join(" ")}))
      9        (func (export "f") (param ${params.join(" ")})
     10            ${params.map((x, i) => `local.get ${i}`).join("\n")}
     11            call 0
     12        )
     13    )`, {"": {"f": funcCallBind}}).exports.f;
     14 }
     15 
     16 // Test passing all kinds of externref values to func through the 'this'
     17 // parameter.
     18 {
     19    let func = function (expected) {
     20        "use strict";
     21        assertEq(this, expected);
     22    };
     23    let test = wrapFunc(["externref", "externref"], func);
     24    for (let val of WasmExternrefValues) {
     25        test(val, val);
     26    }
     27 }
     28 
     29 // Same as above but with two non-this params.
     30 {
     31    let func = function (a, b) {
     32        "use strict";
     33        assertEq(this, a);
     34        assertEq(a, b);
     35    };
     36    let test = wrapFunc(["externref", "externref", "externref"], func);
     37    for (let val of WasmExternrefValues) {
     38        test(val, val, val);
     39    }
     40 }
     41 
     42 // Test passing primitives as the 'this' value.
     43 {
     44    let func = function (expected) {
     45        "use strict";
     46        assertEq(this, expected);
     47    };
     48    let vals = [0, 1, 2, 3, 4, 5];
     49    for (let valType of ["i32", "i64", "f32", "f64"]) {
     50        let test = wrapFunc([valType, valType], func);
     51        for (let val of vals) {
     52            if (valType === "i64") {
     53                val = BigInt(val);
     54            }
     55            test(val, val);
     56        }
     57    }
     58 }
     59 
     60 // Function.prototype.call on a non-strict function will coerce null/undefined
     61 // to the global object.
     62 {
     63    let func = function (expected) {
     64        assertEq(this, expected);
     65    };
     66    let test = wrapFunc(["externref", "externref"], func);
     67    test(null, globalThis);
     68    test(undefined, globalThis);
     69 }
     70 
     71 // Test binding extra JS arguments still works (this should skip the
     72 // optimization)
     73 {
     74    function func(x) {
     75        "use strict";
     76        assertEq(this, 1);
     77        assertEq(x, 2);
     78    }
     79 
     80    // Bind '2' to be the first normal arg to 'call', which will then become
     81    // the 'this' parameter always.
     82    let funcCallBind = Function.prototype.call.bind(func, 1);
     83 
     84    let {test} = wasmEvalText(`(module
     85        (func (import "" "f") (param i32))
     86        (export "test" (func 0))
     87    )`, {"": {"f": funcCallBind}}).exports;
     88 
     89    test(2);
     90 }
     91 
     92 // Test a missing this parameter.
     93 {
     94    let test = wrapFunc([], function () {
     95        "use strict";
     96        assertEq(this, undefined);
     97    });
     98    test();
     99 }