Bug 1734239 - Implement CountQueuingStrategy size function r?smaug draft
authorMatthew Gaudet <mgaudet@mozilla.com>
Fri, 26 Nov 2021 15:11:20 -0700
changeset 4097848 980c94436576ae439b903cc140e0069492c6c3ce
parent 4097847 9fd87cda0c299bb6aac67741f5a3b31e36bf1398
child 4097849 58e742ac272503f21f1cfe04909ad6b12c5af5d0
push id755115
push usermgaudet@mozilla.com
push dateFri, 26 Nov 2021 22:43:38 +0000
treeherdertry@99dda87ae19f [default view] [failures only]
reviewerssmaug
bugs1734239
milestone96.0a1
Bug 1734239 - Implement CountQueuingStrategy size function r?smaug
dom/streams/BaseQueuingStrategy.h
dom/streams/CountQueuingStrategy.cpp
dom/streams/CountQueuingStrategy.h
dom/webidl/QueuingStrategy.webidl
--- a/dom/streams/BaseQueuingStrategy.h
+++ b/dom/streams/BaseQueuingStrategy.h
@@ -2,19 +2,23 @@
 /* vim:set ts=2 sw=2 sts=2 et cindent: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_dom_BaseQueuingStrategy_h
 #define mozilla_dom_BaseQueuingStrategy_h
 
+#include "mozilla/ErrorResult.h"
+#include "mozilla/dom/FunctionBinding.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsIGlobalObject.h"
 
+#include "js/CallArgs.h"
+
 namespace mozilla::dom {
 
 class BaseQueuingStrategy : public nsISupports {
  public:
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_CLASS(BaseQueuingStrategy)
 
   BaseQueuingStrategy(nsISupports* aGlobal, double aHighWaterMark)
@@ -22,16 +26,24 @@ class BaseQueuingStrategy : public nsISu
 
   nsIGlobalObject* GetParentObject() const;
 
   double HighWaterMark() const { return mHighWaterMark; }
 
  protected:
   virtual ~BaseQueuingStrategy() = default;
 
+  JSObject* EnsureCachedSizeFunction(JSContext* aCx,
+                                     const char* dotQueueingStrategySize,
+                                     JSNative native, unsigned nargs,
+                                     ErrorResult& aRv);
+
+  already_AddRefed<Function> GetSizeHelper(const char* dotName, JSNative native,
+                                           unsigned nargs, ErrorResult& aRv);
+
  private:
   nsCOMPtr<nsIGlobalObject> mGlobal;
   double mHighWaterMark = 0.0;
 };
 
 }  // namespace mozilla::dom
 
 #endif
\ No newline at end of file
--- a/dom/streams/CountQueuingStrategy.cpp
+++ b/dom/streams/CountQueuingStrategy.cpp
@@ -1,19 +1,23 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim:set ts=2 sw=2 sts=2 et cindent: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/dom/CountQueuingStrategy.h"
+#include "mozilla/dom/FunctionBinding.h"
 #include "mozilla/dom/QueuingStrategyBinding.h"
 #include "nsCOMPtr.h"
 #include "nsISupports.h"
 
+#include "js/TypeDecls.h"
+#include "js/PropertyAndElement.h"
+
 namespace mozilla {
 namespace dom {
 
 NS_IMPL_CYCLE_COLLECTION(BaseQueuingStrategy, mGlobal)
 NS_IMPL_CYCLE_COLLECTING_ADDREF(BaseQueuingStrategy)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(BaseQueuingStrategy)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(BaseQueuingStrategy)
@@ -23,16 +27,48 @@ NS_INTERFACE_MAP_END
 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(CountQueuingStrategy)
 NS_IMPL_ADDREF_INHERITED(CountQueuingStrategy, BaseQueuingStrategy)
 NS_IMPL_RELEASE_INHERITED(CountQueuingStrategy, BaseQueuingStrategy)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(CountQueuingStrategy)
   NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
 NS_INTERFACE_MAP_END_INHERITING(BaseQueuingStrategy)
 
+// Make sure we get a cached size function off the global. If we can't we insert
+// a new one.
+JSObject* BaseQueuingStrategy::EnsureCachedSizeFunction(
+    JSContext* aCx, const char* dotQueueingStrategySize, JSNative native,
+    unsigned nargs, ErrorResult& aRv) {
+  JS::RootedObject global(aCx, GetParentObject()->GetGlobalJSObject());
+  JS::RootedValue value(aCx);
+  if (!JS_GetProperty(aCx, global, dotQueueingStrategySize, &value)) {
+    aRv.StealExceptionFromJSContext(aCx);
+    return nullptr;
+  }
+
+  // Cached version is unavailable; need to store a new one.
+  if (value.isUndefined()) {
+    JS::RootedFunction function(aCx,
+                                JS_NewFunction(aCx, native, nargs, 0, "size"));
+    if (!function) {
+      aRv.StealExceptionFromJSContext(aCx);
+      return nullptr;
+    }
+    value.setObjectOrNull(JS_GetFunctionObject(function));
+
+    if (!JS_DefineProperty(aCx, global, dotQueueingStrategySize, value, 0)) {
+      aRv.StealExceptionFromJSContext(aCx);
+      return nullptr;
+    }
+  }
+
+  MOZ_ASSERT(value.isObject());
+  return value.toObjectOrNull();
+}
+
 /* static */
 already_AddRefed<CountQueuingStrategy> CountQueuingStrategy::Constructor(
     const GlobalObject& aGlobal, const QueuingStrategyInit& aInit) {
   RefPtr<CountQueuingStrategy> strategy =
       new CountQueuingStrategy(aGlobal.GetAsSupports(), aInit.mHighWaterMark);
   return strategy.forget();
 }
 
