Skip to content

Commit

Permalink
Validation of dynamic modules
Browse files Browse the repository at this point in the history
TEST=pkg/front_end/testcases/general/dynamic_modules


Change-Id: I591d029ed163961f5ece859233874f828d63c857
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/388442
Reviewed-by: Johnni Winther <johnniwinther@google.com>
Commit-Queue: Alexander Markov <alexmarkov@google.com>
Reviewed-by: Sigmund Cherem <sigmund@google.com>
  • Loading branch information
alexmarkov authored and Commit Queue committed Oct 24, 2024
1 parent 6a5b3d0 commit c409e77
Show file tree
Hide file tree
Showing 39 changed files with 3,021 additions and 181 deletions.
194 changes: 194 additions & 0 deletions pkg/_fe_analyzer_shared/lib/src/messages/codes_generated.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1370,6 +1370,77 @@ const MessageCode messageClassInClass = const MessageCode(
correctionMessage: r"""Try moving the class to the top-level.""",
);

// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const Template<Message Function(String name)>
templateClassShouldBeListedAsCallableInDynamicInterface =
const Template<Message Function(String name)>(
"ClassShouldBeListedAsCallableInDynamicInterface",
problemMessageTemplate: r"""Cannot use class '#name' in a dynamic module.""",
correctionMessageTemplate:
r"""Try removing the reference to class '#name' or update the dynamic interface to list class '#name' as callable.""",
withArguments: _withArgumentsClassShouldBeListedAsCallableInDynamicInterface,
);

// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const Code<Message Function(String name)>
codeClassShouldBeListedAsCallableInDynamicInterface =
const Code<Message Function(String name)>(
"ClassShouldBeListedAsCallableInDynamicInterface",
);

// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
Message _withArgumentsClassShouldBeListedAsCallableInDynamicInterface(
String name) {
if (name.isEmpty) throw 'No name provided';
name = demangleMixinApplicationName(name);
return new Message(
codeClassShouldBeListedAsCallableInDynamicInterface,
problemMessage: """Cannot use class '${name}' in a dynamic module.""",
correctionMessage:
"""Try removing the reference to class '${name}' or update the dynamic interface to list class '${name}' as callable.""",
arguments: {
'name': name,
},
);
}

// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const Template<Message Function(String name)>
templateClassShouldBeListedAsExtendableInDynamicInterface =
const Template<Message Function(String name)>(
"ClassShouldBeListedAsExtendableInDynamicInterface",
problemMessageTemplate:
r"""Cannot extend, implement or mix-in class '#name' in a dynamic module.""",
correctionMessageTemplate:
r"""Try removing the reference to class '#name' or update the dynamic interface to list class '#name' as extendable.""",
withArguments:
_withArgumentsClassShouldBeListedAsExtendableInDynamicInterface,
);

// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const Code<Message Function(String name)>
codeClassShouldBeListedAsExtendableInDynamicInterface =
const Code<Message Function(String name)>(
"ClassShouldBeListedAsExtendableInDynamicInterface",
);

// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
Message _withArgumentsClassShouldBeListedAsExtendableInDynamicInterface(
String name) {
if (name.isEmpty) throw 'No name provided';
name = demangleMixinApplicationName(name);
return new Message(
codeClassShouldBeListedAsExtendableInDynamicInterface,
problemMessage:
"""Cannot extend, implement or mix-in class '${name}' in a dynamic module.""",
correctionMessage:
"""Try removing the reference to class '${name}' or update the dynamic interface to list class '${name}' as extendable.""",
arguments: {
'name': name,
},
);
}

// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const Code<Null> codeColonInPlaceOfIn = messageColonInPlaceOfIn;

Expand Down Expand Up @@ -2370,6 +2441,43 @@ const MessageCode messageConstructorNotSync = const MessageCode(
r"""Constructor bodies can't use 'async', 'async*', or 'sync*'.""",
);

// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const Template<Message Function(String name)>
templateConstructorShouldBeListedAsCallableInDynamicInterface =
const Template<Message Function(String name)>(
"ConstructorShouldBeListedAsCallableInDynamicInterface",
problemMessageTemplate:
r"""Cannot invoke constructor '#name' from a dynamic module.""",
correctionMessageTemplate:
r"""Try removing the call or update the dynamic interface to list constructor '#name' as callable.""",
withArguments:
_withArgumentsConstructorShouldBeListedAsCallableInDynamicInterface,
);

// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const Code<Message Function(String name)>
codeConstructorShouldBeListedAsCallableInDynamicInterface =
const Code<Message Function(String name)>(
"ConstructorShouldBeListedAsCallableInDynamicInterface",
);

// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
Message _withArgumentsConstructorShouldBeListedAsCallableInDynamicInterface(
String name) {
if (name.isEmpty) throw 'No name provided';
name = demangleMixinApplicationName(name);
return new Message(
codeConstructorShouldBeListedAsCallableInDynamicInterface,
problemMessage:
"""Cannot invoke constructor '${name}' from a dynamic module.""",
correctionMessage:
"""Try removing the call or update the dynamic interface to list constructor '${name}' as callable.""",
arguments: {
'name': name,
},
);
}

// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const Code<Null> codeConstructorTearOffWithTypeArguments =
messageConstructorTearOffWithTypeArguments;
Expand Down Expand Up @@ -3655,6 +3763,17 @@ Message _withArgumentsDuplicatedRecordTypeFieldNameContext(String name) {
);
}

// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const Code<Null> codeDynamicCallsAreNotAllowedInDynamicModule =
messageDynamicCallsAreNotAllowedInDynamicModule;

// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const MessageCode messageDynamicCallsAreNotAllowedInDynamicModule =
const MessageCode(
"DynamicCallsAreNotAllowedInDynamicModule",
problemMessage: r"""Dynamic calls are not allowed in a dynamic module.""",
);

// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const Code<Null> codeEmptyMapPattern = messageEmptyMapPattern;

Expand Down Expand Up @@ -11865,6 +11984,81 @@ Message _withArgumentsMemberNotFound(String name) {
);
}

// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const Template<Message Function(String name)>
templateMemberShouldBeListedAsCallableInDynamicInterface =
const Template<Message Function(String name)>(
"MemberShouldBeListedAsCallableInDynamicInterface",
problemMessageTemplate:
r"""Cannot invoke member '#name' from a dynamic module.""",
correctionMessageTemplate:
r"""Try removing the call or update the dynamic interface to list member '#name' as callable.""",
withArguments: _withArgumentsMemberShouldBeListedAsCallableInDynamicInterface,
);

// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const Code<Message Function(String name)>
codeMemberShouldBeListedAsCallableInDynamicInterface =
const Code<Message Function(String name)>(
"MemberShouldBeListedAsCallableInDynamicInterface",
);

// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
Message _withArgumentsMemberShouldBeListedAsCallableInDynamicInterface(
String name) {
if (name.isEmpty) throw 'No name provided';
name = demangleMixinApplicationName(name);
return new Message(
codeMemberShouldBeListedAsCallableInDynamicInterface,
problemMessage: """Cannot invoke member '${name}' from a dynamic module.""",
correctionMessage:
"""Try removing the call or update the dynamic interface to list member '${name}' as callable.""",
arguments: {
'name': name,
},
);
}

// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const Template<Message Function(String name, String name2)>
templateMemberShouldBeListedAsCanBeOverriddenInDynamicInterface =
const Template<Message Function(String name, String name2)>(
"MemberShouldBeListedAsCanBeOverriddenInDynamicInterface",
problemMessageTemplate:
r"""Cannot override member '#name.#name2' in a dynamic module.""",
correctionMessageTemplate:
r"""Try removing the override or update the dynamic interface to list member '#name.#name2' as can-be-overridden.""",
withArguments:
_withArgumentsMemberShouldBeListedAsCanBeOverriddenInDynamicInterface,
);

// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const Code<Message Function(String name, String name2)>
codeMemberShouldBeListedAsCanBeOverriddenInDynamicInterface =
const Code<Message Function(String name, String name2)>(
"MemberShouldBeListedAsCanBeOverriddenInDynamicInterface",
);

// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
Message _withArgumentsMemberShouldBeListedAsCanBeOverriddenInDynamicInterface(
String name, String name2) {
if (name.isEmpty) throw 'No name provided';
name = demangleMixinApplicationName(name);
if (name2.isEmpty) throw 'No name provided';
name2 = demangleMixinApplicationName(name2);
return new Message(
codeMemberShouldBeListedAsCanBeOverriddenInDynamicInterface,
problemMessage:
"""Cannot override member '${name}.${name2}' in a dynamic module.""",
correctionMessage:
"""Try removing the override or update the dynamic interface to list member '${name}.${name2}' as can-be-overridden.""",
arguments: {
'name': name,
'name2': name2,
},
);
}

// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const Code<Null> codeMemberWithSameNameAsClass =
messageMemberWithSameNameAsClass;
Expand Down
11 changes: 10 additions & 1 deletion pkg/dart2bytecode/lib/dart2bytecode.dart
Original file line number Diff line number Diff line change
Expand Up @@ -79,13 +79,17 @@ final ArgParser _argParser = ArgParser(allowTrailingOptions: true)
..addOption('invocation-modes',
help: 'Provides information to the front end about how it is invoked.',
defaultsTo: '')
..addOption('validate',
help:
'Validate dynamic module against specified dynamic interface YAML file',
defaultsTo: null)
..addOption('verbosity',
help: 'Sets the verbosity level used for filtering messages during '
'compilation.',
defaultsTo: Verbosity.defaultValue);

