Bug 1342012 - Refactor ModuleScript into ClassicScript class and LoadedScript base class so we can represent all scripts that can perform dynamic import r=smaug
authorJon Coppeard <jcoppeard@mozilla.com>
Thu, 06 Dec 2018 16:52:15 -0500
changeset 509501 c73b0641fc8e233767085a1c5868e82601d4830d
parent 509500 8e6f86cd811a93cce70fc91ac6fbb93405aff803
child 509502 4001453082049c7f1729f464baff027eb079a8a8
push id10547
push userffxbld-merge
push dateMon, 21 Jan 2019 13:03:58 +0000
treeherdermozilla-beta@24ec1916bffe [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug
bugs1342012
milestone66.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1342012 - Refactor ModuleScript into ClassicScript class and LoadedScript base class so we can represent all scripts that can perform dynamic import r=smaug
dom/script/ModuleScript.cpp
dom/script/ModuleScript.h
--- a/dom/script/ModuleScript.cpp
+++ b/dom/script/ModuleScript.cpp
@@ -9,56 +9,96 @@
 #include "mozilla/HoldDropJSObjects.h"
 
 #include "jsfriendapi.h"
 #include "ScriptLoader.h"
 
 namespace mozilla {
 namespace dom {
 
-// A single module script.  May be used to satisfy multiple load requests.
+//////////////////////////////////////////////////////////////
+// LoadedScript
+//////////////////////////////////////////////////////////////
+
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(LoadedScript)
+NS_INTERFACE_MAP_END
+
+NS_IMPL_CYCLE_COLLECTION_CLASS(LoadedScript)
+
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(LoadedScript)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK(mLoader)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK(mFetchOptions)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK(mBaseURL)
+NS_IMPL_CYCLE_COLLECTION_UNLINK_END
+
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(LoadedScript)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mLoader)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mFetchOptions)
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+
+NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(LoadedScript)
+NS_IMPL_CYCLE_COLLECTION_TRACE_END
+
+NS_IMPL_CYCLE_COLLECTING_ADDREF(LoadedScript)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(LoadedScript)
+
+LoadedScript::LoadedScript(ScriptKind aKind, ScriptLoader* aLoader,
+                           ScriptFetchOptions* aFetchOptions, nsIURI* aBaseURL)
+    : mKind(aKind),
+      mLoader(aLoader),
+      mFetchOptions(aFetchOptions),
+      mBaseURL(aBaseURL) {
+  MOZ_ASSERT(mLoader);
+  MOZ_ASSERT(mFetchOptions);
+  MOZ_ASSERT(mBaseURL);
+}
+
+LoadedScript::~LoadedScript() { DropJSObjects(this); }
+
+//////////////////////////////////////////////////////////////
+// ClassicScript
+//////////////////////////////////////////////////////////////
+
+ClassicScript::ClassicScript(ScriptLoader* aLoader,
+                             ScriptFetchOptions* aFetchOptions,
+                             nsIURI* aBaseURL)
+    : LoadedScript(ScriptKind::eClassic, aLoader, aFetchOptions, aBaseURL) {}
+
+//////////////////////////////////////////////////////////////
+// ModuleScript
+//////////////////////////////////////////////////////////////
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ModuleScript)
-NS_INTERFACE_MAP_END
+NS_INTERFACE_MAP_END_INHERITING(LoadedScript)
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(ModuleScript)
 
-NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(ModuleScript)
-  NS_IMPL_CYCLE_COLLECTION_UNLINK(mLoader)
-  NS_IMPL_CYCLE_COLLECTION_UNLINK(mFetchOptions)
-  NS_IMPL_CYCLE_COLLECTION_UNLINK(mBaseURL)
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(ModuleScript, LoadedScript)
   tmp->UnlinkModuleRecord();
   tmp->mParseError.setUndefined();
   tmp->mErrorToRethrow.setUndefined();
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(ModuleScript)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mLoader)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mFetchOptions)
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(ModuleScript, LoadedScript)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
-NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(ModuleScript)
+NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(ModuleScript, LoadedScript)
   NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mModuleRecord)
   NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mParseError)
   NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mErrorToRethrow)
 NS_IMPL_CYCLE_COLLECTION_TRACE_END
 
