Skip to content

Commit c95f961

Browse files
committed
feat: support SharedArrayBuffer in napi_create_dataview (#183)
fix
1 parent 92964e3 commit c95f961

4 files changed

Lines changed: 63 additions & 33 deletions

File tree

packages/emnapi/src/value/create.ts

Lines changed: 29 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -550,46 +550,46 @@ export function napi_create_dataview (
550550
byte_offset: size_t,
551551
result: Pointer<napi_value>
552552
): napi_status {
553-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
554-
let value: number
555-
556553
return $PREAMBLE!(env, (envObject) => {
557554
$CHECK_ARG!(envObject, arraybuffer)
558555
$CHECK_ARG!(envObject, result)
559556
from64('byte_length')
560557
from64('byte_offset')
561558
byte_length = byte_length >>> 0
562559
byte_offset = byte_offset >>> 0
563-
const handle = emnapiCtx.handleStore.get(arraybuffer)!
564-
if (!handle.isArrayBuffer()) {
565-
return envObject.setLastError(napi_status.napi_invalid_arg)
566-
}
567-
const buffer = handle.value
560+
const value = emnapiCtx.handleStore.get(arraybuffer)!.value
568561

569-
if ((byte_length + byte_offset) > buffer.byteLength) {
570-
const err: RangeError & { code?: string } = new RangeError('byte_offset + byte_length should be less than or equal to the size in bytes of the array passed in')
571-
err.code = 'ERR_NAPI_INVALID_DATAVIEW_ARGS'
572-
throw err
573-
}
574-
575-
const dataview = new DataView(buffer, byte_offset, byte_length)
576-
if (buffer === wasmMemory.buffer) {
577-
if (!emnapiExternalMemory.wasmMemoryViewTable.has(dataview)) {
578-
emnapiExternalMemory.wasmMemoryViewTable.set(dataview, {
579-
Ctor: DataView,
580-
address: byte_offset,
581-
length: byte_length,
582-
ownership: ReferenceOwnership.kUserland,
583-
runtimeAllocated: 0
584-
})
562+
const createDataview = (buffer: ArrayBuffer | SharedArrayBuffer): napi_status => {
563+
if ((byte_length + byte_offset) > buffer.byteLength) {
564+
const err: RangeError & { code?: string } = new RangeError('byte_offset + byte_length should be less than or equal to the size in bytes of the array passed in')
565+
err.code = 'ERR_NAPI_INVALID_DATAVIEW_ARGS'
566+
throw err
585567
}
568+
const dataview = new DataView(buffer, byte_offset, byte_length)
569+
if (buffer === wasmMemory.buffer) {
570+
if (!emnapiExternalMemory.wasmMemoryViewTable.has(dataview)) {
571+
emnapiExternalMemory.wasmMemoryViewTable.set(dataview, {
572+
Ctor: DataView,
573+
address: byte_offset,
574+
length: byte_length,
575+
ownership: ReferenceOwnership.kUserland,
576+
runtimeAllocated: 0
577+
})
578+
}
579+
}
580+
581+
from64('result')
582+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
583+
const v = emnapiCtx.addToCurrentScope(dataview).id
584+
makeSetValue('result', 0, 'v', '*')
585+
return envObject.getReturnStatus()
586586
}
587-
from64('result')
588587

589-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
590-
value = emnapiCtx.addToCurrentScope(dataview).id
591-
makeSetValue('result', 0, 'value', '*')
592-
return envObject.getReturnStatus()
588+
if (value instanceof ArrayBuffer || emnapiExternalMemory.isSharedArrayBuffer(value)) {
589+
return createDataview(value)
590+
} else {
591+
return envObject.setLastError(napi_status.napi_invalid_arg)
592+
}
593593
})
594594
}
595595

packages/test/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,7 @@ add_test("array" "./array/binding.c" OFF)
285285
add_test("constructor" "./constructor/binding.c;./constructor/test_null.c" OFF)
286286
add_test("conversion" "./conversion/test_conversions.c;./conversion/test_null.c" OFF)
287287
add_test("dataview" "./dataview/binding.c" OFF)
288+
target_compile_definitions("dataview" PRIVATE "NAPI_EXPERIMENTAL" "NODE_API_EXPERIMENTAL_NO_WARNING")
288289
add_test("date" "./date/binding.c" OFF)
289290
add_test("error" "./error/binding.c" OFF)
290291
add_test("exception" "./exception/binding.c" OFF)

packages/test/dataview/binding.c

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,18 @@ static napi_value CreateDataView(napi_env env, napi_callback_info info) {
2020

2121
bool is_arraybuffer;
2222
NODE_API_CALL(env, napi_is_arraybuffer(env, arraybuffer, &is_arraybuffer));
23-
NODE_API_ASSERT(env, is_arraybuffer,
24-
"Wrong type of arguments. Expects a ArrayBuffer as the first "
25-
"argument.");
23+
24+
if (!is_arraybuffer) {
25+
bool is_sharedarraybuffer;
26+
NODE_API_CALL(
27+
env,
28+
node_api_is_sharedarraybuffer(env, arraybuffer, &is_sharedarraybuffer));
29+
NODE_API_ASSERT(env,
30+
is_sharedarraybuffer,
31+
"Wrong type of arguments. Expects a SharedArrayBuffer or "
32+
"ArrayBuffer as the first "
33+
"argument.");
34+
}
2635

2736
napi_valuetype valuetype1;
2837
NODE_API_CALL(env, napi_typeof(env, args[1], &valuetype1));

packages/test/dataview/dataview.test.js

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

88
module.exports = load('dataview').then(test_dataview => {
9-
// Test for creating dataview
9+
// Test for creating dataview with ArrayBuffer
1010
{
1111
const buffer = new ArrayBuffer(128)
1212
const template = Reflect.construct(DataView, [buffer])
@@ -16,11 +16,31 @@ module.exports = load('dataview').then(test_dataview => {
1616
`Expect ${theDataview} to be a DataView`)
1717
}
1818

19+
// Test for creating dataview with SharedArrayBuffer
20+
{
21+
const buffer = new SharedArrayBuffer(128)
22+
const template = new DataView(buffer)
23+
24+
const theDataview = test_dataview.CreateDataViewFromJSDataView(template)
25+
assert.ok(theDataview instanceof DataView,
26+
`Expect ${theDataview} to be a DataView`)
27+
28+
assert.strictEqual(template.buffer, theDataview.buffer)
29+
}
30+
1931
// Test for creating dataview with invalid range
2032
{
2133
const buffer = new ArrayBuffer(128)
2234
assert.throws(() => {
2335
test_dataview.CreateDataView(buffer, 10, 200)
2436
}, RangeError)
2537
}
38+
39+
// Test for creating dataview with SharedArrayBuffer and invalid range
40+
{
41+
const buffer = new SharedArrayBuffer(128)
42+
assert.throws(() => {
43+
test_dataview.CreateDataView(buffer, 10, 200)
44+
}, RangeError)
45+
}
2646
})

0 commit comments

Comments
 (0)