Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/dom/script/ScriptLoadRequest.cpp
Line
Count
Source (jump to first uncovered line)
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/. */
6
7
#include "ModuleLoadRequest.h"
8
9
#include "mozilla/HoldDropJSObjects.h"
10
#include "mozilla/Unused.h"
11
12
#include "nsICacheInfoChannel.h"
13
#include "ScriptLoadRequest.h"
14
#include "ScriptSettings.h"
15
16
namespace mozilla {
17
namespace dom {
18
19
//////////////////////////////////////////////////////////////
20
// ScriptFetchOptions
21
//////////////////////////////////////////////////////////////
22
23
NS_IMPL_CYCLE_COLLECTION(ScriptFetchOptions,
24
                         mElement,
25
                         mTriggeringPrincipal)
26
27
NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(ScriptFetchOptions, AddRef)
28
NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(ScriptFetchOptions, Release)
29
30
ScriptFetchOptions::ScriptFetchOptions(mozilla::CORSMode aCORSMode,
31
                                       mozilla::net::ReferrerPolicy aReferrerPolicy,
32
                                       nsIScriptElement* aElement,
33
                                       nsIPrincipal* aTriggeringPrincipal)
34
  : mCORSMode(aCORSMode)
35
  , mReferrerPolicy(aReferrerPolicy)
36
  , mElement(aElement)
37
  , mTriggeringPrincipal(aTriggeringPrincipal)
38
0
{
39
0
  MOZ_ASSERT(mTriggeringPrincipal);
40
0
}
41
42
ScriptFetchOptions::~ScriptFetchOptions()
43
0
{}
44
45
//////////////////////////////////////////////////////////////
46
// ScriptLoadRequest
47
//////////////////////////////////////////////////////////////
48
49
0
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ScriptLoadRequest)
50
0
NS_INTERFACE_MAP_END
51
52
NS_IMPL_CYCLE_COLLECTING_ADDREF(ScriptLoadRequest)
53
NS_IMPL_CYCLE_COLLECTING_RELEASE(ScriptLoadRequest)
54
55
NS_IMPL_CYCLE_COLLECTION_CLASS(ScriptLoadRequest)
56
57
0
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(ScriptLoadRequest)
58
0
  NS_IMPL_CYCLE_COLLECTION_UNLINK(mFetchOptions)
59
0
  NS_IMPL_CYCLE_COLLECTION_UNLINK(mCacheInfo)
60
0
  tmp->DropBytecodeCacheReferences();
61
0
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
62
63
0
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(ScriptLoadRequest)
64
0
  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mFetchOptions)
65
0
  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCacheInfo)
66
0
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
67
68
0
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(ScriptLoadRequest)
69
0
  NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mScript)
70
0
NS_IMPL_CYCLE_COLLECTION_TRACE_END
71
72
ScriptLoadRequest::ScriptLoadRequest(ScriptKind aKind,
73
                                     nsIURI* aURI,
74
                                     ScriptFetchOptions* aFetchOptions,
75
                                     const SRIMetadata &aIntegrity,
76
                                     nsIURI* aReferrer)
77
  : mKind(aKind)
78
  , mScriptMode(ScriptMode::eBlocking)
79
  , mProgress(Progress::eLoading)
80
  , mDataType(DataType::eUnknown)
81
  , mScriptFromHead(false)
82
  , mIsInline(true)
83
  , mHasSourceMapURL(false)
84
  , mInDeferList(false)
85
  , mInAsyncList(false)
86
  , mIsNonAsyncScriptInserted(false)
87
  , mIsXSLT(false)
88
  , mIsCanceled(false)
89
  , mWasCompiledOMT(false)
90
  , mIsTracking(false)
91
  , mFetchOptions(aFetchOptions)
92
  , mOffThreadToken(nullptr)
93
  , mScriptTextLength(0)
94
  , mScriptBytecode()
95
  , mBytecodeOffset(0)
96
  , mURI(aURI)
97
  , mLineNo(1)
98
  , mIntegrity(aIntegrity)
99
  , mReferrer(aReferrer)