-NS_IMPL_CYCLE_COLLECTING_ADDREF(ModuleScript)
-NS_IMPL_CYCLE_COLLECTING_RELEASE(ModuleScript)
+NS_IMPL_ADDREF_INHERITED(ModuleScript, LoadedScript)
+NS_IMPL_RELEASE_INHERITED(ModuleScript, LoadedScript)
 
 ModuleScript::ModuleScript(ScriptLoader* aLoader,
                            ScriptFetchOptions* aFetchOptions, nsIURI* aBaseURL)
-    : mLoader(aLoader),
-      mFetchOptions(aFetchOptions),
-      mBaseURL(aBaseURL),
+    : LoadedScript(ScriptKind::eModule, aLoader, aFetchOptions, aBaseURL),
       mSourceElementAssociated(false) {
-  MOZ_ASSERT(mLoader);
-  MOZ_ASSERT(mFetchOptions);
-  MOZ_ASSERT(mBaseURL);
-  MOZ_ASSERT(!mModuleRecord);
+  MOZ_ASSERT(!ModuleRecord());
   MOZ_ASSERT(!HasParseError());
   MOZ_ASSERT(!HasErrorToRethrow());
 }
 
 void ModuleScript::UnlinkModuleRecord() {
   // Remove the module record's pointer to this object if present and
   // decrement our reference count. The reference is added by
   // SetModuleRecord() below.
@@ -68,30 +108,31 @@ void ModuleScript::UnlinkModuleRecord() 
     mModuleRecord = nullptr;
     Release();
   }
 }
 
 ModuleScript::~ModuleScript() {
   // The object may be destroyed without being unlinked first.
   UnlinkModuleRecord();
-  DropJSObjects(this);
 }
 
 void ModuleScript::SetModuleRecord(JS::Handle<JSObject*> aModuleRecord) {
   MOZ_ASSERT(!mModuleRecord);
-  MOZ_ASSERT(!HasParseError());
-  MOZ_ASSERT(!HasErrorToRethrow());
+  MOZ_ASSERT_IF(IsModuleScript(), !AsModuleScript()->HasParseError());
+  MOZ_ASSERT_IF(IsModuleScript(), !AsModuleScript()->HasErrorToRethrow());
 
   mModuleRecord = aModuleRecord;
 
   // Make module's host defined field point to this object and
   // increment our reference count. This is decremented by
   // UnlinkModuleRecord() above.
+  MOZ_ASSERT(JS::GetModulePrivate(mModuleRecord).isUndefined());
   JS::SetModulePrivate(mModuleRecord, JS::PrivateValue(this));
+
   HoldJSObjects(this);
   AddRef();
 }
 
 void HostFinalizeTopLevelScript(JSFreeOp* aFop, const JS::Value& aPrivate) {
   auto script = static_cast<ModuleScript*>(aPrivate.toPrivate());
   if (script) {
     MOZ_ASSERT(JS::GetModulePrivate(script->mModuleRecord.unbarrieredGet()) ==
@@ -110,22 +151,22 @@ void ModuleScript::SetParseError(const J
   HoldJSObjects(this);
 }
 
 void ModuleScript::SetErrorToRethrow(const JS::Value& aError) {
   MOZ_ASSERT(!aError.isUndefined());
 
   // This is only called after SetModuleRecord() or SetParseError() so we don't
   // need to call HoldJSObjects() here.
-  MOZ_ASSERT(mModuleRecord || HasParseError());
+  MOZ_ASSERT(ModuleRecord() || HasParseError());
 
   mErrorToRethrow = aError;
 }
 
 void ModuleScript::SetSourceElementAssociated() {
-  MOZ_ASSERT(mModuleRecord);
+  MOZ_ASSERT(ModuleRecord());
   MOZ_ASSERT(!mSourceElementAssociated);
 
   mSourceElementAssociated = true;
 }
 
 }  // namespace dom
 }  // namespace mozilla
--- a/dom/script/ModuleScript.h
+++ b/dom/script/ModuleScript.h
@@ -1,64 +1,110 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* 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_ModuleScript_h
-#define mozilla_dom_ModuleScript_h
+#ifndef mozilla_dom_LoadedScript_h
+#define mozilla_dom_LoadedScript_h
 
 #include "nsCOMPtr.h"
 #include "nsCycleCollectionParticipant.h"
 #include "jsapi.h"
+#include "ScriptLoadRequest.h"
 
 class nsIURI;
 
 namespace mozilla {
 namespace dom {
 
 class ScriptLoader;
 
 void HostFinalizeTopLevelScript(JSFreeOp* aFop, const JS::Value& aPrivate);
 
-class ModuleScript final : public nsISupports {
+class ClassicScript;
+class ModuleScript;
+
+class LoadedScript : public nsISupports {
+  ScriptKind mKind;
   RefPtr<ScriptLoader> mLoader;
   RefPtr<ScriptFetchOptions> mFetchOptions;
   nsCOMPtr<nsIURI> mBaseURL;
+
+ protected:
+  LoadedScript(ScriptKind aKind, ScriptLoader* aLoader,
+               ScriptFetchOptions* aFetchOptions, nsIURI* aBaseURL);
+
+  virtual ~LoadedScript();
+
+ public:
+  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
+  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(LoadedScript)
+
+  bool IsModuleScript() const { return mKind == ScriptKind::eModule; }
+
+  inline ClassicScript* AsClassicScript();
+  inline ModuleScript* AsModuleScript();
+
+  ScriptLoader* Loader() const { return mLoader; }
+  ScriptFetchOptions* FetchOptions() const { return mFetchOptions; }
+  nsIURI* BaseURL() const { return mBaseURL; }
+};
+
+class ClassicScript final : public LoadedScript {
+  ~ClassicScript() = default;
+
+ public:
+  ClassicScript(ScriptLoader* aLoader, ScriptFetchOptions* aFetchOptions,
+                nsIURI* aBaseURL);
+};
+
+// A single module script. May be used to satisfy multiple load requests.
+
+class ModuleScript final : public LoadedScript {
   JS::Heap<JSObject*> mModuleRecord;
   JS::Heap<JS::Value> mParseError;
   JS::Heap<JS::Value> mErrorToRethrow;
   bool mSourceElementAssociated;
 
   ~ModuleScript();
 
  public:
-  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
-  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(ModuleScript)
+  NS_DECL_ISUPPORTS_INHERITED
+  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(ModuleScript,
+                                                         LoadedScript)
 
   ModuleScript(ScriptLoader* aLoader, ScriptFetchOptions* aFetchOptions,
                nsIURI* aBaseURL);
 
   void SetModuleRecord(JS::Handle<JSObject*> aModuleRecord);
   void SetParseError(const JS::Value& aError);
   void SetErrorToRethrow(const JS::Value& aError);
   void SetSourceElementAssociated();
 
-  ScriptLoader* Loader() const { return mLoader; }
-  ScriptFetchOptions* FetchOptions() const { return mFetchOptions; }
   JSObject* ModuleRecord() const { return mModuleRecord; }
-  nsIURI* BaseURL() const { return mBaseURL; }
+
   JS::Value ParseError() const { return mParseError; }
   JS::Value ErrorToRethrow() const { return mErrorToRethrow; }
   bool HasParseError() const { return !mParseError.isUndefined(); }
   bool HasErrorToRethrow() const { return !mErrorToRethrow.isUndefined(); }
   bool SourceElementAssociated() const { return mSourceElementAssociated; }
 
   void UnlinkModuleRecord();
 
   friend void HostFinalizeTopLevelScript(JSFreeOp*, const JS::Value&);
 };
 
+ClassicScript* LoadedScript::AsClassicScript() {
+  MOZ_ASSERT(!IsModuleScript());
+  return static_cast<ClassicScript*>(this);
+}
+
+ModuleScript* LoadedScript::AsModuleScript() {
+  MOZ_ASSERT(IsModuleScript());
+  return static_cast<ModuleScript*>(this);
+}
+
 }  // namespace dom
 }  // namespace mozilla
 
-#endif  // mozilla_dom_ModuleScript_h
+#endif  // mozilla_dom_LoadedScript_h