Index: tool/input_sdk/private/ddc_runtime/operations.dart |
diff --git a/tool/input_sdk/private/ddc_runtime/operations.dart b/tool/input_sdk/private/ddc_runtime/operations.dart |
index 6c4e7400b3a4c88a397d372d0d392be8b9d08f94..9bf841f0614251be15c2999bcf298d71e69109a1 100644 |
--- a/tool/input_sdk/private/ddc_runtime/operations.dart |
+++ b/tool/input_sdk/private/ddc_runtime/operations.dart |
@@ -39,7 +39,7 @@ dput(obj, field, value) => JS('', '''(() => { |
/// Check that a function of a given type can be applied to |
/// actuals. |
-checkApply(type, actuals) => JS('', '''(() => { |
+_checkApply(type, actuals) => JS('', '''(() => { |
if ($actuals.length < $type.args.length) return false; |
let index = 0; |
for(let i = 0; i < $type.args.length; ++i) { |
@@ -87,7 +87,7 @@ throwNoSuchMethodFunc(obj, name, pArgs, opt_func) => JS('', '''(() => { |
$throwNoSuchMethod($obj, $name, $pArgs); |
})()'''); |
-checkAndCall(f, ftype, obj, args, name) => JS('', '''(() => { |
+_checkAndCall(f, ftype, obj, typeArgs, args, name) => JS('', '''(() => { |
let originalFunction = $f; |
if (!($f instanceof Function)) { |
// We're not a function (and hence not a method either) |
@@ -109,44 +109,72 @@ checkAndCall(f, ftype, obj, args, name) => JS('', '''(() => { |
if (!$ftype) { |
// TODO(leafp): Allow JS objects to go through? |
- // This includes the DOM. |
+ if ($typeArgs != null) { |
+ // TODO(jmesserly): is there a sensible way to handle these? |
+ $throwStrongModeError('call to JS object `' + $obj + |
+ '` with type arguments <' + $typeArgs + '> is not supported.'); |
+ } |
return $f.apply($obj, $args); |
} |
- if ($checkApply($ftype, $args)) { |
+ // Apply type arguments |
+ let formalCount = $ftype[$_typeFormalCount]; |
+ if (formalCount != null) { |
+ if ($typeArgs == null) { |
+ $typeArgs = Array(formalCount).fill($dynamicR); |
+ } else if ($typeArgs.length != formalCount) { |
+ // TODO(jmesserly): is this the right error? |
+ $throwStrongModeError( |
+ 'incorrect number of arguments to generic function ' + |
+ $typeName($ftype) + ', got <' + $typeArgs + '> expected ' + |
+ formalCount + '.'); |
+ } |
+ // Instantiate the function. |
+ $ftype = $ftype(...$typeArgs); |
+ } else if ($typeArgs != null) { |
+ $throwStrongModeError( |
+ 'got type arguments to non-generic function ' + $typeName($ftype) + |
+ ', got <' + $typeArgs + '> expected none.'); |
+ } |
+ |
+ if ($_checkApply($ftype, $args)) { |
+ if ($typeArgs != null) { |
+ return $f.apply($obj, $typeArgs).apply($obj, $args); |
+ } |
return $f.apply($obj, $args); |
} |
// TODO(leafp): throw a type error (rather than NSM) |
// if the arity matches but the types are wrong. |
+ // TODO(jmesserly): nSM should include type args? |
$throwNoSuchMethodFunc($obj, $name, $args, originalFunction); |
})()'''); |
-dcall(f, @rest args) => JS('', '''(() => { |
- let ftype = $read($f); |
- return $checkAndCall($f, ftype, void 0, $args, 'call'); |
-})()'''); |
+dcall(f, @rest args) => |
+ _checkAndCall(f, read(f), JS('', 'void 0'), null, args, 'call'); |
-/// Shared code for dsend, dindex, and dsetindex. */ |
-callMethod(obj, name, args, displayName) => JS('', '''(() => { |
- let symbol = $_canonicalFieldName($obj, $name, $args, $displayName); |
- let f = $obj != null ? $obj[symbol] : null; |
- let ftype = $getMethodType($obj, $name); |
- return $checkAndCall(f, ftype, $obj, $args, $displayName); |
-})()'''); |
-dsend(obj, method, @rest args) => JS('', '''(() => { |
- return $callMethod($obj, $method, $args, $method); |
-})()'''); |
+dgcall(f, typeArgs, @rest args) => |
+ _checkAndCall(f, read(f), JS('', 'void 0'), typeArgs, args, 'call'); |
-dindex(obj, index) => JS('', '''(() => { |
- return $callMethod($obj, 'get', [$index], '[]'); |
-})()'''); |
-dsetindex(obj, index, value) => JS('', '''(() => { |
- $callMethod($obj, 'set', [$index, $value], '[]='); |
- return $value; |
-})()'''); |
+/// Shared code for dsend, dindex, and dsetindex. |
+_callMethod(obj, name, typeArgs, args, displayName) { |
+ var symbol = _canonicalFieldName(obj, name, args, displayName); |
+ var f = obj != null ? JS('', '#[#]', obj, symbol) : null; |
+ var ftype = getMethodType(obj, symbol); |
+ return _checkAndCall(f, ftype, obj, typeArgs, args, displayName); |
+} |
+ |
+dsend(obj, method, @rest args) => _callMethod(obj, method, null, args, method); |
+ |
+dgsend(obj, typeArgs, method, @rest args) => |
+ _callMethod(obj, method, typeArgs, args, method); |
+ |
+dindex(obj, index) => _callMethod(obj, 'get', null, JS('', '[#]', index), '[]'); |
+ |
+dsetindex(obj, index, value) => |
+ _callMethod(obj, 'set', null, JS('', '[#, #]', index, value), '[]='); |
_ignoreTypeFailure(actual, type) => JS('', '''(() => { |
// TODO(vsm): Remove this hack ... |