[ddc] Rolling internal dart_library.js into SDK

Change-Id: Ifb1cf1aed53b04eaa0a258668eab6b4b8f19df80
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/286609
Reviewed-by: Nicholas Shahan <nshahan@google.com>
Commit-Queue: Mark Zhou <markzipan@google.com>
This commit is contained in:
Mark Zhou 2023-03-07 19:44:26 +00:00 committed by Commit Queue
parent 6414db5327
commit a92274cae8
3 changed files with 353 additions and 119 deletions

View file

@ -28,23 +28,55 @@ if (!dart_library) {
dart_library.libraryImports = libraryImports; dart_library.libraryImports = libraryImports;
const _metrics = Symbol('metrics'); const _metrics = Symbol('metrics');
const _logMetrics = false;
// Returns a map from module name to various metrics for module. // Returns a map from module name to various metrics for module.
function metrics() { function moduleMetrics() {
const map = {}; const map = {};
const keys = Array.from(_libraries.keys()); const keys = Array.from(_libraries.keys());
for (const key of keys) { for (const key of keys) {
const lib = _libraries.get(key); const lib = _libraries.get(key);
map[lib._name] = lib._library[_metrics]; map[lib._name] = lib.firstLibraryValue[_metrics];
} }
return map; return map;
} }
dart_library.metrics = metrics; dart_library.moduleMetrics = moduleMetrics;
// Returns an application level overview of the module metrics.
function appMetrics() {
const metrics = moduleMetrics();
let dartSize = 0;
let jsSize = 0;
let sourceMapSize = 0;
let evaluatedModules = 0;
const keys = Array.from(_libraries.keys());
let firstLoadStart = Number.MAX_VALUE;
let lastLoadEnd = Number.MIN_VALUE;
for (const module of keys) {
let data = metrics[module];
if (data != null) {
evaluatedModules++;
dartSize += data.dartSize;
jsSize += data.jsSize;
sourceMapSize += data.sourceMapSize;
firstLoadStart = Math.min(firstLoadStart, data.loadStart);
lastLoadEnd = Math.max(lastLoadEnd, data.loadEnd);
}
}
return {
'dartSize': dartSize,
'jsSize': jsSize,
'sourceMapSize': sourceMapSize,
'evaluatedModules': evaluatedModules,
'loadTimeMs': lastLoadEnd - firstLoadStart
};
}
dart_library.appMetrics = appMetrics;
function _sortFn(key1, key2) { function _sortFn(key1, key2) {
const t1 = _libraries.get(key1)._library[_metrics].loadTime; const t1 = _libraries.get(key1).firstLibraryValue[_metrics].loadStart;
const t2 = _libraries.get(key2)._library[_metrics].loadTime; const t2 = _libraries.get(key2).firstLibraryValue[_metrics].loadStart;
return t1 - t2; return t1 - t2;
} }
@ -52,18 +84,19 @@ if (!dart_library) {
// in CSV format. // in CSV format.
function metricsCsv() { function metricsCsv() {
let buffer = let buffer =
'Module, JS Size, Dart Size, Load Time, Cumulative JS Size\n'; 'Module, JS Size, Dart Size, Load Start, Load End, Cumulative JS Size\n';
const keys = Array.from(_libraries.keys()); const keys = Array.from(_libraries.keys());
keys.sort(_sortFn); keys.sort(_sortFn);
let cumulativeJsSize = 0; let cumulativeJsSize = 0;
for (const key of keys) { for (const key of keys) {
const lib = _libraries.get(key); const lib = _libraries.get(key);
const jsSize = lib._library[_metrics].jsSize; const jsSize = lib.firstLibraryValue[_metrics].jsSize;
cumulativeJsSize += jsSize; cumulativeJsSize += jsSize;
const dartSize = lib._library[_metrics].dartSize; const dartSize = lib.firstLibraryValue[_metrics].dartSize;
const loadTime = lib._library[_metrics].loadTime; const loadStart = lib.firstLibraryValue[_metrics].loadStart;
const loadEnd = lib.firstLibraryValue[_metrics].loadEnd;
buffer += '"' + lib._name + '", ' + jsSize + ', ' + dartSize + ', ' + buffer += '"' + lib._name + '", ' + jsSize + ', ' + dartSize + ', ' +
loadTime + ', ' + cumulativeJsSize + '\n'; loadStart + ', ' + loadEnd + ', ' + cumulativeJsSize + '\n';
} }
return buffer; return buffer;
} }
@ -103,11 +136,32 @@ if (!dart_library) {
let _reverseImports = new Map(); let _reverseImports = new Map();
// Set of libraries that were not only loaded on the page but also executed. // App name to set of libraries that were not only loaded on the page but
let _executedLibraries = new Set(); // also executed.
const _executedLibraries = new Map();
dart_library.executedLibraryCount = function() {
let count = 0;
_executedLibraries.forEach(function(executedLibraries, _) {
count += executedLibraries.size;
});
return count;
};
// Library instance that is going to be loaded or has been loaded.
class LibraryInstance {
constructor(libraryValue) {
this.libraryValue = libraryValue;
// Cyclic import detection
this.loadingState = LibraryLoader.NOT_LOADED;
}
get isNotLoaded() {
return this.loadingState == LibraryLoader.NOT_LOADED;
}
}
class LibraryLoader { class LibraryLoader {
constructor(name, defaultValue, imports, loader, data) { constructor(name, defaultLibraryValue, imports, loader, data) {
imports.forEach(function(i) { imports.forEach(function(i) {
let deps = _reverseImports.get(i); let deps = _reverseImports.get(i);
if (!deps) { if (!deps) {
@ -117,41 +171,71 @@ if (!dart_library) {
deps.add(name); deps.add(name);
}); });
this._name = name; this._name = name;
this._library = defaultValue ? defaultValue : {}; this._defaultLibraryValue =
defaultLibraryValue ? defaultLibraryValue : {};
this._imports = imports; this._imports = imports;
this._loader = loader; this._loader = loader;
data.jsSize = loader.toString().length; data.jsSize = loader.toString().length;
data.loadTime = Infinity; data.loadStart = NaN;
data.loadEnd = NaN;
this._metrics = data; this._metrics = data;
// Cyclic import detection // First loaded instance for supporting logic that assumes there is only
this._state = LibraryLoader.NOT_LOADED; // one app.
// TODO(b/204209941): Remove _firstLibraryInstance after debugger and
// metrics support multiple apps.
this._firstLibraryInstance =
new LibraryInstance(this._deepCopyDefaultValue());
this._firstLibraryInstanceUsed = false;
// App name to instance map.
this._instanceMap = new Map();
} }
loadImports() { /// First loaded value for supporting logic that assumes there is only
let results = []; /// one app.
for (let name of this._imports) { get firstLibraryValue() {
results.push(import_(name)); return this._firstLibraryInstance.libraryValue;
}
/// The loaded instance value for the given `appName`.
libraryValueInApp(appName) {
return this._instanceMap.get(appName).libraryValue;
}
load(appName) {
let instance = this._instanceMap.get(appName);
if (!instance && !this._firstLibraryInstanceUsed) {
// If `_firstLibraryInstance` is already assigned to an app, creates a
// new instance clone (with deep copy) and assigns it the given app.
// Otherwise, reuse `_firstLibraryInstance`.
instance = this._firstLibraryInstance;
this._firstLibraryInstanceUsed = true;
this._instanceMap.set(appName, instance);
}
if (!instance) {
instance = new LibraryInstance(this._deepCopyDefaultValue());
this._instanceMap.set(appName, instance);
} }
return results;
}
load() {
// Check for cycles // Check for cycles
if (this._state == LibraryLoader.LOADING) { if (instance.loadingState == LibraryLoader.LOADING) {
throwLibraryError('Circular dependence on library: ' + this._name); throwLibraryError('Circular dependence on library: ' + this._name);
} else if (this._state >= LibraryLoader.READY) { } else if (instance.loadingState >= LibraryLoader.READY) {
return this._library; return instance.libraryValue;
} }
_executedLibraries.add(this._name); if (!_executedLibraries.has(appName)) {
this._state = LibraryLoader.LOADING; _executedLibraries.set(appName, new Set());
}
_executedLibraries.get(appName).add(this._name);
instance.loadingState = LibraryLoader.LOADING;
// Handle imports // Handle imports
let args = this.loadImports(); let args = this._loadImports(appName);
// Load the library // Load the library
let loader = this; let loader = this;
let library = this._library; let library = instance.libraryValue;
library[libraryImports] = this._imports; library[libraryImports] = this._imports;
library[loadedModule] = library; library[loadedModule] = library;
@ -160,40 +244,50 @@ if (!dart_library) {
if (this._name == 'dart_sdk') { if (this._name == 'dart_sdk') {
// Eagerly load the SDK. // Eagerly load the SDK.
if (!!self.performance) { if (!!self.performance && !!self.performance.now) {
library[_metrics].loadTime = self.performance.now(); library[_metrics].loadStart = self.performance.now();
} }
if (_logMetrics) console.time('Load ' + this._name);
this._loader.apply(null, args); this._loader.apply(null, args);
if (_logMetrics) console.timeEnd('Load ' + this._name); if (!!self.performance && !!self.performance.now) {
library[_metrics].loadEnd = self.performance.now();
}
} else { } else {
// Load / parse other modules on demand. // Load / parse other modules on demand.
let done = false; let done = false;
this._library = new Proxy(library, { instance.libraryValue = new Proxy(library, {
get: function(o, name) { get: function(o, name) {
if (name == _metrics) { if (name == _metrics) {
return o[name]; return o[name];
} }
if (!done) { if (!done) {
done = true; done = true;
if (!!self.performance) { if (!!self.performance && !!self.performance.now) {
library[_metrics].loadTime = self.performance.now(); library[_metrics].loadStart = self.performance.now();
} }
if (_logMetrics) console.time('Load ' + loader._name);
loader._loader.apply(null, args); loader._loader.apply(null, args);
if (_logMetrics) console.timeEnd('Load ' + loader._name); if (!!self.performance && !!self.performance.now) {
library[_metrics].loadEnd = self.performance.now();
}
} }
return o[name]; return o[name];
} }
}); });
} }
this._state = LibraryLoader.READY; instance.loadingState = LibraryLoader.READY;
return this._library; return instance.libraryValue;
} }
stub() { _loadImports(appName) {
return this._library; let results = [];
for (let name of this._imports) {
results.push(import_(name, appName));
}
return results;
}
_deepCopyDefaultValue() {
return JSON.parse(JSON.stringify(this._defaultLibraryValue));
} }
} }
LibraryLoader.NOT_LOADED = 0; LibraryLoader.NOT_LOADED = 0;
@ -208,7 +302,7 @@ if (!dart_library) {
dart_library.debuggerLibraries = function() { dart_library.debuggerLibraries = function() {
let debuggerLibraries = []; let debuggerLibraries = [];
_libraries.forEach(function(value, key, map) { _libraries.forEach(function(value, key, map) {
debuggerLibraries.push(value.load()); debuggerLibraries.push(value.load(_firstStartedAppName));
}); });
debuggerLibraries.__proto__ = null; debuggerLibraries.__proto__ = null;
return debuggerLibraries; return debuggerLibraries;
@ -217,21 +311,24 @@ if (!dart_library) {
// Invalidate a library and all things that depend on it // Invalidate a library and all things that depend on it
function _invalidateLibrary(name) { function _invalidateLibrary(name) {
let lib = _libraries.get(name); let lib = _libraries.get(name);
if (lib._state == LibraryLoader.NOT_LOADED) return; if (lib._instanceMap.size === 0) return;
lib._state = LibraryLoader.NOT_LOADED; lib._firstLibraryInstance =
lib._library = {}; new LibraryInstance(lib._deepCopyDefaultValue());
lib._firstLibraryInstanceUsed = false;
lib._instanceMap.clear();
let deps = _reverseImports.get(name); let deps = _reverseImports.get(name);
if (!deps) return; if (!deps) return;
deps.forEach(_invalidateLibrary); deps.forEach(_invalidateLibrary);
} }
function library(name, defaultValue, imports, loader, data = {}) { function library(name, defaultLibraryValue, imports, loader, data = {}) {
let result = _libraries.get(name); let result = _libraries.get(name);
if (result) { if (result) {
console.log('Re-loading ' + name); console.log('Re-loading ' + name);
_invalidateLibrary(name); _invalidateLibrary(name);
} }
result = new LibraryLoader(name, defaultValue, imports, loader, data); result =
new LibraryLoader(name, defaultLibraryValue, imports, loader, data);
_libraries.set(name, result); _libraries.set(name, result);
return result; return result;
} }
@ -240,20 +337,33 @@ if (!dart_library) {
// Store executed modules upon reload. // Store executed modules upon reload.
if (!!self.addEventListener && !!self.localStorage) { if (!!self.addEventListener && !!self.localStorage) {
self.addEventListener('beforeunload', function(event) { self.addEventListener('beforeunload', function(event) {
let libraryCache = { _nameToApp.forEach(function(_, appName) {
'time': new Date().getTime(), if (!_executedLibraries.get(appName)) {
'modules': Array.from(_executedLibraries.keys()) return;
}; }
self.localStorage.setItem( let libraryCache = {
'dartLibraryCache', JSON.stringify(libraryCache)); 'time': new Date().getTime(),
'modules': Array.from(_executedLibraries.get(appName).keys()),
};
self.localStorage.setItem(
`dartLibraryCache:${appName}`, JSON.stringify(libraryCache));
});
}); });
} }
// Map from module name to corresponding proxy library. // Map from module name to corresponding app to proxy library map.
let _proxyLibs = new Map(); let _proxyLibs = new Map();
function import_(name) { function import_(name, appName) {
let proxy = _proxyLibs.get(name); // For backward compatibility.
if (!appName && _lastStartedSubapp) {
appName = _lastStartedSubapp.appName;
}
let proxy;
if (_proxyLibs.has(name)) {
proxy = _proxyLibs.get(name).get(appName);
}
if (proxy) return proxy; if (proxy) return proxy;
let proxyLib = new Proxy({}, { let proxyLib = new Proxy({}, {
get: function(o, p) { get: function(o, p) {
@ -266,9 +376,21 @@ if (!dart_library) {
xhr.open('GET', sourceURL, false); xhr.open('GET', sourceURL, false);
xhr.withCredentials = true; xhr.withCredentials = true;
xhr.send(); xhr.send();
// Add inline policy to make eval() call Trusted Types compatible
// when running in a TT compatible browser
let policy = {
createScript: function(script) {
return script;
}
};
if (self.trustedTypes && self.trustedTypes.createPolicy) {
policy = self.trustedTypes.createPolicy(
'dartDdcModuleLoading#dart_library', policy);
}
// Append sourceUrl so the resource shows up in the Chrome // Append sourceUrl so the resource shows up in the Chrome
// console. // console.
eval(xhr.responseText + '//@ sourceURL=' + sourceURL); eval(policy.createScript(
xhr.responseText + '//@ sourceURL=' + sourceURL));
lib = _libraries.get(name); lib = _libraries.get(name);
} }
} }
@ -277,10 +399,13 @@ if (!dart_library) {
} }
// Always load the library before accessing a property as it may have // Always load the library before accessing a property as it may have
// been invalidated. // been invalidated.
return lib.load()[p]; return lib.load(appName)[p];
} }
}); });
_proxyLibs.set(name, proxyLib); if (!_proxyLibs.has(name)) {
_proxyLibs.set(name, new Map());
}
_proxyLibs.get(name).set(appName, proxyLib);
return proxyLib; return proxyLib;
} }
dart_library.import = import_; dart_library.import = import_;
@ -297,7 +422,12 @@ if (!dart_library) {
let _debuggerInitialized = false; let _debuggerInitialized = false;
// Called to initiate a hot restart of the application. // Caches the last N runIds to prevent hot reload requests from the same
// runId from executing more than once.
const _hotRestartRunIdCache = new Array();
// Called to initiate a hot restart of the application for a given uuid. If
// it is not set, the last started application will be hot restarted.
// //
// "Hot restart" means all application state is cleared, the newly compiled // "Hot restart" means all application state is cleared, the newly compiled
// modules are loaded, and `main()` is called. // modules are loaded, and `main()` is called.
@ -316,100 +446,190 @@ if (!dart_library) {
// 3. Call dart:_runtime's `hotRestart()` function to clear any state that // 3. Call dart:_runtime's `hotRestart()` function to clear any state that
// `dartdevc` is tracking, such as initialized static fields and type // `dartdevc` is tracking, such as initialized static fields and type
// caches. // caches.
// 4. Call `window.$dartWarmReload()` (provided by the HTML page) to reload // 4. Call `self.$dartReloadModifiedModules()` (provided by the HTML page)
// the relevant JS modules, passing a callback that will invoke `main()`. // to reload the relevant JS modules, passing a callback that will invoke
// 5. `$dartWarmReload` calls the callback to rerun main. // `main()`.
// 5. `$dartReloadModifiedModules` calls the callback to rerun main.
// //
function reload(clearState) { async function hotRestart(config) {
// TODO(jmesserly): once we've rolled out `clearState` make it the if (!self || !self.$dartReloadModifiedModules) {
// default, and eventually remove the parameter.
if (clearState == null) clearState = true;
// TODO(jmesserly): we may want to change these APIs to use the
// "hot restart" terminology for consistency with Flutter. In Flutter,
// "hot reload" refers to keeping the application state and attempting to
// patch the code for the application while it is executing
// (https://flutter.io/hot-reload/), whereas "hot restart" refers to what
// dartdevc supports: tear down the app, update the code, and rerun the
// app.
if (!self || !self.$dartWarmReload) {
console.warn('Hot restart not supported in this environment.'); console.warn('Hot restart not supported in this environment.');
return; return;
} }
// Call the application's `onReloadStart()` function, if provided. // If `config.runId` is set (e.g. a unique build ID that represent the
let result; // current build and shared by multiple subapps), skip the following runs
if (_lastLibrary && _lastLibrary.onReloadStart) { // with the same id.
result = _lastLibrary.onReloadStart(); if (config && config.runId) {
if (_hotRestartRunIdCache.indexOf(config.runId) >= 0) {
// The run has already started (by other subapp or app)
return;
}
_hotRestartRunIdCache.push(config.runId);
// Only cache the runIds for the last N runs. We assume that there are
// less than N requests with different runId can happen in a very short
// period of time (e.g. 1 second).
if (_hotRestartRunIdCache.length > 10) {
_hotRestartRunIdCache.shift();
}
} }
let sdk = _libraries.get('dart_sdk'); self.console.clear();
const sdk = _libraries.get('dart_sdk');
/// Once the `onReloadStart()` completes, this finishes the restart. // Finds out what apps and their subapps should be hot restarted in
function finishHotRestart() { // their starting order.
self.console.clear(); const dirtyAppNames = new Array();
if (clearState) { const dirtySubapps = new Array();
// This resets all initialized fields and clears type caches and other if (config && config.runId) {
// temporary data structures used by the compiler/SDK. _nameToApp.forEach(function(app, appName) {
sdk._library.dart.hotRestart(); dirtySubapps.push(...app.uuidToSubapp.values());
dirtyAppNames.push(appName);
});
} else {
dirtySubapps.push(_lastStartedSubapp);
dirtyAppNames.push(_lastStartedSubapp.appName);
}
// Invokes onReloadStart for each subapp in reversed starting order.
const onReloadStartPromises = new Array();
for (const subapp of dirtySubapps.reverse()) {
// Call the application's `onReloadStart()` function, if provided.
if (subapp.library && subapp.library.onReloadStart) {
const result = subapp.library.onReloadStart();
if (result && result.then) {
let resolve;
onReloadStartPromises.push(new Promise(function(res, _) {
resolve = res;
}));
const dart = sdk.libraryValueInApp(subapp.appName).dart;
result.then(dart.dynamic, function() {
resolve();
});
}
} }
}
// Reverse the subapps back to starting order.
dirtySubapps.reverse();
await Promise.all(onReloadStartPromises);
// Invokes SDK `hotRestart` to reset all initialized fields and clears
// type caches and other temporary data structures used by the
// compiler/SDK.
for (const appName of dirtyAppNames) {
sdk.libraryValueInApp(appName).dart.hotRestart();
}
// Starts the subapps in their starting order.
for (const subapp of dirtySubapps) {
// Call the module loader to reload the necessary modules. // Call the module loader to reload the necessary modules.
self.$dartWarmReload(() => { self.$dartReloadModifiedModules(subapp.appName, function() {
// Once the modules are loaded, rerun `main()`. // Once the modules are loaded, rerun `main()`.
start(_lastModuleName, _lastLibraryName, true); start(
subapp.appName, subapp.uuid, subapp.moduleName,
subapp.libraryName, true);
}); });
} }
}
dart_library.reload = hotRestart;
if (result && result.then) { /// An App contains one or multiple Subapps, all of the subapps share the
result.then(sdk._library.dart.Dynamic)(finishHotRestart); /// same memory copy of library instances, and as a result they share state
} else { /// in Dart statics and top-level fields. There can be one or multiple Apps
finishHotRestart(); /// in a browser window, all of the Apps are isolated from each other
/// (i.e. they create different instances even for the same module).
class App {
constructor(name) {
this.name = name;
// Subapp's uuid to subapps in initial starting order.
// (ES6 preserves iteration order)
this.uuidToSubapp = new Map();
} }
} }
dart_library.reload = reload;
class Subapp {
constructor(uuid, appName, moduleName, libraryName, library) {
this.uuid = uuid;
this.appName = appName;
this.moduleName = moduleName;
this.libraryName = libraryName;
this.library = library;
let _lastModuleName; this.originalBody = null;
let _lastLibraryName; }
let _lastLibrary; }
let _originalBody;
function start(moduleName, libraryName, isReload) { // App name to App map in initial starting order.
// (ES6 preserves iteration order)
const _nameToApp = new Map();
let _firstStartedAppName;
let _lastStartedSubapp;
/// Starts a subapp that is identified with `uuid`, `moduleName`, and
/// `libraryName` inside a parent app that is identified by `appName`.
function start(appName, uuid, moduleName, libraryName, isReload) {
console.info(
`DDC: Subapp Module [${appName}:${moduleName}:${uuid}] is starting`);
if (libraryName == null) libraryName = moduleName; if (libraryName == null) libraryName = moduleName;
_lastModuleName = moduleName; const library = import_(moduleName, appName)[libraryName];
_lastLibraryName = libraryName;
let library = import_(moduleName)[libraryName]; let app = _nameToApp.get(appName);
_lastLibrary = library; if (!isReload) {
let dart_sdk = import_('dart_sdk'); if (!app) {
app = new App(appName);
_nameToApp.set(appName, app);
}
let subapp = app.uuidToSubapp.get(uuid);
if (!subapp) {
subapp = new Subapp(uuid, appName, moduleName, libraryName, library);
app.uuidToSubapp.set(uuid, subapp);
}
_lastStartedSubapp = subapp;
if (!_firstStartedAppName) {
_firstStartedAppName = appName;
}
}
const subapp = app.uuidToSubapp.get(uuid);
const sdk = import_('dart_sdk', appName);
if (!_debuggerInitialized) { if (!_debuggerInitialized) {
// This import is only needed for chrome debugging. We should provide an // This import is only needed for chrome debugging. We should provide an
// option to compile without it. // option to compile without it.
dart_sdk._debugger.registerDevtoolsFormatter(); sdk._debugger.registerDevtoolsFormatter();
// Create isolate. // Create isolate.
_debuggerInitialized = true; _debuggerInitialized = true;
} }
if (isReload) { if (isReload) {
// subapp may have been modified during reload, `subapp.library` needs
// to always point to the latest data.
subapp.library = library;
if (library.onReloadEnd) { if (library.onReloadEnd) {
library.onReloadEnd(); library.onReloadEnd();
return; return;
} else { } else {
if (!!self.document) { if (!!self.document) {
// Note: we expect _originalBody to be undefined in non-browser // Note: we expect originalBody to be undefined in non-browser
// environments, but in that case so is the body. // environments, but in that case so is the body.
if (!_originalBody && !!self.document.body) { if (!subapp.originalBody && !!self.document.body) {
self.console.warn('No body saved to update on reload'); self.console.warn('No body saved to update on reload');
} else { } else {
self.document.body = _originalBody; self.document.body = subapp.originalBody;
} }
} }
} }
} else { } else {
// If not a reload then store the initial html to reset it on reload. // If not a reload and `onReloadEnd` is not defined, store the initial
if (!!self.document && !!self.document.body) { // html to reset it on reload.
_originalBody = self.document.body.cloneNode(true); if (!library.onReloadEnd && !!self.document && !!self.document.body) {
subapp.originalBody = self.document.body.cloneNode(true);
} }
} }
library.main([]); library.main([]);

View file

@ -350,6 +350,8 @@ class TestDriver {
var bootstrapFile = File(htmlBootstrapper.toFilePath())..createSync(); var bootstrapFile = File(htmlBootstrapper.toFilePath())..createSync();
var moduleName = compiler.metadata!.name; var moduleName = compiler.metadata!.name;
var mainLibraryName = compiler.metadataForLibraryUri(input).name; var mainLibraryName = compiler.metadataForLibraryUri(input).name;
var appName = p.relative(
p.withoutExtension(compiler.metadataForLibraryUri(input).importUri));
switch (setup.moduleFormat) { switch (setup.moduleFormat) {
case ModuleFormat.ddc: case ModuleFormat.ddc:
@ -368,6 +370,9 @@ class TestDriver {
var dartLibraryPath = var dartLibraryPath =
escaped(p.join(ddcPath, 'lib', 'js', 'legacy', 'dart_library.js')); escaped(p.join(ddcPath, 'lib', 'js', 'legacy', 'dart_library.js'));
var outputPath = output.toFilePath(); var outputPath = output.toFilePath();
// This is used in the DDC module system for multiapp workflows and is
// stubbed here.
var uuid = '00000000-0000-0000-0000-000000000000';
bootstrapFile.writeAsStringSync(''' bootstrapFile.writeAsStringSync('''
<script src='$dartLibraryPath'></script> <script src='$dartLibraryPath'></script>
<script src='$dartSdkPath'></script> <script src='$dartSdkPath'></script>
@ -384,7 +389,8 @@ class TestDriver {
sdk.dart.nonNullAsserts(true); sdk.dart.nonNullAsserts(true);
sdk.dart.nativeNonNullAsserts(true); sdk.dart.nativeNonNullAsserts(true);
sdk._debugger.registerDevtoolsFormatter(); sdk._debugger.registerDevtoolsFormatter();
dart_library.start('$moduleName', '$mainLibraryName'); dart_library.start('$appName', '$uuid', '$moduleName', '$mainLibraryName',
false);
</script> </script>
'''); ''');
break; break;

View file

@ -136,6 +136,14 @@ void main(List<String> args) async {
var libname = var libname =
js_names.pathToJSIdentifier(p.relative(p.withoutExtension(entry))); js_names.pathToJSIdentifier(p.relative(p.withoutExtension(entry)));
// This is used in the DDC module system and usually corresponds to the
// entrypoint's path.
var appname = p.relative(p.withoutExtension(entry));
// This is used in the DDC module system for multiapp workflows and is
// stubbed in ddb.
var uuid = "00000000-0000-0000-0000-000000000000";
// By default (no `-d`), we use the `dartdevc` binary on the user's path to // By default (no `-d`), we use the `dartdevc` binary on the user's path to
// compute the SDK we use for execution. I.e., we assume that `dart` is // compute the SDK we use for execution. I.e., we assume that `dart` is
// under `$DART_SDK/bin/dart` and use that to find `dartdevc` and related // under `$DART_SDK/bin/dart` and use that to find `dartdevc` and related
@ -353,7 +361,7 @@ sdk.dart.nativeNonNullAsserts($nativeNonNullAsserts);
// Invoke main through the d8 preamble to ensure the code is running // Invoke main through the d8 preamble to ensure the code is running
// within the fake event loop. // within the fake event loop.
self.dartMainRunner(function () { self.dartMainRunner(function () {
dart_library.start("$basename", "$libname"); dart_library.start("$appname", "$uuid", "$basename", "$libname", false);
}); });
'''; ''';
var dart2jsD8Preamble = var dart2jsD8Preamble =