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

Unified Diff: sdk/lib/js/dart2js/js_dart2js.dart

Issue 1318043005: Support user generated custom native JS classes. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: about to land Created 5 years, 2 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
« no previous file with comments | « sdk/lib/_internal/js_runtime/lib/interceptors.dart ('k') | tests/compiler/dart2js/mock_libraries.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: sdk/lib/js/dart2js/js_dart2js.dart
diff --git a/sdk/lib/js/dart2js/js_dart2js.dart b/sdk/lib/js/dart2js/js_dart2js.dart
index 8c5eb301d321be4a526095d489b0c01893c8fe71..417876e5738a9a246e767ab7454883f0b1c45ad9 100644
--- a/sdk/lib/js/dart2js/js_dart2js.dart
+++ b/sdk/lib/js/dart2js/js_dart2js.dart
@@ -92,21 +92,30 @@ import 'dart:collection' show HashMap, ListMixin;
import 'dart:indexed_db' show KeyRange;
import 'dart:typed_data' show TypedData;
-import 'dart:_foreign_helper' show JS, DART_CLOSURE_TO_JS;
-import 'dart:_interceptors' show JavaScriptObject, UnknownJavaScriptObject;
-import 'dart:_js_helper' show Primitives, convertDartClosureToJS,
- getIsolateAffinityTag;
+import 'dart:_foreign_helper' show JS, JS_CONST, DART_CLOSURE_TO_JS;
+import 'dart:_interceptors'
+ show JavaScriptObject, UnknownJavaScriptObject, DART_CLOSURE_PROPERTY_NAME;
+import 'dart:_js_helper'
+ show Primitives, convertDartClosureToJS, getIsolateAffinityTag;
+
+export 'dart:_interceptors' show JavaScriptObject;
final JsObject context = _wrapToDart(JS('', 'self'));
_convertDartFunction(Function f, {bool captureThis: false}) {
- return JS('',
- 'function(_call, f, captureThis) {'
- 'return function() {'
- 'return _call(f, captureThis, this, '
- 'Array.prototype.slice.apply(arguments));'
- '}'
- '}(#, #, #)', DART_CLOSURE_TO_JS(_callDartFunction), f, captureThis);
+ return JS(
+ '',
+ '''
+ function(_call, f, captureThis) {
+ return function() {
+ return _call(f, captureThis, this,
+ Array.prototype.slice.apply(arguments));
+ }
+ }(#, #, #)
+ ''',
+ DART_CLOSURE_TO_JS(_callDartFunction),
+ f,
+ captureThis);
}
_callDartFunction(callback, bool captureThis, self, List arguments) {
@@ -212,8 +221,7 @@ class JsObject {
*/
factory JsObject.fromBrowserObject(object) {
if (object is num || object is String || object is bool || object == null) {
- throw new ArgumentError(
- "object cannot be a num, string, bool, or null");
+ throw new ArgumentError("object cannot be a num, string, bool, or null");
}
return _wrapToDart(_convertToJS(object));
}
@@ -267,7 +275,7 @@ class JsObject {
*
* The type of [property] must be either [String] or [num].
*/
- dynamic operator[](property) {
+ dynamic operator [](property) {
if (property is! String && property is! num) {
throw new ArgumentError("property is not a String or num");
}
@@ -280,7 +288,7 @@ class JsObject {
*
* The type of [property] must be either [String] or [num].
*/
- operator[]=(property, value) {
+ operator []=(property, value) {
if (property is! String && property is! num) {
throw new ArgumentError("property is not a String or num");
}
@@ -289,8 +297,8 @@ class JsObject {
int get hashCode => 0;
- bool operator==(other) => other is JsObject &&
- JS('bool', '# === #', _jsObject, other._jsObject);
+ bool operator ==(other) =>
+ other is JsObject && JS('bool', '# === #', _jsObject, other._jsObject);
/**
* Returns `true` if the JavaScript object contains the specified property
@@ -332,7 +340,7 @@ class JsObject {
String toString() {
try {
return JS('String', 'String(#)', _jsObject);
- } catch(e) {
+ } catch (e) {
return super.toString();
}
}
@@ -347,7 +355,11 @@ class JsObject {
if (method is! String && method is! num) {
throw new ArgumentError("method is not a String or num");
}
- return _convertToDart(JS('', '#[#].apply(#, #)', _jsObject, method,
+ return _convertToDart(JS(
+ '',
+ '#[#].apply(#, #)',
+ _jsObject,
+ method,
_jsObject,
args == null ? null : new List.from(args.map(_convertToJS))));
}
@@ -357,7 +369,6 @@ class JsObject {
* Proxies a JavaScript Function object.
*/
class JsFunction extends JsObject {
-
/**
* Returns a [JsFunction] that captures its 'this' binding and calls [f]
* with the value of this passed as the first argument.
@@ -373,17 +384,18 @@ class JsFunction extends JsObject {
* Invokes the JavaScript function with arguments [args]. If [thisArg] is
* supplied it is the value of `this` for the invocation.
*/
- dynamic apply(List args, { thisArg }) =>
- _convertToDart(JS('', '#.apply(#, #)', _jsObject,
- _convertToJS(thisArg),
- args == null ? null : new List.from(args.map(_convertToJS))));
+ dynamic apply(List args, {thisArg}) => _convertToDart(JS(
+ '',
+ '#.apply(#, #)',
+ _jsObject,
+ _convertToJS(thisArg),
+ args == null ? null : new List.from(args.map(_convertToJS))));
}
/**
* A [List] that proxies a JavaScript array.
*/
class JsArray<E> extends JsObject with ListMixin<E> {
-
/**
* Creates a new JavaScript array.
*/
@@ -449,8 +461,9 @@ class JsArray<E> extends JsObject with ListMixin<E> {
throw new StateError('Bad JsArray length');
}
- set length(int length) { super['length'] = length; }
-
+ void set length(int length) {
+ super['length'] = length;
+ }
// Methods overriden for better performance
@@ -503,12 +516,11 @@ class JsArray<E> extends JsObject with ListMixin<E> {
// property added to a Dart object referencing its JS-side DartObject proxy
final String _DART_OBJECT_PROPERTY_NAME =
getIsolateAffinityTag(r'_$dart_dartObject');
-final String _DART_CLOSURE_PROPERTY_NAME =
- getIsolateAffinityTag(r'_$dart_dartClosure');
// property added to a JS object referencing its Dart-side JsObject proxy
const _JS_OBJECT_PROPERTY_NAME = r'_$dart_jsObject';
const _JS_FUNCTION_PROPERTY_NAME = r'$dart_jsFunction';
+const _JS_FUNCTION_PROPERTY_NAME_CAPTURE_THIS = r'_$dart_jsFunctionCaptureThis';
bool _defineProperty(o, String name, value) {
try {
@@ -520,9 +532,9 @@ bool _defineProperty(o, String name, value) {
return true;
}
} catch (e) {
- // object is native and lies about being extensible
- // see https://bugzilla.mozilla.org/show_bug.cgi?id=775185
- // Or, isExtensible throws for this object.
+ // object is native and lies about being extensible
+ // see https://bugzilla.mozilla.org/show_bug.cgi?id=775185
+ // Or, isExtensible throws for this object.
}
return false;
}
@@ -555,8 +567,13 @@ dynamic _convertToJS(dynamic o) {
if (o is JsObject) {
return o._jsObject;
}
- if (o is Blob || o is Event || o is KeyRange || o is ImageData || o is Node ||
- o is TypedData || o is Window) {
+ if (o is Blob ||
+ o is Event ||
+ o is KeyRange ||
+ o is ImageData ||
+ o is Node ||
+ o is TypedData ||
+ o is Window) {
return o;
}
if (o is DateTime) {
@@ -566,13 +583,13 @@ dynamic _convertToJS(dynamic o) {
return _getJsProxy(o, _JS_FUNCTION_PROPERTY_NAME, (o) {
var jsFunction = _convertDartFunction(o);
// set a property on the JS closure referencing the Dart closure
- _defineProperty(jsFunction, _DART_CLOSURE_PROPERTY_NAME, o);
+ _defineProperty(jsFunction, DART_CLOSURE_PROPERTY_NAME, o);
return jsFunction;
});
}
var ctor = _dartProxyCtor;
- return _getJsProxy(o, _JS_OBJECT_PROPERTY_NAME,
- (o) => JS('', 'new #(#)', ctor, o));
+ return _getJsProxy(
+ o, _JS_OBJECT_PROPERTY_NAME, (o) => JS('', 'new #(#)', ctor, o));
}
Object _getJsProxy(o, String propertyName, createProxy(o)) {
@@ -592,9 +609,14 @@ Object _convertToDart(o) {
JS('bool', 'typeof # == "number"', o) ||
JS('bool', 'typeof # == "boolean"', o)) {
return o;
- } else if (_isLocalObject(o)
- && (o is Blob || o is Event || o is KeyRange || o is ImageData
- || o is Node || o is TypedData || o is Window)) {
+ } else if (_isLocalObject(o) &&
+ (o is Blob ||
+ o is Event ||
+ o is KeyRange ||
+ o is ImageData ||
+ o is Node ||
+ o is TypedData ||
+ o is Window)) {
// long line: dart2js doesn't allow string concatenation in the JS() form
return JS('Blob|Event|KeyRange|ImageData|Node|TypedData|Window', '#', o);
} else if (JS('bool', '# instanceof Date', o)) {
@@ -609,15 +631,15 @@ Object _convertToDart(o) {
JsObject _wrapToDart(o) {
if (JS('bool', 'typeof # == "function"', o)) {
- return _getDartProxy(o, _DART_CLOSURE_PROPERTY_NAME,
- (o) => new JsFunction._fromJs(o));
+ return _getDartProxy(
+ o, DART_CLOSURE_PROPERTY_NAME, (o) => new JsFunction._fromJs(o));
}
if (JS('bool', '# instanceof Array', o)) {
- return _getDartProxy(o, _DART_OBJECT_PROPERTY_NAME,
- (o) => new JsArray._fromJs(o));
+ return _getDartProxy(
+ o, _DART_OBJECT_PROPERTY_NAME, (o) => new JsArray._fromJs(o));
}
- return _getDartProxy(o, _DART_OBJECT_PROPERTY_NAME,
- (o) => new JsObject._fromJs(o));
+ return _getDartProxy(
+ o, _DART_OBJECT_PROPERTY_NAME, (o) => new JsObject._fromJs(o));
}
Object _getDartProxy(o, String propertyName, createProxy(o)) {
@@ -635,3 +657,72 @@ Object _getDartProxy(o, String propertyName, createProxy(o)) {
}
return dartProxy;
}
+
+// ---------------------------------------------------------------------------
+// Start of methods for new style Dart-JS interop.
+
+_convertDartFunctionFast(Function f) {
+ var existing = JS('', '#.#', f, _JS_FUNCTION_PROPERTY_NAME);
+ if (existing != null) return existing;
+ var ret = JS(
+ '',
+ '''
+ function(_call, f) {
+ return function() {
+ return _call(f, Array.prototype.slice.apply(arguments));
+ }
+ }(#, #)
+ ''',
+ DART_CLOSURE_TO_JS(_callDartFunctionFast),
+ f);
+ JS('', '#.# = #', ret, DART_CLOSURE_PROPERTY_NAME, f);
+ JS('', '#.# = #', f, _JS_FUNCTION_PROPERTY_NAME, ret);
+ return ret;
+}
+
+_convertDartFunctionFastCaptureThis(Function f) {
+ var existing = JS('', '#.#', f, _JS_FUNCTION_PROPERTY_NAME_CAPTURE_THIS);
+ if (existing != null) return existing;
+ var ret = JS(
+ '',
+ '''
+ function(_call, f) {
+ return function() {
+ return _call(f, this,Array.prototype.slice.apply(arguments));
+ }
+ }(#, #)
+ ''',
+ DART_CLOSURE_TO_JS(_callDartFunctionFastCaptureThis),
+ f);
+ JS('', '#.# = #', ret, DART_CLOSURE_PROPERTY_NAME, f);
+ JS('', '#.# = #', f, _JS_FUNCTION_PROPERTY_NAME_CAPTURE_THIS, ret);
+ return ret;
+}
+
+_callDartFunctionFast(callback, List arguments) {
+ return Function.apply(callback, arguments);
+}
+
+_callDartFunctionFastCaptureThis(callback, self, List arguments) {
+ return _convertToJS(Function.apply(callback, [self]..addAll(arguments)));
+}
+
+Function allowInterop(Function f) {
+ if (JS('bool', 'typeof(#) == "function"', f)) {
+ // Already supports interop, just use the existing function.
+ return f;
+ } else {
+ return _convertDartFunctionFast(f);
+ }
+}
+
+Function allowInteropCaptureThis(Function f) {
+ if (JS('bool', 'typeof(#) == "function"', f)) {
+ // Behavior when the function is already a JS function is unspecified.
+ throw new ArgumentError(
+ "Function is already a JS function so cannot capture this.");
+ return f;
+ } else {
+ return _convertDartFunctionFastCaptureThis(f);
+ }
+}
« no previous file with comments | « sdk/lib/_internal/js_runtime/lib/interceptors.dart ('k') | tests/compiler/dart2js/mock_libraries.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698