Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/js/xpconnect/loader/mozJSComponentLoader.h
Line
Count
Source (jump to first uncovered line)
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
#ifndef mozJSComponentLoader_h
8
#define mozJSComponentLoader_h
9
10
#include "mozilla/dom/ScriptSettings.h"
11
#include "mozilla/MemoryReporting.h"
12
#include "mozilla/ModuleLoader.h"
13
#include "nsAutoPtr.h"
14
#include "nsISupports.h"
15
#include "nsIObserver.h"
16
#include "nsIURI.h"
17
#include "xpcIJSModuleLoader.h"
18
#include "nsClassHashtable.h"
19
#include "nsDataHashtable.h"
20
#include "jsapi.h"
21
22
#include "xpcIJSGetFactory.h"
23
#include "xpcpublic.h"
24
25
class nsIFile;
26
class ComponentLoaderInfo;
27
28
namespace mozilla {
29
    class ScriptPreloader;
30
} // namespace mozilla
31
32
33
/* 6bd13476-1dd2-11b2-bbef-f0ccb5fa64b6 (thanks, mozbot) */
34
35
#define MOZJSCOMPONENTLOADER_CID                                              \
36
  {0x6bd13476, 0x1dd2, 0x11b2,                                                \
37
    { 0xbb, 0xef, 0xf0, 0xcc, 0xb5, 0xfa, 0x64, 0xb6 }}
38
#define MOZJSCOMPONENTLOADER_CONTRACTID "@mozilla.org/moz/jsloader;1"
39
40
#if defined(NIGHTLY_BUILD) || defined(MOZ_DEV_EDITION) || defined(DEBUG)
41
#define STARTUP_RECORDER_ENABLED
42
#endif
43
44
class mozJSComponentLoader final : public mozilla::ModuleLoader,
45
                                   public xpcIJSModuleLoader,
46
                                   public nsIObserver
47
{
48
 public:
49
    NS_DECL_ISUPPORTS
50
    NS_DECL_XPCIJSMODULELOADER
51
    NS_DECL_NSIOBSERVER
52
53
    mozJSComponentLoader();
54
55
    // ModuleLoader
56
    const mozilla::Module* LoadModule(mozilla::FileLocation& aFile) override;
57
58
    void FindTargetObject(JSContext* aCx,
59
                          JS::MutableHandleObject aTargetObject);
60
61
    static already_AddRefed<mozJSComponentLoader> GetOrCreate();
62
63
8
    static mozJSComponentLoader* Get() { return sSelf; }
64
65
    nsresult ImportInto(const nsACString& aResourceURI, JS::HandleValue aTargetObj,
66
                        JSContext* aCx, uint8_t aArgc, JS::MutableHandleValue aRetval);
67
68
    nsresult Import(JSContext* aCx, const nsACString& aResourceURI,
69
                    JS::MutableHandleObject aModuleGlobal,
70
                    JS::MutableHandleObject aModuleExports,
71
                    bool aIgnoreExports = false);
72
73
    nsresult Unload(const nsACString& aResourceURI);
74
    nsresult IsModuleLoaded(const nsACString& aResourceURI, bool* aRetval);
75
8
    bool IsLoaderGlobal(JSObject* aObj) {
76
8
        return mLoaderGlobal == aObj;
77
8
    }
78
79
    size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf);
80
81
    /**
82
     * Temporary diagnostic function for startup crashes in bug 1403348:
83
     *
84
     * Annotate the crash report with the contents of the async shutdown
85
     * module/component scripts.
86
     */
87
    nsresult AnnotateCrashReport();
88
89
 protected:
90
    virtual ~mozJSComponentLoader();
91
92
    friend class XPCJSRuntime;
93
94
    JSObject* CompilationScope(JSContext* aCx)
95
0
    {
96
0
        if (mLoaderGlobal) {
97
0
            return mLoaderGlobal;
98
0
        }
99
0
        return GetSharedGlobal(aCx);
100
0
    }
101
102
 private:
103
    static mozJSComponentLoader* sSelf;
104
105
    nsresult ReallyInit();
106
    void UnloadModules();
107
108
    void CreateLoaderGlobal(JSContext* aCx,
109
                            const nsACString& aLocation,
110
                            JS::MutableHandleObject aGlobal);
111
112
    bool ReuseGlobal(nsIURI* aComponent);
113
114
    JSObject* GetSharedGlobal(JSContext* aCx);
115
116
    JSObject* PrepareObjectForLocation(JSContext* aCx,
117
                                       nsIFile* aComponentFile,
118
                                       nsIURI* aComponent,
119
                                       bool* aReuseGlobal,
120
                                       bool* aRealFile);
