| 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 d936333eb597ac7899138f4fad420911976adc1e..a923ec905d746c81f54c19006eae70edace25bde 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
|
| @@ -14,7 +14,7 @@ class InvocationImpl extends Invocation {
|
| final bool isGetter;
|
| final bool isSetter;
|
|
|
| - InvocationImpl(String memberName, this.positionalArguments,
|
| + InvocationImpl(memberName, this.positionalArguments,
|
| {namedArguments,
|
| this.isMethod: false,
|
| this.isGetter: false,
|
| @@ -29,12 +29,19 @@ class InvocationImpl extends Invocation {
|
| }
|
| }
|
|
|
| +// Warning: dload, dput, and dsend assume they are never called on methods
|
| +// implemented by the Object base class as those methods can always be
|
| +// statically resolved.
|
| dload(obj, field) {
|
| var f = _canonicalMember(obj, field);
|
| +
|
| _trackCall(obj);
|
| if (f != null) {
|
| - if (hasMethod(obj, f)) return bind(obj, f, JS('', 'void 0'));
|
| - return JS('', '#[#]', obj, f);
|
| + // XXX verify it is a Dart type first
|
| + var type = getType(obj);
|
| +
|
| + if (hasField(type, f) || hasGetter(type, f)) return JS('', '#[#]', obj, f);
|
| + if (hasMethod(type, f)) return bind(obj, f, JS('', 'void 0'));
|
| }
|
| return noSuchMethod(
|
| obj, new InvocationImpl(field, JS('', '[]'), isGetter: true));
|
| @@ -44,7 +51,26 @@ dput(obj, field, value) {
|
| var f = _canonicalMember(obj, field);
|
| _trackCall(obj);
|
| if (f != null) {
|
| - return JS('', '#[#] = #', obj, f, value);
|
| + // XXX verify it is a Dart type first
|
| + var type = getType(obj);
|
| + var setter = getSetterType(type, f);
|
| + if (JS('bool', '# != void 0', setter)) {
|
| + // TODO(jacobr): throw a type error instead of a NoSuchMethodError if
|
| + // the type of the setter doesn't match.
|
| + if (instanceOfOrNull(value, JS('', '#.args[0]', setter))) {
|
| + return JS('', '#[#] = #', obj, f, value);
|
| + }
|
| + } else {
|
| + var field = getFieldType(type, f);
|
| + // TODO(jacobr): propogate metadata tracking which fields are private.
|
| + if (JS('bool', '# != void 0', field)) {
|
| + // TODO(jacobr): throw a type error instead of a NoSuchMethodError if
|
| + // the type of the field doesn't match.
|
| + if (instanceOfOrNull(value, field)) {
|
| + return JS('', '#[#] = #', obj, f, value);
|
| + }
|
| + }
|
| + }
|
| }
|
| return noSuchMethod(
|
| obj, new InvocationImpl(field, JS('', '[#]', value), isSetter: true));
|
| @@ -89,8 +115,42 @@ _checkApply(type, actuals) => JS(
|
| return true;
|
| })()''');
|
|
|
| -Symbol _dartSymbol(name) =>
|
| - JS('', '#(#.new(#.toString()))', const_, Symbol, name);
|
| +_toSymbolName(symbol) => JS(
|
| + '',
|
| + '''(() => {
|
| + let str = $symbol.toString();
|
| + // Strip leading 'Symbol(' and trailing ')'
|
| + return str.substring(7, str.length-1);
|
| + })()''');
|
| +
|
| +_toDisplayName(name) => JS(
|
| + '',
|
| + '''(() => {
|
| + // Names starting with _ are escaped names used to disambiguate Dart and
|
| + // JS names.
|
| + if ($name[0] === '_') {
|
| + // Inverse of
|
| + switch($name) {
|
| + case '_get':
|
| + return '[]';
|
| + case '_set':
|
| + return '[]=';
|
| + case '_negate':
|
| + return 'unary-';
|
| + case '_constructor':
|
| + case '_prototype':
|
| + return $name.substring(1);
|
| + }
|
| + }
|
| + return $name;
|
| + })()''');
|
| +
|
| +Symbol _dartSymbol(name) {
|
| + return (JS('bool', 'typeof # === "symbol"', name))
|
| + ? JS('', '#(new #.es6(#, #))', const_, _internal.Symbol,
|
| + _toSymbolName(name), name)
|
| + : JS('', '#(#.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.
|
| @@ -121,7 +181,7 @@ _checkAndCall(f, ftype, obj, typeArgs, args, name) => JS(
|
| // We're not a function (and hence not a method either)
|
| // Grab the `call` method if it's not a function.
|
| if ($f != null) {
|
| - $ftype = $getMethodType($f, 'call');
|
| + $ftype = $getMethodType($getType($f), 'call');
|
| $f = $f.call;
|
| }
|
| if (!($f instanceof Function)) {
|
| @@ -303,7 +363,9 @@ _callMethod(obj, name, typeArgs, args, displayName) {
|
| obj, new InvocationImpl(displayName, args, isMethod: true));
|
| }
|
| var f = obj != null ? JS('', '#[#]', obj, symbol) : null;
|
| - var ftype = getMethodType(obj, symbol);
|
| + var type = getType(obj);
|
| + var ftype = getMethodType(type, symbol);
|
| + // No such method if dart object and ftype is missing.
|
| return _checkAndCall(f, ftype, obj, typeArgs, args, displayName);
|
| }
|
|
|
| @@ -837,9 +899,13 @@ _canonicalMember(obj, name) {
|
| }
|
|
|
| // Check for certain names that we can't use in JS
|
| - if (name == 'constructor' || name == 'prototype') {
|
| + /*(if (name == 'constructor' || name == 'prototype') {
|
| name = '+' + name;
|
| - }
|
| + }*/
|
| + if (JS('bool', '# instanceof #', obj, Object)) {
|
| + // This is a Dart type not a JS interop type.
|
| +
|
| + } else {}
|
| return name;
|
| }
|
|
|
|
|