Summary
ArrayBuffer.isView(buf), util.types.isArrayBufferView(buf) and util.types.isUint8Array(buf) all return false for a Node Buffer under Perry. Node returns true for all three (a Buffer is a Uint8Array). buf instanceof Uint8Array is already true under Perry, so only these predicates are wrong.
Repro (no packages)
import { types } from "node:util";
const buf = Buffer.alloc(4);
const isView = ArrayBuffer.isView;
console.log(ArrayBuffer.isView(buf)); // direct call
console.log(isView(buf)); // through the value (thunk path)
console.log(types.isArrayBufferView(buf));
console.log(types.isUint8Array(buf));
console.log(ArrayBuffer.isView(Buffer.from("abc")));
console.log(ArrayBuffer.isView(buf.subarray(1, 3)));
console.log(ArrayBuffer.isView(Buffer.from(new ArrayBuffer(32), 8, 16)));
console.log(ArrayBuffer.isView(new Uint8Array(4))); // control
console.log(buf instanceof Uint8Array); // control
| line |
Node 26.5.1 |
Perry (main @ 19e7d4a, + #11235) |
ArrayBuffer.isView(buf) |
true |
false |
isView(buf) (value call) |
true |
false |
types.isArrayBufferView(buf) |
true |
false |
types.isUint8Array(buf) |
true |
false |
Buffer.from("abc") |
true |
false |
buf.subarray(1, 3) |
true |
false |
Buffer.from(ab, 8, 16) |
true |
false |
new Uint8Array(4) (control) |
true |
true |
buf instanceof Uint8Array (control) |
true |
true |
Checked with PERRY_NO_AUTO_OPTIMIZE=1 on perrymaster (linux-x64).
Where
- The direct call
ArrayBuffer.isView(x) lowers to util/types.isArrayBufferView (crates/perry-hir/src/lower/expr_call/module_static.rs).
js_util_types_is_array_buffer_view (crates/perry-runtime/src/object/util_types.rs) accepts is_uint8array_buffer(addr) || is_data_view(addr) || typed_array_kind(..). None of these recognise a BufferHeader registered only through register_buffer (is_registered_buffer), which is what Buffer.alloc / Buffer.from / buf.subarray produce.
array_buffer_is_view_thunk (crates/perry-runtime/src/object/global_this/typed_array.rs) has the same predicate, so the value-call form fails the same way.
js_util_types_is_uint8_array goes through jsvalue_typed_array_kind only, which also misses Buffers.
Real-world impact
This breaks the npm mongodb driver compiled from source. bson 7.3.3 decodes every binary subtype-4 value (UUID) as new UUID(buffer.subarray(...)), and UUID's constructor accepts the bytes only if ArrayBuffer.isView(input) && input.byteLength === 16. Under Perry that check is false, so the constructor throws:
BSONError: Argument passed in UUID constructor must be a UUID, a 16 byte Buffer or a 32/36 character hex string ...
A plain db.listCollections().toArray() hits it, because the server includes each collection's info.uuid. So does reading back any document that stores a UUID. This is the only failure left in a broad mongodb 7.5.0 probe (CRUD, cursors, bulkWrite, indexes, aggregate, transactions, change streams) run against mongod 8.0.4. It is what blocks removing the native perry-ext-mongodb binding.
Summary
ArrayBuffer.isView(buf),util.types.isArrayBufferView(buf)andutil.types.isUint8Array(buf)all returnfalsefor a NodeBufferunder Perry. Node returnstruefor all three (aBufferis aUint8Array).buf instanceof Uint8Arrayis alreadytrueunder Perry, so only these predicates are wrong.Repro (no packages)
ArrayBuffer.isView(buf)truefalseisView(buf)(value call)truefalsetypes.isArrayBufferView(buf)truefalsetypes.isUint8Array(buf)truefalseBuffer.from("abc")truefalsebuf.subarray(1, 3)truefalseBuffer.from(ab, 8, 16)truefalsenew Uint8Array(4)(control)truetruebuf instanceof Uint8Array(control)truetrueChecked with
PERRY_NO_AUTO_OPTIMIZE=1on perrymaster (linux-x64).Where
ArrayBuffer.isView(x)lowers toutil/types.isArrayBufferView(crates/perry-hir/src/lower/expr_call/module_static.rs).js_util_types_is_array_buffer_view(crates/perry-runtime/src/object/util_types.rs) acceptsis_uint8array_buffer(addr) || is_data_view(addr) || typed_array_kind(..). None of these recognise aBufferHeaderregistered only throughregister_buffer(is_registered_buffer), which is whatBuffer.alloc/Buffer.from/buf.subarrayproduce.array_buffer_is_view_thunk(crates/perry-runtime/src/object/global_this/typed_array.rs) has the same predicate, so the value-call form fails the same way.js_util_types_is_uint8_arraygoes throughjsvalue_typed_array_kindonly, which also misses Buffers.Real-world impact
This breaks the npm
mongodbdriver compiled from source. bson 7.3.3 decodes every binary subtype-4 value (UUID) asnew UUID(buffer.subarray(...)), andUUID's constructor accepts the bytes only ifArrayBuffer.isView(input) && input.byteLength === 16. Under Perry that check is false, so the constructor throws:A plain
db.listCollections().toArray()hits it, because the server includes each collection'sinfo.uuid. So does reading back any document that stores aUUID. This is the only failure left in a broad mongodb 7.5.0 probe (CRUD, cursors, bulkWrite, indexes, aggregate, transactions, change streams) run against mongod 8.0.4. It is what blocks removing the nativeperry-ext-mongodbbinding.