final String _usage = '''
Usage: dart2bytecode --platform vm_platform_strong.dill [--import-dill host_app.dill] [options] input.dart
Usage: dart2bytecode --platform vm_platform_strong.dill [--import-dill host_app.dill] [--validate dynamic_interface.yaml] [options] input.dart
Compiles Dart sources to Dart bytecode.
Options:
Expand Down Expand Up @@ -140,6 +144,10 @@ Future<int> runCompiler(ArgResults options) async {
additionalDills.add(Uri.base.resolveUri(new Uri.file(importDill)));
}

final String? validate = options['validate'];
final Uri? dynamicInterfaceSpecificationUri =
(validate != null) ? resolveInputUri(validate) : null;

final verbosity = Verbosity.parseArgument(options['verbosity']);
final errorPrinter = ErrorPrinter(verbosity);
final errorDetector = ErrorDetector(previousErrorHandler: errorPrinter.call);
Expand All @@ -154,6 +162,7 @@ Future<int> runCompiler(ArgResults options) async {
..fileSystem = fileSystem
..additionalDills = additionalDills
..packagesFileUri = packagesUri
..dynamicInterfaceSpecificationUri = dynamicInterfaceSpecificationUri
..explicitExperimentalFlags = parseExperimentalFlags(
parseExperimentalArguments(experimentalFlags),
onError: print)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,6 @@ callable:
# TODO(sigmund): This should be included by default
- library: 'dart:core'
class: 'Object'
member: ''
- library: 'dart:core'
class: 'pragma'
member: '_'
10 changes: 10 additions & 0 deletions pkg/dynamic_modules/test/data/extend_class/dynamic_interface.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,13 @@ callable:
- library: 'shared/shared.dart'
class: 'Base'
member: ''
# TODO(sigmund): This should be included by default
- library: 'dart:core'
class: 'Object'
- library: 'dart:core'
class: 'int'
- library: 'dart:core'
class: 'pragma'
member: '_'
- library: 'dart:core'
member: 'override'
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,13 @@ callable:
# TODO(sigmund): This should be included by default
- library: 'dart:core'
class: 'Object'
member: ''
- library: 'dart:core'
class: 'int'
- library: 'dart:core'
class: 'pragma'
member: '_'
- library: 'dart:core'
member: 'override'

can-be-overridden:
- library: 'shared/shared.dart'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,6 @@ callable:
# TODO(sigmund): This should be included by default
- library: 'dart:core'
class: 'Object'
member: ''
- library: 'dart:core'
class: 'pragma'
member: '_'
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,9 @@ callable:
- library: 'main.dart'
class: 'B'
member: ''
# TODO(sigmund): This should be included by default
- library: 'dart:core'
class: 'Object'
- library: 'dart:core'
class: 'pragma'
member: '_'
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,7 @@
# BSD-style license that can be found in the LICENSE file.
callable:
- library: 'shared/shared.dart'
# TODO(sigmund): This should be included by default
- library: 'dart:core'
class: 'pragma'
member: '_'
2 changes: 2 additions & 0 deletions pkg/dynamic_modules/test/runner/aot.dart
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,8 @@ class AotExecutor implements TargetExecutor {
'-Ddart.vm.product=true',
'--import-dill',
'${test.main}_no_aot.dill',
'--validate',
'$rootScheme:/data/${test.name}/dynamic_interface.yaml',
'--verbosity=all',
'--filesystem-root',
test.folder.resolve('../../').toFilePath(),
Expand Down
14 changes: 14 additions & 0 deletions pkg/front_end/lib/src/api_prototype/compiler_options.dart
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,16 @@ class CompilerOptions {
/// at a default location within [sdkRoot].
Uri? sdkSummary;

/// Uri to a dynamic interface specification file.
///
/// A dynamic interface specification file is a YAML file that lists
/// Dart APIs (libraries, classes and members) available for a dynamic module.
///
/// If value is specified, the compiled Dart libraries are validated
/// to conform to the dynamic module interface and other dynamic module
/// restrictions.
Uri? dynamicInterfaceSpecificationUri;

/// The declared variables for use by configurable imports and constant
/// evaluation.
Map<String, String>? declaredVariables;
Expand Down Expand Up @@ -345,6 +355,10 @@ class CompilerOptions {
if (packagesFileUri != other.packagesFileUri) return false;
if (!equalLists(additionalDills, other.additionalDills)) return false;
if (sdkSummary != other.sdkSummary) return false;
if (dynamicInterfaceSpecificationUri !=
other.dynamicInterfaceSpecificationUri) {
return false;
}
if (!equalMaps(declaredVariables, other.declaredVariables)) return false;
if (fileSystem != other.fileSystem) return false;
if (compileSdk != other.compileSdk) return false;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

library front_end.dynamic_module_validator;

export '../kernel/dynamic_module_validator.dart'
show DynamicInterfaceSpecification;
Loading

0 comments on commit c409e77

Please sign in to comment.