Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  globals.js   Sprache: JAVA

 
const { Instance, Module, LinkError } = WebAssembly;

// Locally-defined globals
assertErrorMessage(() => wasmEvalText(`(module (global))`), SyntaxError, /wasm text error/);
// A global field in the text format is valid with an empty expression, but this produces an invalid module
assertErrorMessage(() => wasmEvalText(`(module (global i32))`), WebAssembly.CompileError, /popping value/);
assertErrorMessage(() => wasmEvalText(`(module (global (mut i32)))`), WebAssembly.CompileError, /popping value/);

// Initializer expressions.
wasmFailValidateText(`(module (global i32 (f32.const 13.37)))`, /type mismatch/);
wasmFailValidateText(`(module (global f64 (f32.const 13.37)))`, /type mismatch/);

wasmFailValidateText(`(module (global i32 (global.get 0)))`, /out of range/);
wasmFailValidateText(`(module (global i32 (global.get 1)) (global i32 (i32.const 1)))`, /out of range/);

// Test a well-defined global section.
function testInner(type, initialValue, nextValue, coercion)
{
    var module = wasmEvalText(`(module
        (global (mut ${type}) (${type}.const ${initialValue}))
        (global ${type} (${type}.const ${initialValue}))

        (func $get (result ${type}) (global.get 0))
        (func $set (param ${type}) (global.set 0 (local.get 0)))

        (func $get_cst (result ${type}) (global.get 1))

        (export "get" (func $get))
        (export "get_cst" (func $get_cst))

        (export "set" (func $set))
    )`).exports;

    assertEq(module.get(), coercion(initialValue));
    assertEq(module.set(coercion(nextValue)), undefined);
    assertEq(module.get(), coercion(nextValue));

    assertEq(module.get_cst(), coercion(initialValue));
}

testInner('i32', 13, 37, x => x|0);
testInner('f32', 13.37, 0.1989, Math.fround);
testInner('f64', 13.37, 0.1989, x => +x);

// Basic global shenanigans
{
    const module = wasmEvalText(`(module
        ;; -2 * (5 - (-10 + 20)) = 10
        (global i32 (i32.mul (i32.const -2) (i32.sub (i32.const 5) (i32.add (i32.const -10) (i32.const 20)))))
        ;; ((1 + 2) - (3 * 4)) = -9
        (global i64 (i64.sub (i64.add (i64.const 1) (i64.const 2)) (i64.mul (i64.const 3) (i64.const 4))))

        (func (export "get0") (result i32) global.get 0)
        (func (export "get1") (result i64) global.get 1)
    )`).exports;

    assertEq(module.get0(), 10);
    assertEq(module.get1(), -9n);
}

// Example use of dynamic linking
{
    // Make a memory for two dynamically-linked modules to share. Each module gets five pages.
    const mem = new WebAssembly.Memory({ initial: 15, maximum: 15 });

    const mod1 = new WebAssembly.Module(wasmTextToBinary(`(module
        (memory (import "env" "memory") 15 15)
        (global $memBase (import "env" "__memory_base") i32)
        (data (offset (global.get $memBase)) "Hello from module 1.")
        (data (offset (i32.add (global.get $memBase) (i32.const 65536))) "Goodbye from module 1.")
    )`));
    const instance1 = new WebAssembly.Instance(mod1, {
        env: {
            memory: mem,
            __memory_base: 65536 * 5, // this module's memory starts at page 5
        },
    });

    const mod2 = new WebAssembly.Module(wasmTextToBinary(`(module
        (memory (import "env" "memory") 15 15)
        (global $memBase (import "env" "__memory_base") i32)
        (data (offset (global.get $memBase)) "Hello from module 2.")
        (data (offset (i32.add (global.get $memBase) (i32.const 65536))) "Goodbye from module 2.")
    )`));
    const instance2 = new WebAssembly.Instance(mod2, {
        env: {
            memory: mem,
            __memory_base: 65536 * 10, // this module's memory starts at page 10
        },
    });

    // All four strings should now be present in the memory.

    function assertStringInMem(mem, str, addr) {
        const bytes = new Uint8Array(mem.buffer).slice(addr, addr + str.length);
        let memStr = String.fromCharCode(...bytes);
        assertEq(memStr, str);
    }

    assertStringInMem(mem, "Hello from module 1.", 65536 * 5);
    assertStringInMem(mem, "Goodbye from module 1.", 65536 * 6);
    assertStringInMem(mem, "Hello from module 2.", 65536 * 10);
    assertStringInMem(mem, "Goodbye from module 2.", 65536 * 11);
}

