Skip to content
File

Blob: src/workerd/jsg/buffersource-test.c++

4.4 KB
1// Copyright (c) 2017-2022 Cloudflare, Inc.
2// Licensed under the Apache 2.0 license found in the LICENSE file or at:
3// https://opensource.org/licenses/Apache-2.0
4 
5#include "buffersource.h"
6#include "jsg-test.h"
7 
8// ========================================================================================
9namespace workerd::jsg::test {
10namespace {
11 
12V8System v8System;
13 
14struct BufferSourceContext: public jsg::Object, public jsg::ContextGlobal {
15 BufferSource takeBufferSource(BufferSource buf) {
16 auto ptr = buf.asArrayPtr();
17 KJ_ASSERT(!buf.isDetached());
18 KJ_ASSERT(buf.size() == 8);
19 KJ_ASSERT(ptr[0] == 0);
20 
21 ptr[0] = 1;
22 KJ_ASSERT(ptr[0] == 1);
23 
24 return kj::mv(buf);
25 }
26 
27 BufferSource takeUint8Array(Lock& js, BufferSource buf) {
28 // A BufferSource that is initially attached can be detached, releasing the original
29 // object, then recreated as a new instance of the same type of JS object.
30 KJ_ASSERT(!buf.isDetached());
31 auto handle = buf.getHandle(js);
32 KJ_ASSERT(handle->IsUint8Array());
33 KJ_ASSERT(handle.As<v8::Uint8Array>()->ByteLength() > 0);
34 
35 // Detaching removes the BackingStore from the BufferSource,
36 // rendering the BufferSource useless.
37 auto backingStore = buf.detach(js);
38 KJ_ASSERT(buf.isDetached());
39 KJ_ASSERT(handle.As<v8::Uint8Array>()->ByteLength() == 0);
40 
41 // We can create a new view over the same shared backing store.
42 auto newView = backingStore.getTypedView<v8::DataView>();
43 auto dataView = newView.createHandle(js);
44 KJ_ASSERT(dataView->IsDataView());
45 
46 // We can create a new BufferSource from the detached BackingStore.
47 return BufferSource(js, kj::mv(backingStore));
48 }
49 
50 BufferSource makeBufferSource(jsg::Lock& js) {
51 return BufferSource(js, BackingStore::from(js, kj::arr<kj::byte>(1, 2, 3)));
52 }
53 
54 BufferSource makeArrayBuffer(jsg::Lock& js) {
55 return BufferSource(js, BackingStore::alloc<v8::ArrayBuffer>(js, 3));
56 }
57 
58 bool doTest(jsg::Lock& js, jsg::BufferSource buf) {
59 buf.asArrayPtr()[0] = 1;
60 buf.asArrayPtr()[1] = 2;
61 buf.asArrayPtr()[2] = 3;
62 buf.asArrayPtr()[3] = 4;
63 buf.asArrayPtr()[4] = 5;
64 buf.asArrayPtr()[5] = 6;
65 buf.asArrayPtr()[6] = 7;
66 buf.asArrayPtr()[7] = 8;
67 
68 auto ptr = buf.asArrayPtr<uint32_t>();
69 KJ_ASSERT(ptr.size() == 2);
70 KJ_ASSERT(ptr[0] == 0x04030201);
71 KJ_ASSERT(ptr[1] == 0x08070605);
72 return true;
73 }
74 
75 JSG_RESOURCE_TYPE(BufferSourceContext) {
76 JSG_METHOD(takeBufferSource);
77 JSG_METHOD(takeUint8Array);
78 JSG_METHOD(makeBufferSource);
79 JSG_METHOD(makeArrayBuffer);
80 JSG_METHOD(doTest);
81 }
82};
83JSG_DECLARE_ISOLATE_TYPE(BufferSourceIsolate, BufferSourceContext);
84 
85KJ_TEST("BufferSource works") {
86 Evaluator<BufferSourceContext, BufferSourceIsolate> e(v8System);
87 
88 // By default, a BufferSource handle is created as a DataView
89 e.expectEval("makeBufferSource() instanceof Uint8Array", "boolean", "true");
90 
91 // ... but can be other types also
92 e.expectEval("makeArrayBuffer() instanceof ArrayBuffer", "boolean", "true");
93 
94 e.expectEval(
95 "const ab = new ArrayBuffer(9); takeBufferSource(new Uint8Array(ab, 1, 8)).byteLength === 8",
96 "boolean", "true");
97 
98 e.expectEval("const ab = new ArrayBuffer(8); takeBufferSource(ab) === ab", "boolean", "true");
99 
100 e.expectEval("const ab = new Uint8Array(8); takeBufferSource(ab) === ab", "boolean", "true");
101 
102 e.expectEval("const ab = new Uint16Array(4); takeBufferSource(ab) === ab", "boolean", "true");
103 
104 e.expectEval("const ab = new Uint32Array(2); takeBufferSource(ab) === ab", "boolean", "true");
105 
106 e.expectEval("const ab = new BigInt64Array(1); takeBufferSource(ab) === ab", "boolean", "true");
107 
108 e.expectEval("const ab = new Float16Array(4); takeBufferSource(ab) === ab", "boolean", "true");
109 
110 e.expectEval("const ab = new Float32Array(2); takeBufferSource(ab) === ab", "boolean", "true");
111 
112 e.expectEval("const ab = new Float64Array(1); takeBufferSource(ab) === ab", "boolean", "true");
113 
114 e.expectEval("const ab = new ArrayBuffer(4); "
115 "const u8 = new Uint8Array(ab, 1, 1);"
116 "const u2 = takeUint8Array(u8);"
117 "u8.byteLength === 0 && u2.byteLength === 1 && u2 instanceof Uint8Array && "
118 "u2.buffer.byteLength === 4 && u2.byteOffset === 1 && u8 !== u2",
119 "boolean", "true");
120 
121 e.expectEval("const buf = new Uint8Array(12); doTest(buf.subarray(4))", "boolean", "true");
122}
123 
124} // namespace
125} // namespace workerd::jsg::test