Skip to content

Commit 61c497e

Browse files
committed
fix: early update wasm memory for views (#206)
1 parent 8037eb8 commit 61c497e

5 files changed

Lines changed: 41 additions & 12 deletions

File tree

packages/emnapi/src/memory.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -139,8 +139,7 @@ export const emnapiExternalMemory: {
139139
return view
140140
}
141141

142-
const maybeOldWasmMemory = emnapiExternalMemory.isDetachedArrayBuffer(view.buffer) ||
143-
((typeof SharedArrayBuffer === 'function') && (view.buffer instanceof SharedArrayBuffer))
142+
const maybeOldWasmMemory = emnapiExternalMemory.isDetachedArrayBuffer(view.buffer) || emnapiExternalMemory.isSharedArrayBuffer(view.buffer)
144143
if (maybeOldWasmMemory && emnapiExternalMemory.wasmMemoryViewTable.has(view)) {
145144
const info = emnapiExternalMemory.wasmMemoryViewTable.get(view)!
146145
const Ctor = info.Ctor

packages/emnapi/src/value/convert2c.ts

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ export function napi_get_typedarray_info (
116116
if (!handle.isTypedArray()) {
117117
return envObject.setLastError(napi_status.napi_invalid_arg)
118118
}
119-
const v: ArrayBufferView = handle.value
119+
let v: ArrayBufferView = handle.value
120120
if (type) {
121121
from64('type')
122122
let t: napi_typedarray_type
@@ -150,13 +150,13 @@ export function napi_get_typedarray_info (
150150
}
151151
makeSetValue('type', 0, 't', 'i32')
152152
}
153+
v = emnapiExternalMemory.getOrUpdateMemoryView(v)
153154
if (length) {
154155
from64('length')
155156
makeSetValue('length', 0, 'v.length', SIZE_TYPE)
156157
}
157-
let buffer: ArrayBufferLike
158+
158159
if (data || arraybuffer) {
159-
buffer = v.buffer
160160
if (data) {
161161
from64('data')
162162

@@ -168,7 +168,7 @@ export function napi_get_typedarray_info (
168168
from64('arraybuffer')
169169

170170
// eslint-disable-next-line @typescript-eslint/no-unused-vars
171-
const ab = envObject.ensureHandleId(buffer)
171+
const ab = envObject.ensureHandleId(v.buffer)
172172
makeSetValue('arraybuffer', 0, 'ab', '*')
173173
}
174174
}
@@ -215,14 +215,13 @@ export function napi_get_dataview_info (
215215
if (!handle.isDataView()) {
216216
return envObject.setLastError(napi_status.napi_invalid_arg)
217217
}
218-
const v = handle.value as DataView<ArrayBufferLike>
218+
const v = emnapiExternalMemory.getOrUpdateMemoryView(handle.value as DataView<ArrayBufferLike>)
219219
if (byte_length) {
220220
from64('byte_length')
221221
makeSetValue('byte_length', 0, 'v.byteLength', SIZE_TYPE)
222222
}
223-
let buffer: ArrayBufferLike
223+
224224
if (data || arraybuffer) {
225-
buffer = v.buffer
226225
if (data) {
227226
from64('data')
228227

@@ -234,7 +233,7 @@ export function napi_get_dataview_info (
234233
from64('arraybuffer')
235234

236235
// eslint-disable-next-line @typescript-eslint/no-unused-vars
237-
const ab = envObject.ensureHandleId(buffer)
236+
const ab = envObject.ensureHandleId(v.buffer)
238237
makeSetValue('arraybuffer', 0, 'ab', '*')
239238
}
240239
}

packages/test/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ if(IS_EMSCRIPTEN)
9393
"-sMAXIMUM_MEMORY=4294967296"
9494
"-sSAFE_HEAP=1"
9595
"-sMODULARIZE=1"
96-
"-sEXPORTED_RUNTIME_METHODS=['emnapiInit','ExitStatus']"
96+
"-sEXPORTED_RUNTIME_METHODS=['emnapiInit','ExitStatus','wasmMemory','growMemory']"
9797
)
9898
elseif(IS_WASI_THREADS)
9999
add_compile_options("-fno-exceptions")

packages/test/dataview/dataview.test.js

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@
55
const assert = require('assert')
66
const { load } = require('../util')
77

8-
module.exports = load('dataview').then(test_dataview => {
8+
const loadPromise = load('dataview')
9+
10+
module.exports = loadPromise.then(test_dataview => {
911
// Test for creating dataview with ArrayBuffer
1012
{
1113
const buffer = new ArrayBuffer(128)
@@ -43,4 +45,31 @@ module.exports = load('dataview').then(test_dataview => {
4345
test_dataview.CreateDataView(buffer, 10, 200)
4446
}, RangeError)
4547
}
48+
49+
{
50+
const binding = test_dataview
51+
const wasmMemory = loadPromise.Module.wasmMemory
52+
const before = wasmMemory.buffer
53+
const view = binding.CreateDataView(before, 0, 4)
54+
if (loadPromise.Module.growMemory) {
55+
loadPromise.Module.growMemory(before.byteLength + 65536)
56+
} else {
57+
wasmMemory.grow(1)
58+
}
59+
60+
const after = wasmMemory.buffer
61+
const cloned = binding.CreateDataViewFromJSDataView(view)
62+
63+
const result = {
64+
trackedViewUsesCurrentBuffer: view.buffer === before,
65+
bufferIdentityChangedAfterGrow: before !== after,
66+
oldBufferLength: before.byteLength,
67+
newBufferLength: after.byteLength,
68+
returnedViewUsesOldBuffer: cloned.buffer === before,
69+
returnedViewUsesNewBuffer: cloned.buffer === after
70+
}
71+
console.log(result)
72+
assert.strictEqual(result.returnedViewUsesOldBuffer, false)
73+
assert.strictEqual(result.returnedViewUsesNewBuffer, true)
74+
}
4675
})

packages/test/util.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ function loadPath (request, options) {
8787
}
8888
}
8989
}).then((source) => {
90+
napiModule.wasmMemory = source.instance.exports.memory
9091
if (process.env.EMNAPI_TEST_4GB) {
9192
source.instance.exports.malloc(2147483648)
9293
}
@@ -149,6 +150,7 @@ function loadPath (request, options) {
149150
}
150151
}).then(({ instance }) => {
151152
wasmMemory = instance.exports.memory || sharedMemory
153+
napiModule.wasmMemory = wasmMemory
152154
resolve(napiModule.exports)
153155
}).catch(reject)
154156
})

0 commit comments

Comments
 (0)