// Semantic errors.
wasmFailValidateText(`(module (global (mut i32) (i32.const 1337)) (func (global.set 1 (i32.const 0))))`, /(out of range)|(global index out of bounds)/);
wasmFailValidateText(`(module (global i32 (i32.const 1337)) (func (global.set 0 (i32.const 0))))`, /(can't write an immutable global)|(global is immutable)/);

// Big module with many variables: test that setting one doesn't overwrite the
// other ones.
function get_set(i, type) {
    return `
        (func $get_${i} (result ${type}) (global.get ${i}))
        (func $set_${i} (param ${type}) (global.set ${i} (local.get 0)))
    `;
}

var module = wasmEvalText(`(module
    (global (mut i32) (i32.const 42))
    (global (mut i32) (i32.const 10))
    (global (mut f32) (f32.const 13.37))
    (global (mut f64) (f64.const 13.37))
    (global (mut i32) (i32.const -18))

    ${get_set(0, 'i32')}
    ${get_set(1, 'i32')}
    ${get_set(2, 'f32')}
    ${get_set(3, 'f64')}
    ${get_set(4, 'i32')}

    (export "get0" (func $get_0)) (export "set0" (func $set_0))
    (export "get1" (func $get_1)) (export "set1" (func $set_1))
    (export "get2" (func $get_2)) (export "set2" (func $set_2))
    (export "get3" (func $get_3)) (export "set3" (func $set_3))
    (export "get4" (func $get_4)) (export "set4" (func $set_4))
)`).exports;

let values = [42, 10, Math.fround(13.37), 13.37, -18];
let nextValues = [13, 37, Math.fround(-17.89), 9.3, -13];
for (let i = 0; i < 5; i++) {
    assertEq(module[`get${i}`](), values[i]);
    assertEq(module[`set${i}`](nextValues[i]), undefined);
    assertEq(module[`get${i}`](), nextValues[i]);
    for (let j = 0; j < 5; j++) {
        if (i === j)
            continue;
        assertEq(module[`get${j}`](), values[j]);
    }
    assertEq(module[`set${i}`](values[i]), undefined);
    assertEq(module[`get${i}`](), values[i]);
}

// Initializer expressions can also be used in elem section initializers.
wasmFailValidateText(`(module (import "globals" "a" (global f32)) (table 4 funcref) (elem (global.get 0) $f) (func $f))`, /type mismatch/);

module = wasmEvalText(`(module
    (import "globals" "a" (global i32))
    (table (export "tbl") 4 funcref)
    (elem (global.get 0) $f)
    (func $f)
    (export "f" (func $f))
)`, {
    globals: {
        a: 1
    }
}).exports;
assertEq(module.f, module.tbl.get(1));

// Import/export semantics.
module = wasmEvalText(`(module
 (import "globals" "x" (global $g i32))
 (func $get (result i32) (global.get $g))
 (export "getter" (func $get))
 (export "value" (global 0))
)`, { globals: {x: 42} }).exports;

assertEq(module.getter(), 42);

// assertEq() will not trigger @@toPrimitive, so we must have a cast here.
assertEq(Number(module.value), 42);

// Can only import numbers (no implicit coercions).
module = new Module(wasmTextToBinary(`(module
    (global (import "globs" "i32") i32)
    (global (import "globs" "f32") f32)
    (global (import "globs" "f64") f32)
)`));

const assertLinkFails = (m, imp, err) => {
    assertErrorMessage(() => new Instance(m, imp), LinkError, err);
}

var imp = {
    globs: {
        i32: 0,
        f32: Infinity,
        f64: NaN
    }
};

let i = new Instance(module, imp);

for (let v of [
    null,
    {},
    "42",
    /not a number/,
    false,
    undefined,
    Symbol(),
    { valueOf() { return 42; } }
]) {
    imp.globs.i32 = v;
    assertLinkFails(module, imp, /not a Number/);

    imp.globs.i32 = 0;
    imp.globs.f32 = v;
    assertLinkFails(module, imp, /not a Number/);

    imp.globs.f32 = Math.fround(13.37);
    imp.globs.f64 = v;
    assertLinkFails(module, imp, /not a Number/);

    imp.globs.f64 = 13.37;
}

// Imported globals and locally defined globals use the same index space.
module = wasmEvalText(`(module
 (import "globals" "x" (global i32))
 (global i32 (i32.const 1337))
 (export "imported" (global 0))
 (export "defined" (global 1))
)`, { globals: {x: 42} }).exports;

assertEq(Number(module.imported), 42);
assertEq(Number(module.defined), 1337);

wasmFailValidateText(`(module (import "globals" "a" (global f32)) (global i32 (global.get 0)))`, /type mismatch/);

function testInitExpr(type, initialValue, nextValue, coercion, assertFunc = assertEq) {
    var module = wasmEvalText(`(module
        (import "globals" "a" (global ${type}))

        (global $glob_mut (mut ${type}) (global.get 0))
        (global $glob_imm ${type} (global.get 0))

        (func $get0 (result ${type}) (global.get 0))

        (func $get1 (result ${type}) (global.get 1))
        (func $set1 (param ${type}) (global.set 1 (local.get 0)))

        (func $get_cst (result ${type}) (global.get 2))

        (export "get0" (func $get0))
        (export "get1" (func $get1))
        (export "get_cst" (func $get_cst))

        (export "set1" (func $set1))
        (export "global_imm" (global $glob_imm))
    )`, {
        globals: {
            a: coercion(initialValue)
        }
    }).exports;

    assertFunc(module.get0(), coercion(initialValue));
    assertFunc(module.get1(), coercion(initialValue));
    assertFunc(Number(module.global_imm), coercion(initialValue));

    assertEq(module.set1(coercion(nextValue)), undefined);
    assertFunc(module.get1(), coercion(nextValue));
    assertFunc(module.get0(), coercion(initialValue));
    assertFunc(Number(module.global_imm), coercion(initialValue));

    assertFunc(module.get_cst(), coercion(initialValue));
}

testInitExpr('i32', 13, 37, x => x|0);
testInitExpr('f32', 13.37, 0.1989, Math.fround);
testInitExpr('f64', 13.37, 0.1989, x => +x);

// Int64.

// Import and export

// Test inner
var initialValue = '0x123456789abcdef0';
var nextValue = '0x531642753864975F';
wasmAssert(`(module
    (global (mut i64) (i64.const ${initialValue}))
    (global i64 (i64.const ${initialValue}))
    (func $get (result i64) (global.get 0))
    (func $set (param i64) (global.set 0 (local.get 0)))
    (func $get_cst (result i64) (global.get 1))
    (export "get" (func $get))
    (export "get_cst" (func $get_cst))
    (export "set" (func $set))
)`, [
    {type: 'i64', func: '$get', expected: initialValue},
    {type: 'i64', func: '$set', args: [`i64.const ${nextValue}`]},
    {type: 'i64', func: '$get', expected: nextValue},
    {type: 'i64', func: '$get_cst', expected: initialValue},
]);

// Custom NaN.
{
    let dv = new DataView(new ArrayBuffer(8));
    module = wasmEvalText(`(module
     (global $g f64 (f64.const -nan:0xe7ffff1591120))
     (global $h f32 (f32.const -nan:0x651234))
     (export "nan64" (global $g))(export "nan32" (global $h))
    )`, {}).exports;

    dv.setFloat64(0, module.nan64, true);
    assertEq(dv.getUint32(4, true), 0x7ff80000);
    assertEq(dv.getUint32(0, true), 0x00000000);

    dv.setFloat32(0, module.nan32, true);
    assertEq(dv.getUint32(0, true), 0x7fc00000);
}

// WebAssembly.Global
{
    const Global = WebAssembly.Global;

    // These types should work:
    assertEq(new Global({value: "i32"}) instanceof Global, true);
    assertEq(new Global({value: "f32"}) instanceof Global, true);
    assertEq(new Global({value: "f64"}) instanceof Global, true);
    assertEq(new Global({value: "i64"}) instanceof Global, true); // No initial value works

    // Coercion of init value; ".value" accessor
    assertEq((new Global({value: "i32"}, 3.14)).value, 3);
    assertEq((new Global({value: "f32"}, { valueOf: () => 33.5 })).value, 33.5);
    assertEq((new Global({value: "f64"}, "3.25")).value, 3.25);

    // Nothing special about NaN, it coerces just fine
    assertEq((new Global({value: "i32"}, NaN)).value, 0);

    // The default init value is zero.
    assertEq((new Global({value: "i32"})).value, 0);
    assertEq((new Global({value: "f32"})).value, 0);
    assertEq((new Global({value: "f64"})).value, 0);
    let mod = wasmEvalText(`(module
                             (import "" "g" (global i64))
                             (func (export "f") (result i32)
                              (i64.eqz (global.get 0))))`,
                           {"":{g: new Global({value: "i64"})}});
    assertEq(mod.exports.f(), 1);

    {
        // "value" is enumerable
        let x = new Global({value: "i32"});
        let s = "";
        for ( let i in x )
            s = s + i + ",";
        if (getBuildConfiguration("release_or_beta")) {
            assertEq(s, "valueOf,value,");
        } else {
            assertEq(s, "type,valueOf,value,");
        }
    }

    // "value" is defined on the prototype, not on the object
    assertEq("value" in Global.prototype, true);

    // Can't set the value of an immutable global
    assertErrorMessage(() => (new Global({value: "i32"})).value = 10,
                       TypeError,
                       /can't set value of immutable global/);

    {
        // Can set the value of a mutable global
        let g = new Global({value: "i32", mutable: true}, 37);
        g.value = 10;
        assertEq(g.value, 10);
    }

    {
        // Misc internal conversions
        let g = new Global({value: "i32"}, 42);

        // valueOf
        assertEq(g - 5, 37);

        // @@toStringTag
        assertEq(g.toString(), "[object WebAssembly.Global]");
    }

    {
        // An exported global should appear as a Global instance:
        let i = wasmEvalText(`(module (global (export "g") i32 (i32.const 42)))`);

        assertEq(typeof i.exports.g, "object");
        assertEq(i.exports.g instanceof Global, true);

        // An exported global can be imported into another instance even if
        // it is an object:
        let j = wasmEvalText(`(module
                               (global (import "" "g") i32)
                               (func (export "f") (result i32)
                                (global.get 0)))`,
                             { "": { "g": i.exports.g }});

        // And when it is then accessed it has the right value:
        assertEq(j.exports.f(), 42);
    }

    // Identity of Global objects (independent of mutablity).
    {
        // When a global is exported twice, the two objects are the same.
        let i = wasmEvalText(`(module
                               (global i32 (i32.const 0))
                               (export "a" (global 0))
                               (export "b" (global 0)))`);
        assertEq(i.exports.a, i.exports.b);

        // When a global is imported and then exported, the exported object is
        // the same as the imported object.
        let j = wasmEvalText(`(module
                               (import "" "a" (global i32))
                               (export "x" (global 0)))`,
                             { "": {a: i.exports.a}});

        assertEq(i.exports.a, j.exports.x);

        // When a global is imported twice (ie aliased) and then exported twice,
        // the exported objects are the same, and are also the same as the
        // imported object.
        let k = wasmEvalText(`(module
                               (import "" "a" (global i32))
                               (import "" "b" (global i32))
                               (export "x" (global 0))
                               (export "y" (global 1)))`,
                             { "": {a: i.exports.a,
                                    b: i.exports.a}});

        assertEq(i.exports.a, k.exports.x);
        assertEq(k.exports.x, k.exports.y);
    }

    // Mutability
    {
        let i = wasmEvalText(`(module
                               (global (export "g") (mut i32) (i32.const 37))
                               (func (export "getter") (result i32)
                                (global.get 0))
                               (func (export "setter") (param i32)
                                (global.set 0 (local.get 0))))`);

        let j = wasmEvalText(`(module
                               (import "" "g" (global (mut i32)))
                               (func (export "getter") (result i32)
                                (global.get 0))
                               (func (export "setter") (param i32)
                                (global.set 0 (local.get 0))))`,
                             {"": {g: i.exports.g}});

        // Initial values
        assertEq(i.exports.g.value, 37);
        assertEq(i.exports.getter(), 37);
        assertEq(j.exports.getter(), 37);

        // Set in i, observe everywhere
        i.exports.setter(42);

        assertEq(i.exports.g.value, 42);
        assertEq(i.exports.getter(), 42);
        assertEq(j.exports.getter(), 42);

        // Set in j, observe everywhere
        j.exports.setter(78);

        assertEq(i.exports.g.value, 78);
        assertEq(i.exports.getter(), 78);
        assertEq(j.exports.getter(), 78);

        // Set on global object, observe everywhere
        i.exports.g.value = 197;

        assertEq(i.exports.g.value, 197);
        assertEq(i.exports.getter(), 197);
        assertEq(j.exports.getter(), 197);
    }

    // Mutability of import declaration and imported value have to match
    {
        const mutErr = /imported global mutability mismatch/;

        let m1 = new Module(wasmTextToBinary(`(module
                                               (import "m" "g" (global i32)))`));

        // Mutable Global matched to immutable import
        let gm = new Global({value: "i32", mutable: true}, 42);
        assertErrorMessage(() => new Instance(m1, {m: {g: gm}}),
                           LinkError,
                           mutErr);

        let m2 = new Module(wasmTextToBinary(`(module
                                               (import "m" "g" (global (mut i32))))`));

        // Immutable Global matched to mutable import
        let gi = new Global({value: "i32", mutable: false}, 42);
        assertErrorMessage(() => new Instance(m2, {m: {g: gi}}),
                           LinkError,
                           mutErr);

        // Constant value is the same as immutable Global
        assertErrorMessage(() => new Instance(m2, {m: {g: 42}}),
                           LinkError,
                           mutErr);
    }

    // TEST THIS LAST

    // "value" is deletable
    assertEq(delete Global.prototype.value, true);
    assertEq("value" in Global.prototype, false);

    // ADD NO MORE TESTS HERE!
}

// Standard wat syntax: the parens around the initializer expression are
// optional.
{
    let i1 = wasmEvalText(
        `(module
           (global $g i32 i32.const 37)
           (func (export "f") (result i32) (global.get $g)))`);
    assertEq(i1.exports.f(), 37);

    let i2 = wasmEvalText(
        `(module
           (global $g (mut f64) f64.const 42.0)
           (func (export "f") (result f64) (global.get $g)))`);
    assertEq(i2.exports.f(), 42);

    let i3 = wasmEvalText(
        `(module
           (global $x (import "m" "x") i32)
           (global $g i32 global.get $x)
           (func (export "f") (result i32) (global.get $g)))`,
        {m:{x:86}});
    assertEq(i3.exports.f(), 86);
}

Messung V0.5
C=97 H=98 G=97

¤ Dauer der Verarbeitung: 0.6 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge