3d77741666
Instead of possibly looping over the closure function parameter names array multiple times, just do it once. Check each entry against the provided argument names. If none match, check the required bit (if in null-safe mode). Also keep a count of matched names to check that all provided names matched after the iteration. Now that optional name checking is part of the fragment built by BuildClosureCallArgumentsValidCheck, that method builds checks for exactly the same things as its namesake in Function. Also refactor the variables used by the checker into read/write ones that need to be allocated in the parsed function and read-only ones that can just be temporaries since no Phi nodes are needed. Cq-Include-Trybots: luci.dart.try:vm-kernel-linux-release-x64-try,vm-kernel-precomp-linux-product-x64-try,vm-kernel-linux-debug-x64-try,vm-kernel-precomp-linux-release-simarm_x64-try,vm-kernel-linux-release-simarm-try,vm-kernel-linux-release-simarm64-try Bug: https://github.com/dart-lang/sdk/issues/40813 Change-Id: I3cb421dd538629d7f5499f3bbf0653d34b850dce Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/160725 Commit-Queue: Tess Strickland <sstrickl@google.com> Reviewed-by: Martin Kustermann <kustermann@google.com> Reviewed-by: Daco Harkes <dacoharkes@google.com>
134 lines
3.2 KiB
Dart
134 lines
3.2 KiB
Dart
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
|
|
// for details. All rights reserved. Use of this source code is governed by a
|
|
// BSD-style license that can be found in the LICENSE file.
|
|
//
|
|
// Test named arguments work as expected regardless of whether the function or
|
|
// method is called via function call syntax or method call syntax.
|
|
// VMOptions=--optimization-counter-threshold=10
|
|
|
|
import "package:expect/expect.dart";
|
|
|
|
Validate(tag, a, b) {
|
|
// tag encodes which parameters are passed in with values a: 111, b: 222.
|
|
if (tag == 'ab') {
|
|
Expect.equals(a, 111);
|
|
Expect.equals(b, 222);
|
|
}
|
|
if (tag == 'a') {
|
|
Expect.equals(a, 111);
|
|
Expect.equals(b, 20);
|
|
}
|
|
if (tag == 'b') {
|
|
Expect.equals(a, 10);
|
|
Expect.equals(b, 222);
|
|
}
|
|
if (tag == '') {
|
|
Expect.equals(a, 10);
|
|
Expect.equals(b, 20);
|
|
}
|
|
}
|
|
|
|
class HasMethod {
|
|
int calls = 0;
|
|
|
|
HasMethod();
|
|
|
|
foo(tag, [a = 10, b = 20]) {
|
|
calls += 1;
|
|
Validate(tag, a, b);
|
|
}
|
|
|
|
foo2(tag, {a: 10, b: 20}) {
|
|
calls += 1;
|
|
Validate(tag, a, b);
|
|
}
|
|
}
|
|
|
|
class HasField {
|
|
int calls = 0;
|
|
dynamic foo, foo2;
|
|
|
|
HasField() {
|
|
foo = makeFoo(this);
|
|
foo2 = makeFoo2(this);
|
|
}
|
|
|
|
makeFoo(owner) {
|
|
// This function is closed-over 'owner'.
|
|
return (tag, [a = 10, b = 20]) {
|
|
owner.calls += 1;
|
|
Validate(tag, a, b);
|
|
};
|
|
}
|
|
|
|
makeFoo2(owner) {
|
|
// This function is closed-over 'owner'.
|
|
return (tag, {a: 10, b: 20}) {
|
|
owner.calls += 1;
|
|
Validate(tag, a, b);
|
|
};
|
|
}
|
|
}
|
|
|
|
class NamedParametersWithConversionsTest {
|
|
static testMethodCallSyntax(a) {
|
|
a.foo('');
|
|
a.foo('a', 111);
|
|
a.foo('ab', 111, 222);
|
|
a.foo2('a', a: 111);
|
|
a.foo2('b', b: 222);
|
|
a.foo2('ab', a: 111, b: 222);
|
|
a.foo2('ab', b: 222, a: 111);
|
|
|
|
Expect.equals(7, a.calls);
|
|
|
|
Expect.throwsNoSuchMethodError(() => a.foo()); // Too few arguments.
|
|
Expect.throwsNoSuchMethodError(
|
|
() => a.foo('abc', 1, 2, 3)); // Too many arguments.
|
|
Expect.throwsNoSuchMethodError(() => a.foo2('c', c: 1)); // Bad name.
|
|
Expect.throwsNoSuchMethodError(
|
|
() => a.foo2('c', a: 111, c: 1)); // Bad name.
|
|
|
|
Expect.equals(7, a.calls);
|
|
}
|
|
|
|
static testFunctionCallSyntax(a) {
|
|
var f = a.foo;
|
|
var f2 = a.foo2;
|
|
f('');
|
|
f('a', 111);
|
|
f('ab', 111, 222);
|
|
f2('a', a: 111);
|
|
f2('b', b: 222);
|
|
f2('ab', a: 111, b: 222);
|
|
f2('ab', b: 222, a: 111);
|
|
|
|
Expect.equals(7, a.calls);
|
|
|
|
Expect.throwsNoSuchMethodError(() => f()); // Too few arguments.
|
|
Expect.throwsNoSuchMethodError(
|
|
() => f('abc', 1, 2, 3)); // Too many arguments.
|
|
Expect.throwsNoSuchMethodError(() => f2('c', c: 1)); // Bad name.
|
|
Expect.throwsNoSuchMethodError(() => f2('c', a: 111, c: 1)); // Bad name.
|
|
|
|
Expect.equals(7, a.calls);
|
|
}
|
|
|
|
static testMain() {
|
|
// 'Plain' calls where the method/field syntax matches the object.
|
|
testMethodCallSyntax(new HasMethod());
|
|
testFunctionCallSyntax(new HasField());
|
|
|
|
// 'Conversion' calls where method/field call syntax does not match the
|
|
// object.
|
|
testMethodCallSyntax(new HasField());
|
|
testFunctionCallSyntax(new HasMethod());
|
|
}
|
|
}
|
|
|
|
main() {
|
|
for (var i = 0; i < 20; i++) {
|
|
NamedParametersWithConversionsTest.testMain();
|
|
}
|
|
}
|