Bug 1776680 [wpt PR 34603] - [@container] Test invalidation of font-relative units...
[gecko.git] / dom / streams / ByteStreamHelpers.cpp
blob9d3f54b96a7835f828acf4afa25311b8f37d1d05
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim:set ts=2 sw=2 sts=2 et cindent: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "mozilla/dom/BodyStream.h"
8 #include "mozilla/dom/ByteStreamHelpers.h"
9 #include "mozilla/dom/ReadableByteStreamController.h"
10 #include "js/ArrayBuffer.h"
11 #include "js/RootingAPI.h"
12 #include "js/experimental/TypedData.h"
13 #include "mozilla/ErrorResult.h"
15 namespace mozilla::dom {
17 // https://streams.spec.whatwg.org/#transfer-array-buffer
18 // As some parts of the specifcation want to use the abrupt completion value,
19 // this function may leave a pending exception if it returns nullptr.
20 JSObject* TransferArrayBuffer(JSContext* aCx, JS::Handle<JSObject*> aObject) {
21 MOZ_ASSERT(JS::IsArrayBufferObject(aObject));
23 // Step 1.
24 MOZ_ASSERT(!JS::IsDetachedArrayBufferObject(aObject));
26 // Step 3 (Reordered)
27 size_t bufferLength = JS::GetArrayBufferByteLength(aObject);
29 // Step 2 (Reordered)
30 void* bufferData = JS::StealArrayBufferContents(aCx, aObject);
32 // Step 4.
33 if (!JS::DetachArrayBuffer(aCx, aObject)) {
34 return nullptr;
37 // Step 5.
38 return JS::NewArrayBufferWithContents(aCx, bufferLength, bufferData);
41 // https://streams.spec.whatwg.org/#can-transfer-array-buffer
42 bool CanTransferArrayBuffer(JSContext* aCx, JS::Handle<JSObject*> aObject,
43 ErrorResult& aRv) {
44 // Step 1. Assert: Type(O) is Object. (Implicit in types)
45 // Step 2. Assert: O has an [[ArrayBufferData]] internal slot.
46 MOZ_ASSERT(JS::IsArrayBufferObject(aObject));
48 // Step 3. If ! IsDetachedBuffer(O) is true, return false.
49 if (JS::IsDetachedArrayBufferObject(aObject)) {
50 return false;
53 // Step 4. If SameValue(O.[[ArrayBufferDetachKey]], undefined) is false,
54 // return false.
55 // Step 5. Return true.
56 // Note: WASM memories are the only buffers that would qualify
57 // as having an undefined [[ArrayBufferDetachKey]],
58 bool hasDefinedArrayBufferDetachKey = false;
59 if (!JS::HasDefinedArrayBufferDetachKey(aCx, aObject,
60 &hasDefinedArrayBufferDetachKey)) {
61 aRv.StealExceptionFromJSContext(aCx);
62 return false;
64 return !hasDefinedArrayBufferDetachKey;
67 // https://streams.spec.whatwg.org/#abstract-opdef-cloneasuint8array
68 JSObject* CloneAsUint8Array(JSContext* aCx, JS::Handle<JSObject*> aObject) {
69 // Step 1. Assert: Type(O) is Object. Implicit.
70 // Step 2. Assert: O has an [[ViewedArrayBuffer]] internal slot.
71 MOZ_ASSERT(JS_IsArrayBufferViewObject(aObject));
73 // Step 3. Assert: !IsDetachedBuffer(O.[[ViewedArrayBuffer]]) is false.
74 bool isShared;
75 JS::Rooted<JSObject*> viewedArrayBuffer(
76 aCx, JS_GetArrayBufferViewBuffer(aCx, aObject, &isShared));
77 if (!viewedArrayBuffer) {
78 return nullptr;
80 MOZ_ASSERT(!JS::IsDetachedArrayBufferObject(viewedArrayBuffer));
82 // Step 4. Let buffer be ?CloneArrayBuffer(O.[[ViewedArrayBuffer]],
83 // O.[[ByteOffset]], O.[[ByteLength]], %ArrayBuffer%).
84 size_t byteOffset = JS_GetTypedArrayByteOffset(aObject);
85 size_t byteLength = JS_GetTypedArrayByteLength(aObject);
86 JS::Rooted<JSObject*> buffer(
87 aCx,
88 JS::ArrayBufferClone(aCx, viewedArrayBuffer, byteOffset, byteLength));
89 if (!buffer) {
90 return nullptr;
93 // Step 5. Let array be ! Construct(%Uint8Array%, « buffer »).
94 JS::Rooted<JSObject*> array(
95 aCx, JS_NewUint8ArrayWithBuffer(aCx, buffer, 0,
96 static_cast<int64_t>(byteLength)));
97 if (!array) {
98 return nullptr;
101 // Step 6. Return array.
102 return array;
105 class BodyStreamUnderlyingSourceAlgorithms final
106 : public UnderlyingSourceAlgorithmsBase {
107 public:
108 NS_DECL_ISUPPORTS_INHERITED
109 NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(BodyStreamUnderlyingSourceAlgorithms,
110 UnderlyingSourceAlgorithmsBase)
112 explicit BodyStreamUnderlyingSourceAlgorithms(
113 BodyStreamHolder* underlyingSource)
114 : mUnderlyingSource(underlyingSource) {}
116 MOZ_CAN_RUN_SCRIPT void StartCallback(JSContext* aCx,
117 ReadableStreamController& aController,
118 JS::MutableHandle<JS::Value> aRetVal,
119 ErrorResult& aRv) override {
120 aRetVal.setUndefined();
123 MOZ_CAN_RUN_SCRIPT already_AddRefed<Promise> PullCallback(
124 JSContext* aCx, ReadableStreamController& aController,
125 ErrorResult& aRv) override {
126 RefPtr<BodyStream> bodyStream = mUnderlyingSource->GetBodyStream();
127 return bodyStream->PullCallback(aCx, aController, aRv);
130 MOZ_CAN_RUN_SCRIPT already_AddRefed<Promise> CancelCallback(
131 JSContext* aCx, const Optional<JS::Handle<JS::Value>>& aReason,
132 ErrorResult& aRv) override {
133 RefPtr<BodyStream> bodyStream = mUnderlyingSource->GetBodyStream();
134 return bodyStream->CancelCallback(aCx, aReason, aRv);
137 void ErrorCallback() override {
138 RefPtr<BodyStream> bodyStream = mUnderlyingSource->GetBodyStream();
139 bodyStream->ErrorCallback();
142 protected:
143 ~BodyStreamUnderlyingSourceAlgorithms() override = default;
145 private:
146 RefPtr<BodyStreamHolder> mUnderlyingSource;
149 NS_IMPL_CYCLE_COLLECTION_INHERITED(BodyStreamUnderlyingSourceAlgorithms,
150 UnderlyingSourceAlgorithmsBase,
151 mUnderlyingSource)
152 NS_IMPL_ADDREF_INHERITED(BodyStreamUnderlyingSourceAlgorithms,
153 UnderlyingSourceAlgorithmsBase)
154 NS_IMPL_RELEASE_INHERITED(BodyStreamUnderlyingSourceAlgorithms,
155 UnderlyingSourceAlgorithmsBase)
156 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(BodyStreamUnderlyingSourceAlgorithms)
157 NS_INTERFACE_MAP_END_INHERITING(UnderlyingSourceAlgorithmsBase)
159 // This is gently modelled on the pre-existing
160 // SetUpExternalReadableByteStreamController, but specialized to the
161 // BodyStreamUnderlyingSource model vs. the External streams of the JS
162 // implementation.
164 // https://streams.spec.whatwg.org/#set-up-readable-byte-stream-controller-from-underlying-source
165 void SetUpReadableByteStreamControllerFromBodyStreamUnderlyingSource(
166 JSContext* aCx, ReadableStream* aStream,
167 BodyStreamHolder* aUnderlyingSource, ErrorResult& aRv) {
168 // Step 1.
169 auto controller =
170 MakeRefPtr<ReadableByteStreamController>(aStream->GetParentObject());
172 // Step 2 - 7.
173 auto algorithms =
174 MakeRefPtr<BodyStreamUnderlyingSourceAlgorithms>(aUnderlyingSource);
176 // Step 8
177 Maybe<uint64_t> autoAllocateChunkSize = mozilla::Nothing();
178 // Step 9 (Skipped)
180 // Not Specified: Native underlying sources always use 0.0 high water mark.
181 double highWaterMark = 0.0;
183 // Step 10.
184 SetUpReadableByteStreamController(aCx, aStream, controller, algorithms,
185 highWaterMark, autoAllocateChunkSize, aRv);
188 } // namespace mozilla::dom