Description
import 'dart:js_interop';
@JS()
extension type ObjectLiteral._(JSObject _) implements JSObject {
external ObjectLiteral({String prop});
}
void main() {
ObjectLiteral();
}
results in:
The compiler crashed: Assertion failure: Unknown external method j:method(ObjectLiteral|constructor#)
#0 failedAt (package:compiler/src/diagnostics/invariant.dart:39:3)
#1 KernelSsaGraphBuilder._buildExternalFunctionNode (package:compiler/src/ssa/builder.dart:1819:5)
#2 KernelSsaGraphBuilder.build.<anonymous closure> (package:compiler/src/ssa/builder.dart:439:15)
#3 DiagnosticReporter.withCurrentElement (package:compiler/src/diagnostics/diagnostic_listener.dart:154:15)
#4 KernelSsaGraphBuilder.build (package:compiler/src/ssa/builder.dart:427:21)
#5 KernelSsaBuilder.build.<anonymous closure> (package:compiler/src/js_model/js_strategy.dart:525:22)
#6 CompilerTask.measure (package:compiler/src/common/tasks.dart:66:51)
#7 KernelSsaBuilder.build (package:compiler/src/js_model/js_strategy.dart:507:18)
#8 SsaBuilderTask.build (package:compiler/src/ssa/ssa.dart:365:21)
#9 SsaFunctionCompiler.compile (package:compiler/src/ssa/ssa.dart:99:28)
#10 OnDemandCodegenResults.getCodegenResults (package:compiler/src/common/codegen.dart:409:30)
#11 JsBackendStrategy.generateCode (package:compiler/src/js_model/js_strategy.dart:331:43)
#12 KernelCodegenWorkItem.run (package:compiler/src/js_model/js_strategy.dart:466:29)
#13 Compiler.emptyQueue.<anonymous closure>.<anonymous closure>.<anonymous closure>.<anonymous closure>.<anonymous closure> (package:compiler/src/compiler.dart:752:70)
#14 CompilerTask.measureSubtask (package:compiler/src/common/tasks.dart:181:35)
#15 Compiler.emptyQueue.<anonymous closure>.<anonymous closure>.<anonymous closure>.<anonymous closure> (package:compiler/src/compiler.dart:752:32)
#16 CompilerTask.measureSubtask (package:compiler/src/common/tasks.dart:181:35)
#17 Compiler.emptyQueue.<anonymous closure>.<anonymous closure>.<anonymous closure> (package:compiler/src/compiler.dart:750:28)
#18 DiagnosticReporter.withCurrentElement (package:compiler/src/diagnostics/diagnostic_listener.dart:154:15)
#19 Compiler.emptyQueue.<anonymous closure>.<anonymous closure> (package:compiler/src/compiler.dart:748:18)
#20 CodegenEnqueuer._forEach (package:compiler/src/js_backend/enqueuer.dart:266:12)
#21 CodegenEnqueuer.forEach (package:compiler/src/js_backend/enqueuer.dart:282:5)
#22 Compiler.emptyQueue.<anonymous closure> (package:compiler/src/compiler.dart:744:16)
#23 CompilerTask.measureSubtask (package:compiler/src/common/tasks.dart:181:35)
#24 Compiler.emptyQueue (package:compiler/src/compiler.dart:743:14)
#25 Compiler.processQueue.<anonymous closure> (package:compiler/src/compiler.dart:767:7)
#26 CompilerTask.measureSubtask (package:compiler/src/common/tasks.dart:181:35)
#27 Compiler.processQueue (package:compiler/src/compiler.dart:761:14)
#28 Compiler.runCodegenEnqueuer (package:compiler/src/compiler.dart:472:5)
#29 Compiler.runSequentialPhases (package:compiler/src/compiler.dart:680:27)
<asynchronous suspension>
#30 Compiler.runInternal.<anonymous closure> (package:compiler/src/compiler.dart:315:7)
<asynchronous suspension>
#31 Compiler.runInternal (package:compiler/src/compiler.dart:314:5)
<asynchronous suspension>
#32 Compiler.run.<anonymous closure> (package:compiler/src/compiler.dart:235:11)
<asynchronous suspension>
#33 compile.<anonymous closure> (package:compiler/compiler_api.dart:256:30)
<asynchronous suspension>
#34 compile.compilationDone (package:compiler/src/dart2js.dart:729:3)
<asynchronous suspension>
#35 batchMain.<anonymous closure>.<anonymous closure> (package:compiler/src/dart2js.dart:1347:13)
<asynchronous suspension>
#36 batchMain.<anonymous closure>.<anonymous closure> (package:compiler/src/dart2js.dart:1355:21)
<asynchronous suspension>
because dart2js doesn't recognize the constructor as a JS interop member.
Adding an @JS
annotation onto the library tells dart2js it's meant to be an interop member e.g.
@JS()
library literal;
import 'dart:js_interop';
@JS()
extension type ObjectLiteral._(JSObject _) implements JSObject {
external ObjectLiteral({String prop});
}
void main() {
ObjectLiteral();
}
DDC doesn't come across this issue because it assumes all external
, extension type members with named parameters are object literal constructors. We can make this same assumption in dart2js as a fix, but long-term, we should have a more robust lowering here. With extension types, we use the representation type to determine if a type is an interop type. However, this information requires indexing all the extension types and their members, which is expensive, so we don't do this in the backends. Ideally, we'd be able to construct the literal in the transformers (where we already do the indexing) before we get to the backend, but this isn't possible today as we don't have a lowering to create an arbitrary object with keys and values in JS.
Metadata
Metadata
Assignees
Labels
Type
Projects
Status