Line data Source code
1 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /* vim: set ts=8 sts=4 et sw=4 tw=99: */
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 "mozilla/Attributes.h"
8 :
9 : #include <cstdarg>
10 :
11 : #include "mozilla/Logging.h"
12 : #ifdef ANDROID
13 : #include <android/log.h>
14 : #endif
15 : #ifdef XP_WIN
16 : #include <windows.h>
17 : #endif
18 :
19 : #include "jsapi.h"
20 : #include "nsCOMPtr.h"
21 : #include "nsAutoPtr.h"
22 : #include "nsIComponentManager.h"
23 : #include "mozilla/Module.h"
24 : #include "nsIFile.h"
25 : #include "mozJSComponentLoader.h"
26 : #include "mozJSLoaderUtils.h"
27 : #include "nsIXPConnect.h"
28 : #include "nsIObserverService.h"
29 : #include "nsIScriptSecurityManager.h"
30 : #include "nsIFileURL.h"
31 : #include "nsIJARURI.h"
32 : #include "nsNetUtil.h"
33 : #include "jsprf.h"
34 : #include "nsJSPrincipals.h"
35 : #include "nsJSUtils.h"
36 : #include "xpcprivate.h"
37 : #include "xpcpublic.h"
38 : #include "nsContentUtils.h"
39 : #include "nsXULAppAPI.h"
40 : #include "GeckoProfiler.h"
41 : #include "WrapperFactory.h"
42 :
43 : #include "AutoMemMap.h"
44 : #include "ScriptPreloader-inl.h"
45 :
46 : #include "mozilla/AddonPathService.h"
47 : #include "mozilla/scache/StartupCache.h"
48 : #include "mozilla/scache/StartupCacheUtils.h"
49 : #include "mozilla/MacroForEach.h"
50 : #include "mozilla/Preferences.h"
51 : #include "mozilla/ScriptPreloader.h"
52 : #include "mozilla/dom/ScriptSettings.h"
53 : #include "mozilla/UniquePtrExtensions.h"
54 : #include "mozilla/Unused.h"
55 :
56 : using namespace mozilla;
57 : using namespace mozilla::scache;
58 : using namespace mozilla::loader;
59 : using namespace xpc;
60 : using namespace JS;
61 :
62 : static const char kObserverServiceContractID[] = "@mozilla.org/observer-service;1";
63 : static const char kJSCachePrefix[] = "jsloader";
64 :
65 : /**
66 : * Buffer sizes for serialization and deserialization of scripts.
67 : * FIXME: bug #411579 (tune this macro!) Last updated: Jan 2008
68 : */
69 : #define XPC_SERIALIZATION_BUFFER_SIZE (64 * 1024)
70 : #define XPC_DESERIALIZATION_BUFFER_SIZE (12 * 8192)
71 :
72 : // MOZ_LOG=JSComponentLoader:5
73 : static LazyLogModule gJSCLLog("JSComponentLoader");
74 :
75 : #define LOG(args) MOZ_LOG(gJSCLLog, mozilla::LogLevel::Debug, args)
76 :
77 : // Components.utils.import error messages
78 : #define ERROR_SCOPE_OBJ "%s - Second argument must be an object."
79 : #define ERROR_NOT_PRESENT "%s - EXPORTED_SYMBOLS is not present."
80 : #define ERROR_NOT_AN_ARRAY "%s - EXPORTED_SYMBOLS is not an array."
81 : #define ERROR_GETTING_ARRAY_LENGTH "%s - Error getting array length of EXPORTED_SYMBOLS."
82 : #define ERROR_ARRAY_ELEMENT "%s - EXPORTED_SYMBOLS[%d] is not a string."
83 : #define ERROR_GETTING_SYMBOL "%s - Could not get symbol '%s'."
84 : #define ERROR_SETTING_SYMBOL "%s - Could not set symbol '%s' on target object."
85 :
86 : static bool
87 1 : Dump(JSContext* cx, unsigned argc, Value* vp)
88 : {
89 1 : CallArgs args = CallArgsFromVp(argc, vp);
90 :
91 1 : if (args.length() == 0)
92 0 : return true;
93 :
94 2 : RootedString str(cx, JS::ToString(cx, args[0]));
95 1 : if (!str)
96 0 : return false;
97 :
98 2 : JSAutoByteString utf8str;
99 1 : if (!utf8str.encodeUtf8(cx, str))
100 0 : return false;
101 :
102 : #ifdef ANDROID
103 : __android_log_print(ANDROID_LOG_INFO, "Gecko", "%s", utf8str.ptr());
104 : #endif
105 : #ifdef XP_WIN
106 : if (IsDebuggerPresent()) {
107 : nsAutoJSString wstr;
108 : if (!wstr.init(cx, str))
109 : return false;
110 : OutputDebugStringW(wstr.get());
111 : }
112 : #endif
113 1 : fputs(utf8str.ptr(), stdout);
114 1 : fflush(stdout);
115 1 : return true;
116 : }
117 :
118 : static bool
119 0 : Debug(JSContext* cx, unsigned argc, Value* vp)
120 : {
121 : #ifdef DEBUG
122 0 : return Dump(cx, argc, vp);
123 : #else
124 : return true;
125 : #endif
126 : }
127 :
128 : static const JSFunctionSpec gGlobalFun[] = {
129 : JS_FS("dump", Dump, 1,0),
130 : JS_FS("debug", Debug, 1,0),
131 : JS_FS("atob", Atob, 1,0),
132 : JS_FS("btoa", Btoa, 1,0),
133 : JS_FS_END
134 : };
135 :
136 : class MOZ_STACK_CLASS JSCLContextHelper
137 : {
138 : public:
139 : explicit JSCLContextHelper(JSContext* aCx);
140 : ~JSCLContextHelper();
141 :
142 : void reportErrorAfterPop(UniqueChars&& buf);
143 :
144 : private:
145 : JSContext* mContext;
146 : UniqueChars mBuf;
147 :
148 : // prevent copying and assignment
149 : JSCLContextHelper(const JSCLContextHelper&) = delete;
150 : const JSCLContextHelper& operator=(const JSCLContextHelper&) = delete;
151 : };
152 :
153 : static nsresult
154 : MOZ_FORMAT_PRINTF(2, 3)
155 0 : ReportOnCallerUTF8(JSContext* callerContext,
156 : const char* format, ...) {
157 0 : if (!callerContext) {
158 0 : return NS_ERROR_FAILURE;
159 : }
160 :
161 : va_list ap;
162 0 : va_start(ap, format);
163 :
164 0 : UniqueChars buf = JS_vsmprintf(format, ap);
165 0 : if (!buf) {
166 0 : va_end(ap);
167 0 : return NS_ERROR_OUT_OF_MEMORY;
168 : }
169 :
170 0 : JS_ReportErrorUTF8(callerContext, "%s", buf.get());
171 :
172 0 : va_end(ap);
173 0 : return NS_OK;
174 : }
175 :
176 : static nsresult
177 : MOZ_FORMAT_PRINTF(2, 3)
178 0 : ReportOnCallerUTF8(JSCLContextHelper& helper,
179 : const char* format, ...)
180 : {
181 : va_list ap;
182 0 : va_start(ap, format);
183 :
184 0 : UniqueChars buf = JS_vsmprintf(format, ap);
185 0 : if (!buf) {
186 0 : va_end(ap);
187 0 : return NS_ERROR_OUT_OF_MEMORY;
188 : }
189 :
190 0 : helper.reportErrorAfterPop(Move(buf));
191 0 : va_end(ap);
192 0 : return NS_OK;
193 : }
194 :
195 3 : mozJSComponentLoader::mozJSComponentLoader()
196 : : mModules(16),
197 : mImports(16),
198 : mInProgressImports(16),
199 3 : mInitialized(false)
200 : {
201 3 : MOZ_ASSERT(!sSelf, "mozJSComponentLoader should be a singleton");
202 :
203 3 : sSelf = this;
204 3 : }
205 :
206 : #define ENSURE_DEP(name) { nsresult rv = Ensure##name(); NS_ENSURE_SUCCESS(rv, rv); }
207 : #define ENSURE_DEPS(...) MOZ_FOR_EACH(ENSURE_DEP, (), (__VA_ARGS__));
208 : #define BEGIN_ENSURE(self, ...) { \
209 : if (m##self) \
210 : return NS_OK; \
211 : ENSURE_DEPS(__VA_ARGS__); \
212 : }
213 :
214 1047 : class MOZ_STACK_CLASS ComponentLoaderInfo {
215 : public:
216 1046 : explicit ComponentLoaderInfo(const nsACString& aLocation) : mLocation(aLocation) {}
217 :
218 : nsIIOService* IOService() { MOZ_ASSERT(mIOService); return mIOService; }
219 2044 : nsresult EnsureIOService() {
220 2044 : if (mIOService)
221 998 : return NS_OK;
222 : nsresult rv;
223 1046 : mIOService = do_GetIOService(&rv);
224 1046 : return rv;
225 : }
226 :
227 765 : nsIURI* URI() { MOZ_ASSERT(mURI); return mURI; }
228 2503 : nsresult EnsureURI() {
229 2503 : BEGIN_ENSURE(URI, IOService);
230 1046 : return mIOService->NewURI(mLocation, nullptr, nullptr, getter_AddRefs(mURI));
231 : }
232 :
233 0 : nsIChannel* ScriptChannel() { MOZ_ASSERT(mScriptChannel); return mScriptChannel; }
234 998 : nsresult EnsureScriptChannel() {
235 998 : BEGIN_ENSURE(ScriptChannel, IOService, URI);
236 1996 : return NS_NewChannel(getter_AddRefs(mScriptChannel),
237 : mURI,
238 : nsContentUtils::GetSystemPrincipal(),
239 : nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL,
240 : nsIContentPolicy::TYPE_SCRIPT,
241 : nullptr, // aLoadGroup
242 : nullptr, // aCallbacks
243 : nsIRequest::LOAD_NORMAL,
244 998 : mIOService);
245 : }
246 :
247 1996 : nsIURI* ResolvedURI() { MOZ_ASSERT(mResolvedURI); return mResolvedURI; }
248 1996 : nsresult EnsureResolvedURI() {
249 1996 : BEGIN_ENSURE(ResolvedURI, ScriptChannel);
250 998 : return mScriptChannel->GetURI(getter_AddRefs(mResolvedURI));
251 : }
252 :
253 1828 : nsAutoCString& Key() { return *mKey; }
254 998 : nsresult EnsureKey() {
255 998 : ENSURE_DEPS(ResolvedURI);
256 998 : mKey.emplace();
257 998 : return mResolvedURI->GetSpec(*mKey);
258 : }
259 :
260 995 : MOZ_MUST_USE nsresult GetLocation(nsCString& aLocation) {
261 995 : nsresult rv = EnsureURI();
262 995 : NS_ENSURE_SUCCESS(rv, rv);
263 995 : return mURI->GetSpec(aLocation);
264 : }
265 :
266 : private:
267 : const nsACString& mLocation;
268 : nsCOMPtr<nsIIOService> mIOService;
269 : nsCOMPtr<nsIURI> mURI;
270 : nsCOMPtr<nsIChannel> mScriptChannel;
271 : nsCOMPtr<nsIURI> mResolvedURI;
272 : Maybe<nsAutoCString> mKey; // This is safe because we're MOZ_STACK_CLASS
273 : };
274 :
275 : #undef BEGIN_ENSURE
276 : #undef ENSURE_DEPS
277 : #undef ENSURE_DEP
278 :
279 0 : mozJSComponentLoader::~mozJSComponentLoader()
280 : {
281 0 : if (mInitialized) {
282 0 : NS_ERROR("'xpcom-shutdown-loaders' was not fired before cleaning up mozJSComponentLoader");
283 0 : UnloadModules();
284 : }
285 :
286 0 : sSelf = nullptr;
287 0 : }
288 :
289 : mozJSComponentLoader*
290 : mozJSComponentLoader::sSelf;
291 :
292 3390 : NS_IMPL_ISUPPORTS(mozJSComponentLoader,
293 : mozilla::ModuleLoader,
294 : xpcIJSModuleLoader,
295 : nsIObserver)
296 :
297 : nsresult
298 3 : mozJSComponentLoader::ReallyInit()
299 : {
300 : nsresult rv;
301 : nsCOMPtr<nsIObserverService> obsSvc =
302 6 : do_GetService(kObserverServiceContractID, &rv);
303 3 : NS_ENSURE_SUCCESS(rv, rv);
304 :
305 3 : rv = obsSvc->AddObserver(this, "xpcom-shutdown-loaders", false);
306 3 : NS_ENSURE_SUCCESS(rv, rv);
307 :
308 3 : mInitialized = true;
309 :
310 3 : return NS_OK;
311 : }
312 :
313 : // For terrible compatibility reasons, we need to consider both the global
314 : // lexical environment and the global of modules when searching for exported
315 : // symbols.
316 : static JSObject*
317 1047 : ResolveModuleObjectProperty(JSContext* aCx, HandleObject aModObj, const char* name)
318 : {
319 1047 : if (JS_HasExtensibleLexicalEnvironment(aModObj)) {
320 2094 : RootedObject lexical(aCx, JS_ExtensibleLexicalEnvironment(aModObj));
321 : bool found;
322 1047 : if (!JS_HasOwnProperty(aCx, lexical, name, &found)) {
323 0 : return nullptr;
324 : }
325 1047 : if (found) {
326 0 : return lexical;
327 : }
328 : }
329 1047 : return aModObj;
330 : }
331 :
332 : const mozilla::Module*
333 48 : mozJSComponentLoader::LoadModule(FileLocation& aFile)
334 : {
335 48 : if (!NS_IsMainThread()) {
336 0 : MOZ_ASSERT(false, "Don't use JS components off the main thread");
337 : return nullptr;
338 : }
339 :
340 97 : nsCOMPtr<nsIFile> file = aFile.GetBaseFile();
341 :
342 97 : nsCString spec;
343 48 : aFile.GetURIString(spec);
344 97 : ComponentLoaderInfo info(spec);
345 48 : nsresult rv = info.EnsureURI();
346 48 : NS_ENSURE_SUCCESS(rv, nullptr);
347 :
348 48 : if (!mInitialized) {
349 3 : rv = ReallyInit();
350 3 : if (NS_FAILED(rv))
351 0 : return nullptr;
352 : }
353 :
354 97 : AUTO_PROFILER_LABEL_DYNAMIC("mozJSComponentLoader::LoadModule", OTHER,
355 : spec.get());
356 :
357 : ModuleEntry* mod;
358 48 : if (mModules.Get(spec, &mod))
359 0 : return mod;
360 :
361 97 : dom::AutoJSAPI jsapi;
362 48 : jsapi.Init();
363 48 : JSContext* cx = jsapi.cx();
364 :
365 145 : nsAutoPtr<ModuleEntry> entry(new ModuleEntry(RootingContext::get(cx)));
366 97 : RootedValue dummy(cx);
367 145 : rv = ObjectForLocation(info, file, &entry->obj, &entry->thisObjectKey,
368 96 : &entry->location, false, &dummy);
369 49 : if (NS_FAILED(rv)) {
370 0 : return nullptr;
371 : }
372 :
373 98 : nsCOMPtr<nsIComponentManager> cm;
374 49 : rv = NS_GetComponentManager(getter_AddRefs(cm));
375 49 : if (NS_FAILED(rv))
376 0 : return nullptr;
377 :
378 98 : JSAutoCompartment ac(cx, entry->obj);
379 98 : RootedObject entryObj(cx, entry->obj);
380 :
381 98 : RootedObject NSGetFactoryHolder(cx, ResolveModuleObjectProperty(cx, entryObj, "NSGetFactory"));
382 98 : RootedValue NSGetFactory_val(cx);
383 294 : if (!NSGetFactoryHolder ||
384 343 : !JS_GetProperty(cx, NSGetFactoryHolder, "NSGetFactory", &NSGetFactory_val) ||
385 49 : NSGetFactory_val.isUndefined())
386 : {
387 0 : return nullptr;
388 : }
389 :
390 49 : if (JS_TypeOfValue(cx, NSGetFactory_val) != JSTYPE_FUNCTION) {
391 : /*
392 : * spec's encoding is ASCII unless it's zip file, otherwise it's
393 : * random encoding. Latin1 variant is safe for random encoding.
394 : */
395 0 : JS_ReportErrorLatin1(cx, "%s has NSGetFactory property that is not a function",
396 0 : spec.get());
397 0 : return nullptr;
398 : }
399 :
400 98 : RootedObject jsGetFactoryObj(cx);
401 98 : if (!JS_ValueToObject(cx, NSGetFactory_val, &jsGetFactoryObj) ||
402 49 : !jsGetFactoryObj) {
403 : /* XXX report error properly */
404 0 : return nullptr;
405 : }
406 :
407 98 : rv = nsXPConnect::XPConnect()->WrapJS(cx, jsGetFactoryObj,
408 : NS_GET_IID(xpcIJSGetFactory),
409 147 : getter_AddRefs(entry->getfactoryobj));
410 49 : if (NS_FAILED(rv)) {
411 : /* XXX report error properly */
412 : #ifdef DEBUG
413 0 : fprintf(stderr, "mJCL: couldn't get nsIModule from jsval\n");
414 : #endif
415 0 : return nullptr;
416 : }
417 :
418 : // Cache this module for later
419 49 : mModules.Put(spec, entry);
420 :
421 : // The hash owns the ModuleEntry now, forget about it
422 49 : return entry.forget();
423 : }
424 :
425 : void
426 599 : mozJSComponentLoader::FindTargetObject(JSContext* aCx,
427 : MutableHandleObject aTargetObject)
428 : {
429 599 : aTargetObject.set(CurrentGlobalOrNull(aCx));
430 599 : }
431 :
432 : // This requires that the keys be strings and the values be pointers.
433 : template <class Key, class Data, class UserData>
434 : static size_t
435 0 : SizeOfTableExcludingThis(const nsBaseHashtable<Key, Data, UserData>& aTable,
436 : MallocSizeOf aMallocSizeOf)
437 : {
438 0 : size_t n = aTable.ShallowSizeOfExcludingThis(aMallocSizeOf);
439 0 : for (auto iter = aTable.ConstIter(); !iter.Done(); iter.Next()) {
440 0 : n += iter.Key().SizeOfExcludingThisIfUnshared(aMallocSizeOf);
441 0 : n += iter.Data()->SizeOfIncludingThis(aMallocSizeOf);
442 : }
443 0 : return n;
444 : }
445 :
446 : size_t
447 0 : mozJSComponentLoader::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf)
448 : {
449 0 : size_t n = aMallocSizeOf(this);
450 0 : n += SizeOfTableExcludingThis(mModules, aMallocSizeOf);
451 0 : n += SizeOfTableExcludingThis(mImports, aMallocSizeOf);
452 0 : n += SizeOfTableExcludingThis(mInProgressImports, aMallocSizeOf);
453 0 : return n;
454 : }
455 :
456 : void
457 255 : mozJSComponentLoader::CreateLoaderGlobal(JSContext* aCx,
458 : nsACString& aLocation,
459 : JSAddonId* aAddonID,
460 : MutableHandleObject aGlobal)
461 : {
462 510 : RefPtr<BackstagePass> backstagePass;
463 255 : nsresult rv = NS_NewBackstagePass(getter_AddRefs(backstagePass));
464 255 : NS_ENSURE_SUCCESS_VOID(rv);
465 :
466 255 : CompartmentOptions options;
467 :
468 255 : options.creationOptions()
469 255 : .setSystemZone()
470 255 : .setAddonId(aAddonID);
471 :
472 255 : options.behaviors().setVersion(JSVERSION_LATEST);
473 :
474 255 : if (xpc::SharedMemoryEnabled())
475 255 : options.creationOptions().setSharedMemoryAndAtomicsEnabled(true);
476 :
477 : // Defer firing OnNewGlobalObject until after the __URI__ property has
478 : // been defined so the JS debugger can tell what module the global is
479 : // for
480 510 : nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
481 : rv = nsXPConnect::XPConnect()->
482 510 : InitClassesWithNewWrappedGlobal(aCx,
483 255 : static_cast<nsIGlobalObject*>(backstagePass),
484 : nsContentUtils::GetSystemPrincipal(),
485 : nsIXPConnect::DONT_FIRE_ONNEWGLOBALHOOK,
486 : options,
487 510 : getter_AddRefs(holder));
488 255 : NS_ENSURE_SUCCESS_VOID(rv);
489 :
490 510 : RootedObject global(aCx, holder->GetJSObject());
491 255 : NS_ENSURE_TRUE_VOID(global);
492 :
493 255 : backstagePass->SetGlobalObject(global);
494 :
495 510 : JSAutoCompartment ac(aCx, global);
496 1020 : if (!JS_DefineFunctions(aCx, global, gGlobalFun) ||
497 765 : !JS_DefineProfilingFunctions(aCx, global)) {
498 0 : return;
499 : }
500 :
501 : // Set the location information for the new global, so that tools like
502 : // about:memory may use that information
503 255 : xpc::SetLocationForGlobal(global, aLocation);
504 :
505 255 : aGlobal.set(global);
506 : }
507 :
508 : JSObject*
509 255 : mozJSComponentLoader::PrepareObjectForLocation(JSContext* aCx,
510 : nsIFile* aComponentFile,
511 : nsIURI* aURI,
512 : bool* aRealFile)
513 : {
514 510 : nsAutoCString nativePath;
515 255 : NS_ENSURE_SUCCESS(aURI->GetSpec(nativePath), nullptr);
516 :
517 510 : RootedObject globalObj(aCx);
518 :
519 255 : CreateLoaderGlobal(aCx, nativePath, MapURIToAddonID(aURI), &globalObj);
520 :
521 : // |thisObj| is the object we set properties on for a particular .jsm.
522 : // XXX Right now, thisObj is always globalObj, but if we start
523 : // sharing globals between jsms, they won't be the same.
524 : // See bug 1186409.
525 510 : RootedObject thisObj(aCx, globalObj);
526 255 : NS_ENSURE_TRUE(thisObj, nullptr);
527 :
528 510 : JSAutoCompartment ac(aCx, thisObj);
529 :
530 255 : *aRealFile = false;
531 :
532 : // need to be extra careful checking for URIs pointing to files
533 : // EnsureFile may not always get called, especially on resource URIs
534 : // so we need to call GetFile to make sure this is a valid file
535 255 : nsresult rv = NS_OK;
536 510 : nsCOMPtr<nsIFileURL> fileURL = do_QueryInterface(aURI, &rv);
537 510 : nsCOMPtr<nsIFile> testFile;
538 255 : if (NS_SUCCEEDED(rv)) {
539 248 : fileURL->GetFile(getter_AddRefs(testFile));
540 : }
541 :
542 255 : if (testFile) {
543 248 : *aRealFile = true;
544 :
545 248 : if (XRE_IsParentProcess()) {
546 362 : RootedObject locationObj(aCx);
547 :
548 362 : rv = nsXPConnect::XPConnect()->WrapNative(aCx, thisObj, aComponentFile,
549 : NS_GET_IID(nsIFile),
550 181 : locationObj.address());
551 181 : NS_ENSURE_SUCCESS(rv, nullptr);
552 181 : NS_ENSURE_TRUE(locationObj, nullptr);
553 :
554 181 : if (!JS_DefineProperty(aCx, thisObj, "__LOCATION__", locationObj, 0))
555 0 : return nullptr;
556 : }
557 : }
558 :
559 : // Expose the URI from which the script was imported through a special
560 : // variable that we insert into the JSM.
561 510 : RootedString exposedUri(aCx, JS_NewStringCopyN(aCx, nativePath.get(), nativePath.Length()));
562 255 : NS_ENSURE_TRUE(exposedUri, nullptr);
563 :
564 255 : if (!JS_DefineProperty(aCx, thisObj, "__URI__", exposedUri, 0))
565 0 : return nullptr;
566 :
567 : {
568 : // AutoEntryScript required to invoke debugger hook, which is a
569 : // Gecko-specific concept at present.
570 : dom::AutoEntryScript aes(globalObj,
571 510 : "component loader report global");
572 255 : JS_FireOnNewGlobalObject(aes.cx(), globalObj);
573 : }
574 :
575 255 : return thisObj;
576 : }
577 :
578 : nsresult
579 255 : mozJSComponentLoader::ObjectForLocation(ComponentLoaderInfo& aInfo,
580 : nsIFile* aComponentFile,
581 : MutableHandleObject aObject,
582 : MutableHandleScript aTableScript,
583 : char** aLocation,
584 : bool aPropagateExceptions,
585 : MutableHandleValue aException)
586 : {
587 255 : MOZ_ASSERT(NS_IsMainThread(), "Must be on main thread.");
588 :
589 511 : dom::AutoJSAPI jsapi;
590 255 : jsapi.Init();
591 255 : JSContext* cx = jsapi.cx();
592 :
593 255 : bool realFile = false;
594 255 : nsresult rv = aInfo.EnsureURI();
595 255 : NS_ENSURE_SUCCESS(rv, rv);
596 510 : RootedObject obj(cx, PrepareObjectForLocation(cx, aComponentFile, aInfo.URI(),
597 511 : &realFile));
598 255 : NS_ENSURE_TRUE(obj, NS_ERROR_FAILURE);
599 255 : MOZ_ASSERT(JS_IsGlobalObject(obj));
600 :
601 511 : JSAutoCompartment ac(cx, obj);
602 :
603 511 : RootedScript script(cx);
604 :
605 511 : nsAutoCString nativePath;
606 255 : rv = aInfo.URI()->GetSpec(nativePath);
607 255 : NS_ENSURE_SUCCESS(rv, rv);
608 :
609 : // Before compiling the script, first check to see if we have it in
610 : // the startupcache. Note: as a rule, startupcache errors are not fatal
611 : // to loading the script, since we can always slow-load.
612 :
613 255 : bool writeToCache = false;
614 255 : StartupCache* cache = StartupCache::GetSingleton();
615 :
616 511 : nsAutoCString cachePath(kJSCachePrefix);
617 255 : rv = PathifyURI(aInfo.URI(), cachePath);
618 255 : NS_ENSURE_SUCCESS(rv, rv);
619 :
620 255 : script = ScriptPreloader::GetSingleton().GetCachedScript(cx, cachePath);
621 255 : if (!script && cache) {
622 77 : ReadCachedScript(cache, cachePath, cx, &script);
623 : }
624 :
625 255 : if (script) {
626 154 : LOG(("Successfully loaded %s from startupcache\n", nativePath.get()));
627 101 : } else if (cache) {
628 : // This is ok, it just means the script is not yet in the
629 : // cache. Could mean that the cache was corrupted and got removed,
630 : // but either way we're going to write this out.
631 51 : writeToCache = true;
632 : // ReadCachedScript may have set a pending exception.
633 51 : JS_ClearPendingException(cx);
634 : }
635 :
636 255 : if (!script) {
637 : // The script wasn't in the cache , so compile it now.
638 101 : LOG(("Slow loading %s\n", nativePath.get()));
639 :
640 : // Use lazy source if we're using the startup cache. Non-lazy source +
641 : // startup cache regresses installer size (due to source code stored in
642 : // XDR encoded modules in omni.ja). Also, XDR decoding is relatively
643 : // fast. When we're not using the startup cache, we want to use non-lazy
644 : // source code so that we can use lazy parsing.
645 : // See bug 1303754.
646 202 : CompileOptions options(cx);
647 101 : options.setNoScriptRval(true)
648 101 : .setVersion(JSVERSION_LATEST)
649 202 : .setFileAndLine(nativePath.get(), 1)
650 202 : .setSourceIsLazy(!!cache);
651 :
652 101 : if (realFile) {
653 202 : AutoMemMap map;
654 101 : MOZ_TRY(map.init(aComponentFile));
655 :
656 : // Note: exceptions will get handled further down;
657 : // don't early return for them here.
658 101 : auto buf = map.get<char>();
659 101 : Compile(cx, options, buf.get(), map.size(), &script);
660 : } else {
661 0 : rv = aInfo.EnsureScriptChannel();
662 0 : NS_ENSURE_SUCCESS(rv, rv);
663 0 : nsCOMPtr<nsIInputStream> scriptStream;
664 0 : rv = NS_MaybeOpenChannelUsingOpen2(aInfo.ScriptChannel(),
665 0 : getter_AddRefs(scriptStream));
666 0 : NS_ENSURE_SUCCESS(rv, rv);
667 :
668 : uint64_t len64;
669 : uint32_t bytesRead;
670 :
671 0 : rv = scriptStream->Available(&len64);
672 0 : NS_ENSURE_SUCCESS(rv, rv);
673 0 : NS_ENSURE_TRUE(len64 < UINT32_MAX, NS_ERROR_FILE_TOO_BIG);
674 0 : if (!len64)
675 0 : return NS_ERROR_FAILURE;
676 0 : uint32_t len = (uint32_t)len64;
677 :
678 : /* malloc an internal buf the size of the file */
679 0 : auto buf = MakeUniqueFallible<char[]>(len + 1);
680 0 : if (!buf)
681 0 : return NS_ERROR_OUT_OF_MEMORY;
682 :
683 : /* read the file in one swoop */
684 0 : rv = scriptStream->Read(buf.get(), len, &bytesRead);
685 0 : if (bytesRead != len)
686 0 : return NS_BASE_STREAM_OSERROR;
687 :
688 0 : buf[len] = '\0';
689 :
690 0 : Compile(cx, options, buf.get(), bytesRead, &script);
691 : }
692 : // Propagate the exception, if one exists. Also, don't leave the stale
693 : // exception on this context.
694 101 : if (!script && aPropagateExceptions && jsapi.HasException()) {
695 0 : if (!jsapi.StealException(aException))
696 0 : return NS_ERROR_OUT_OF_MEMORY;
697 : }
698 : }
699 :
700 255 : if (!script) {
701 0 : return NS_ERROR_FAILURE;
702 : }
703 :
704 255 : ScriptPreloader::GetSingleton().NoteScript(nativePath, cachePath, script);
705 :
706 255 : if (writeToCache) {
707 : // We successfully compiled the script, so cache it.
708 51 : rv = WriteCachedScript(cache, cachePath, cx, script);
709 :
710 : // Don't treat failure to write as fatal, since we might be working
711 : // with a read-only cache.
712 51 : if (NS_SUCCEEDED(rv)) {
713 51 : LOG(("Successfully wrote to cache\n"));
714 : } else {
715 0 : LOG(("Failed to write to cache\n"));
716 : }
717 : }
718 :
719 : // Assign aObject here so that it's available to recursive imports.
720 : // See bug 384168.
721 255 : aObject.set(obj);
722 :
723 255 : aTableScript.set(script);
724 :
725 :
726 : { // Scope for AutoEntryScript
727 :
728 : // We're going to run script via JS_ExecuteScript, so we need an
729 : // AutoEntryScript. This is Gecko-specific and not in any spec.
730 : dom::AutoEntryScript aes(CurrentGlobalOrNull(cx),
731 511 : "component loader load module");
732 255 : JSContext* aescx = aes.cx();
733 511 : JS::RootedValue rval(cx);
734 255 : if (!JS::CloneAndExecuteScript(aescx, script, &rval)) {
735 0 : if (aPropagateExceptions && aes.HasException()) {
736 : // Ignore return value because we're returning an error code
737 : // anyway.
738 0 : Unused << aes.StealException(aException);
739 : }
740 0 : aObject.set(nullptr);
741 0 : aTableScript.set(nullptr);
742 0 : return NS_ERROR_FAILURE;
743 : }
744 : }
745 :
746 : /* Freed when we remove from the table. */
747 256 : *aLocation = ToNewCString(nativePath);
748 256 : if (!*aLocation) {
749 0 : aObject.set(nullptr);
750 0 : aTableScript.set(nullptr);
751 0 : return NS_ERROR_OUT_OF_MEMORY;
752 : }
753 :
754 256 : return NS_OK;
755 : }
756 :
757 : void
758 0 : mozJSComponentLoader::UnloadModules()
759 : {
760 0 : mInitialized = false;
761 :
762 0 : mInProgressImports.Clear();
763 0 : mImports.Clear();
764 :
765 0 : for (auto iter = mModules.Iter(); !iter.Done(); iter.Next()) {
766 0 : iter.Data()->Clear();
767 0 : iter.Remove();
768 : }
769 0 : }
770 :
771 : NS_IMETHODIMP
772 998 : mozJSComponentLoader::Import(const nsACString& registryLocation,
773 : HandleValue targetValArg,
774 : JSContext* cx,
775 : uint8_t optionalArgc,
776 : MutableHandleValue retval)
777 : {
778 998 : MOZ_ASSERT(nsContentUtils::IsCallerChrome());
779 :
780 1996 : RootedValue targetVal(cx, targetValArg);
781 1996 : RootedObject targetObject(cx, nullptr);
782 998 : if (optionalArgc) {
783 : // The caller passed in the optional second argument. Get it.
784 401 : if (targetVal.isObject()) {
785 : // If we're passing in something like a content DOM window, chances
786 : // are the caller expects the properties to end up on the object
787 : // proper and not on the Xray holder. This is dubious, but can be used
788 : // during testing. Given that dumb callers can already leak JSMs into
789 : // content by passing a raw content JS object (where Xrays aren't
790 : // possible), we aim for consistency here. Waive xray.
791 1203 : if (WrapperFactory::IsXrayWrapper(&targetVal.toObject()) &&
792 401 : !WrapperFactory::WaiveXrayAndWrap(cx, &targetVal))
793 : {
794 0 : return NS_ERROR_FAILURE;
795 : }
796 401 : targetObject = &targetVal.toObject();
797 0 : } else if (!targetVal.isNull()) {
798 : // If targetVal isNull(), we actually want to leave targetObject null.
799 : // Not doing so breaks |make package|.
800 0 : return ReportOnCallerUTF8(cx, ERROR_SCOPE_OBJ,
801 0 : PromiseFlatCString(registryLocation).get());
802 : }
803 : } else {
804 597 : FindTargetObject(cx, &targetObject);
805 : }
806 :
807 1996 : Maybe<JSAutoCompartment> ac;
808 998 : if (targetObject) {
809 998 : ac.emplace(cx, targetObject);
810 : }
811 :
812 1996 : RootedObject global(cx);
813 998 : nsresult rv = ImportInto(registryLocation, targetObject, cx, &global);
814 :
815 998 : if (global) {
816 998 : if (!JS_WrapObject(cx, &global)) {
817 0 : NS_ERROR("can't wrap return value");
818 0 : return NS_ERROR_FAILURE;
819 : }
820 :
821 998 : retval.setObject(*global);
822 : }
823 998 : return rv;
824 : }
825 :
826 : NS_IMETHODIMP
827 0 : mozJSComponentLoader::ImportInto(const nsACString& aLocation,
828 : JSObject* aTargetObj,
829 : nsAXPCNativeCallContext* cc,
830 : JSObject** _retval)
831 : {
832 : JSContext* callercx;
833 0 : nsresult rv = cc->GetJSContext(&callercx);
834 0 : NS_ENSURE_SUCCESS(rv, rv);
835 :
836 0 : RootedObject targetObject(callercx, aTargetObj);
837 0 : RootedObject global(callercx);
838 0 : rv = ImportInto(aLocation, targetObject, callercx, &global);
839 0 : NS_ENSURE_SUCCESS(rv, rv);
840 0 : *_retval = global;
841 0 : return NS_OK;
842 : }
843 :
844 : NS_IMETHODIMP
845 0 : mozJSComponentLoader::IsModuleLoaded(const nsACString& aLocation,
846 : bool* retval)
847 : {
848 0 : MOZ_ASSERT(nsContentUtils::IsCallerChrome());
849 :
850 : nsresult rv;
851 0 : if (!mInitialized) {
852 0 : rv = ReallyInit();
853 0 : NS_ENSURE_SUCCESS(rv, rv);
854 : }
855 :
856 0 : ComponentLoaderInfo info(aLocation);
857 0 : rv = info.EnsureKey();
858 0 : NS_ENSURE_SUCCESS(rv, rv);
859 :
860 0 : *retval = !!mImports.Get(info.Key());
861 0 : return NS_OK;
862 : }
863 :
864 3 : NS_IMETHODIMP mozJSComponentLoader::LoadedModules(uint32_t* length,
865 : char*** aModules)
866 : {
867 6 : char** modules = new char*[mImports.Count()];
868 3 : *length = mImports.Count();
869 3 : *aModules = modules;
870 :
871 185 : for (auto iter = mImports.Iter(); !iter.Done(); iter.Next()) {
872 182 : *modules = NS_strdup(iter.Data()->location);
873 182 : modules++;
874 : }
875 :
876 3 : return NS_OK;
877 : }
878 :
879 3 : NS_IMETHODIMP mozJSComponentLoader::LoadedComponents(uint32_t* length,
880 : char*** aComponents)
881 : {
882 6 : char** comp = new char*[mModules.Count()];
883 3 : *length = mModules.Count();
884 3 : *aComponents = comp;
885 :
886 61 : for (auto iter = mModules.Iter(); !iter.Done(); iter.Next()) {
887 58 : *comp = NS_strdup(iter.Data()->location);
888 58 : comp++;
889 : }
890 :
891 3 : return NS_OK;
892 : }
893 :
894 : static JSObject*
895 1619 : ResolveModuleObjectPropertyById(JSContext* aCx, HandleObject aModObj, HandleId id)
896 : {
897 1619 : if (JS_HasExtensibleLexicalEnvironment(aModObj)) {
898 3223 : RootedObject lexical(aCx, JS_ExtensibleLexicalEnvironment(aModObj));
899 : bool found;
900 1619 : if (!JS_HasOwnPropertyById(aCx, lexical, id, &found)) {
901 0 : return nullptr;
902 : }
903 1619 : if (found) {
904 15 : return lexical;
905 : }
906 : }
907 1604 : return aModObj;
908 : }
909 :
910 : nsresult
911 998 : mozJSComponentLoader::ImportInto(const nsACString& aLocation,
912 : HandleObject targetObj,
913 : JSContext* callercx,
914 : MutableHandleObject vp)
915 : {
916 998 : vp.set(nullptr);
917 :
918 : nsresult rv;
919 998 : if (!mInitialized) {
920 0 : rv = ReallyInit();
921 0 : NS_ENSURE_SUCCESS(rv, rv);
922 : }
923 :
924 1996 : ComponentLoaderInfo info(aLocation);
925 998 : rv = info.EnsureResolvedURI();
926 998 : NS_ENSURE_SUCCESS(rv, rv);
927 :
928 : // get the JAR if there is one
929 1996 : nsCOMPtr<nsIJARURI> jarURI;
930 998 : jarURI = do_QueryInterface(info.ResolvedURI(), &rv);
931 1996 : nsCOMPtr<nsIFileURL> baseFileURL;
932 998 : if (NS_SUCCEEDED(rv)) {
933 0 : nsCOMPtr<nsIURI> baseURI;
934 0 : while (jarURI) {
935 0 : jarURI->GetJARFile(getter_AddRefs(baseURI));
936 0 : jarURI = do_QueryInterface(baseURI, &rv);
937 : }
938 0 : baseFileURL = do_QueryInterface(baseURI, &rv);
939 0 : NS_ENSURE_SUCCESS(rv, rv);
940 : } else {
941 998 : baseFileURL = do_QueryInterface(info.ResolvedURI(), &rv);
942 998 : NS_ENSURE_SUCCESS(rv, rv);
943 : }
944 :
945 1996 : nsCOMPtr<nsIFile> sourceFile;
946 998 : rv = baseFileURL->GetFile(getter_AddRefs(sourceFile));
947 998 : NS_ENSURE_SUCCESS(rv, rv);
948 :
949 1996 : nsCOMPtr<nsIFile> sourceLocalFile;
950 998 : sourceLocalFile = do_QueryInterface(sourceFile, &rv);
951 998 : NS_ENSURE_SUCCESS(rv, rv);
952 :
953 998 : rv = info.EnsureKey();
954 998 : NS_ENSURE_SUCCESS(rv, rv);
955 :
956 : ModuleEntry* mod;
957 1996 : nsAutoPtr<ModuleEntry> newEntry;
958 998 : if (!mImports.Get(info.Key(), &mod) && !mInProgressImports.Get(info.Key(), &mod)) {
959 414 : newEntry = new ModuleEntry(RootingContext::get(callercx));
960 207 : if (!newEntry)
961 0 : return NS_ERROR_OUT_OF_MEMORY;
962 207 : mInProgressImports.Put(info.Key(), newEntry);
963 :
964 207 : rv = info.EnsureURI();
965 207 : NS_ENSURE_SUCCESS(rv, rv);
966 414 : RootedValue exception(callercx);
967 621 : rv = ObjectForLocation(info, sourceLocalFile, &newEntry->obj,
968 207 : &newEntry->thisObjectKey,
969 207 : &newEntry->location, true, &exception);
970 :
971 207 : mInProgressImports.Remove(info.Key());
972 :
973 207 : if (NS_FAILED(rv)) {
974 0 : if (!exception.isUndefined()) {
975 : // An exception was thrown during compilation. Propagate it
976 : // out to our caller so they can report it.
977 0 : if (!JS_WrapValue(callercx, &exception))
978 0 : return NS_ERROR_OUT_OF_MEMORY;
979 0 : JS_SetPendingException(callercx, exception);
980 0 : return NS_OK;
981 : }
982 :
983 : // Something failed, but we don't know what it is, guess.
984 0 : return NS_ERROR_FILE_NOT_FOUND;
985 : }
986 :
987 207 : mod = newEntry;
988 : }
989 :
990 998 : MOZ_ASSERT(mod->obj, "Import table contains entry with no object");
991 998 : vp.set(mod->obj);
992 :
993 998 : if (targetObj) {
994 : // cxhelper must be created before jsapi, so that jsapi is destroyed and
995 : // pops any context it has pushed before we report to the caller context.
996 1996 : JSCLContextHelper cxhelper(callercx);
997 :
998 : // Even though we are calling JS_SetPropertyById on targetObj, we want
999 : // to ensure that we never run script here, so we use an AutoJSAPI and
1000 : // not an AutoEntryScript.
1001 1996 : dom::AutoJSAPI jsapi;
1002 998 : jsapi.Init();
1003 998 : JSContext* cx = jsapi.cx();
1004 1996 : JSAutoCompartment ac(cx, mod->obj);
1005 :
1006 1996 : RootedValue symbols(cx);
1007 1996 : RootedObject exportedSymbolsHolder(cx, ResolveModuleObjectProperty(cx, mod->obj,
1008 1996 : "EXPORTED_SYMBOLS"));
1009 4990 : if (!exportedSymbolsHolder ||
1010 4990 : !JS_GetProperty(cx, exportedSymbolsHolder,
1011 : "EXPORTED_SYMBOLS", &symbols)) {
1012 0 : nsCString location;
1013 0 : rv = info.GetLocation(location);
1014 0 : NS_ENSURE_SUCCESS(rv, rv);
1015 0 : return ReportOnCallerUTF8(cxhelper, ERROR_NOT_PRESENT,
1016 0 : location.get());
1017 : }
1018 :
1019 : bool isArray;
1020 998 : if (!JS_IsArrayObject(cx, symbols, &isArray)) {
1021 0 : return NS_ERROR_FAILURE;
1022 : }
1023 998 : if (!isArray) {
1024 0 : nsCString location;
1025 0 : rv = info.GetLocation(location);
1026 0 : NS_ENSURE_SUCCESS(rv, rv);
1027 0 : return ReportOnCallerUTF8(cxhelper, ERROR_NOT_AN_ARRAY,
1028 0 : location.get());
1029 : }
1030 :
1031 1996 : RootedObject symbolsObj(cx, &symbols.toObject());
1032 :
1033 : // Iterate over symbols array, installing symbols on targetObj:
1034 :
1035 998 : uint32_t symbolCount = 0;
1036 998 : if (!JS_GetArrayLength(cx, symbolsObj, &symbolCount)) {
1037 0 : nsCString location;
1038 0 : rv = info.GetLocation(location);
1039 0 : NS_ENSURE_SUCCESS(rv, rv);
1040 0 : return ReportOnCallerUTF8(cxhelper, ERROR_GETTING_ARRAY_LENGTH,
1041 0 : location.get());
1042 : }
1043 :
1044 : #ifdef DEBUG
1045 1996 : nsAutoCString logBuffer;
1046 : #endif
1047 :
1048 1996 : RootedValue value(cx);
1049 1996 : RootedId symbolId(cx);
1050 1996 : RootedObject symbolHolder(cx);
1051 2617 : for (uint32_t i = 0; i < symbolCount; ++i) {
1052 9714 : if (!JS_GetElement(cx, symbolsObj, i, &value) ||
1053 11333 : !value.isString() ||
1054 6476 : !JS_ValueToId(cx, value, &symbolId)) {
1055 0 : nsCString location;
1056 0 : rv = info.GetLocation(location);
1057 0 : NS_ENSURE_SUCCESS(rv, rv);
1058 0 : return ReportOnCallerUTF8(cxhelper, ERROR_ARRAY_ELEMENT,
1059 0 : location.get(), i);
1060 : }
1061 :
1062 1619 : symbolHolder = ResolveModuleObjectPropertyById(cx, mod->obj, symbolId);
1063 9714 : if (!symbolHolder ||
1064 9714 : !JS_GetPropertyById(cx, symbolHolder, symbolId, &value)) {
1065 0 : JSAutoByteString bytes;
1066 0 : RootedString symbolStr(cx, JSID_TO_STRING(symbolId));
1067 0 : if (!bytes.encodeUtf8(cx, symbolStr))
1068 0 : return NS_ERROR_FAILURE;
1069 0 : nsCString location;
1070 0 : rv = info.GetLocation(location);
1071 0 : NS_ENSURE_SUCCESS(rv, rv);
1072 0 : return ReportOnCallerUTF8(cxhelper, ERROR_GETTING_SYMBOL,
1073 0 : location.get(), bytes.ptr());
1074 : }
1075 :
1076 3238 : JSAutoCompartment target_ac(cx, targetObj);
1077 :
1078 1619 : JS_MarkCrossZoneId(cx, symbolId);
1079 :
1080 8095 : if (!JS_WrapValue(cx, &value) ||
1081 6476 : !JS_SetPropertyById(cx, targetObj, symbolId, value)) {
1082 0 : JSAutoByteString bytes;
1083 0 : RootedString symbolStr(cx, JSID_TO_STRING(symbolId));
1084 0 : if (!bytes.encodeUtf8(cx, symbolStr))
1085 0 : return NS_ERROR_FAILURE;
1086 0 : nsCString location;
1087 0 : rv = info.GetLocation(location);
1088 0 : NS_ENSURE_SUCCESS(rv, rv);
1089 0 : return ReportOnCallerUTF8(cxhelper, ERROR_SETTING_SYMBOL,
1090 0 : location.get(), bytes.ptr());
1091 : }
1092 : #ifdef DEBUG
1093 1619 : if (i == 0) {
1094 995 : logBuffer.AssignLiteral("Installing symbols [ ");
1095 : }
1096 3238 : JSAutoByteString bytes(cx, JSID_TO_STRING(symbolId));
1097 1619 : if (!!bytes)
1098 1619 : logBuffer.Append(bytes.ptr());
1099 1619 : logBuffer.Append(' ');
1100 1619 : if (i == symbolCount - 1) {
1101 1990 : nsCString location;
1102 995 : rv = info.GetLocation(location);
1103 995 : NS_ENSURE_SUCCESS(rv, rv);
1104 995 : LOG(("%s] from %s\n", logBuffer.get(), location.get()));
1105 : }
1106 : #endif
1107 : }
1108 : }
1109 :
1110 : // Cache this module for later
1111 998 : if (newEntry) {
1112 207 : mImports.Put(info.Key(), newEntry);
1113 207 : newEntry.forget();
1114 : }
1115 :
1116 998 : return NS_OK;
1117 : }
1118 :
1119 : NS_IMETHODIMP
1120 0 : mozJSComponentLoader::Unload(const nsACString & aLocation)
1121 : {
1122 : nsresult rv;
1123 :
1124 0 : if (!mInitialized) {
1125 0 : return NS_OK;
1126 : }
1127 :
1128 0 : ComponentLoaderInfo info(aLocation);
1129 0 : rv = info.EnsureKey();
1130 0 : NS_ENSURE_SUCCESS(rv, rv);
1131 : ModuleEntry* mod;
1132 0 : if (mImports.Get(info.Key(), &mod)) {
1133 0 : mImports.Remove(info.Key());
1134 : }
1135 :
1136 0 : return NS_OK;
1137 : }
1138 :
1139 : NS_IMETHODIMP
1140 0 : mozJSComponentLoader::Observe(nsISupports* subject, const char* topic,
1141 : const char16_t* data)
1142 : {
1143 0 : if (!strcmp(topic, "xpcom-shutdown-loaders")) {
1144 0 : UnloadModules();
1145 : } else {
1146 0 : NS_ERROR("Unexpected observer topic.");
1147 : }
1148 :
1149 0 : return NS_OK;
1150 : }
1151 :
1152 : size_t
1153 0 : mozJSComponentLoader::ModuleEntry::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
1154 : {
1155 0 : size_t n = aMallocSizeOf(this);
1156 0 : n += aMallocSizeOf(location);
1157 :
1158 0 : return n;
1159 : }
1160 :
1161 : /* static */ already_AddRefed<nsIFactory>
1162 51 : mozJSComponentLoader::ModuleEntry::GetFactory(const mozilla::Module& module,
1163 : const mozilla::Module::CIDEntry& entry)
1164 : {
1165 51 : const ModuleEntry& self = static_cast<const ModuleEntry&>(module);
1166 51 : MOZ_ASSERT(self.getfactoryobj, "Handing out an uninitialized module?");
1167 :
1168 102 : nsCOMPtr<nsIFactory> f;
1169 51 : nsresult rv = self.getfactoryobj->Get(*entry.cid, getter_AddRefs(f));
1170 51 : if (NS_FAILED(rv))
1171 0 : return nullptr;
1172 :
1173 51 : return f.forget();
1174 : }
1175 :
1176 : //----------------------------------------------------------------------
1177 :
1178 998 : JSCLContextHelper::JSCLContextHelper(JSContext* aCx)
1179 : : mContext(aCx)
1180 998 : , mBuf(nullptr)
1181 : {
1182 998 : }
1183 :
1184 1996 : JSCLContextHelper::~JSCLContextHelper()
1185 : {
1186 998 : if (mBuf) {
1187 0 : JS_ReportErrorUTF8(mContext, "%s", mBuf.get());
1188 : }
1189 998 : }
1190 :
1191 : void
1192 0 : JSCLContextHelper::reportErrorAfterPop(UniqueChars&& buf)
1193 : {
1194 0 : MOZ_ASSERT(!mBuf, "Already called reportErrorAfterPop");
1195 0 : mBuf = Move(buf);
1196 0 : }
|