Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(848)

Unified Diff: pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/operations.dart

Issue 2979353002: implement `Invocation.typeArguments` in DDC (Closed)
Patch Set: fix Created 3 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/operations.dart
diff --git a/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/operations.dart b/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/operations.dart
index d8014d99ed6feb7339dd88c153a6a3d89553b003..880d0db1adcd1316285ab24d7a8407404a9c9d44 100644
--- a/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/operations.dart
+++ b/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/operations.dart
@@ -10,17 +10,23 @@ class InvocationImpl extends Invocation {
final Symbol memberName;
final List positionalArguments;
final Map<Symbol, dynamic> namedArguments;
+ final List<Type> typeArguments;
final bool isMethod;
final bool isGetter;
final bool isSetter;
InvocationImpl(memberName, this.positionalArguments,
{namedArguments,
+ List typeArguments,
this.isMethod: false,
this.isGetter: false,
this.isSetter: false})
- : memberName = _dartSymbol(memberName),
- namedArguments = _namedArgsToSymbols(namedArguments);
+ : memberName =
+ isSetter ? _setterSymbol(memberName) : _dartSymbol(memberName),
+ namedArguments = _namedArgsToSymbols(namedArguments),
+ typeArguments = typeArguments == null
+ ? const []
+ : typeArguments.map(wrapType).toList();
static Map<Symbol, dynamic> _namedArgsToSymbols(namedArgs) {
if (namedArgs == null) return {};
@@ -174,9 +180,7 @@ dput(obj, field, value) {
/// Check that a function of a given type can be applied to
/// actuals.
-_checkApply(type, actuals) => JS(
- '',
- '''(() => {
+_checkApply(type, actuals) => JS('', '''(() => {
// TODO(vsm): Remove when we no longer need mirrors metadata.
// An array is used to encode annotations attached to the type.
if ($type instanceof Array) {
@@ -216,17 +220,13 @@ _checkApply(type, actuals) => JS(
return true;
})()''');
-_toSymbolName(symbol) => JS(
- '',
- '''(() => {
+_toSymbolName(symbol) => JS('', '''(() => {
let str = $symbol.toString();
// Strip leading 'Symbol(' and trailing ')'
return str.substring(7, str.length-1);
})()''');
-_toDisplayName(name) => JS(
- '',
- '''(() => {
+_toDisplayName(name) => JS('', '''(() => {
// Names starting with _ are escaped names used to disambiguate Dart and
// JS names.
if ($name[0] === '_') {
@@ -253,6 +253,13 @@ Symbol _dartSymbol(name) {
: JS('Symbol', '#(#.new(#))', const_, Symbol, _toDisplayName(name));
}
+Symbol _setterSymbol(name) {
+ return (JS('bool', 'typeof # === "symbol"', name))
+ ? JS('Symbol', '#(new #.new(# + "=", #))', const_,
+ _internal.PrivateSymbol, _toSymbolName(name), name)
+ : JS('Symbol', '#(#.new(# + "="))', const_, Symbol, _toDisplayName(name));
+}
+
/// Extracts the named argument array from a list of arguments, and returns it.
// TODO(jmesserly): we need to handle named arguments better.
extractNamedArgs(args) {
@@ -266,17 +273,18 @@ extractNamedArgs(args) {
return null;
}
-_checkAndCall(f, ftype, obj, typeArgs, args, name) => JS(
- '',
- '''(() => {
+_checkAndCall(f, ftype, obj, typeArgs, args, name) => JS('', '''(() => {
$_trackCall($obj);
let originalTarget = obj === void 0 ? f : obj;
function callNSM() {
return $noSuchMethod(originalTarget, new $InvocationImpl.new(
- $name, $args,
- {namedArguments: $extractNamedArgs($args), isMethod: true}));
+ $name, $args, {
+ namedArguments: $extractNamedArgs($args),
+ typeArguments: $typeArgs,
+ isMethod: true
+ }));
}
if (!($f instanceof Function)) {
// We're not a function (and hence not a method either)
@@ -349,9 +357,7 @@ dgcall(f, typeArgs, @rest args) => _checkAndCall(
/// Helper for REPL dynamic invocation variants that make a best effort to
/// enable accessing private members across library boundaries.
-_dhelperRepl(object, field, callback) => JS(
- '',
- '''(() => {
+_dhelperRepl(object, field, callback) => JS('', '''(() => {
let rawField = $field;
if (typeof(field) == 'symbol') {
// test if the specified field exists in which case it is safe to use it.
@@ -431,9 +437,7 @@ dsetindex(obj, index, value) =>
/// TODO(leafp): This duplicates code in types.dart.
/// I haven't found a way to factor it out that makes the
/// code generator happy though.
-_ignoreMemo(f) => JS(
- '',
- '''(() => {
+_ignoreMemo(f) => JS('', '''(() => {
let memo = new Map();
return (t1, t2) => {
let map = memo.get(t1);
@@ -450,9 +454,7 @@ _ignoreMemo(f) => JS(
};
})()''');
-final _ignoreTypeFailure = JS(
- '',
- '''(() => {
+final _ignoreTypeFailure = JS('', '''(() => {
return $_ignoreMemo((actual, type) => {
// TODO(vsm): Remove this hack ...
// This is primarily due to the lack of generic methods,
@@ -486,9 +488,7 @@ final _ignoreTypeFailure = JS(
/// and strong mode
/// Returns null if [obj] is not an instance of [type] in strong mode
/// but might be in spec mode
-bool strongInstanceOf(obj, type, ignoreFromWhiteList) => JS(
- '',
- '''(() => {
+bool strongInstanceOf(obj, type, ignoreFromWhiteList) => JS('', '''(() => {
let actual = $getReifiedType($obj);
let result = $isSubtype(actual, $type);
if (result || (actual == $int && $isSubtype($double, $type))) return true;
@@ -508,18 +508,14 @@ bool strongInstanceOf(obj, type, ignoreFromWhiteList) => JS(
/// Returns true if [obj] is null or an instance of [type]
/// Returns false if [obj] is non-null and not an instance of [type]
/// in strong mode
-instanceOfOrNull(obj, type) => JS(
- '',
- '''(() => {
+instanceOfOrNull(obj, type) => JS('', '''(() => {
// If strongInstanceOf returns null, convert to false here.
if (($obj == null) || $strongInstanceOf($obj, $type, true)) return true;
return false;
})()''');
@JSExportName('is')
-bool instanceOf(obj, type) => JS(
- '',
- '''(() => {
+bool instanceOf(obj, type) => JS('', '''(() => {
if ($obj == null) {
return $type == $Null || $_isTop($type);
}
@@ -612,9 +608,7 @@ asInt(obj) {
/// Adds type type test predicates to a constructor for a non-parameterized
/// type. Non-parameterized types can use `instanceof` for subclass checks and
/// fall through to a helper for subtype tests.
-addSimpleTypeTests(ctor) => JS(
- '',
- '''(() => {
+addSimpleTypeTests(ctor) => JS('', '''(() => {
$ctor.is = function is_C(object) {
// This is incorrect for classes [Null] and [Object], so we do not use
// [addSimpleTypeTests] for these classes.
@@ -634,9 +628,7 @@ addSimpleTypeTests(ctor) => JS(
/// Adds type type test predicates to a constructor. Used for parmeterized
/// types. We avoid `instanceof` for, e.g. `x is ListQueue` since there is
/// no common class for `ListQueue<int>` and `ListQueue<String>`.
-addTypeTests(ctor) => JS(
- '',
- '''(() => {
+addTypeTests(ctor) => JS('', '''(() => {
$ctor.as = function as_G(object) {
return dart.as(object, this);
};
@@ -650,9 +642,7 @@ addTypeTests(ctor) => JS(
// TODO(vsm): Consider optimizing this. We may be able to statically
// determine which == operation to invoke given the static types.
-equals(x, y) => JS(
- '',
- '''(() => {
+equals(x, y) => JS('', '''(() => {
if ($x == null || $y == null) return $x == $y;
let eq = $x[dartx['==']] || $x['=='];
return eq ? eq.call($x, $y) : $x === $y;
@@ -680,9 +670,7 @@ notNull(x) {
// TODO(jmesserly): this could be faster
// TODO(jmesserly): we can use default values `= dynamic` once #417 is fixed.
// TODO(jmesserly): move this to classes for consistency with list literals?
-map(values, [K, V]) => JS(
- '',
- '''(() => {
+map(values, [K, V]) => JS('', '''(() => {
if ($K == null) $K = $dynamic;
if ($V == null) $V = $dynamic;
let map = ${getGenericClass(LinkedHashMap)}($K, $V).new();
@@ -795,9 +783,7 @@ final _value = JS('', 'Symbol("_value")');
///
/// { 1: { 2: { 'hi ': { 'there ': 'world' } } } }
///
-multiKeyPutIfAbsent(map, keys, valueFn) => JS(
- '',
- '''(() => {
+multiKeyPutIfAbsent(map, keys, valueFn) => JS('', '''(() => {
for (let k of $keys) {
let value = $map.get(k);
if (!value) {
@@ -829,9 +815,7 @@ final constants = JS('', 'new Map()');
/// - nested values of the object are themselves already canonicalized.
///
@JSExportName('const')
-const_(obj) => JS(
- '',
- '''(() => {
+const_(obj) => JS('', '''(() => {
// TODO(leafp): This table gets quite large in apps.
// Keeping the paths is probably expensive. It would probably
// be more space efficient to just use a direct hash table with
@@ -878,12 +862,8 @@ const_(obj) => JS(
/// type and contains the canonical version of the list.
final constantLists = JS('', 'new Map()');
-///
/// Canonicalize a constant list
-///
-constList(elements, elementType) => JS(
- '',
- '''(() => {
+constList(elements, elementType) => JS('', '''(() => {
function lookupNonTerminal(map, key) {
let result = map.get(key);
if (result !== void 0) return result;
@@ -897,7 +877,8 @@ constList(elements, elementType) => JS(
}
let value = map.get($elementType);
if (value) return value;
- value = $list($elements, $elementType);
+
+ value = $setType($elements, ${getGenericClass(JSArray)}($elementType));
map.set($elementType, value);
return value;
})()''');
@@ -915,9 +896,11 @@ hashCode(obj) {
// From JSBool.hashCode, see comment there.
return JS('', '# ? (2 * 3 * 23 * 3761) : (269 * 811)', obj);
case "function":
- var hashFn = JS('', '#[#]', obj, _tearoffHashcode);
- if (hashFn != null) return JS('int', '#()', hashFn);
- return Primitives.objectHashCode(obj);
+ if (JS('bool', '# instanceof Function', obj)) {
+ var hashFn = JS('', '#[#]', obj, _tearoffHashcode);
+ if (hashFn != null) return JS('int', '#()', hashFn);
+ return Primitives.objectHashCode(obj);
+ }
}
var extension = getExtensionType(obj);
@@ -935,7 +918,7 @@ String _toString(obj) {
if (extension != null) {
return JS('String', '#[dartx.toString]()', obj);
}
- if (JS('bool', 'typeof # == "function"', obj)) {
+ if (JS('bool', 'typeof # == "function" && # instanceof Function', obj, obj)) {
// If the function is a Type object, we should just display the type name.
// Regular Dart code should typically get wrapped type objects instead of
// raw type (aka JS constructor) objects however raw type objects can be
@@ -954,7 +937,8 @@ String _toString(obj) {
// TODO(jmesserly): is the argument type verified statically?
noSuchMethod(obj, Invocation invocation) {
- if (obj == null || JS('bool', 'typeof # == "function"', obj)) {
+ if (obj == null ||
+ JS('bool', 'typeof # == "function" && # instanceof Function', obj, obj)) {
throwNoSuchMethodError(obj, invocation.memberName,
invocation.positionalArguments, invocation.namedArguments);
}
@@ -980,7 +964,7 @@ runtimeType(obj) {
// If extension doesn't override runtimeType, return the extension type.
return result ?? wrapType(extension);
}
- if (JS('bool', 'typeof # == "function"', obj)) {
+ if (JS('bool', 'typeof # == "function" && # instanceof Function', obj, obj)) {
return wrapType(getReifiedType(obj));
}
return JS('', '#.runtimeType', obj);
@@ -989,9 +973,7 @@ runtimeType(obj) {
/// Implements Dart's interpolated strings as ES2015 tagged template literals.
///
/// For example: dart.str`hello ${name}`
-String str(strings, @rest values) => JS(
- '',
- '''(() => {
+String str(strings, @rest values) => JS('', '''(() => {
let s = $strings[0];
for (let i = 0, len = $values.length; i < len; ) {
s += $notNull($_toString($values[i])) + $strings[++i];
@@ -999,9 +981,7 @@ String str(strings, @rest values) => JS(
return s;
})()''');
-final JsIterator = JS(
- '',
- '''
+final JsIterator = JS('', '''
class JsIterator {
constructor(dartIterator) {
this.dartIterator = dartIterator;

Powered by Google App Engine
This is Rietveld 408576698