121
122
    nsresult ObjectForLocation(ComponentLoaderInfo& aInfo,
123
                               nsIFile* aComponentFile,
124
                               JS::MutableHandleObject aObject,
125
                               JS::MutableHandleScript aTableScript,
126
                               char** location,
127
                               bool aCatchException,
128
                               JS::MutableHandleValue aException);
129
130
    nsresult ImportInto(const nsACString& aLocation,
131
                        JS::HandleObject targetObj,
132
                        JSContext* callercx,
133
                        JS::MutableHandleObject vp);
134
135
    nsCOMPtr<nsIComponentManager> mCompMgr;
136
137
    class ModuleEntry : public mozilla::Module
138
    {
139
    public:
140
        explicit ModuleEntry(JS::RootingContext* aRootingCx)
141
          : mozilla::Module(), obj(aRootingCx), exports(aRootingCx),
142
            thisObjectKey(aRootingCx)
143
5
        {
144
5
            mVersion = mozilla::Module::kVersion;
145
5
            mCIDs = nullptr;
146
5
            mContractIDs = nullptr;
147
5
            mCategoryEntries = nullptr;
148
5
            getFactoryProc = GetFactory;
149
5
            loadProc = nullptr;
150
5
            unloadProc = nullptr;
151
5
152
5
            location = nullptr;
153
5
        }
154
155
0
        ~ModuleEntry() {
156
0
            Clear();
157
0
        }
158
159
0
        void Clear() {
160
0
            getfactoryobj = nullptr;
161
0
162
0
            if (obj) {
163
0
                mozilla::AutoJSContext cx;
164
0
                JSAutoRealm ar(cx, obj);
165
0
166
0
                if (JS_HasExtensibleLexicalEnvironment(obj)) {
167
0
                    JS_SetAllNonReservedSlotsToUndefined(cx, JS_ExtensibleLexicalEnvironment(obj));
168
0
                }
169
0
                JS_SetAllNonReservedSlotsToUndefined(cx, obj);
170
0
                obj = nullptr;
171
0
                thisObjectKey = nullptr;
172
0
            }
173
0
174
0
            if (location) {
175
0
                free(location);
176
0
            }
177
0
178
0
            obj = nullptr;
179
0
            thisObjectKey = nullptr;
180
0
            location = nullptr;
181
0
#ifdef STARTUP_RECORDER_ENABLED
182
0
            importStack.Truncate();
183
0
#endif
184
0
        }
185
186
        size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
187
188
        static already_AddRefed<nsIFactory> GetFactory(const mozilla::Module& module,
189
                                                       const mozilla::Module::CIDEntry& entry);
190
191
        nsCOMPtr<xpcIJSGetFactory> getfactoryobj;
192
        JS::PersistentRootedObject obj;
193
        JS::PersistentRootedObject exports;
194
        JS::PersistentRootedScript thisObjectKey;
195
        char* location;
196
        nsCString resolvedURL;
197
#ifdef STARTUP_RECORDER_ENABLED
198
        nsCString importStack;
199
#endif
200
    };
201
202
    nsresult ExtractExports(JSContext* aCx, ComponentLoaderInfo& aInfo,
203
                            ModuleEntry* aMod,
204
                            JS::MutableHandleObject aExports);
205
206
    static size_t DataEntrySizeOfExcludingThis(const nsACString& aKey, ModuleEntry* const& aData,
207
                                               mozilla::MallocSizeOf aMallocSizeOf, void* arg);
208
    static size_t ClassEntrySizeOfExcludingThis(const nsACString& aKey,
209
                                                const nsAutoPtr<ModuleEntry>& aData,
210
                                                mozilla::MallocSizeOf aMallocSizeOf, void* arg);
211
212
    // Modules are intentionally leaked, but still cleared.
213
    nsDataHashtable<nsCStringHashKey, ModuleEntry*> mModules;
214
215
    nsClassHashtable<nsCStringHashKey, ModuleEntry> mImports;
216
    nsDataHashtable<nsCStringHashKey, ModuleEntry*> mInProgressImports;
217
218
    // A map of on-disk file locations which are loaded as modules to the
219
    // pre-resolved URIs they were loaded from. Used to prevent the same file
220
    // from being loaded separately, from multiple URLs.
221
    nsClassHashtable<nsCStringHashKey, nsCString> mLocations;
222
223
    bool mInitialized;
224
    bool mShareLoaderGlobal;
225
    JS::PersistentRooted<JSObject*> mLoaderGlobal;
226
};
227
228
#endif