Reputation: 199
(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?
Upvotes: 0
Views: 409
Reputation: 199
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('\x00\x61\x73\x6d\x01\x00\x00\x00\x05\x04\x01\x01\x01\x01\x07\x0a\x01\x06\x6d\x65\x6d\x6f\x72\x79\x02\x00\x0b\x12\x01\x00\x41\x00\x0b\x0c\x48\x65\x6c\x6c\x6f\x20\x57\x6f\x72\x6c\x64\x21\x00\x08\x04\x6e\x61\x6d\x65\x02\x01\x00');
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>
Upvotes: 0
Reputation: 36098
You have to declare it as shared:
(module
(memory (export "memory") 1 1 shared)
(data (i32.const 0) "Hello World!")
)
Upvotes: 1