Skip to content

Commit c8b50bd

Browse files
committed
Version 2.15.0-268.8.beta
* Cherry-pick 243fb5c to beta * Cherry-pick 1ca06b9 to beta * Cherry-pick b8e419d to beta * Cherry-pick dc7e082 to beta * Cherry-pick 6225f46 to beta * Cherry-pick b97737c to beta * Cherry-pick 109c317 to beta
2 parents 177911f + 9465112 commit c8b50bd

File tree

16 files changed

+351
-67
lines changed

16 files changed

+351
-67
lines changed

CHANGELOG.md

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -429,9 +429,12 @@
429429

430430
#### `dart:js_util`
431431

432-
- The `js_util` methods `getProperty`, `setProperty`, `callMethod`,
433-
`callConstructor`, and `newObject` now support a generic type argument
434-
to specify the return type.
432+
- The `js_util` methods `setProperty`, `callMethod`, and `callConstructor` have
433+
been optimized to remove checks on arguments when the checks can be elided.
434+
Also, those methods, along with `getProperty` and `newObject`, now support a
435+
generic type argument to specify a return type. These two changes make simple
436+
`js_util` usage, like reading and writing primitive properties or calling
437+
methods with simple arguments, have zero overhead.
435438

436439
#### `dart:web_sql`
437440

@@ -592,6 +595,14 @@ This feature requires
592595
`dart pub get/upgrade/downgrade/add/remove` that will result in the `example/`
593596
folder dependencies to be updated after operating in the current directory.
594597

598+
### Other libraries
599+
600+
#### `package:js`
601+
602+
- Extensions on JS interop or native `dart:html` classes can now declare
603+
members as `external`. These members are equivalent to regular extension
604+
members that use `js_util` to expose the underlying JavaScript.
605+
595606
## 2.14.4 - 2021-10-14
596607

597608
This is a patch release that fixes:

