| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 library _js_helper; | 5 library _js_helper; |
| 6 | 6 |
| 7 import 'dart:collection'; | 7 import 'dart:collection'; |
| 8 | 8 |
| 9 import 'dart:_foreign_helper' show | 9 import 'dart:_foreign_helper' show |
| 10 DART_CLOSURE_TO_JS, | 10 DART_CLOSURE_TO_JS, |
| (...skipping 348 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 359 final int optionalParameterCount; | 359 final int optionalParameterCount; |
| 360 | 360 |
| 361 /// Are optional parameters named. | 361 /// Are optional parameters named. |
| 362 final bool areOptionalParametersNamed; | 362 final bool areOptionalParametersNamed; |
| 363 | 363 |
| 364 /// Either an index to the function type in [:init.metadata:] or a JavaScript | 364 /// Either an index to the function type in [:init.metadata:] or a JavaScript |
| 365 /// function object which can compute such a type (presumably due to free | 365 /// function object which can compute such a type (presumably due to free |
| 366 /// type variables). | 366 /// type variables). |
| 367 final functionType; | 367 final functionType; |
| 368 | 368 |
| 369 List cachedSortedIndices; | |
| 370 | |
| 371 ReflectionInfo.internal(this.jsFunction, | 369 ReflectionInfo.internal(this.jsFunction, |
| 372 this.data, | 370 this.data, |
| 373 this.isAccessor, | 371 this.isAccessor, |
| 374 this.requiredParameterCount, | 372 this.requiredParameterCount, |
| 375 this.optionalParameterCount, | 373 this.optionalParameterCount, |
| 376 this.areOptionalParametersNamed, | 374 this.areOptionalParametersNamed, |
| 377 this.functionType); | 375 this.functionType); |
| 378 | 376 |
| 379 factory ReflectionInfo(jsFunction) { | 377 factory ReflectionInfo(jsFunction) { |
| 380 List data = JS('JSExtendableArray|Null', r'#.$reflectionInfo', jsFunction); | 378 List data = JS('JSExtendableArray|Null', r'#.$reflectionInfo', jsFunction); |
| (...skipping 26 matching lines...) Expand all Loading... |
| 407 return JS('', '#[2 * # + # + # + 1]', data, parameter, | 405 return JS('', '#[2 * # + # + # + 1]', data, parameter, |
| 408 optionalParameterCount, FIRST_DEFAULT_ARGUMENT); | 406 optionalParameterCount, FIRST_DEFAULT_ARGUMENT); |
| 409 } | 407 } |
| 410 | 408 |
| 411 int defaultValue(int parameter) { | 409 int defaultValue(int parameter) { |
| 412 if (parameter < requiredParameterCount) return null; | 410 if (parameter < requiredParameterCount) return null; |
| 413 return JS('int', '#[# + # - #]', data, | 411 return JS('int', '#[# + # - #]', data, |
| 414 FIRST_DEFAULT_ARGUMENT, parameter, requiredParameterCount); | 412 FIRST_DEFAULT_ARGUMENT, parameter, requiredParameterCount); |
| 415 } | 413 } |
| 416 | 414 |
| 417 /// Returns the default value of the [parameter]th entry of the list of | |
| 418 /// parameters sorted by name. | |
| 419 int defaultValueInOrder(int parameter) { | |
| 420 if (parameter < requiredParameterCount) return null; | |
| 421 | |
| 422 if (!areOptionalParametersNamed || optionalParameterCount == 1) { | |
| 423 return defaultValue(parameter); | |
| 424 } | |
| 425 | |
| 426 int index = sortedIndex(parameter - requiredParameterCount); | |
| 427 return defaultValue(index); | |
| 428 } | |
| 429 | |
| 430 /// Returns the default value of the [parameter]th entry of the list of | |
| 431 /// parameters sorted by name. | |
| 432 String parameterNameInOrder(int parameter) { | |
| 433 if (parameter < requiredParameterCount) return null; | |
| 434 | |
| 435 if (!areOptionalParametersNamed || | |
| 436 optionalParameterCount == 1) { | |
| 437 return parameterName(parameter); | |
| 438 } | |
| 439 | |
| 440 int index = sortedIndex(parameter - requiredParameterCount); | |
| 441 return parameterName(index); | |
| 442 } | |
| 443 | |
| 444 /// Computes the index of the parameter in the list of named parameters sorted | |
| 445 /// by their name. | |
| 446 int sortedIndex(int unsortedIndex) { | |
| 447 if (cachedSortedIndices == null) { | |
| 448 // TODO(karlklose): cache this between [ReflectionInfo] instances or cache | |
| 449 // [ReflectionInfo] instances by [jsFunction]. | |
| 450 cachedSortedIndices = new List(optionalParameterCount); | |
| 451 Map<String, int> positions = <String, int>{}; | |
| 452 for (int i = 0; i < optionalParameterCount; i++) { | |
| 453 int index = requiredParameterCount + i; | |
| 454 positions[parameterName(index)] = index; | |
| 455 } | |
| 456 int index = 0; | |
| 457 (positions.keys.toList()..sort()).forEach((String name) { | |
| 458 cachedSortedIndices[index++] = positions[name] + requiredParameterCount; | |
| 459 }); | |
| 460 } | |
| 461 return cachedSortedIndices[unsortedIndex]; | |
| 462 } | |
| 463 | |
| 464 @NoInline() | 415 @NoInline() |
| 465 computeFunctionRti(jsConstructor) { | 416 computeFunctionRti(jsConstructor) { |
| 466 if (JS('bool', 'typeof # == "number"', functionType)) { | 417 if (JS('bool', 'typeof # == "number"', functionType)) { |
| 467 return getMetadata(functionType); | 418 return getMetadata(functionType); |
| 468 } else if (JS('bool', 'typeof # == "function"', functionType)) { | 419 } else if (JS('bool', 'typeof # == "function"', functionType)) { |
| 469 var fakeInstance = JS('', 'new #()', jsConstructor); | 420 var fakeInstance = JS('', 'new #()', jsConstructor); |
| 470 setRuntimeTypeInfo( | 421 setRuntimeTypeInfo( |
| 471 fakeInstance, JS('JSExtendableArray', '#["<>"]', fakeInstance)); | 422 fakeInstance, JS('JSExtendableArray', '#["<>"]', fakeInstance)); |
| 472 return JS('=Object|Null', r'#.apply({$receiver:#})', | 423 return JS('=Object|Null', r'#.apply({$receiver:#})', |
| 473 functionType, fakeInstance); | 424 functionType, fakeInstance); |
| (...skipping 491 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 965 } else { | 916 } else { |
| 966 positionalArguments = []; | 917 positionalArguments = []; |
| 967 } | 918 } |
| 968 // Check the number of positional arguments is valid. | 919 // Check the number of positional arguments is valid. |
| 969 if (info.requiredParameterCount != positionalArguments.length) { | 920 if (info.requiredParameterCount != positionalArguments.length) { |
| 970 return functionNoSuchMethod( | 921 return functionNoSuchMethod( |
| 971 function, positionalArguments, namedArguments); | 922 function, positionalArguments, namedArguments); |
| 972 } | 923 } |
| 973 var defaultArguments = new Map(); | 924 var defaultArguments = new Map(); |
| 974 for (int i = 0; i < info.optionalParameterCount; i++) { | 925 for (int i = 0; i < info.optionalParameterCount; i++) { |
| 975 int index = i + info.requiredParameterCount; | 926 var parameterName = info.parameterName(i + info.requiredParameterCount); |
| 976 var parameterName = info.parameterNameInOrder(index); | 927 var defaultValue = |
| 977 var value = info.defaultValueInOrder(index); | 928 getMetadata(info.defaultValue(i + info.requiredParameterCount)); |
| 978 var defaultValue = getMetadata(value); | |
| 979 defaultArguments[parameterName] = defaultValue; | 929 defaultArguments[parameterName] = defaultValue; |
| 980 } | 930 } |
| 981 bool bad = false; | 931 bool bad = false; |
| 982 namedArguments.forEach((String parameter, value) { | 932 namedArguments.forEach((String parameter, value) { |
| 983 if (defaultArguments.containsKey(parameter)) { | 933 if (defaultArguments.containsKey(parameter)) { |
| 984 defaultArguments[parameter] = value; | 934 defaultArguments[parameter] = value; |
| 985 } else { | 935 } else { |
| 986 // Extraneous named argument. | 936 // Extraneous named argument. |
| 987 bad = true; | 937 bad = true; |
| 988 } | 938 } |
| (...skipping 2122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3111 * Returns a property name for placing data on JavaScript objects shared between | 3061 * Returns a property name for placing data on JavaScript objects shared between |
| 3112 * DOM isolates. This happens when multiple programs are loaded in the same | 3062 * DOM isolates. This happens when multiple programs are loaded in the same |
| 3113 * JavaScript context (i.e. page). The name is based on [name] but with an | 3063 * JavaScript context (i.e. page). The name is based on [name] but with an |
| 3114 * additional part that is unique for each isolate. | 3064 * additional part that is unique for each isolate. |
| 3115 * | 3065 * |
| 3116 * The form of the name is '___dart_$name_$id'. | 3066 * The form of the name is '___dart_$name_$id'. |
| 3117 */ | 3067 */ |
| 3118 String getIsolateAffinityTag(String name) { | 3068 String getIsolateAffinityTag(String name) { |
| 3119 return JS('String', 'init.getIsolateTag(#)', name); | 3069 return JS('String', 'init.getIsolateTag(#)', name); |
| 3120 } | 3070 } |
| OLD | NEW |