[ddc] Adding a runtime flag for real deferred loading in DDC

Change-Id: If50f7437c827a32829f5093cb3a14cbc5e55f7a7
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/289340
Commit-Queue: Mark Zhou <markzipan@google.com>
Reviewed-by: Anna Gringauze <annagrin@google.com>
This commit is contained in:
Mark Zhou
2023-03-17 18:04:48 +00:00
committed by Commit Queue
parent 2cec283bd0
commit 80c2b02bd0
2 changed files with 52 additions and 22 deletions
+17 -6
View File
@@ -608,16 +608,25 @@ class ProgramCompiler extends ComputeOnceConstantVisitor<js_ast.Expression>
}
@override
String libraryToModule(Library library) {
String libraryToModule(Library library, {bool throwIfNotFound = true}) {
if (library.importUri.isScheme('dart')) {
// TODO(jmesserly): we need to split out HTML.
return js_ast.dartSdkModule;
}
var summary = _importToSummary[library]!;
var summary = _importToSummary[library];
if (summary == null) {
if (throwIfNotFound) {
throw StateError('Could not find summary for library "$library".');
}
return '';
}
var moduleName = _summaryToModule[summary];
if (moduleName == null) {
throw StateError('Could not find module name for library "$library" '
'from component "$summary".');
if (throwIfNotFound) {
throw StateError('Could not find module name for library "$library" '
'from component "$summary".');
}
return '';
}
return moduleName;
}
@@ -7050,9 +7059,11 @@ class ProgramCompiler extends ComputeOnceConstantVisitor<js_ast.Expression>
@override
js_ast.Expression visitLoadLibrary(LoadLibrary node) =>
runtimeCall('loadLibrary(#, #)', [
runtimeCall('loadLibrary(#, #, #)', [
js.string(node.import.enclosingLibrary.importUri.toString()),
js.string(node.import.name!)
js.string(node.import.name!),
js.string(
libraryToModule(node.import.targetLibrary, throwIfNotFound: false))
]);
// TODO(jmesserly): DDC loads all libraries eagerly.
@@ -856,32 +856,51 @@ _canonicalMember(obj, name) {
return name;
}
@notNull
bool _realDeferredLoading = false;
/// Sets the runtime mode to perform deferred loading (instead of just runtime
/// correctness checks on loaded libraries).
///
/// This is only supported in the DDC module system.
void realDeferredLoading(bool enable) {
_realDeferredLoading = enable;
}
/// A map from libraries to a set of import prefixes that have been loaded.
///
/// Used to validate deferred library conventions.
final deferredImports = JS<Object>('!', 'new Map()');
/// Emulates the implicit "loadLibrary" function provided by a deferred library.
/// Loads the element [importPrefix] in the module [targetModule] from the
/// context of the library [libraryUri].
///
/// Libraries are not actually deferred in DDC, so this just records the import
/// for runtime validation, then returns a future that completes immediately.
Future loadLibrary(
@notNull String enclosingLibrary, @notNull String importPrefix) {
var result = JS('', '#.get(#)', deferredImports, enclosingLibrary);
if (JS<bool>('', '# === void 0', result)) {
JS('', '#.set(#, # = new Set())', deferredImports, enclosingLibrary,
result);
/// Will load any modules required by [targetModule] as a side effect.
/// Only supported in the DDC module system.
Future<void> loadLibrary(@notNull String libraryUri,
@notNull String importPrefix, @notNull String targetModule) {
if (!_realDeferredLoading) {
var result = JS('', '#.get(#)', deferredImports, libraryUri);
if (JS<bool>('', '# === void 0', result)) {
JS('', '#.set(#, # = new Set())', deferredImports, libraryUri, result);
}
JS('', '#.add(#)', result, importPrefix);
return Future.value();
} else {
throw UnimplementedError('realDeferredLoading flag is not yet supported');
}
JS('', '#.add(#)', result, importPrefix);
return Future.value();
}
void checkDeferredIsLoaded(
@notNull String enclosingLibrary, @notNull String importPrefix) {
var loaded = JS('', '#.get(#)', deferredImports, enclosingLibrary);
if (JS<bool>('', '# === void 0', loaded) ||
JS<bool>('', '!#.has(#)', loaded, importPrefix)) {
throwDeferredIsLoadedError(enclosingLibrary, importPrefix);
@notNull String libraryUri, @notNull String importPrefix) {
if (!_realDeferredLoading) {
var loaded = JS('', '#.get(#)', deferredImports, libraryUri);
if (JS<bool>('', '# === void 0', loaded) ||
JS<bool>('', '!#.has(#)', loaded, importPrefix)) {
throwDeferredIsLoadedError(libraryUri, importPrefix);
}
} else {
throw UnimplementedError('realDeferredLoading flag is not yet supported');
}
}