☠☠ backed out by 7682952aed89 ☠ ☠ | |
author | Tooru Fujisawa <arai_a@mac.com> |
Tue, 13 Feb 2024 14:34:22 +0000 (17 months ago) | |
changeset 695519 | 9699c18e5bf7719e0cbee26e4d27521576ed12f2 |
parent 695518 | 84cdfd738db6ab8687b3138e3bf70894e4292184 |
child 695520 | 2e2f01296233a4f7adb3d1fac1c4e67d5f7b16ab |
push id | 199908 |
push user | arai_a@mac.com |
push date | Tue, 13 Feb 2024 14:42:56 +0000 (17 months ago) |
treeherder | autoland@d5df64b38425 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | jonco, ochameau |
bugs | 1803810 |
milestone | 124.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
|
dom/base/ChromeUtils.cpp | file | annotate | diff | comparison | revisions | |
dom/chrome-webidl/ChromeUtils.webidl | file | annotate | diff | comparison | revisions |
--- a/dom/base/ChromeUtils.cpp +++ b/dom/base/ChromeUtils.cpp @@ -27,16 +27,17 @@ #include "mozilla/IntentionalCrash.h" #include "mozilla/PerfStats.h" #include "mozilla/Preferences.h" #include "mozilla/ProcInfo.h" #include "mozilla/ResultExtensions.h" #include "mozilla/ScopeExit.h" #include "mozilla/ScrollingMetrics.h" #include "mozilla/SharedStyleSheetCache.h" +#include "mozilla/SpinEventLoopUntil.h" #include "mozilla/TimeStamp.h" #include "mozilla/dom/ContentParent.h" #include "mozilla/dom/IdleDeadline.h" #include "mozilla/dom/InProcessParent.h" #include "mozilla/dom/JSActorService.h" #include "mozilla/dom/MediaSessionBinding.h" #include "mozilla/dom/PBrowserParent.h" #include "mozilla/dom/Performance.h" @@ -613,47 +614,156 @@ static mozJSModuleLoader* GetContextualE (devToolsModuleloader && !aLoadInDevToolsLoader.WasPassed() && devToolsModuleloader->IsLoaderGlobal(aGlobal)); if (shouldUseDevToolsLoader) { return mozJSModuleLoader::GetOrCreateDevToolsLoader(); } return mozJSModuleLoader::Get(); } +static mozJSModuleLoader* GetModuleLoaderForCurrentGlobal( + JSContext* aCx, const GlobalObject& aGlobal, + Maybe<loader::NonSharedGlobalSyncModuleLoaderScope>& + aMaybeSyncLoaderScope) { + nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(aGlobal.GetAsSupports()); + + if (mozJSModuleLoader::IsSharedSystemGlobal(global)) { + return mozJSModuleLoader::Get(); + } + if (mozJSModuleLoader::IsDevToolsLoaderGlobal(global)) { + return mozJSModuleLoader::GetOrCreateDevToolsLoader(); + } + + if (loader::NonSharedGlobalSyncModuleLoaderScope::IsActive()) { + mozJSModuleLoader* moduleloader = + loader::NonSharedGlobalSyncModuleLoaderScope::ActiveLoader(); + + if (!moduleloader->IsLoaderGlobal(global->GetGlobalJSObject())) { + JS_ReportErrorASCII(aCx, + "global: \"current\" option cannot be used for " + "different global while other importESModule " + "with global: \"current\" is on the stack"); + return nullptr; + } + + return moduleloader; + } + + RefPtr targetModuleLoader = global->GetModuleLoader(aCx); + if (!targetModuleLoader) { + // Sandbox without associated window returns nullptr for GetModuleLoader. + JS_ReportErrorASCII(aCx, "No ModuleLoader found for the current context"); + return nullptr; + } + + if (targetModuleLoader->HasFetchingModules()) { + if (!mozilla::SpinEventLoopUntil( + "importESModule for current global"_ns, [&]() -> bool { + return !targetModuleLoader->HasFetchingModules(); + })) { + JS_ReportErrorASCII(aCx, "Failed to wait for ongoing module requests"); + return nullptr; + } + } + + aMaybeSyncLoaderScope.emplace(aCx, global); + return aMaybeSyncLoaderScope->ActiveLoader(); +} + +static mozJSModuleLoader* GetModuleLoaderForOptions( + JSContext* aCx, const GlobalObject& aGlobal, + const ImportESModuleOptionsDictionary& aOptions, + Maybe<loader::NonSharedGlobalSyncModuleLoaderScope>& + aMaybeSyncLoaderScope) { + if (!aOptions.mGlobal.WasPassed()) { + return GetContextualESLoader(aOptions.mLoadInDevToolsLoader, aGlobal.Get()); + } + + switch (aOptions.mGlobal.Value()) { + case ImportESModuleTargetGlobal::Shared: + return mozJSModuleLoader::Get(); + + case ImportESModuleTargetGlobal::Devtools: + return mozJSModuleLoader::GetOrCreateDevToolsLoader(); + + case ImportESModuleTargetGlobal::Contextual: { + RefPtr devToolsModuleloader = mozJSModuleLoader::GetDevToolsLoader(); + if (devToolsModuleloader && + devToolsModuleloader->IsLoaderGlobal(aGlobal.Get())) { + return mozJSModuleLoader::GetOrCreateDevToolsLoader(); + } + return mozJSModuleLoader::Get(); + } + + case ImportESModuleTargetGlobal::Current: + return GetModuleLoaderForCurrentGlobal(aCx, aGlobal, + aMaybeSyncLoaderScope); + + default: + MOZ_CRASH("Unknown ImportESModuleTargetGlobal"); + } +} + +static bool ValidateImportOptions( + JSContext* aCx, const ImportESModuleOptionsDictionary& aOptions) { + if (aOptions.mGlobal.WasPassed() && + aOptions.mLoadInDevToolsLoader.WasPassed()) { + JS_ReportErrorASCII(aCx, + "global option and loadInDevToolsLoader option " + "cannot be used at the same time"); + return false; + } + + return true; +} + /* static */ void ChromeUtils::ImportESModule( const GlobalObject& aGlobal, const nsAString& aResourceURI, const ImportESModuleOptionsDictionary& aOptions, JS::MutableHandle<JSObject*> aRetval, ErrorResult& aRv) { - RefPtr moduleloader = - GetContextualESLoader(aOptions.mLoadInDevToolsLoader, aGlobal.Get()); - MOZ_ASSERT(moduleloader); + JSContext* cx = aGlobal.Context(); + + if (!ValidateImportOptions(cx, aOptions)) { + aRv.Throw(NS_ERROR_FAILURE); + return; + } + + Maybe<loader::NonSharedGlobalSyncModuleLoaderScope> maybeSyncLoaderScope; + RefPtr<mozJSModuleLoader> moduleloader = + GetModuleLoaderForOptions(cx, aGlobal, aOptions, maybeSyncLoaderScope); + if (!moduleloader) { + aRv.Throw(NS_ERROR_FAILURE); + return; + } NS_ConvertUTF16toUTF8 registryLocation(aResourceURI); AUTO_PROFILER_LABEL_DYNAMIC_NSCSTRING_NONSENSITIVE( "ChromeUtils::ImportESModule", OTHER, registryLocation); - JSContext* cx = aGlobal.Context(); - JS::Rooted<JSObject*> moduleNamespace(cx); nsresult rv = moduleloader->ImportESModule(cx, registryLocation, &moduleNamespace); if (NS_FAILED(rv)) { aRv.Throw(rv); return; } MOZ_ASSERT(!JS_IsExceptionPending(cx)); if (!JS_WrapObject(cx, &moduleNamespace)) { aRv.Throw(NS_ERROR_FAILURE); return; } aRetval.set(moduleNamespace); + + if (maybeSyncLoaderScope) { + maybeSyncLoaderScope->Finish(); + } } namespace lazy_getter { static const size_t SLOT_ID = 0; static const size_t SLOT_URI = 1; static const size_t SLOT_PARAMS = 1;
--- a/dom/chrome-webidl/ChromeUtils.webidl +++ b/dom/chrome-webidl/ChromeUtils.webidl @@ -508,24 +508,26 @@ partial namespace ChromeUtils { [Throws] object import(UTF8String aResourceURI, optional object aTargetObj); /** * Synchronously loads and evaluates the JS module source located at * 'aResourceURI'. * * @param aResourceURI A resource:// URI string to load the module from. + * @param aOption An option to specify where to load the module into. * @returns the module's namespace object. * * The implementation maintains a hash of aResourceURI->global obj. * Subsequent invocations of import with 'aResourceURI' pointing to * the same file will not cause the module to be re-evaluated. */ [Throws] - object importESModule(DOMString aResourceURI, optional ImportESModuleOptionsDictionary options = {}); + object importESModule(DOMString aResourceURI, + optional ImportESModuleOptionsDictionary aOptions = {}); /** * Defines a property on the given target which lazily imports a JavaScript * module when accessed. * * The first time the property is accessed, the module at the given URL is * imported, and the property is replaced with the module's exported symbol * of the same name. @@ -978,23 +980,59 @@ dictionary CompileScriptOptionsDictionar * If true, the script will be compiled so that its last expression will be * returned as the value of its execution. This makes certain types of * optimization impossible, and disables the JIT in many circumstances, so * should not be used when not absolutely necessary. */ boolean hasReturnValue = false; }; +/** + * Where the modules are loaded into with importESModule. + */ +enum ImportESModuleTargetGlobal { + /** + * Load into the shared system global. + * This is the default value. + */ + "shared", + + /** + * Load into a distinct system global for DevTools, so that the DevTools can + * load a distinct set of modules and do not interfere with its debuggee. + */ + "devtools", + + /** + * If the current global is DevTools' distinct system global, load into the + * DevTools' distinct system global. + * Otherwise load into the shared system global. + * + * This is a temporary workaround until DevTools modules are ESMified. + */ + "contextual", + + /** + * Load into current global. + * + * This can be used for any global. If this is used for shared global or + * devtools global, this has the same effect as "shared" or "devtools". + */ + "current", +}; + dictionary ImportESModuleOptionsDictionary { /** * If true, a distinct module loader will be used, in the system principal, * but with a distinct global so that the DevTools can load a distinct set * of modules and do not interfere with its debuggee. */ boolean loadInDevToolsLoader; + + ImportESModuleTargetGlobal global; }; /** * A JS object whose properties specify what portion of the heap graph to * write. The recognized properties are: * * * globals: [ global, ... ] * Dump only nodes that either: