[ddc] Fix named args in redirecting constructors

Change-Id: Iaed36c3cab43672338a5b1750aad25951428052c
Fixes: https://github.com/dart-lang/sdk/issues/47831
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/221887
Reviewed-by: Mark Zhou <markzipan@google.com>
Commit-Queue: Nicholas Shahan <nshahan@google.com>
This commit is contained in:
Nicholas Shahan 2021-12-03 00:02:57 +00:00 committed by Commit Bot
parent 51508627c4
commit 73f4377011

View file

@ -1612,14 +1612,12 @@ class ProgramCompiler extends ComputeOnceConstantVisitor<js_ast.Expression>
var fn = node.function; var fn = node.function;
var body = _emitArgumentInitializers(fn, node.name.text); var body = _emitArgumentInitializers(fn, node.name.text);
// Redirecting constructors: these are not allowed to have initializers, // Redirecting constructors are not allowed to have conventional
// and the redirecting ctor invocation runs before field initializers. // initializers but can have variable declarations in the form of
var redirectCall = node.initializers // initializers to support named arguments appearing anywhere in the
.firstWhere((i) => i is RedirectingInitializer, orElse: () => null) // arguments list.
as RedirectingInitializer; if (node.initializers.any((i) => i is RedirectingInitializer)) {
body.add(_emitRedirectingConstructor(node.initializers, className));
if (redirectCall != null) {
body.add(_emitRedirectingConstructor(redirectCall, className));
return body; return body;
} }
@ -1652,15 +1650,23 @@ class ProgramCompiler extends ComputeOnceConstantVisitor<js_ast.Expression>
} }
js_ast.Statement _emitRedirectingConstructor( js_ast.Statement _emitRedirectingConstructor(
RedirectingInitializer node, js_ast.Expression className) { List<Initializer> initializers, js_ast.Expression className) {
var ctor = node.target; var jsInitializers = <js_ast.Statement>[
// We can't dispatch to the constructor with `this.new` as that might hit a for (var init in initializers)
// derived class constructor with the same name. if (init is LocalInitializer)
return js.statement('#.#.call(this, #);', [ // Temporary locals are created when named arguments don't appear at
className, // the end of the arguments list.
_constructorName(ctor.name.text), visitVariableDeclaration(init.variable)
_emitArgumentList(node.arguments, types: false) else if (init is RedirectingInitializer)
]); // We can't dispatch to the constructor with `this.new` as that might
// hit a derived class constructor with the same name.
js.statement('#.#.call(this, #);', [
className,
_constructorName(init.target.name.text),
_emitArgumentList(init.arguments, types: false)
])
];
return js_ast.Block(jsInitializers);
} }
js_ast.Statement _emitSuperConstructorCallIfNeeded( js_ast.Statement _emitSuperConstructorCallIfNeeded(