1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
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 "LoadedScript.h"
9 #include "mozilla/HoldDropJSObjects.h"
11 #include "jsfriendapi.h"
12 #include "js/Modules.h" // JS::{Get,Set}ModulePrivate
14 namespace JS::loader
{
16 //////////////////////////////////////////////////////////////
18 //////////////////////////////////////////////////////////////
20 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(LoadedScript
)
23 NS_IMPL_CYCLE_COLLECTION_CLASS(LoadedScript
)
25 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(LoadedScript
)
26 NS_IMPL_CYCLE_COLLECTION_UNLINK(mFetchOptions
)
27 NS_IMPL_CYCLE_COLLECTION_UNLINK(mBaseURL
)
28 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
30 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(LoadedScript
)
31 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mFetchOptions
)
32 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
34 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(LoadedScript
)
35 NS_IMPL_CYCLE_COLLECTION_TRACE_END
37 NS_IMPL_CYCLE_COLLECTING_ADDREF(LoadedScript
)
38 NS_IMPL_CYCLE_COLLECTING_RELEASE(LoadedScript
)
40 LoadedScript::LoadedScript(ScriptKind aKind
, ScriptFetchOptions
* aFetchOptions
,
42 : mKind(aKind
), mFetchOptions(aFetchOptions
), mBaseURL(aBaseURL
) {
43 MOZ_ASSERT(mFetchOptions
);
47 LoadedScript::~LoadedScript() { mozilla::DropJSObjects(this); }
49 void LoadedScript::AssociateWithScript(JSScript
* aScript
) {
50 // Set a JSScript's private value to point to this object. The JS engine will
51 // increment our reference count by calling HostAddRefTopLevelScript(). This
52 // is decremented by HostReleaseTopLevelScript() below when the JSScript dies.
54 MOZ_ASSERT(JS::GetScriptPrivate(aScript
).isUndefined());
55 JS::SetScriptPrivate(aScript
, JS::PrivateValue(this));
58 inline void CheckModuleScriptPrivate(LoadedScript
* script
,
59 const JS::Value
& aPrivate
) {
61 if (script
->IsModuleScript()) {
62 JSObject
* module
= script
->AsModuleScript()->mModuleRecord
.unbarrieredGet();
63 MOZ_ASSERT_IF(module
, JS::GetModulePrivate(module
) == aPrivate
);
68 void HostAddRefTopLevelScript(const JS::Value
& aPrivate
) {
69 // Increment the reference count of a LoadedScript object that is now pointed
70 // to by a JSScript. The reference count is decremented by
71 // HostReleaseTopLevelScript() below.
73 auto script
= static_cast<LoadedScript
*>(aPrivate
.toPrivate());
74 CheckModuleScriptPrivate(script
, aPrivate
);
78 void HostReleaseTopLevelScript(const JS::Value
& aPrivate
) {
79 // Decrement the reference count of a LoadedScript object that was pointed to
80 // by a JSScript. The reference count was originally incremented by
81 // HostAddRefTopLevelScript() above.
83 auto script
= static_cast<LoadedScript
*>(aPrivate
.toPrivate());
84 CheckModuleScriptPrivate(script
, aPrivate
);
88 //////////////////////////////////////////////////////////////
90 //////////////////////////////////////////////////////////////
92 EventScript::EventScript(ScriptFetchOptions
* aFetchOptions
, nsIURI
* aBaseURL
)
93 : LoadedScript(ScriptKind::eEvent
, aFetchOptions
, aBaseURL
) {}
95 //////////////////////////////////////////////////////////////
97 //////////////////////////////////////////////////////////////
99 ClassicScript::ClassicScript(ScriptFetchOptions
* aFetchOptions
,
101 : LoadedScript(ScriptKind::eClassic
, aFetchOptions
, aBaseURL
) {}
103 //////////////////////////////////////////////////////////////
105 //////////////////////////////////////////////////////////////
107 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ModuleScript
)
108 NS_INTERFACE_MAP_END_INHERITING(LoadedScript
)
110 NS_IMPL_CYCLE_COLLECTION_CLASS(ModuleScript
)
112 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(ModuleScript
, LoadedScript
)
113 tmp
->UnlinkModuleRecord();
114 tmp
->mParseError
.setUndefined();
115 tmp
->mErrorToRethrow
.setUndefined();
116 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
118 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(ModuleScript
, LoadedScript
)
119 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
121 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(ModuleScript
, LoadedScript
)
122 NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mModuleRecord
)
123 NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mParseError
)
124 NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mErrorToRethrow
)
125 NS_IMPL_CYCLE_COLLECTION_TRACE_END
127 NS_IMPL_ADDREF_INHERITED(ModuleScript
, LoadedScript
)
128 NS_IMPL_RELEASE_INHERITED(ModuleScript
, LoadedScript
)
130 ModuleScript::ModuleScript(ScriptFetchOptions
* aFetchOptions
, nsIURI
* aBaseURL
)
131 : LoadedScript(ScriptKind::eModule
, aFetchOptions
, aBaseURL
),
132 mDebuggerDataInitialized(false) {
133 MOZ_ASSERT(!ModuleRecord());
134 MOZ_ASSERT(!HasParseError());
135 MOZ_ASSERT(!HasErrorToRethrow());
138 void ModuleScript::Shutdown() {
140 JS::ClearModuleEnvironment(mModuleRecord
);
143 UnlinkModuleRecord();
146 void ModuleScript::UnlinkModuleRecord() {
147 // Remove the module record's pointer to this object if present and
148 // decrement our reference count. The reference is added by
149 // SetModuleRecord() below.
151 MOZ_ASSERT(JS::GetModulePrivate(mModuleRecord
).toPrivate() == this);
152 JS::SetModulePrivate(mModuleRecord
, JS::UndefinedValue());
153 mModuleRecord
= nullptr;
157 ModuleScript::~ModuleScript() {
158 // The object may be destroyed without being unlinked first.
159 UnlinkModuleRecord();
162 void ModuleScript::SetModuleRecord(JS::Handle
<JSObject
*> aModuleRecord
) {
163 MOZ_ASSERT(!mModuleRecord
);
164 MOZ_ASSERT_IF(IsModuleScript(), !AsModuleScript()->HasParseError());
165 MOZ_ASSERT_IF(IsModuleScript(), !AsModuleScript()->HasErrorToRethrow());
167 mModuleRecord
= aModuleRecord
;
169 // Make module's host defined field point to this object. The JS engine will
170 // increment our reference count by calling HostAddRefTopLevelScript(). This
171 // is decremented when the field is cleared in UnlinkModuleRecord() above or
172 // when the module record dies.
173 MOZ_ASSERT(JS::GetModulePrivate(mModuleRecord
).isUndefined());
174 JS::SetModulePrivate(mModuleRecord
, JS::PrivateValue(this));
176 mozilla::HoldJSObjects(this);
179 void ModuleScript::SetParseError(const JS::Value
& aError
) {
180 MOZ_ASSERT(!aError
.isUndefined());
181 MOZ_ASSERT(!HasParseError());
182 MOZ_ASSERT(!HasErrorToRethrow());
184 UnlinkModuleRecord();
185 mParseError
= aError
;
186 mozilla::HoldJSObjects(this);
189 void ModuleScript::SetErrorToRethrow(const JS::Value
& aError
) {
190 MOZ_ASSERT(!aError
.isUndefined());
192 // This is only called after SetModuleRecord() or SetParseError() so we don't
193 // need to call HoldJSObjects() here.
194 MOZ_ASSERT(ModuleRecord() || HasParseError());
196 mErrorToRethrow
= aError
;
199 void ModuleScript::SetDebuggerDataInitialized() {
200 MOZ_ASSERT(ModuleRecord());
201 MOZ_ASSERT(!mDebuggerDataInitialized
);
203 mDebuggerDataInitialized
= true;
206 } // namespace JS::loader