100
0
{
101
0
  MOZ_ASSERT(mFetchOptions);
102
0
}
103
104
ScriptLoadRequest::~ScriptLoadRequest()
105
0
{
106
0
  // We should always clean up any off-thread script parsing resources.
107
0
  MOZ_ASSERT(!mOffThreadToken);
108
0
109
0
  // But play it safe in release builds and try to clean them up here
110
0
  // as a fail safe.
111
0
  MaybeCancelOffThreadScript();
112
0
113
0
  if (mScript) {
114
0
    DropBytecodeCacheReferences();
115
0
  }
116
0
}
117
118
void
119
ScriptLoadRequest::SetReady()
120
0
{
121
0
  MOZ_ASSERT(mProgress != Progress::eReady);
122
0
  mProgress = Progress::eReady;
123
0
}
124
125
void
126
ScriptLoadRequest::Cancel()
127
0
{
128
0
  MaybeCancelOffThreadScript();
129
0
  mIsCanceled = true;
130
0
}
131
132
void
133
ScriptLoadRequest::MaybeCancelOffThreadScript()
134
0
{
135
0
  MOZ_ASSERT(NS_IsMainThread());
136
0
137
0
  if (!mOffThreadToken) {
138
0
    return;
139
0
  }
140
0
141
0
  JSContext* cx = danger::GetJSContext();
142
0
  // Follow the same conditions as ScriptLoader::AttemptAsyncScriptCompile
143
0
  if (IsModuleRequest()) {
144
0
    JS::CancelOffThreadModule(cx, mOffThreadToken);
145
0
  } else if (IsSource()) {
146
0
    JS::CancelOffThreadScript(cx, mOffThreadToken);
147
0
  } else {
148
0
    MOZ_ASSERT(IsBytecode());
149
0
    JS::CancelOffThreadScriptDecoder(cx, mOffThreadToken);
150
0
  }
151
0
  mOffThreadToken = nullptr;
152
0
}
153
154
void
155
ScriptLoadRequest::DropBytecodeCacheReferences()
156
0
{
157
0
  mCacheInfo = nullptr;
158
0
  mScript = nullptr;
159
0
  DropJSObjects(this);
160
0
}
161
162
inline ModuleLoadRequest*
163
ScriptLoadRequest::AsModuleRequest()
164
0
{
165
0
  MOZ_ASSERT(IsModuleRequest());
166
0
  return static_cast<ModuleLoadRequest*>(this);
167
0
}
168
169
void
170
ScriptLoadRequest::SetScriptMode(bool aDeferAttr, bool aAsyncAttr)
171
0
{
172
0
  if (aAsyncAttr) {
173
0
    mScriptMode = ScriptMode::eAsync;
174
0
  } else if (aDeferAttr || IsModuleRequest()) {
175
0
    mScriptMode = ScriptMode::eDeferred;
176
0
  } else {
177
0
    mScriptMode = ScriptMode::eBlocking;
178
0
  }
179
0
}
180
181
void
182
ScriptLoadRequest::SetUnknownDataType()
183
0
{
184
0
  mDataType = DataType::eUnknown;
185
0
  mScriptData.reset();
186
0
}
187
188
void
189
ScriptLoadRequest::SetTextSource()
190
0
{
191
0
  MOZ_ASSERT(IsUnknownDataType());
192
0
  mDataType = DataType::eTextSource;
193
0
  mScriptData.emplace(VariantType<ScriptTextBuffer>());
194
0
}
195
196
void
197
ScriptLoadRequest::SetBinASTSource()
198
0
{
199
0
#ifdef JS_BUILD_BINAST
200
0
  MOZ_ASSERT(IsUnknownDataType());
201
0
  mDataType = DataType::eBinASTSource;
202
0
  mScriptData.emplace(VariantType<BinASTSourceBuffer>());
203
#else
204
  MOZ_CRASH("BinAST not supported");
205
#endif
206
}
207
208
void
209
ScriptLoadRequest::SetBytecode()
210
0
{
211
0
  MOZ_ASSERT(IsUnknownDataType());
212
0
  mDataType = DataType::eBytecode;
213
0
}
214
215
bool
216
ScriptLoadRequest::ShouldAcceptBinASTEncoding() const
217
0
{
218
0
#ifdef JS_BUILD_BINAST
219
0
  // We accept the BinAST encoding if we're using a secure connection.
220
0
221
0
  bool isHTTPS = false;
222
0
  nsresult rv = mURI->SchemeIs("https", &isHTTPS);
223
0
  MOZ_ASSERT(NS_SUCCEEDED(rv));
224
0
  Unused << rv;
225
0
226
0
  return isHTTPS;
227
#else
228
  MOZ_CRASH("BinAST not supported");
229
#endif
230
}
231
232
void
233
ScriptLoadRequest::ClearScriptSource()
234
0
{
235
0
  if (IsTextSource()) {
236
0
    ScriptText().clearAndFree();
237
0
  } else if (IsBinASTSource()) {
238
0
    ScriptBinASTData().clearAndFree();
239
0
  }
240
0
}
241
242
//////////////////////////////////////////////////////////////
243
// ScriptLoadRequestList
244
//////////////////////////////////////////////////////////////
245
246
ScriptLoadRequestList::~ScriptLoadRequestList()
247
0
{
248
0
  Clear();
249
0
}
250
251
void
252
ScriptLoadRequestList::Clear()
253
0
{
254
0
  while (!isEmpty()) {
255
0
    RefPtr<ScriptLoadRequest> first = StealFirst();
256
0
    first->Cancel();
257
0
    // And just let it go out of scope and die.
258
0
  }
259
0
}
260
261
#ifdef DEBUG
262
bool
263
ScriptLoadRequestList::Contains(ScriptLoadRequest* aElem) const
264
{
265
  for (const ScriptLoadRequest* req = getFirst();
266
       req; req = req->getNext()) {
267
    if (req == aElem) {
268
      return true;
269
    }
270
  }
271
272
  return false;
273
}
274
#endif // DEBUG
275
276
inline void
277
ImplCycleCollectionUnlink(ScriptLoadRequestList& aField)
278
0
{
279
0
  while (!aField.isEmpty()) {
280
0
    RefPtr<ScriptLoadRequest> first = aField.StealFirst();
281
0
  }
282
0
}
283
284
inline void
285
ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& aCallback,
286
                            ScriptLoadRequestList& aField,
287
                            const char* aName,
288
                            uint32_t aFlags)
289
0
{
290
0
  for (ScriptLoadRequest* request = aField.getFirst();
291
0
       request; request = request->getNext())
292
0
  {
293
0
    CycleCollectionNoteChild(aCallback, request, aName, aFlags);
294
0
  }
295
0
}
296
297
} // dom namespace
298
} // mozilla namespace