Version 2.19.0-28.0.dev
Merge commit 'a13ef8a5d5e96e1176488c66797181377389bbc3' into 'dev'
diff --git a/pkg/_fe_analyzer_shared/pubspec.yaml b/pkg/_fe_analyzer_shared/pubspec.yaml
index d64e8b8..9a47861 100644
--- a/pkg/_fe_analyzer_shared/pubspec.yaml
+++ b/pkg/_fe_analyzer_shared/pubspec.yaml
@@ -1,5 +1,5 @@
name: _fe_analyzer_shared
-version: 41.0.0
+version: 42.0.0
description: Logic that is shared between the front_end and analyzer packages.
repository: https://github.com/dart-lang/sdk/tree/main/pkg/_fe_analyzer_shared
diff --git a/pkg/analyzer/CHANGELOG.md b/pkg/analyzer/CHANGELOG.md
index c0781e9..ba6892e 100644
--- a/pkg/analyzer/CHANGELOG.md
+++ b/pkg/analyzer/CHANGELOG.md
@@ -1,7 +1,7 @@
-## 4.3.0-dev
+## 4.3.0
* Deprecated `Directive.keyword`, use corresponding `xyzToken` in specific directives.
* Deprecated `LibraryElement.parts`, use `parts2` instead.
-* Deprecated `LibraryElement.exports`, use `libraryexports` instead.
+* Deprecated `LibraryElement.exports`, use `libraryExports` instead.
* Deprecated `LibraryElement.imports`, use `libraryImports` instead.
* Deprecated `Element.enclosingElement`, use `enclosingElement2` instead.
* `Member` is not equal to `ElementImpl`, use `Element.declaration`.
diff --git a/pkg/analyzer/pubspec.yaml b/pkg/analyzer/pubspec.yaml
index 4b27f79..6c3c45f 100644
--- a/pkg/analyzer/pubspec.yaml
+++ b/pkg/analyzer/pubspec.yaml
@@ -1,5 +1,5 @@
name: analyzer
-version: 4.3.0-dev
+version: 4.3.0
description: This package provides a library that performs static analysis of Dart code.
repository: https://github.com/dart-lang/sdk/tree/main/pkg/analyzer
@@ -7,7 +7,7 @@
sdk: '>=2.17.0 <3.0.0'
dependencies:
- _fe_analyzer_shared: ^41.0.0
+ _fe_analyzer_shared: ^42.0.0
collection: ^1.15.0
convert: ^3.0.0
crypto: ^3.0.0
diff --git a/pkg/compiler/lib/src/inferrer/powersets/powerset_bits.dart b/pkg/compiler/lib/src/inferrer/powersets/powerset_bits.dart
index 2ef3f29..d6e4d47 100644
--- a/pkg/compiler/lib/src/inferrer/powersets/powerset_bits.dart
+++ b/pkg/compiler/lib/src/inferrer/powersets/powerset_bits.dart
@@ -2,8 +2,6 @@
// 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.
-// @dart = 2.10
-
import '../../common/elements.dart' show CommonElements;
import '../../constants/values.dart';
import '../../elements/entities.dart';
@@ -11,7 +9,7 @@
import '../../elements/types.dart';
import '../../ir/class_relation.dart';
import '../../universe/selector.dart';
-import '../../world.dart';
+import '../../world_interfaces.dart';
import '../abstract_value_domain.dart';
/// This class is used to store bits information about class entities.
@@ -172,7 +170,7 @@
// TODO(coam): This currently returns null if we are not sure if it's a primitive.
// It could be improved because we can also tell when we're certain it's not a primitive.
- PrimitiveConstantValue getPrimitiveValue(int value) {
+ PrimitiveConstantValue? getPrimitiveValue(int value) {
if (isDefinitelyTrue(value)) {
return TrueConstantValue();
}
@@ -355,7 +353,7 @@
}
ClassInfo _computeClassInfo(ClassEntity cls) {
- ClassInfo classInfo = _storedClassInfo[cls];
+ ClassInfo? classInfo = _storedClassInfo[cls];
if (classInfo != null) {
return classInfo;
}
@@ -442,7 +440,10 @@
}
int createFromStaticType(DartType type,
- {ClassRelation classRelation = ClassRelation.subtype, bool nullable}) {
+ {ClassRelation classRelation = ClassRelation.subtype,
+ required bool nullable}) {
+ // TODO(48820): Remove after sound null safety is enabled.
+ // ignore: unnecessary_null_comparison
assert(nullable != null);
if ((classRelation == ClassRelation.subtype ||
@@ -481,8 +482,6 @@
int _createFromStaticType(
DartType type, ClassRelation classRelation, bool nullable) {
- assert(nullable != null);
-
int finish(int value, bool isPrecise) {
// [isPrecise] is ignored since we only treat singleton partitions as
// precise.
@@ -576,26 +575,21 @@
int get emptyType => powersetBottom;
- int _constMapType;
- int get constMapType => _constMapType ??=
+ late final int constMapType =
createNonNullSubtype(commonElements.constMapLiteralClass);
int get constSetType => otherValue;
- int _constListType;
- int get constListType => _constListType ??=
+ late final int constListType =
createNonNullExact(commonElements.jsUnmodifiableArrayClass);
- int _fixedListType;
- int get fixedListType =>
- _fixedListType ??= createNonNullExact(commonElements.jsFixedArrayClass);
+ late final int fixedListType =
+ createNonNullExact(commonElements.jsFixedArrayClass);
- int _growableListType;
- int get growableListType => _growableListType ??=
+ late final int growableListType =
createNonNullExact(commonElements.jsExtendableArrayClass);
- int _mutableArrayType;
- int get mutableArrayType => _mutableArrayType ??=
+ late final int mutableArrayType =
createNonNullSubtype(commonElements.jsMutableArrayClass);
int get nullType => nullValue;
@@ -605,33 +599,21 @@
// TODO(fishythefish): Support tracking late sentinels in the powerset domain.
int get lateSentinelType => powersetBottom;
- int _mapType;
- int get mapType =>
- _mapType ??= createNonNullSubtype(commonElements.mapLiteralClass);
+ late final int mapType = createNonNullSubtype(commonElements.mapLiteralClass);
- int _setType;
- int get setType =>
- _setType ??= createNonNullSubtype(commonElements.setLiteralClass);
+ late final int setType = createNonNullSubtype(commonElements.setLiteralClass);
- int _listType;
- int get listType =>
- _listType ??= createNonNullExact(commonElements.jsArrayClass);
+ late final int listType = createNonNullExact(commonElements.jsArrayClass);
- int _stringType;
- int get stringType =>
- _stringType ??= createNonNullSubtype(commonElements.jsStringClass);
+ late final int stringType =
+ createNonNullSubtype(commonElements.jsStringClass);
- int _numType;
- int get numType =>
- _numType ??= createNonNullSubclass(commonElements.jsNumberClass);
+ late final int numType = createNonNullSubclass(commonElements.jsNumberClass);
- int _numNotIntType;
- int get numNotIntType =>
- _numNotIntType ??= createNonNullExact(commonElements.jsNumNotIntClass);
+ late final int numNotIntType =
+ createNonNullExact(commonElements.jsNumNotIntClass);
- int _intType;
- int get intType =>
- _intType ??= createNonNullSubtype(commonElements.jsIntClass);
+ late final int intType = createNonNullSubtype(commonElements.jsIntClass);
int get positiveIntType => intType;
int get uint32Type => intType;
@@ -639,9 +621,8 @@
int get boolType => boolValue;
- int _functionType;
- int get functionType =>
- _functionType ??= createNonNullSubtype(commonElements.functionClass);
+ late final int functionType =
+ createNonNullSubtype(commonElements.functionClass);
int get typeType => otherValue;
}
diff --git a/pkg/compiler/lib/src/js_backend/codegen_listener.dart b/pkg/compiler/lib/src/js_backend/codegen_listener.dart
index b63bba17..886ccfc 100644
--- a/pkg/compiler/lib/src/js_backend/codegen_listener.dart
+++ b/pkg/compiler/lib/src/js_backend/codegen_listener.dart
@@ -2,8 +2,6 @@
// 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.
-// @dart = 2.10
-
library js_backend.backend.codegen_listener;
import 'dart:collection';
@@ -101,7 +99,7 @@
@override
void onQueueOpen(
- Enqueuer enqueuer, FunctionEntity mainMethod, Iterable<Uri> libraries) {
+ Enqueuer enqueuer, FunctionEntity? mainMethod, Iterable<Uri> libraries) {
enqueuer.applyImpact(_nativeEnqueuer.processNativeClasses(libraries));
if (mainMethod != null) {
enqueuer.applyImpact(_computeMainImpact(mainMethod));
@@ -178,8 +176,8 @@
.registerTypeUse(TypeUse.instantiation(_commonElements.typeType));
// If the type is a web component, we need to ensure the constructors are
// available to 'upgrade' the native object.
- if (constant.representedType is InterfaceType) {
- InterfaceType representedType = constant.representedType;
+ final representedType = constant.representedType;
+ if (representedType is InterfaceType) {
_customElementsAnalysis.registerTypeConstant(representedType.element);
}
} else if (constant is InstantiationConstantValue) {
@@ -228,10 +226,10 @@
_customElementsAnalysis.registerStaticUse(member);
if (member.isFunction && member.isInstanceMember) {
- ClassEntity cls = member.enclosingClass;
+ ClassEntity cls = member.enclosingClass!;
if (member.name == Identifiers.call &&
_elementEnvironment.isGenericClass(cls) &&
- _rtiNeed.methodNeedsSignature(member)) {
+ _rtiNeed.methodNeedsSignature(member as FunctionEntity)) {
worldImpact.addImpact(_registerComputeSignature());
}
}
diff --git a/pkg/compiler/lib/src/resolution/enqueuer.dart b/pkg/compiler/lib/src/resolution/enqueuer.dart
index 3a27e62..e2af326 100644
--- a/pkg/compiler/lib/src/resolution/enqueuer.dart
+++ b/pkg/compiler/lib/src/resolution/enqueuer.dart
@@ -35,7 +35,7 @@
final Set<ClassEntity> _recentClasses = Setlet<ClassEntity>();
bool _recentConstants = false;
- final ResolutionWorldBuilderForEnqueuer worldBuilder;
+ final ResolutionWorldBuilder worldBuilder;
WorkItemBuilder? _workItemBuilder;
final DiagnosticReporter _reporter;
final AnnotationsData _annotationsData;
diff --git a/pkg/compiler/lib/src/universe/resolution_world_builder.dart b/pkg/compiler/lib/src/universe/resolution_world_builder.dart
index 40433ca..a7aa234 100644
--- a/pkg/compiler/lib/src/universe/resolution_world_builder.dart
+++ b/pkg/compiler/lib/src/universe/resolution_world_builder.dart
@@ -193,7 +193,7 @@
}
class ResolutionWorldBuilder extends WorldBuilder
- implements World, interfaces.ResolutionWorldBuilderForEnqueuer {
+ implements World, interfaces.ResolutionWorldBuilder {
/// Instantiation information for all classes with instantiated types.
///
/// Invariant: Elements are declaration elements.
@@ -921,6 +921,7 @@
/// Here `A.m` is inherited into `A`, `B`, and `C`. Because `B` and
/// `C` implement `I`, `isInheritedInSubtypeOf(A.m, I)` is true, but
/// `isInheritedInSubtypeOf(A.m, J)` is false.
+ @override
bool isInheritedIn(
MemberEntity member, ClassEntity type, ClassRelation relation) {
// TODO(johnniwinther): Use the [member] itself to avoid enqueueing members
diff --git a/pkg/compiler/lib/src/universe/resolution_world_builder_interfaces.dart b/pkg/compiler/lib/src/universe/resolution_world_builder_interfaces.dart
index 6c31592..eae29e5 100644
--- a/pkg/compiler/lib/src/universe/resolution_world_builder_interfaces.dart
+++ b/pkg/compiler/lib/src/universe/resolution_world_builder_interfaces.dart
@@ -4,10 +4,12 @@
import '../elements/entities.dart';
import '../elements/types.dart';
+import '../ir/class_relation.dart';
import 'member_usage.dart';
import 'use.dart';
+import '../world_interfaces.dart';
-abstract class ResolutionWorldBuilderForEnqueuer {
+abstract class ResolutionWorldBuilder implements World {
Iterable<ClassEntity> get directlyInstantiatedClasses;
Iterable<MemberEntity> get processedMembers;
@@ -19,6 +21,9 @@
void processClassMembers(ClassEntity cls, MemberUsedCallback memberUsed,
{bool checkEnqueuerConsistency = false});
+ bool isInheritedIn(
+ MemberEntity member, ClassEntity type, ClassRelation relation);
+
void registerDynamicUse(DynamicUse dynamicUse, MemberUsedCallback memberUsed);
bool registerConstantUse(ConstantUse use);
diff --git a/pkg/compiler/lib/src/universe/world_builder.dart b/pkg/compiler/lib/src/universe/world_builder.dart
index 7d3e254..1c5c834 100644
--- a/pkg/compiler/lib/src/universe/world_builder.dart
+++ b/pkg/compiler/lib/src/universe/world_builder.dart
@@ -2,8 +2,6 @@
// 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.
-// @dart = 2.10
-
library world_builder;
import '../common/elements.dart';
@@ -12,10 +10,10 @@
import '../elements/types.dart';
import '../ir/class_relation.dart';
import '../js_backend/native_data.dart' show NativeBasicData;
-import '../universe/resolution_world_builder.dart' show ResolutionWorldBuilder;
-import '../world.dart' show World;
+import '../world_interfaces.dart' show World;
import 'selector.dart' show Selector;
import 'use.dart' show DynamicUse, StaticUse;
+import 'resolution_world_builder_interfaces.dart' show ResolutionWorldBuilder;
import 'strong_mode_constraint.dart' show StrongModeConstraintInterface;
/// The combined constraints on receivers all the dynamic call sites of the same
@@ -73,7 +71,7 @@
abstract class UniverseSelectorConstraints extends SelectorConstraints {
/// Adds [constraint] to these selector constraints. Return `true` if the set
/// of potential receivers expanded due to the new constraint.
- bool addReceiverConstraint(covariant Object constraint);
+ bool addReceiverConstraint(covariant Object? constraint);
}
/// Strategy for computing the constraints on potential receivers of dynamic
@@ -82,7 +80,7 @@
/// Create a [UniverseSelectorConstraints] to represent the global receiver
/// constraints for dynamic call sites with [selector].
UniverseSelectorConstraints createSelectorConstraints(
- Selector selector, Object initialConstraint);
+ Selector selector, Object? initialConstraint);
/// Returns `true` if [member] is a potential target of [dynamicUse].
bool appliedUnnamed(DynamicUse dynamicUse, MemberEntity member, World world);
@@ -97,16 +95,16 @@
@override
StrongModeWorldConstraints createSelectorConstraints(
- Selector selector, Object initialConstraint) {
+ Selector selector, Object? initialConstraint) {
return StrongModeWorldConstraints()
- ..addReceiverConstraint(initialConstraint);
+ ..addReceiverConstraint(initialConstraint as StrongModeConstraint?);
}
@override
bool appliedUnnamed(DynamicUse dynamicUse, MemberEntity member,
covariant ResolutionWorldBuilder world) {
Selector selector = dynamicUse.selector;
- StrongModeConstraint constraint = dynamicUse.receiverConstraint;
+ final constraint = dynamicUse.receiverConstraint as StrongModeConstraint?;
return selector.appliesUnnamed(member) &&
(constraint == null ||
constraint.canHit(member, selector.memberName, world));
@@ -115,55 +113,41 @@
class StrongModeWorldConstraints extends UniverseSelectorConstraints {
bool isAll = false;
- Set<StrongModeConstraint> _constraints;
+ late Set<StrongModeConstraint> _constraints = {};
@override
bool canHit(MemberEntity element, Name name, World world) {
if (isAll) return true;
- if (_constraints == null) return false;
- for (StrongModeConstraint constraint in _constraints) {
- if (constraint.canHit(element, name, world)) {
- return true;
- }
- }
- return false;
+ return _constraints.any((constraint) =>
+ constraint.canHit(element, name, world as ResolutionWorldBuilder));
}
@override
bool needsNoSuchMethodHandling(Selector selector, World world) {
- if (isAll) {
- return true;
- }
- if (_constraints != null) {
- for (StrongModeConstraint constraint in _constraints) {
- if (constraint.needsNoSuchMethodHandling(selector, world)) {
- return true;
- }
- }
- }
- return false;
+ if (isAll) return true;
+ return _constraints.any(
+ (constraint) => constraint.needsNoSuchMethodHandling(selector, world));
}
@override
- bool addReceiverConstraint(StrongModeConstraint constraint) {
+ bool addReceiverConstraint(StrongModeConstraint? constraint) {
if (isAll) return false;
if (constraint?.cls == null) {
isAll = true;
- _constraints = null;
+ _constraints = const {};
return true;
}
- _constraints ??= {};
- return _constraints.add(constraint);
+ return _constraints.add(constraint!);
}
@override
String toString() {
if (isAll) {
return '<all>';
- } else if (_constraints != null) {
- return '<${_constraints.map((c) => c.cls).join(',')}>';
- } else {
+ } else if (_constraints.isEmpty) {
return '<none>';
+ } else {
+ return '<${_constraints.map((c) => c.cls).join(',')}>';
}
}
}
@@ -238,11 +222,9 @@
}
void registerStaticInvocation(StaticUse staticUse) {
- if (staticUse.typeArguments == null || staticUse.typeArguments.isEmpty) {
- return;
- }
- _registerStaticTypeArgumentDependency(
- staticUse.element, staticUse.typeArguments);
+ final typeArguments = staticUse.typeArguments;
+ if (typeArguments == null || typeArguments.isEmpty) return;
+ _registerStaticTypeArgumentDependency(staticUse.element, typeArguments);
}
void registerDynamicInvocation(
diff --git a/pkg/compiler/lib/src/world.dart b/pkg/compiler/lib/src/world.dart
index 3f9581a..9c400e0 100644
--- a/pkg/compiler/lib/src/world.dart
+++ b/pkg/compiler/lib/src/world.dart
@@ -48,6 +48,7 @@
InterceptorData get interceptorData;
+ @override
JElementEnvironment get elementEnvironment;
@override
@@ -105,6 +106,7 @@
Iterable<ClassEntity> mixinUsesOf(ClassEntity cls);
/// Returns `true` if [cls] is mixed into a live class.
+ @override
bool isUsedAsMixin(ClassEntity cls);
/// Returns `true` if any live class that mixes in [cls] implements [type].
diff --git a/pkg/compiler/lib/src/world_interfaces.dart b/pkg/compiler/lib/src/world_interfaces.dart
index 6009784..fadcbce 100644
--- a/pkg/compiler/lib/src/world_interfaces.dart
+++ b/pkg/compiler/lib/src/world_interfaces.dart
@@ -23,10 +23,14 @@
DartTypes get dartTypes;
+ ElementEnvironment get elementEnvironment;
+
NativeData get nativeData;
AnnotationsData get annotationsData;
+ bool isUsedAsMixin(ClassEntity cls);
+
bool includesClosureCall(Selector selector, AbstractValue? receiver);
Iterable<MemberEntity> locateMembers(
diff --git a/pkg/dart2wasm/lib/closures.dart b/pkg/dart2wasm/lib/closures.dart
index 221113c..6eb4bdf 100644
--- a/pkg/dart2wasm/lib/closures.dart
+++ b/pkg/dart2wasm/lib/closures.dart
@@ -233,6 +233,18 @@
}
@override
+ void visitSuperPropertyGet(SuperPropertyGet node) {
+ _visitThis();
+ super.visitSuperPropertyGet(node);
+ }
+
+ @override
+ void visitSuperPropertySet(SuperPropertySet node) {
+ _visitThis();
+ super.visitSuperPropertySet(node);
+ }
+
+ @override
void visitTypeParameterType(TypeParameterType node) {
if (node.parameter.parent == member.enclosingClass) {
_visitThis();
diff --git a/pkg/dart2wasm/lib/code_generator.dart b/pkg/dart2wasm/lib/code_generator.dart
index fb2ac5f..d59ad92 100644
--- a/pkg/dart2wasm/lib/code_generator.dart
+++ b/pkg/dart2wasm/lib/code_generator.dart
@@ -492,7 +492,8 @@
types.makeType(
this, TypeParameterType(typeParam, Nullability.nonNullable));
}
- _visitArguments(node.arguments, node.targetReference, 1);
+ _visitArguments(
+ node.arguments, node.targetReference, 1 + cls.typeParameters.length);
call(node.targetReference);
}
diff --git a/pkg/dart2wasm/lib/translator.dart b/pkg/dart2wasm/lib/translator.dart
index c130f70..8e6c7d9 100644
--- a/pkg/dart2wasm/lib/translator.dart
+++ b/pkg/dart2wasm/lib/translator.dart
@@ -298,6 +298,28 @@
};
}
+ // Finds the `main` method for a given library which is assumed to contain
+ // `main`, either directly or indirectly.
+ Procedure _findMainMethod(Library entryLibrary) {
+ // First check to see if the library itself contains main.
+ for (final procedure in entryLibrary.procedures) {
+ if (procedure.name.text == 'main') {
+ return procedure;
+ }
+ }
+
+ // In some cases, a main method is defined in another file, and then
+ // exported. In these cases, we search for the main method in
+ // [additionalExports].
+ for (final export in entryLibrary.additionalExports) {
+ if (export.node is Procedure && export.asProcedure.name.text == 'main') {
+ return export.asProcedure;
+ }
+ }
+ throw ArgumentError(
+ 'Entry uri ${entryLibrary.fileUri} has no main method.');
+ }
+
Uint8List translate() {
m = w.Module(watchPoints: options.watchPoints);
voidMarker = w.RefType.def(w.StructType("void"), nullable: true);
@@ -305,8 +327,7 @@
classInfoCollector.collect();
functions.collectImportsAndExports();
- mainFunction =
- libraries.first.procedures.firstWhere((p) => p.name.text == "main");
+ mainFunction = _findMainMethod(libraries.first);
functions.addExport(mainFunction.reference, "main");
initFunction = m.addFunction(functionType(const [], const []), "#init");
diff --git a/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/operations.dart b/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/operations.dart
index 6a2f7b6..a976f9e4 100644
--- a/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/operations.dart
+++ b/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/operations.dart
@@ -260,81 +260,99 @@
///
/// NOTE: The contents of [args] may be modified before calling [f]. If it
/// originated outside of the SDK it must be copied first.
-_checkAndCall(f, ftype, obj, typeArgs, args, named, displayName) =>
- JS('', '''(() => {
- $trackCall($obj);
+_checkAndCall(f, ftype, obj, typeArgs, args, named, displayName) {
+ trackCall(obj);
+ var originalTarget = JS<bool>('!', '# === void 0', obj) ? f : obj;
- let originalTarget = obj === void 0 ? f : obj;
-
- function callNSM(errorMessage) {
- return $noSuchMethod(originalTarget, new $InvocationImpl.new(
- $displayName, $args, {
- namedArguments: $named,
- // Repeated the default value here to avoid passing null from JS to a
- // non-nullable argument.
- typeArguments: $typeArgs || [],
- isMethod: true,
- failureMessage: errorMessage
- }));
+ callNSM(@notNull String errorMessage) {
+ return noSuchMethod(
+ originalTarget,
+ InvocationImpl(displayName, JS<List<Object?>>('!', '#', args),
+ namedArguments: named,
+ // Repeated the default value here in JS to preserve the historic
+ // behavior.
+ typeArguments: JS('!', '# || []', typeArgs),
+ isMethod: true,
+ failureMessage: errorMessage));
}
- if ($f == null) return callNSM('Dynamic call of null.');
- if (!($f instanceof Function)) {
+
+ if (f == null) return callNSM('Dynamic call of null.');
+ if (!JS<bool>('!', '# instanceof Function', f)) {
// We're not a function (and hence not a method either)
// Grab the `call` method if it's not a function.
- if ($f != null) {
+ if (f != null) {
// Getting the member succeeded, so update the originalTarget.
// (we're now trying `call()` on `f`, so we want to call its nSM rather
// than the original target's nSM).
originalTarget = f;
- $f = ${bindCall(f, _canonicalMember(f, 'call'))};
- $ftype = null;
- $displayName = "call";
+ f = bindCall(f, _canonicalMember(f, 'call'));
+ ftype = null;
+ displayName = 'call';
}
- if ($f == null) return callNSM(
- "Dynamic call of object has no instance method 'call'.");
+ if (f == null) {
+ return callNSM("Dynamic call of object has no instance method 'call'.");
+ }
}
// If f is a function, but not a method (no method type)
// then it should have been a function valued field, so
// get the type from the function.
- if ($ftype == null) $ftype = $f[$_runtimeType];
+ if (ftype == null) ftype = JS('', '#[#]', f, _runtimeType);
- if ($ftype == null) {
+ if (ftype == null) {
// TODO(leafp): Allow JS objects to go through?
- if ($typeArgs != null) {
+ if (typeArgs != null) {
// TODO(jmesserly): is there a sensible way to handle these?
- $throwTypeError('call to JS object `' + $obj +
- '` with type arguments <' + $typeArgs + '> is not supported.');
+ throwTypeError('call to JS object `' +
+ // Not a String but historically relying on the default JavaScript
+ // behavior.
+ JS<String>('!', '#', obj) +
+ '` with type arguments <' +
+ // Not a String but historically relying on the default JavaScript
+ // behavior.
+ JS<String>('!', '#', typeArgs) +
+ '> is not supported.');
}
- if ($named != null) $args.push($named);
- return $f.apply($obj, $args);
+ if (named != null) JS('', '#.push(#)', args, named);
+ return JS('', '#.apply(#, #)', f, obj, args);
}
// Apply type arguments
- if (${_jsInstanceOf(ftype, GenericFunctionType)}) {
- let formalCount = $ftype.formalCount;
+ if (_jsInstanceOf(ftype, GenericFunctionType)) {
+ var formalCount = JS<int>('!', '#.formalCount', ftype);
- if ($typeArgs == null) {
- $typeArgs = $ftype.instantiateDefaultBounds();
- } else if ($typeArgs.length != formalCount) {
+ if (typeArgs == null) {
+ typeArgs = JS<List>('!', '#.instantiateDefaultBounds()', ftype);
+ } else if (JS<bool>('!', '#.length != #', typeArgs, formalCount)) {
return callNSM('Dynamic call with incorrect number of type arguments. ' +
- 'Expected: ' + formalCount + ' Actual: ' + $typeArgs.length);
+ 'Expected: ' +
+ // Not a String but historically relying on the default JavaScript
+ // behavior.
+ JS<String>('!', '#', formalCount) +
+ ' Actual: ' +
+ // Not a String but historically relying on the default JavaScript
+ // behavior.
+ JS<String>('!', '#.length', typeArgs));
} else {
- $ftype.checkBounds($typeArgs);
+ JS('', '#.checkBounds(#)', ftype, typeArgs);
}
- $ftype = $ftype.instantiate($typeArgs);
- } else if ($typeArgs != null) {
+ ftype = JS('', '#.instantiate(#)', ftype, typeArgs);
+ } else if (typeArgs != null) {
return callNSM('Dynamic call with unexpected type arguments. ' +
- 'Expected: 0 Actual: ' + $typeArgs.length);
+ 'Expected: 0 Actual: ' +
+ // Not a String but historically relying on the default JavaScript
+ // behavior.
+ JS<String>('!', '#.length', typeArgs));
}
- let errorMessage = $_argumentErrors($ftype, $args, $named);
+ var errorMessage = _argumentErrors(
+ JS<FunctionType>('!', '#', ftype), JS<List>('!', '#', args), named);
if (errorMessage == null) {
- if ($typeArgs != null) $args = $typeArgs.concat($args);
- if ($named != null) $args.push($named);
- return $f.apply($obj, $args);
+ if (typeArgs != null) args = JS('', '#.concat(#)', typeArgs, args);
+ if (named != null) JS('', '#.push(#)', args, named);
+ return JS('', '#.apply(#, #)', f, obj, args);
}
return callNSM(errorMessage);
-})()''');
+}
dcall(f, args, [@undefined named]) => _checkAndCall(
f, null, JS('', 'void 0'), null, args, named, JS('', 'f.name'));
diff --git a/tools/VERSION b/tools/VERSION
index 83893d8..7f5c1e2 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 2
MINOR 19
PATCH 0
-PRERELEASE 27
+PRERELEASE 28
PRERELEASE_PATCH 0
\ No newline at end of file