@@ -172,6 +172,11 @@ class ProgramCompiler extends ComputeOnceConstantVisitor<js_ast.Expression>
172
172
/// Table of named and possibly hoisted types.
173
173
late TypeTable _typeTable;
174
174
175
+ /// Table of instantiated generic class references.
176
+ ///
177
+ /// Provides a cache for the instantiated generic types local to a module.
178
+ late TypeTable _genericClassTable;
179
+
175
180
/// The global extension type table.
176
181
// TODO(jmesserly): rename to `_nativeTypes`
177
182
final NativeTypeSet _extensionTypes;
@@ -367,6 +372,7 @@ class ProgramCompiler extends ComputeOnceConstantVisitor<js_ast.Expression>
367
372
_assertInteropMethod = sdk.getTopLevelMember (
368
373
'dart:_runtime' , 'assertInterop' ) as Procedure ,
369
374
_futureOrNormalizer = FutureOrNormalizer (_coreTypes),
375
+ _extensionTypeEraser = ExtensionTypeEraser (),
370
376
_typeRecipeGenerator = TypeRecipeGenerator (_coreTypes, _hierarchy),
371
377
_extensionIndex =
372
378
ExtensionIndex (_coreTypes, _staticTypeContext.typeEnvironment);
@@ -390,6 +396,8 @@ class ProgramCompiler extends ComputeOnceConstantVisitor<js_ast.Expression>
390
396
391
397
final FutureOrNormalizer _futureOrNormalizer;
392
398
399
+ final ExtensionTypeEraser _extensionTypeEraser;
400
+
393
401
/// Module can be emitted only once, and the compiler can be reused after
394
402
/// only in incremental mode, for expression compilation only.
395
403
js_ast.Program emitModule (Component component) {
@@ -451,7 +459,8 @@ class ProgramCompiler extends ComputeOnceConstantVisitor<js_ast.Expression>
451
459
}
452
460
453
461
_nullableInference.allowNotNullDeclarations = isBuildingSdk;
454
- _typeTable = TypeTable (runtimeCall);
462
+ _typeTable = TypeTable ('T' , runtimeCall);
463
+ _genericClassTable = TypeTable ('G' , runtimeCall);
455
464
456
465
// Collect all class/type Element -> Node mappings
457
466
// in case we need to forward declare any classes.
@@ -616,6 +625,10 @@ class ProgramCompiler extends ComputeOnceConstantVisitor<js_ast.Expression>
616
625
items.addAll (_typeTable.dischargeBoundTypes ());
617
626
_ticker? .logMs ('Emitted type table' );
618
627
628
+ // Emit the hoisted instantiated generic class table cache variables
629
+ items.addAll (_genericClassTable.dischargeBoundTypes ());
630
+ _ticker? .logMs ('Emitted instantiated generic class table' );
631
+
619
632
var module = finishModule (items, _options.moduleName,
620
633
header: generateCompilationHeader ());
621
634
_ticker? .logMs ('Finished emitting module' );
@@ -1057,8 +1070,13 @@ class ProgramCompiler extends ComputeOnceConstantVisitor<js_ast.Expression>
1057
1070
body = js_ast.Statement .from ([body, varianceStatement]);
1058
1071
}
1059
1072
1060
- var typeConstructor = js.call ('(#) => { #; #; return #; }' ,
1061
- [jsFormals, _typeTable.dischargeFreeTypes (formals), body, className]);
1073
+ var typeConstructor = js.call ('(#) => { #; #; #; return #; }' , [
1074
+ jsFormals,
1075
+ _typeTable.dischargeFreeTypes (formals),
1076
+ _genericClassTable.dischargeFreeTypes (formals),
1077
+ body,
1078
+ className
1079
+ ]);
1062
1080
1063
1081
var genericArgs = [
1064
1082
typeConstructor,
@@ -1268,6 +1286,7 @@ class ProgramCompiler extends ComputeOnceConstantVisitor<js_ast.Expression>
1268
1286
if (t is RecordType ) {
1269
1287
return t.positional.any (defer) || t.named.any ((n) => defer (n.type));
1270
1288
}
1289
+ if (t is ExtensionType ) return defer (t.typeErasure);
1271
1290
return false ;
1272
1291
}
1273
1292
@@ -1631,7 +1650,10 @@ class ProgramCompiler extends ComputeOnceConstantVisitor<js_ast.Expression>
1631
1650
_classEmittingSignatures = c;
1632
1651
1633
1652
var interfaces = c.implementedTypes.toList ()..addAll (c.onClause);
1634
- if (interfaces.isNotEmpty) {
1653
+ if (interfaces.isNotEmpty &&
1654
+ // New runtime types don't use this data structure to lookup interfaces
1655
+ // a class implements.
1656
+ ! _options.newRuntimeTypes) {
1635
1657
body.add (js.statement ('#[#] = () => [#];' , [
1636
1658
className,
1637
1659
runtimeCall ('implements' ),
@@ -3260,6 +3282,7 @@ class ProgramCompiler extends ComputeOnceConstantVisitor<js_ast.Expression>
3260
3282
if (type is TypedefType ) {
3261
3283
return type.typeArguments.every (_canEmitTypeAtTopLevel);
3262
3284
}
3285
+ if (type is ExtensionType ) return _canEmitTypeAtTopLevel (type.typeErasure);
3263
3286
return true ;
3264
3287
}
3265
3288
@@ -3304,6 +3327,8 @@ class ProgramCompiler extends ComputeOnceConstantVisitor<js_ast.Expression>
3304
3327
// An environment with a single type parameter can be simplified to
3305
3328
// just that parameter.
3306
3329
env = _emitTypeParameter (environment.parameters.single);
3330
+ // Skip a no-op evaluation and just return the parameter.
3331
+ if (recipe == '0' ) return env;
3307
3332
} else {
3308
3333
var environmentTypes = environment.parameters;
3309
3334
// Create a dummy interface type to "hold" type arguments.
@@ -3334,16 +3359,15 @@ class ProgramCompiler extends ComputeOnceConstantVisitor<js_ast.Expression>
3334
3359
}
3335
3360
}
3336
3361
3337
- // TODO(nshahan) Avoid calling _emitType when we actually want a
3338
- // reference to an rti that already exists in scope.
3339
- if (type is TypeParameterType && type.isPotentiallyNonNullable) {
3340
- return _emitTypeParameterType (type, emitNullability: false );
3341
- }
3342
- var normalizedType = _futureOrNormalizer.normalize (type);
3362
+ var normalizedType =
3363
+ _futureOrNormalizer.normalize (_extensionTypeEraser.erase (type));
3343
3364
try {
3344
3365
var result = _typeRecipeGenerator.recipeInEnvironment (
3345
3366
normalizedType, _currentTypeEnvironment);
3346
- return evalInEnvironment (result.requiredEnvironment, result.recipe);
3367
+ var typeRep =
3368
+ evalInEnvironment (result.requiredEnvironment, result.recipe);
3369
+ if (_cacheTypes) typeRep = _typeTable.nameType (normalizedType, typeRep);
3370
+ return typeRep;
3347
3371
} on UnsupportedError catch (e) {
3348
3372
_typeCompilationError (normalizedType, e.message ?? 'Unknown Error' );
3349
3373
}
@@ -3496,7 +3520,10 @@ class ProgramCompiler extends ComputeOnceConstantVisitor<js_ast.Expression>
3496
3520
if (args.any ((a) => a != const DynamicType ())) {
3497
3521
jsArgs = args.map (_emitType);
3498
3522
}
3499
- if (jsArgs != null ) return _emitGenericClassType (type, jsArgs);
3523
+ if (jsArgs != null ) {
3524
+ return _genericClassTable.nameType (
3525
+ type, _emitGenericClassType (type, jsArgs));
3526
+ }
3500
3527
return _emitTopLevelNameNoExternalInterop (type.classNode);
3501
3528
}
3502
3529
@@ -3567,11 +3594,12 @@ class ProgramCompiler extends ComputeOnceConstantVisitor<js_ast.Expression>
3567
3594
bool get _emittingClassExtends =>
3568
3595
_currentClass != null && identical (_currentClass, _classEmittingExtends);
3569
3596
3570
- bool get _cacheTypes =>
3571
- ! _emittingDeferredType &&
3572
- ! _emittingClassExtends &&
3573
- ! _emittingClassSignatures ||
3574
- _currentFunction != null ;
3597
+ bool get _cacheTypes => _options.newRuntimeTypes
3598
+ ? ! _emittingDeferredType && ! _emittingClassExtends
3599
+ : ! _emittingDeferredType &&
3600
+ ! _emittingClassExtends &&
3601
+ ! _emittingClassSignatures ||
3602
+ _currentFunction != null ;
3575
3603
3576
3604
js_ast.Expression _emitGenericClassType (
3577
3605
InterfaceType t, Iterable <js_ast.Expression > typeArgs) {
@@ -3853,6 +3881,7 @@ class ProgramCompiler extends ComputeOnceConstantVisitor<js_ast.Expression>
3853
3881
var body = js_ast.Block ([
3854
3882
...extensionSymbols,
3855
3883
..._typeTable.dischargeBoundTypes (),
3884
+ ..._genericClassTable.dischargeBoundTypes (),
3856
3885
...symbolContainer.emit (),
3857
3886
..._emitConstTable (),
3858
3887
..._uriContainer.emit (),
@@ -6851,23 +6880,21 @@ class ProgramCompiler extends ComputeOnceConstantVisitor<js_ast.Expression>
6851
6880
js_ast.Expression _emitMapImplType (InterfaceType type, {bool ? identity}) {
6852
6881
var typeArgs = type.typeArguments;
6853
6882
if (typeArgs.isEmpty) {
6854
- return _emitInterfaceType (type, emitNullability : false );
6883
+ return _emitClassRef (type);
6855
6884
}
6856
6885
identity ?? = _typeRep.isPrimitive (typeArgs[0 ]);
6857
6886
var c = identity ? _identityHashMapImplClass : _linkedHashMapImplClass;
6858
- return _emitInterfaceType (InterfaceType (c, Nullability .legacy, typeArgs),
6859
- emitNullability: false );
6887
+ return _emitClassRef (InterfaceType (c, Nullability .legacy, typeArgs));
6860
6888
}
6861
6889
6862
6890
js_ast.Expression _emitSetImplType (InterfaceType type, {bool ? identity}) {
6863
6891
var typeArgs = type.typeArguments;
6864
6892
if (typeArgs.isEmpty) {
6865
- return _emitInterfaceType (type, emitNullability : false );
6893
+ return _emitClassRef (type);
6866
6894
}
6867
6895
identity ?? = _typeRep.isPrimitive (typeArgs[0 ]);
6868
6896
var c = identity ? _identityHashSetImplClass : _linkedHashSetImplClass;
6869
- return _emitInterfaceType (InterfaceType (c, Nullability .legacy, typeArgs),
6870
- emitNullability: false );
6897
+ return _emitClassRef (InterfaceType (c, Nullability .legacy, typeArgs));
6871
6898
}
6872
6899
6873
6900
js_ast.Expression _emitObjectLiteral (Arguments node, Member ctor) {
@@ -7199,9 +7226,8 @@ class ProgramCompiler extends ComputeOnceConstantVisitor<js_ast.Expression>
7199
7226
if (itemType == const DynamicType ()) return list;
7200
7227
7201
7228
// Call `new JSArray<E>.of(list)`
7202
- var arrayType = _emitInterfaceType (
7203
- InterfaceType (_jsArrayClass, Nullability .legacy, [itemType]),
7204
- emitNullability: false );
7229
+ var arrayType = _emitClassRef (
7230
+ InterfaceType (_jsArrayClass, Nullability .nonNullable, [itemType]));
7205
7231
return js.call ('#.of(#)' , [arrayType, list]);
7206
7232
}
7207
7233
@@ -7217,10 +7243,8 @@ class ProgramCompiler extends ComputeOnceConstantVisitor<js_ast.Expression>
7217
7243
js_ast.Expression visitSetLiteral (SetLiteral node) {
7218
7244
// TODO(markzipan): remove const check when we use front-end const eval
7219
7245
if (! node.isConst) {
7220
- var setType = _emitInterfaceType (
7221
- InterfaceType (
7222
- _linkedHashSetClass, Nullability .legacy, [node.typeArgument]),
7223
- emitNullability: false );
7246
+ var setType = _emitClassRef (InterfaceType (
7247
+ _linkedHashSetClass, Nullability .legacy, [node.typeArgument]));
7224
7248
if (node.expressions.isEmpty) {
7225
7249
return js.call ('#.new()' , [setType]);
7226
7250
}
@@ -7674,8 +7698,7 @@ class ProgramCompiler extends ComputeOnceConstantVisitor<js_ast.Expression>
7674
7698
var type = node
7675
7699
.getType (_staticTypeContext)
7676
7700
.withDeclaredNullability (Nullability .nonNullable);
7677
- var classRef =
7678
- _emitInterfaceType (type as InterfaceType , emitNullability: false );
7701
+ var classRef = _emitClassRef (type as InterfaceType );
7679
7702
var prototype = js.call ('#.prototype' , [classRef]);
7680
7703
var properties = [
7681
7704
if (_options.newRuntimeTypes && type.typeArguments.isNotEmpty)
0 commit comments