| 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 {
|
|
|