skip to Main Content
(module
  (memory (export "memory") 1)
  (data (i32.const 0) "Hello World!")
)
fetch('hello.wasm')
  .then(response => response.arrayBuffer())
  .then(bytes => WebAssembly.instantiate(bytes))
  .then(result => {
    // Access the memory
    const memory = result.instance.exports.memory;
    const buffer = new Uint8Array(memory.buffer);

    // Use the memory
    const offset = 0; // Start offset
    const length = 13; // Length of the string to read
    const message = new TextDecoder().decode(buffer.slice(offset, offset + length));
    console.log(message); // This should print "Hello, World!"

    // Check if the memory is shared
    if (memory.buffer instanceof SharedArrayBuffer) {
      console.log("WebAssembly memory is shared.");
    } else {
      console.log("WebAssembly memory is not shared.");
    }
  })
  .catch(error => console.error(error));

Data type of "memory.buffer" is ArrayBuffer and therefore cannot be used as shared data in a worker. Is there a way to make the exported memory usable as shared?

2

Answers


  1. Chosen as BEST ANSWER

    When I change the flag to 0, it causes an error. That's why it works correctly only when I change the flags that are set to 1.

      const code = (new TextEncoder()).encode('x00x61x73x6dx01x00x00x00x05x04x01x01x01x01x07x0ax01x06x6dx65x6dx6fx72x79x02x00x0bx12x01x00x41x00x0bx0cx48x65x6cx6cx6fx20x57x6fx72x6cx64x21x00x08x04x6ex61x6dx65x02x01x00');
    async function runner(code) {
    const result=await WebAssembly.instantiate(code)
      try{
        // Access the memory
        const memory = result.instance.exports.memory;
        const buffer = new Uint8Array(memory.buffer);
    
        // Use the memory
        const offset = 0; // Start offset
        const length = 13; // Length of the string to read
        const message = new TextDecoder().decode(buffer.slice(offset, offset + length));
        console.log(message); // This should print "Hello, World!"
    
        // Check if the memory is shared
        if (memory.buffer instanceof ArrayBuffer) {
           console.log(`WebAssembly memory is not shared.(${memory.buffer.constructor.name})`);
        } else {
         console.log(`WebAssembly memory is shared.(${memory.buffer.constructor.name})`);
        }
      }catch(error){ console.error(error)};
    }
    runner(code);
    function decodeLEB128(bytes, offset) {
      let result = 0;
      let shift = 0;
      let byte;
    
      do {
        byte = bytes[offset];
        result |= (byte & 0x7f) << shift;
        shift += 7;
        offset++;
      } while (byte & 0x80);
    
      return [result, offset];
    }
    
    // Load or fetch the WebAssembly binary file
    const buffer=code.buffer
      try{
        const buffer=code.buffer
        const view = new DataView(buffer);
    
        // Skip the header information (WASM_BINARY_MAGIC and WASM_BINARY_VERSION)
        let headerOffset = 8; // Skip the first 8 bytes (4 bytes MAGIC, 4 bytes VERSION)
    
        const sectionNames = {
          0: 'Custom',
          1: 'Type',
          2: 'Import',
          3: 'Function',
          4: 'Table',
          5: 'Memory',
          6: 'Global',
          7: 'Export',
          8: 'Start',
          9: 'Element',
          10: 'Code',
          11: 'Data',
        };
    
        const sectionInfo = {};
        const memories = [];
    
        // Iterate through the sections and collect information
        for (let i = headerOffset; i < buffer.byteLength;) {
          const sectionId = view.getUint8(i, true); // Read the Section ID
          i++;
          let sectionSize, sectionCount;
          let start;
          [sectionSize, i] = decodeLEB128(new Uint8Array(buffer), i);
          [sectionCount, start] = decodeLEB128(new Uint8Array(buffer), i); // Read the size encoded with LEB128
    
          const sectionName = sectionNames[sectionId];
          if (!sectionInfo[sectionId]) {
            sectionInfo[sectionId] = {
              start: i,
              size: sectionSize,
              count: sectionCount,
            };
          } else {
            sectionInfo[sectionId].size += sectionSize;
            sectionInfo[sectionId].count += sectionCount;
          }
    
          if (sectionId === 5) { // Memory Section
            for (let j = start; j < i + sectionSize;) {
              let flag = view.getUint8(j, true);
              if (flag === 1) {
                view.setUint8(j, 3);
                flag = 3;
              }
              j++;
              let initial;
              let maximum;
    
              if (flag === 0) {
                [initial, j] = decodeLEB128(new Uint8Array(buffer), j);
              } else if (flag === 1 || flag === 3) {
                [initial, j] = decodeLEB128(new Uint8Array(buffer), j);
                [maximum, j] = decodeLEB128(new Uint8Array(buffer), j);
              }
    
              memories.push({ flag, initial, maximum });
            }
          }
    
          // Skip other sections
          i += sectionSize;
        }
    
        // Write to the HTML document
        const resultContainer = document.getElementById('result-container');
    
        // Print in sorted order by the start value
        const sortedSectionInfo = Object.entries(sectionInfo).sort((a, b) => a[1].start - b[1].start);
        let html = "<h2>Sections:</h2><ul>";
    
        for (const [sectionId, section] of sortedSectionInfo) {
          const end = section.start + section.size;
          html += `<li>${sectionNames[sectionId]} start=0x${section.start.toString(16)} end=0x${end.toString(16)} (size=0x${section.size.toString(16)}) count: ${section.count}</li>`;
        }
        html += "</ul>";
    
        // Print the memories array
        html += "<h2>Memories:</h2><ul>";
        memories.forEach((memory, index) => {
          html += `<li>Memory ${index + 1}: Flag=${memory.flag}, Initial=${memory.initial}, Maximum=${memory.maximum}</li>`;
        });
        html += "</ul>";
    
        resultContainer.innerHTML = html;
    runner(buffer);
      }catch(error) {
        const errorText = "Error: " + error.message;
        const errorElement = document.createElement('div');
        errorElement.textContent = errorText;
        document.body.appendChild(errorElement); // Add the error message to the HTML document
      };
      <div id="result-container"></div>


  2. You have to declare it as shared:

    (module
      (memory (export "memory") 1 1 shared)
      (data (i32.const 0) "Hello World!")
    )
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search