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

Unified Diff: dart/sdk/lib/_internal/lib/js_helper.dart

Issue 27524003: Generate tear-off closures dynamically. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 7 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
Index: dart/sdk/lib/_internal/lib/js_helper.dart
diff --git a/dart/sdk/lib/_internal/lib/js_helper.dart b/dart/sdk/lib/_internal/lib/js_helper.dart
index e346734f1b13f6f0b4f5e06622b5d618d70c3138..21789e2a792dd3a1e8514be2429ce07d9befc3da 100644
--- a/dart/sdk/lib/_internal/lib/js_helper.dart
+++ b/dart/sdk/lib/_internal/lib/js_helper.dart
@@ -1553,9 +1553,70 @@ convertDartClosureToJS(closure, int arity) {
* Super class for Dart closures.
*/
class Closure implements Function {
+ // TODO(ahe): These constants must be in sync with
+ // reflection_data_parser.dart.
+ static const FUNCTION_INDEX = 0;
+ static const NAME_INDEX = 1;
+ static const CALL_NAME_INDEX = 2;
+ static const REQUIRED_PARAMETER_INDEX = 3;
+ static const OPTIONAL_PARAMETER_INDEX = 4;
+ static const DEFAULT_ARGUMENTS_INDEX = 5;
+
+ Closure();
+
+ /**
+ * Creates a closure for use by implicit getters associated with a method.
+ *
+ * In other words, creates a tear-off closure.
+ *
+ * Called from [closureFromTearOff] as well as from reflection when tearing
+ * of a method via [:getField:].
+ *
+ * This method assumes that [array] was created by
+ * [dart2js.js_emitter.ContainerBuilder.addMemberMethod].
+ */
+ factory Closure.fromTearOff(receiver, List array, bool isStatic) {
+ var function = array[FUNCTION_INDEX];
+ String name = array[NAME_INDEX];
+ String callName = array[CALL_NAME_INDEX];
+ int requiredParameterCount = array[REQUIRED_PARAMETER_INDEX] - 1;
+ bool isReflectable = requiredParameterCount != -1;
+ int optionalParameterCount = array[OPTIONAL_PARAMETER_INDEX];
+ int index = DEFAULT_ARGUMENTS_INDEX + optionalParameterCount;
+
+ // Create a closure and "monkey" patch it with call stubs.
+ Closure closure = new Closure();
+ JS('', '#[#] = #', closure, callName,
+ isStatic ? function : forwardTo(receiver, function));
+ while (index < array.length) {
+ if (!JS('bool', 'typeof # == "function"', array[index])) break;
+ var stub = array[index++];
+ var stubName = array[index++];
+ var stubCallName = array[index++];
+ JS('', '#[#] = #', closure, stubCallName,
+ isStatic ? stub : forwardTo(receiver, stub));
+ }
+
+ return closure;
+ }
+
+ static forwardTo(receiver, function) {
+ return JS(
+ '',
+ 'function(r,f){return function(){return f.apply(r,arguments)}}(#,#)',
+ receiver, function);
+ }
+
String toString() => "Closure";
}
+/// Called from implicit method getter (aka tear-off).
+Closure closureFromTearOff(receiver, jsArray, isStatic) {
+ return new Closure.fromTearOff(
+ receiver, JS('JSExtendableArray', '#', jsArray),
+ JS('bool', '!!#', isStatic));
+}
+
/// Represents a 'tear-off' closure, that is an instance method bound
/// to a specific receiver (instance).
class BoundClosure extends Closure {

Powered by Google App Engine
This is Rietveld 408576698