@@ -40,10 +76,46 @@ nsIGlobalObject* BaseQueuingStrategy::Ge
   return mGlobal;
 }
 
 JSObject* CountQueuingStrategy::WrapObject(JSContext* aCx,
                                            JS::Handle<JSObject*> aGivenProto) {
   return CountQueuingStrategy_Binding::Wrap(aCx, this, aGivenProto);
 }
 
+static bool CountQueuingStrategySize(JSContext* cx, unsigned argc,
+                                     JS::Value* vp) {
+  JS::CallArgs args = CallArgsFromVp(argc, vp);
+
+  // Step 1: Return 1.
+  args.rval().setInt32(1);
+  return true;
+}
+
+already_AddRefed<Function> BaseQueuingStrategy::GetSizeHelper(
+    const char* dotName, JSNative native, unsigned nargs, ErrorResult& aRv) {
+  AutoJSAPI jsapi;
+  if (!jsapi.Init(GetParentObject())) {
+    // Report to aRv?
+    return nullptr;
+  }
+
+  JSContext* cx = jsapi.cx();
+  JS::RootedObject sizeFunction(
+      cx, EnsureCachedSizeFunction(cx, dotName, native, nargs, aRv));
+  if (aRv.Failed()) {
+    return nullptr;
+  }
+
+  JS::RootedObject global(cx, GetParentObject()->GetGlobalJSObject());
+  RefPtr<Function> func =
+      new Function(cx, sizeFunction, global, GetParentObject());
+
+  return func.forget();
+}
+
+already_AddRefed<Function> CountQueuingStrategy::GetSize(ErrorResult& aRv) {
+  return GetSizeHelper(".CountQueuingStrategySizeFunction",
+                       CountQueuingStrategySize, 0, aRv);
+}
+
 }  // namespace dom
 }  // namespace mozilla
--- a/dom/streams/CountQueuingStrategy.h
+++ b/dom/streams/CountQueuingStrategy.h
@@ -7,16 +7,17 @@
 #ifndef mozilla_dom_CountQueuingStrategy_h
 #define mozilla_dom_CountQueuingStrategy_h
 
 #include "js/TypeDecls.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/ErrorResult.h"
 #include "mozilla/dom/BaseQueuingStrategy.h"
 #include "mozilla/dom/BindingDeclarations.h"
+#include "mozilla/dom/FunctionBinding.h"
 #include "mozilla/dom/QueuingStrategyBinding.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsWrapperCache.h"
 #include "nsIGlobalObject.h"
 
 namespace mozilla {
 namespace dom {
 
@@ -35,14 +36,16 @@ class CountQueuingStrategy final : publi
   ~CountQueuingStrategy() = default;
 
  public:
   JSObject* WrapObject(JSContext* aCx,
                        JS::Handle<JSObject*> aGivenProto) override;
 
   static already_AddRefed<CountQueuingStrategy> Constructor(
       const GlobalObject& aGlobal, const QueuingStrategyInit& aInit);
+
+  already_AddRefed<Function> GetSize(ErrorResult& aRv);
 };
 
 }  // namespace dom
 }  // namespace mozilla
 
 #endif  // mozilla_dom_CountQueuingStrategy_h
--- a/dom/webidl/QueuingStrategy.webidl
+++ b/dom/webidl/QueuingStrategy.webidl
@@ -11,13 +11,11 @@ dictionary QueuingStrategyInit {
 
 
 [Exposed=(Window,Worker,Worklet)]
 interface CountQueuingStrategy {
   constructor(QueuingStrategyInit init);
 
   readonly attribute unrestricted double highWaterMark;
 
-  // This is currently inlined, but will need to be implemented
-  // See Bug 1734239
-  //
-  // readonly attribute Function size;
+  [Throws]
+  readonly attribute Function size;
 };