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

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

Issue 2061373003: implement user-defined nSM, Object members on functions (Closed) Base URL: git@github.com:dart-lang/dev_compiler.git@master
Patch Set: fix Created 4 years, 6 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: 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 c64546271822394781d492987138c68c1d4f87af..f34801cf6cd94ee4fe01e1013316ffb390533fe2 100644
--- a/tool/input_sdk/private/ddc_runtime/operations.dart
+++ b/tool/input_sdk/private/ddc_runtime/operations.dart
@@ -6,39 +6,51 @@
/// generator.
part of dart._runtime;
-_canonicalFieldName(obj, name, args, displayName) => JS('', '''(() => {
- $name = $canonicalMember($obj, $name);
- if ($name) return $name;
- // TODO(jmesserly): in the future we might have types that "overlay" Dart
- // methods while also exposing the full native API, e.g. dart:html vs
- // dart:dom. To support that we'd need to fall back to the normal name
- // if an extension method wasn't found.
- $throwNoSuchMethodFunc($obj, $displayName, $args);
-})()''');
-
-dload(obj, field) => JS('', '''(() => {
- $field = $_canonicalFieldName($obj, $field, [], $field);
- $_trackCall($obj, $field);
- if ($hasMethod($obj, $field)) {
- return $bind($obj, $field);
- }
- // TODO(vsm): Implement NSM robustly. An 'in' check breaks on certain
- // types. hasOwnProperty doesn't chase the proto chain.
- // Also, do we want an NSM on regular JS objects?
- // See: https://github.com/dart-lang/dev_compiler/issues/169
- let result = $obj[$field];
- return result;
-})()''');
+class _Invocation extends Invocation {
+ final Symbol memberName;
+ final List positionalArguments;
+ final Map<Symbol, dynamic> namedArguments;
+ final bool isMethod;
+ final bool isGetter;
+ final bool isSetter;
+
+ _Invocation(String memberName, this.positionalArguments,
+ {namedArguments,
+ this.isMethod: false,
+ this.isGetter: false,
+ this.isSetter: false})
+ : memberName = _dartSymbol(memberName),
+ namedArguments = _namedArgsToSymbols(namedArguments);
+
+ static Map<Symbol, dynamic> _namedArgsToSymbols(namedArgs) {
+ if (namedArgs == null) return {};
+ return new Map.fromIterable(
+ getOwnPropertyNames(namedArgs),
+ key: _dartSymbol,
+ value: (k) => JS('', '#[#]', namedArgs, k));
+ }
+}
-dput(obj, field, value) => JS('', '''(() => {
- $field = $_canonicalFieldName($obj, $field, [$value], $field);
- $_trackCall($obj, $field);
+dload(obj, field) {
+ var f = _canonicalMember(obj, field);
+ _trackCall(obj, f);
+ if (f != null) {
+ if (hasMethod(obj, f)) return bind(obj, f, JS('', 'void 0'));
+ return JS('', '#[#]', obj, f);
+ }
+ return noSuchMethod(obj,
+ new _Invocation(field, JS('', '[]'), isGetter: true));
+}
- // TODO(vsm): Implement NSM and type checks.
- // See: https://github.com/dart-lang/dev_compiler/issues/170
- $obj[$field] = $value;
- return $value;
-})()''');
+dput(obj, field, value) {
+ var f = _canonicalMember(obj, field);
+ _trackCall(obj, f);
+ if (f != null) {
+ return JS('', '#[#] = #', obj, f, value);
+ }
+ return noSuchMethod(obj,
+ new _Invocation(field, JS('', '[#]', value), isSetter: true));
+}
/// Check that a function of a given type can be applied to
/// actuals.
@@ -77,23 +89,24 @@ _checkApply(type, actuals) => JS('', '''(() => {
return true;
})()''');
-_dartSymbol(name) => JS('', '''
- $const_($Symbol.new($name.toString()))
-''');
-
-throwNoSuchMethod(obj, name, pArgs, nArgs, extras) => JS('', '''(() => {
- $throw_(new $NoSuchMethodError($obj, $_dartSymbol($name), $pArgs, $nArgs, $extras));
-})()''');
-
-throwNoSuchMethodFunc(obj, name, pArgs, opt_func) => JS('', '''(() => {
- if ($obj === void 0) $obj = $opt_func;
- $throwNoSuchMethod($obj, $name, $pArgs);
-})()''');
+Symbol _dartSymbol(name) =>
+ JS('', '#(#.new(#.toString()))', const_, Symbol, name);
+// TODO(jmesserly): we need to handle named arguments better.
_checkAndCall(f, ftype, obj, typeArgs, args, name) => JS('', '''(() => {
$_trackCall($obj, $name);
- let originalFunction = $f;
+ let originalTarget = obj === void 0 ? f : obj;
+
+ function callNSM() {
+ let namedArgs = null;
+ if (args.length > 0 &&
+ args[args.length - 1].__proto__ == Object.prototype) {
+ namedArgs = args.pop();
+ }
+ return $noSuchMethod(originalTarget, new $_Invocation(
+ $name, $args, {namedArguments: namedArgs, isMethod: true}));
+ }
if (!($f instanceof Function)) {
// We're not a function (and hence not a method either)
// Grab the `call` method if it's not a function.
@@ -102,7 +115,7 @@ _checkAndCall(f, ftype, obj, typeArgs, args, name) => JS('', '''(() => {
$f = $f.call;
}
if (!($f instanceof Function)) {
- $throwNoSuchMethodFunc($obj, $name, $args, originalFunction);
+ return callNSM();
}
}
// If f is a function, but not a method (no method type)
@@ -152,13 +165,12 @@ _checkAndCall(f, ftype, obj, typeArgs, args, name) => JS('', '''(() => {
// 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);
+ return callNSM();
})()''');
dcall(f, @rest args) => _checkAndCall(
f, _getRuntimeType(f), JS('', 'void 0'), null, args, 'call');
-
dgcall(f, typeArgs, @rest args) => _checkAndCall(
f, _getRuntimeType(f), JS('', 'void 0'), typeArgs, args, 'call');
@@ -209,7 +221,11 @@ _trackCall(obj, name) {
/// Shared code for dsend, dindex, and dsetindex.
_callMethod(obj, name, typeArgs, args, displayName) {
- var symbol = _canonicalFieldName(obj, name, args, displayName);
+ var symbol = _canonicalMember(obj, name);
+ if (symbol == null) {
+ return noSuchMethod(obj,
+ new _Invocation(displayName, args, isMethod: true));
+ }
var f = obj != null ? JS('', '#[#]', obj, symbol) : null;
var ftype = getMethodType(obj, symbol);
return _checkAndCall(f, ftype, obj, typeArgs, args, displayName);
@@ -611,6 +627,9 @@ hashCode(obj) {
case "boolean":
// From JSBool.hashCode, see comment there.
return JS('', '# ? (2 * 3 * 23 * 3761) : (269 * 811)', obj);
+ case "function":
+ // TODO(jmesserly): this doesn't work for method tear-offs.
+ return Primitives.objectHashCode(obj);
}
var extension = getExtensionType(obj);
@@ -628,6 +647,10 @@ String _toString(obj) {
if (extension != null) {
return JS('String', '#[dartx.toString]()', obj);
}
+ if (JS('bool', 'typeof # == "function"', obj)) {
+ return JS('String', r'"Closure: " + # + " from: " + #',
+ getReifiedType(obj), obj);
+ }
// TODO(jmesserly): restore this faster path once ES Symbol is treated as
// an extension type (and thus hits the above code path).
// See https://github.com/dart-lang/dev_compiler/issues/578.
@@ -637,9 +660,9 @@ String _toString(obj) {
// TODO(jmesserly): is the argument type verified statically?
noSuchMethod(obj, Invocation invocation) {
- if (obj == null) {
+ if (obj == null || JS('bool', 'typeof # == "function"', obj)) {
throw new NoSuchMethodError(
- null,
+ obj,
invocation.memberName,
invocation.positionalArguments,
invocation.namedArguments);
@@ -664,6 +687,9 @@ runtimeType(obj) {
if (extension != null) {
return JS('', '#[dartx.runtimeType]', obj);
}
+ if (JS('bool', 'typeof # == "function"', obj)) {
+ return wrapType(getReifiedType(obj));
+ }
return JS('', '#.runtimeType', obj);
}
@@ -691,3 +717,18 @@ final JsIterator = JS('', '''
}
}
''');
+
+_canonicalMember(obj, name) {
+ // Private names are symbols and are already canonical.
+ if (JS('bool', 'typeof # === "symbol"', name)) return name;
+
+ if (obj != null && getExtensionType(obj) != null) {
+ return JS('', 'dartx.#', name);
+ }
+
+ // Check for certain names that we can't use in JS
+ if (name == 'constructor' || name == 'prototype') {
+ name = '+' + name;
+ }
+ return name;
+}

Powered by Google App Engine
This is Rietveld 408576698