DEPS

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ vars = {
107107
"dart_style_rev": "08b0294d0a500d5c02168ef57dcb8868d0c3cb48",
108108

109109
"dartdoc_rev" : "520e64977de7a87b2fd5be56e5c2e1a58d55bdad",
110-
"devtools_rev" : "8881a7caa9067471008a8e00750b161f53cdb843",
110+
"devtools_rev" : "3a2f570813200e6dee141f3e7a9edcae5f31c2e8",
111111
"jsshell_tag": "version:88.0",
112112
"ffi_rev": "4dd32429880a57b64edaf54c9d5af8a9fa9a4ffb",
113113
"fixnum_rev": "16d3890c6dc82ca629659da1934e412292508bba",
@@ -139,7 +139,7 @@ vars = {
139139
"pool_rev": "7abe634002a1ba8a0928eded086062f1307ccfae",
140140
"process_rev": "56ece43b53b64c63ae51ec184b76bd5360c28d0b",
141141
"protobuf_rev": "c1eb6cb51af39ccbaa1a8e19349546586a5c8e31",
142-
"pub_rev": "0035a40f25d027130c0314571da53ffafc6d973b",
142+
"pub_rev": "96404e0749864c9fbf8b12e1d424e8078809e00a",
143143
"pub_semver_rev": "a43ad72fb6b7869607581b5fedcb186d1e74276a",
144144
"root_certificates_rev": "692f6d6488af68e0121317a9c2c9eb393eb0ee50",
145145
"rust_revision": "b7856f695d65a8ebc846754f97d15814bcb1c244",

pkg/analyzer/lib/src/dart/constant/evaluation.dart

Lines changed: 22 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -632,39 +632,31 @@ class ConstantVisitor extends UnifyingAstVisitor<DartObjectImpl> {
632632

633633
@override
634634
DartObjectImpl? visitConstructorReference(ConstructorReference node) {
635-
var constructorTearoffResult = DartObjectImpl(
635+
var constructorFunctionType = node.typeOrThrow as FunctionType;
636+
var classType = constructorFunctionType.returnType as InterfaceType;
637+
var typeArguments = classType.typeArguments;
638+
// The result is already instantiated during resolution;
639+
// [_dartObjectComputer.typeInstantiate] is unnecessary.
640+
var typeElement =
641+
node.constructorName.type2.name.staticElement as TypeDefiningElement;
642+
643+
TypeAliasElement? viaTypeAlias;
644+
if (typeElement is TypeAliasElementImpl) {
645+
if (constructorFunctionType.typeFormals.isNotEmpty &&
646+
!typeElement.isProperRename()) {
647+
// The type alias is not a proper rename of the aliased class, so
648+
// the constructor tear-off is distinct from the associated
649+
// constructor function of the aliased class.
650+
viaTypeAlias = typeElement;
651+
}
652+
}
653+
654+
return DartObjectImpl(
636655
typeSystem,
637656
node.typeOrThrow,
638-
FunctionState(node.constructorName.staticElement),
657+
FunctionState(node.constructorName.staticElement,
658+
typeArguments: typeArguments, viaTypeAlias: viaTypeAlias),
639659
);
640-
var typeArgumentList = node.constructorName.type2.typeArguments;
641-
if (typeArgumentList == null) {
642-
return constructorTearoffResult;
643-
} else {
644-
var typeArguments = <DartType>[];
645-
for (var typeArgument in typeArgumentList.arguments) {
646-
var object = typeArgument.accept(this);
647-
if (object == null) {
648-
return null;
649-
}
650-
var typeArgumentType = object.toTypeValue();
651-
if (typeArgumentType == null) {
652-
return null;
653-
}
654-
// TODO(srawlins): Test type alias types (`typedef i = int`) used as
655-
// type arguments. Possibly change implementation based on
656-
// canonicalization rules.
657-
typeArguments.add(typeArgumentType);
658-
}
659-
// The result is already instantiated during resolution;
660-
// [_dartObjectComputer.typeInstantiate] is unnecessary.
661-
return DartObjectImpl(
662-
typeSystem,
663-
node.typeOrThrow,
664-
FunctionState(node.constructorName.staticElement,
665-
typeArguments: typeArguments),
666-
);
667-
}
668660
}
669661

670662
@override

pkg/analyzer/lib/src/dart/constant/value.dart

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -920,11 +920,14 @@ class DartObjectImpl implements DartObject {
920920
List<DartType> typeArguments,
921921
) {
922922
var functionState = _state as FunctionState;
923-
var element = functionState._element;
924923
return DartObjectImpl(
925924
typeSystem,
926925
type,
927-
FunctionState(element, typeArguments: typeArguments),
926+
FunctionState(
927+
functionState._element,
928+
typeArguments: typeArguments,
929+
viaTypeAlias: functionState._viaTypeAlias,
930+
),
928931
);
929932
}
930933

@@ -1245,10 +1248,22 @@ class FunctionState extends InstanceState {
12451248

12461249
final List<DartType>? _typeArguments;
12471250

1251+
/// The type alias which was referenced when tearing off a constructor,
1252+
/// if this function is a constructor tear-off, referenced via a type alias,
1253+
/// and the type alias is not a proper rename for the class, and the
1254+
/// constructor tear-off is generic, so the tear-off cannot be considered
1255+
/// equivalent to tearing off the associated constructor function of the
1256+
/// aliased class.
1257+
///
1258+
/// Otherwise null.
1259+
final TypeDefiningElement? _viaTypeAlias;
1260+
12481261
/// Initialize a newly created state to represent the function with the given
12491262
/// [element].
1250-
FunctionState(this._element, {List<DartType>? typeArguments})
1251-
: _typeArguments = typeArguments;
1263+
FunctionState(this._element,
1264+
{List<DartType>? typeArguments, TypeDefiningElement? viaTypeAlias})
1265+
: _typeArguments = typeArguments,
1266+
_viaTypeAlias = viaTypeAlias;
12521267

12531268
@override
12541269
int get hashCode => _element == null ? 0 : _element.hashCode;
@@ -1272,6 +1287,9 @@ class FunctionState extends InstanceState {
12721287
if (typeArguments.length != otherTypeArguments.length) {
12731288
return false;
12741289
}
1290+
if (_viaTypeAlias != object._viaTypeAlias) {
1291+
return false;
1292+
}
12751293
for (var i = 0; i < typeArguments.length; i++) {
12761294
if (typeArguments[i] != otherTypeArguments[i]) {
12771295
return false;
@@ -1309,6 +1327,9 @@ class FunctionState extends InstanceState {
13091327
if (element?.declaration != otherElement?.declaration) {
13101328
return BoolState.FALSE_STATE;
13111329
}
1330+
if (_viaTypeAlias != rightOperand._viaTypeAlias) {
1331+
return BoolState.FALSE_STATE;
1332+
}
13121333
var typeArguments = _typeArguments;
13131334
var otherTypeArguments = rightOperand._typeArguments;
13141335
if (typeArguments == null || otherTypeArguments == null) {

pkg/analyzer/lib/src/dart/element/element.dart

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5582,6 +5582,37 @@ class TypeAliasElementImpl extends _ExistingElementImpl
55825582
}
55835583
}
55845584

5585+
/// Returns whether this alias is a "proper rename" of [aliasedClass], as
5586+
/// defined in the constructor-tearoffs specification.
5587+
bool isProperRename() {
5588+
var aliasedType_ = aliasedType;
5589+
if (aliasedType_ is! InterfaceType) {
5590+
return false;
5591+
}
5592+
var aliasedClass = aliasedType_.element;
5593+
var typeArguments = aliasedType_.typeArguments;
5594+
var typeParameterCount = typeParameters.length;
5595+
if (typeParameterCount != aliasedClass.typeParameters.length) {
5596+
return false;
5597+
}
5598+
if (typeParameterCount != typeArguments.length) {
5599+
return false;
5600+
}
5601+
for (var i = 0; i < typeParameterCount; i++) {
5602+
var bound = typeParameters[i].bound ?? library.typeProvider.dynamicType;
5603+
var aliasedBound = aliasedClass.typeParameters[i].bound ??
5604+
library.typeProvider.dynamicType;
5605+
if (!library.typeSystem.isSubtypeOf(bound, aliasedBound) ||
5606+
!library.typeSystem.isSubtypeOf(aliasedBound, bound)) {
5607+
return false;
5608+
}
5609+
if (typeParameters[i] != typeArguments[i].element) {
5610+
return false;
5611+
}
5612+
}
5613+
return true;
5614+
}
5615+
55855616
void setLinkedData(Reference reference, ElementLinkedData linkedData) {
55865617
this.reference = reference;
55875618
reference.element = this;

pkg/analyzer/lib/src/dart/resolver/constructor_reference_resolver.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ class ConstructorReferenceResolver {
123123
constructorName.staticElement = constructorElement.declaration;
124124
constructorName.name?.staticElement = constructorElement.declaration;
125125
node.staticType = inferred;
126+
// The NamedType child of `constructorName` doesn't have a static type.
126127
constructorName.type2.type = null;
127128
}
128129
} else {
@@ -132,6 +133,7 @@ class ConstructorReferenceResolver {
132133
} else {
133134
node.staticType = constructorElement.type;
134135
}
136+
// The NamedType child of `constructorName` doesn't have a static type.
135137
constructorName.type2.type = null;
136138
}
137139
}

pkg/analyzer/test/src/dart/constant/evaluation_test.dart

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,126 @@ main() {
2828
@reflectiveTest
2929
class ConstantVisitorTest extends ConstantVisitorTestSupport
3030
with ConstantVisitorTestCases {
31+
test_identical_constructorReference_aliasIsNotGeneric() async {
32+
await resolveTestCode('''
33+
class C<T> {}
34+
typedef MyC = C<int>;
35+
const a = identical(MyC.new, C<int>.new);
36+
''');
37+
expect(
38+
_evaluateConstant('a'),
39+
_boolValue(true),
40+
);
41+
}
42+
43+
test_identical_constructorReference_aliasIsNotProperRename_differentBound() async {
44+
await resolveTestCode('''
45+
class C<T> {}
46+
typedef MyC<T extends num> = C<T>;
47+
const a = identical(MyC.new, C.new);
48+
''');
49+
expect(
50+
_evaluateConstant('a'),
51+
_boolValue(false),
52+
);
53+
}
54+
55+
test_identical_constructorReference_aliasIsNotProperRename_differentCount() async {
56+
await resolveTestCode('''
57+
class C<T, U> {}
58+
typedef MyC<T> = C<T, int>;
59+
const a = identical(MyC.new, C.new);
60+
''');
61+
expect(
62+
_evaluateConstant('a'),
63+
_boolValue(false),
64+
);
65+
}
66+
67+
test_identical_constructorReference_aliasIsNotProperRename_differentOrder() async {
68+
await resolveTestCode('''
69+
class C<T, U> {}
70+
typedef MyC<T, U> = C<U, T>;
71+
const a = identical(MyC.new, C.new);
72+
''');
73+
expect(
74+
_evaluateConstant('a'),
75+
_boolValue(false),
76+
);
77+
}
78+
79+
test_identical_constructorReference_aliasIsNotProperRename_instantiated() async {
80+
await resolveTestCode('''
81+
class C<T> {}
82+
typedef MyC<T extends num> = C<T>;
83+
const a = identical(MyC<int>.new, C<int>.new);
84+
''');
85+
expect(
86+
_evaluateConstant('a'),
87+
_boolValue(true),
88+
);
89+
}
90+
91+
test_identical_constructorReference_aliasIsNotProperRename_mixedInstantiations() async {
92+
await resolveTestCode('''
93+
class C<T> {}
94+
typedef MyC<T extends num> = C<T>;
95+
const a = identical(MyC<int>.new, (MyC.new)<int>);
96+
''');
97+
expect(
98+
_evaluateConstant('a'),
99+
_boolValue(false),
100+
);
101+
}
102+
103+
test_identical_constructorReference_aliasIsProperRename_instantiated() async {
104+
await resolveTestCode('''
105+
class C<T> {}
106+
typedef MyC<T> = C<T>;
107+
const a = identical(MyC<int>.new, MyC<int>.new);
108+
''');
109+
expect(
110+
_evaluateConstant('a'),
111+
_boolValue(true),
112+
);
113+
}
114+
115+
test_identical_constructorReference_aliasIsProperRename_mixedInstantiations() async {
116+
await resolveTestCode('''
117+
class C<T> {}
118+
typedef MyC<T> = C<T>;
119+
const a = identical(MyC<int>.new, (MyC.new)<int>);
120+
''');
121+
expect(
122+
_evaluateConstant('a'),
123+
_boolValue(true),
124+
);
125+
}
126+
127+
test_identical_constructorReference_aliasIsProperRename_mutualSubtypes() async {
128+
await resolveTestCode('''
129+
class C<T> {}
130+
typedef MyC<T extends Object?> = C<T>;
131+
const a = identical(MyC<int>.new, MyC<int>.new);
132+
''');
133+
expect(
134+
_evaluateConstant('a'),
135+
_boolValue(true),
136+
);
137+
}
138+
139+
test_identical_constructorReference_aliasIsProperRename_uninstantiated() async {
140+
await resolveTestCode('''
141+
class C<T> {}
142+
typedef MyC<T> = C<T>;
143+
const a = identical(MyC.new, MyC.new);
144+
''');
145+
expect(
146+
_evaluateConstant('a'),
147+
_boolValue(true),
148+
);
149+
}
150+
31151
test_identical_constructorReference_explicitTypeArgs_differentClasses() async {
32152
await resolveTestCode('''
33153
class C<T> {}
@@ -76,6 +196,19 @@ const a = identical(C<int>.new, C<int>.new);
76196
);
77197
}
78198

199+
test_identical_constructorReference_inferredTypeArgs_sameElement() async {
200+
await resolveTestCode('''
201+
class C<T> {}
202+
const C<int> Function() c1 = C.new;
203+
const c2 = C<int>.new;
204+
const a = identical(c1, c2);
205+
''');
206+
expect(
207+
_evaluateConstant('a'),
208+
_boolValue(true),
209+
);
210+
}
211+
79212
test_identical_constructorReference_notInstantiated_differentClasses() async {
80213
await resolveTestCode('''
81214
class C<T> {}

0 commit comments

Comments
 (0)