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:_js_embedded_names' show | 7 import 'dart:_js_embedded_names' show |
8 GET_TYPE_FROM_NAME, | 8 GET_TYPE_FROM_NAME, |
9 GET_ISOLATE_TAG, | 9 GET_ISOLATE_TAG, |
10 INTERCEPTED_NAMES, | 10 INTERCEPTED_NAMES, |
(...skipping 1025 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1036 | 1036 |
1037 return function.noSuchMethod( | 1037 return function.noSuchMethod( |
1038 createUnmangledInvocationMirror( | 1038 createUnmangledInvocationMirror( |
1039 #call, | 1039 #call, |
1040 selectorName, | 1040 selectorName, |
1041 JSInvocationMirror.METHOD, | 1041 JSInvocationMirror.METHOD, |
1042 arguments, | 1042 arguments, |
1043 namedArgumentList)); | 1043 namedArgumentList)); |
1044 } | 1044 } |
1045 | 1045 |
| 1046 static applyFunctionNewEmitter(Function function, |
| 1047 List positionalArguments, |
| 1048 Map<String, dynamic> namedArguments) { |
| 1049 if (namedArguments == null) { |
| 1050 int requiredParameterCount = JS('int', r'#[#]', function, |
| 1051 JS_GET_NAME("REQUIRED_PARAMETER_PROPERTY")); |
| 1052 int argumentCount = positionalArguments.length; |
| 1053 if (argumentCount < requiredParameterCount) { |
| 1054 return functionNoSuchMethod(function, positionalArguments, null); |
| 1055 } |
| 1056 String selectorName = '${JS_GET_NAME("CALL_PREFIX")}\$$argumentCount'; |
| 1057 var jsStub = JS('var', r'#[#]', function, selectorName); |
| 1058 if (jsStub == null) { |
| 1059 // Do a dynamic call. |
| 1060 var interceptor = getInterceptor(function); |
| 1061 var jsFunction = JS('', '#[#]', interceptor, |
| 1062 JS_GET_NAME('CALL_CATCH_ALL')); |
| 1063 var defaultValues = JS('var', r'#[#]', function, |
| 1064 JS_GET_NAME("DEFAULT_VALUES_PROPERTY")); |
| 1065 if (!JS('bool', '# instanceof Array', defaultValues)) { |
| 1066 // The function expects named arguments! |
| 1067 return functionNoSuchMethod(function, positionalArguments, null); |
| 1068 } |
| 1069 int defaultsLength = JS('int', "#.length", defaultValues); |
| 1070 int maxArguments = requiredParameterCount + defaultsLength; |
| 1071 if (argumentCount > maxArguments) { |
| 1072 // The function expects less arguments! |
| 1073 return functionNoSuchMethod(function, positionalArguments, null); |
| 1074 } |
| 1075 List arguments = new List.from(positionalArguments); |
| 1076 List missingDefaults = JS('JSArray', '#.slice(#)', defaultValues, |
| 1077 argumentCount - requiredParameterCount); |
| 1078 arguments.addAll(missingDefaults); |
| 1079 return JS('var', '#.apply(#, #)', jsFunction, function, arguments); |
| 1080 } |
| 1081 return JS('var', '#.apply(#, #)', jsStub, function, positionalArguments); |
| 1082 } else { |
| 1083 var interceptor = getInterceptor(function); |
| 1084 var jsFunction = JS('', '#[#]', interceptor, |
| 1085 JS_GET_NAME('CALL_CATCH_ALL')); |
| 1086 var defaultValues = JS('JSArray', r'#[#]', function, |
| 1087 JS_GET_NAME("DEFAULT_VALUES_PROPERTY")); |
| 1088 List keys = JS('JSArray', r'Object.keys(#)', defaultValues); |
| 1089 List arguments = new List.from(positionalArguments); |
| 1090 int used = 0; |
| 1091 for (String key in keys) { |
| 1092 var value = namedArguments[key]; |
| 1093 if (value != null) { |
| 1094 used++; |
| 1095 arguments.add(value); |
| 1096 } else { |
| 1097 arguments.add(JS('var', r'#[#]', defaultValues, key)); |
| 1098 } |
| 1099 } |
| 1100 if (used != namedArguments.length) { |
| 1101 return functionNoSuchMethod(function, positionalArguments, |
| 1102 namedArguments); |
| 1103 } |
| 1104 return JS('var', r'#.apply(#, #)', jsFunction, function, arguments); |
| 1105 } |
| 1106 } |
| 1107 |
1046 static applyFunction(Function function, | 1108 static applyFunction(Function function, |
1047 List positionalArguments, | 1109 List positionalArguments, |
1048 Map<String, dynamic> namedArguments) { | 1110 Map<String, dynamic> namedArguments) { |
1049 // Dispatch on presence of named arguments to improve tree-shaking. | 1111 // Dispatch on presence of named arguments to improve tree-shaking. |
1050 // | 1112 // |
1051 // This dispatch is as simple as possible to help the compiler detect the | 1113 // This dispatch is as simple as possible to help the compiler detect the |
1052 // common case of `null` namedArguments, either via inlining or | 1114 // common case of `null` namedArguments, either via inlining or |
1053 // specialization. | 1115 // specialization. |
1054 return namedArguments == null | 1116 return namedArguments == null |
1055 ? applyFunctionWithPositionalArguments( | 1117 ? applyFunctionWithPositionalArguments( |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1092 static applyFunctionWithNamedArguments(Function function, | 1154 static applyFunctionWithNamedArguments(Function function, |
1093 List positionalArguments, | 1155 List positionalArguments, |
1094 Map<String, dynamic> namedArguments) { | 1156 Map<String, dynamic> namedArguments) { |
1095 if (namedArguments.isEmpty) { | 1157 if (namedArguments.isEmpty) { |
1096 return applyFunctionWithPositionalArguments( | 1158 return applyFunctionWithPositionalArguments( |
1097 function, positionalArguments); | 1159 function, positionalArguments); |
1098 } | 1160 } |
1099 // TODO(ahe): The following code can be shared with | 1161 // TODO(ahe): The following code can be shared with |
1100 // JsInstanceMirror.invoke. | 1162 // JsInstanceMirror.invoke. |
1101 var interceptor = getInterceptor(function); | 1163 var interceptor = getInterceptor(function); |
1102 var jsFunction = JS('', '#["call*"]', interceptor); | 1164 var jsFunction = JS('', '#[#]', interceptor, JS_GET_NAME('CALL_CATCH_ALL')); |
1103 | 1165 |
1104 if (jsFunction == null) { | 1166 if (jsFunction == null) { |
1105 return functionNoSuchMethod( | 1167 return functionNoSuchMethod( |
1106 function, positionalArguments, namedArguments); | 1168 function, positionalArguments, namedArguments); |
1107 } | 1169 } |
1108 ReflectionInfo info = new ReflectionInfo(jsFunction); | 1170 ReflectionInfo info = new ReflectionInfo(jsFunction); |
1109 if (info == null || !info.areOptionalParametersNamed) { | 1171 if (info == null || !info.areOptionalParametersNamed) { |
1110 return functionNoSuchMethod( | 1172 return functionNoSuchMethod( |
1111 function, positionalArguments, namedArguments); | 1173 function, positionalArguments, namedArguments); |
1112 } | 1174 } |
(...skipping 863 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1976 jsArguments, | 2038 jsArguments, |
1977 String propertyName) { | 2039 String propertyName) { |
1978 JS_EFFECT(() { | 2040 JS_EFFECT(() { |
1979 BoundClosure.receiverOf(JS('BoundClosure', 'void 0')); | 2041 BoundClosure.receiverOf(JS('BoundClosure', 'void 0')); |
1980 BoundClosure.selfOf(JS('BoundClosure', 'void 0')); | 2042 BoundClosure.selfOf(JS('BoundClosure', 'void 0')); |
1981 }); | 2043 }); |
1982 // TODO(ahe): All the place below using \$ should be rewritten to go | 2044 // TODO(ahe): All the place below using \$ should be rewritten to go |
1983 // through the namer. | 2045 // through the namer. |
1984 var function = JS('', '#[#]', functions, 0); | 2046 var function = JS('', '#[#]', functions, 0); |
1985 String name = JS('String|Null', '#.\$stubName', function); | 2047 String name = JS('String|Null', '#.\$stubName', function); |
1986 String callName = JS('String|Null', '#.\$callName', function); | 2048 String callName = JS('String|Null', '#[#]', function, |
| 2049 JS_GET_NAME("CALL_NAME_PROPERTY")); |
1987 | 2050 |
1988 var functionType; | 2051 var functionType; |
1989 if (reflectionInfo is List) { | 2052 if (reflectionInfo is List) { |
1990 JS('', '#.\$reflectionInfo = #', function, reflectionInfo); | 2053 JS('', '#.\$reflectionInfo = #', function, reflectionInfo); |
1991 ReflectionInfo info = new ReflectionInfo(function); | 2054 ReflectionInfo info = new ReflectionInfo(function); |
1992 functionType = info.functionType; | 2055 functionType = info.functionType; |
1993 } else { | 2056 } else { |
1994 functionType = reflectionInfo; | 2057 functionType = reflectionInfo; |
1995 } | 2058 } |
1996 | 2059 |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2078 '}(#,#)', functionType, getReceiver); | 2141 '}(#,#)', functionType, getReceiver); |
2079 } else { | 2142 } else { |
2080 throw 'Error in reflectionInfo.'; | 2143 throw 'Error in reflectionInfo.'; |
2081 } | 2144 } |
2082 | 2145 |
2083 JS('', '#[#] = #', prototype, JS_SIGNATURE_NAME(), signatureFunction); | 2146 JS('', '#[#] = #', prototype, JS_SIGNATURE_NAME(), signatureFunction); |
2084 | 2147 |
2085 JS('', '#[#] = #', prototype, callName, trampoline); | 2148 JS('', '#[#] = #', prototype, callName, trampoline); |
2086 for (int i = 1; i < functions.length; i++) { | 2149 for (int i = 1; i < functions.length; i++) { |
2087 var stub = functions[i]; | 2150 var stub = functions[i]; |
2088 var stubCallName = JS('String|Null', '#.\$callName', stub); | 2151 var stubCallName = JS('String|Null', '#[#]', stub, |
| 2152 JS_GET_NAME("CALL_NAME_PROPERTY")); |
2089 if (stubCallName != null) { | 2153 if (stubCallName != null) { |
2090 JS('', '#[#] = #', prototype, stubCallName, | 2154 JS('', '#[#] = #', prototype, stubCallName, |
2091 isStatic ? stub : forwardCallTo(receiver, stub, isIntercepted)); | 2155 isStatic ? stub : forwardCallTo(receiver, stub, isIntercepted)); |
2092 } | 2156 } |
2093 } | 2157 } |
2094 | 2158 |
2095 JS('', '#["call*"] = #', prototype, trampoline); | 2159 JS('', '#[#] = #', prototype, JS_GET_NAME('CALL_CATCH_ALL'), trampoline); |
| 2160 String reqArgProperty = JS_GET_NAME("REQUIRED_PARAMETER_PROPERTY"); |
| 2161 String defValProperty = JS_GET_NAME("DEFAULT_VALUES_PROPERTY"); |
| 2162 JS('', '#.# = #.#', prototype, reqArgProperty, function, reqArgProperty); |
| 2163 JS('', '#.# = #.#', prototype, defValProperty, function, defValProperty); |
2096 | 2164 |
2097 return constructor; | 2165 return constructor; |
2098 } | 2166 } |
2099 | 2167 |
2100 static cspForwardCall(int arity, bool isSuperCall, String stubName, | 2168 static cspForwardCall(int arity, bool isSuperCall, String stubName, |
2101 function) { | 2169 function) { |
2102 var getSelf = RAW_DART_FUNCTION_REF(BoundClosure.selfOf); | 2170 var getSelf = RAW_DART_FUNCTION_REF(BoundClosure.selfOf); |
2103 // Handle intercepted stub-names with the default slow case. | 2171 // Handle intercepted stub-names with the default slow case. |
2104 if (isSuperCall) arity = -1; | 2172 if (isSuperCall) arity = -1; |
2105 switch (arity) { | 2173 switch (arity) { |
(...skipping 1614 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3720 // This is a function that will return a helper function that does the | 3788 // This is a function that will return a helper function that does the |
3721 // iteration of the sync*. | 3789 // iteration of the sync*. |
3722 // | 3790 // |
3723 // Each invocation should give a helper with fresh state. | 3791 // Each invocation should give a helper with fresh state. |
3724 final dynamic /* js function */ _outerHelper; | 3792 final dynamic /* js function */ _outerHelper; |
3725 | 3793 |
3726 SyncStarIterable(this._outerHelper); | 3794 SyncStarIterable(this._outerHelper); |
3727 | 3795 |
3728 Iterator get iterator => new SyncStarIterator(JS('', '#()', _outerHelper)); | 3796 Iterator get iterator => new SyncStarIterator(JS('', '#()', _outerHelper)); |
3729 } | 3797 } |
OLD | NEW |