@@ -1236,12 +1236,32 @@ class LibraryCompiler extends ComputeOnceConstantVisitor<js_ast.Expression>
12361236
12371237 var jsCtors = _defineConstructors (c, className);
12381238 var jsProperties = _emitClassProperties (c);
1239+ var jsStaticMethodTypeTags = < js_ast.Statement > [];
1240+ for (var member in c.procedures) {
1241+ // TODO(#57049): We tag all static members because we don't know if
1242+ // they've been changed after a hot reload. This won't be necessary if we
1243+ // can tag them during the delta diff phase.
1244+ if (member.isStatic && _reifyTearoff (member) && ! member.isExternal) {
1245+ var propertyAccessor = _emitStaticTarget (member);
1246+ var result = js.call (
1247+ '#.#' , [propertyAccessor.receiver, propertyAccessor.selector]);
1248+ // We only need to tag static functions that are torn off at
1249+ // compile-time. We attach these at late so tearoffs have access to
1250+ // their types.
1251+ var reifiedType = member.function
1252+ .computeThisFunctionType (member.enclosingLibrary.nonNullable);
1253+ jsStaticMethodTypeTags.add (
1254+ _emitFunctionTagged (result, reifiedType, asLazy: true )
1255+ .toStatement ());
1256+ }
1257+ }
12391258
12401259 _emitSuperHelperSymbols (body);
12411260
12421261 // Emit the class, e.g. `core.Object = class Object { ... }`
12431262 _defineClass (c, className, jsProperties, body);
12441263 body.addAll (jsCtors);
1264+ body.addAll (jsStaticMethodTypeTags);
12451265
12461266 // Emit things that come after the ES6 `class ... { ... }`.
12471267
@@ -2473,7 +2493,6 @@ class LibraryCompiler extends ComputeOnceConstantVisitor<js_ast.Expression>
24732493 } else {
24742494 method.sourceInformation = _nodeEnd (member.fileEndOffset);
24752495 }
2476-
24772496 return method;
24782497 }
24792498
@@ -3454,10 +3473,23 @@ class LibraryCompiler extends ComputeOnceConstantVisitor<js_ast.Expression>
34543473 .where ((p) =>
34553474 ! p.isExternal && ! p.isAbstract && ! _isStaticInteropTearOff (p))
34563475 .toList ();
3457- _moduleItems.addAll (procedures
3458- .where ((p) => ! p.isAccessor)
3459- .map (_emitLibraryFunction)
3460- .toList ());
3476+ for (var p in procedures) {
3477+ if (! p.isAccessor) {
3478+ _moduleItems.add (_emitLibraryFunction (p));
3479+ }
3480+ // TODO(#57049): We tag all static members because we don't know if
3481+ // they've been changed after a hot reload. This won't be necessary if we
3482+ // can tag them during the delta diff phase.
3483+ if (p.isStatic && _reifyTearoff (p) && ! p.isExternal) {
3484+ var nameExpr = _emitTopLevelName (p);
3485+ _moduleItems.add (_emitFunctionTagged (
3486+ nameExpr,
3487+ p.function
3488+ .computeThisFunctionType (p.enclosingLibrary.nonNullable),
3489+ asLazy: true )
3490+ .toStatement ());
3491+ }
3492+ }
34613493 var accessors =
34623494 procedures.where ((p) => p.isAccessor).map (_emitLibraryAccessor);
34633495 libraryProperties.addAll (accessors);
@@ -3638,22 +3670,27 @@ class LibraryCompiler extends ComputeOnceConstantVisitor<js_ast.Expression>
36383670 return candidateName;
36393671 }
36403672
3641- js_ast.Expression _emitFunctionTagged (
3642- js_ast. Expression fn, FunctionType type ) {
3673+ js_ast.Expression _emitFunctionTagged (js_ast. Expression fn, FunctionType type,
3674+ { bool asLazy = false } ) {
36433675 var typeRep = _emitType (
36443676 // Avoid tagging a closure as Function? or Function*
36453677 type.withDeclaredNullability (Nullability .nonNullable));
36463678 if (type.typeParameters.isEmpty) {
3647- return _runtimeCall ('fn(#, #)' , [fn, typeRep]);
3679+ return asLazy
3680+ ? _runtimeCall ('lazyFn(#, () => #)' , [fn, typeRep])
3681+ : _runtimeCall ('fn(#, #)' , [fn, typeRep]);
36483682 } else {
36493683 var typeParameterDefaults = [
36503684 for (var parameter in type.typeParameters)
36513685 _emitType (parameter.defaultType)
36523686 ];
36533687 var defaultInstantiatedBounds =
36543688 _emitConstList (const DynamicType (), typeParameterDefaults);
3655- return _runtimeCall (
3656- 'gFn(#, #, #)' , [fn, typeRep, defaultInstantiatedBounds]);
3689+ return asLazy
3690+ ? _runtimeCall ('lazyGFn(#, () => #, () => #)' ,
3691+ [fn, typeRep, defaultInstantiatedBounds])
3692+ : _runtimeCall (
3693+ 'gFn(#, #, #)' , [fn, typeRep, defaultInstantiatedBounds]);
36573694 }
36583695 }
36593696
@@ -5422,7 +5459,7 @@ class LibraryCompiler extends ComputeOnceConstantVisitor<js_ast.Expression>
54225459 }
54235460 var jsMemberName = _emitMemberName (memberName, member: member);
54245461 if (_reifyTearoff (member)) {
5425- return _runtimeCall ('bind (#, #)' , [jsReceiver, jsMemberName]);
5462+ return _runtimeCall ('tearoff (#, #)' , [jsReceiver, jsMemberName]);
54265463 }
54275464 var jsPropertyAccess = js_ast.PropertyAccess (jsReceiver, jsMemberName);
54285465 return isJsMember (member)
@@ -5612,15 +5649,12 @@ class LibraryCompiler extends ComputeOnceConstantVisitor<js_ast.Expression>
56125649 _emitStaticGet (node.target);
56135650
56145651 js_ast.Expression _emitStaticGet (Member target) {
5615- var result = _emitStaticTarget (target);
5652+ var propertyAccessor = _emitStaticTarget (target);
5653+ var context = propertyAccessor.receiver;
5654+ var property = propertyAccessor.selector;
5655+ var result = js.call ('#.#' , [context, property]);
56165656 if (_reifyTearoff (target)) {
5617- // TODO(jmesserly): we could tag static/top-level function types once
5618- // in the module initialization, rather than at the point where they
5619- // escape.
5620- return _emitFunctionTagged (
5621- result,
5622- target.function!
5623- .computeThisFunctionType (target.enclosingLibrary.nonNullable));
5657+ return _runtimeCall ('staticTearoff(#, #)' , [context, property]);
56245658 }
56255659 return result;
56265660 }
@@ -6721,7 +6755,7 @@ class LibraryCompiler extends ComputeOnceConstantVisitor<js_ast.Expression>
67216755 }
67226756
67236757 /// Emits the target of a [StaticInvocation] , [StaticGet] , or [StaticSet] .
6724- js_ast.Expression _emitStaticTarget (Member target) {
6758+ js_ast.PropertyAccess _emitStaticTarget (Member target) {
67256759 var c = target.enclosingClass;
67266760 if (c != null ) {
67276761 // A static native element should just forward directly to the JS type's
@@ -6731,9 +6765,12 @@ class LibraryCompiler extends ComputeOnceConstantVisitor<js_ast.Expression>
67316765 if (isExternal && (target as Procedure ).isStatic) {
67326766 var nativeName = _extensionTypes.getNativePeers (c);
67336767 if (nativeName.isNotEmpty) {
6734- var memberName = _annotationName (target, isJSName) ??
6735- _emitStaticMemberName (target.name.text, target);
6736- return _runtimeCall ('global.#.#' , [nativeName[0 ], memberName]);
6768+ var annotationName = _annotationName (target, isJSName);
6769+ var memberName = annotationName == null
6770+ ? _emitStaticMemberName (target.name.text, target)
6771+ : js.string (annotationName);
6772+ return js_ast.PropertyAccess (
6773+ _runtimeCall ('global.#' , [nativeName[0 ]]), memberName);
67376774 }
67386775 }
67396776 return js_ast.PropertyAccess (_emitStaticClassName (c, isExternal),
0 commit comments