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

Side by Side Diff: dart/sdk/lib/_internal/lib/js_helper.dart

Issue 57773002: Repro for OOM bug in test.dart (applies to r29345). (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 7 years, 1 month 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 import 'dart:_foreign_helper' show DART_CLOSURE_TO_JS, 8 import 'dart:_foreign_helper' show DART_CLOSURE_TO_JS,
9 JS, 9 JS,
10 JS_CALL_IN_ISOLATE, 10 JS_CALL_IN_ISOLATE,
(...skipping 13 matching lines...) Expand all
24 JS_OBJECT_CLASS_NAME, 24 JS_OBJECT_CLASS_NAME,
25 JS_NULL_CLASS_NAME, 25 JS_NULL_CLASS_NAME,
26 JS_OPERATOR_AS_PREFIX, 26 JS_OPERATOR_AS_PREFIX,
27 JS_OPERATOR_IS_PREFIX, 27 JS_OPERATOR_IS_PREFIX,
28 JS_SIGNATURE_NAME, 28 JS_SIGNATURE_NAME,
29 RAW_DART_FUNCTION_REF; 29 RAW_DART_FUNCTION_REF;
30 import 'dart:_interceptors'; 30 import 'dart:_interceptors';
31 import 'dart:_collection-dev' as _symbol_dev; 31 import 'dart:_collection-dev' as _symbol_dev;
32 32
33 import 'dart:_js_names' show 33 import 'dart:_js_names' show
34 extractKeys,
34 mangledNames, 35 mangledNames,
35 unmangleGlobalNameIfPreservedAnyways; 36 unmangleGlobalNameIfPreservedAnyways;
36 37
37 part 'constant_map.dart'; 38 part 'constant_map.dart';
38 part 'native_helper.dart'; 39 part 'native_helper.dart';
39 part 'regexp_helper.dart'; 40 part 'regexp_helper.dart';
40 part 'string_helper.dart'; 41 part 'string_helper.dart';
41 part 'js_rti.dart'; 42 part 'js_rti.dart';
42 43
43 bool isJsIndexable(var object, var record) { 44 bool isJsIndexable(var object, var record) {
(...skipping 230 matching lines...) Expand 10 before | Expand all | Expand 10 after
274 int hash = JS('int|Null', r'#.$identityHash', object); 275 int hash = JS('int|Null', r'#.$identityHash', object);
275 if (hash == null) { 276 if (hash == null) {
276 hash = JS('int', '(Math.random() * 0x3fffffff) | 0'); 277 hash = JS('int', '(Math.random() * 0x3fffffff) | 0');
277 JS('void', r'#.$identityHash = #', object, hash); 278 JS('void', r'#.$identityHash = #', object, hash);
278 } 279 }
279 return JS('int', '#', hash); 280 return JS('int', '#', hash);
280 } 281 }
281 282
282 static computeGlobalThis() => JS('', 'function() { return this; }()'); 283 static computeGlobalThis() => JS('', 'function() { return this; }()');
283 284
285 /**
286 * This is the low-level method that is used to implement
287 * [print]. It is possible to override this function from JavaScript
288 * by defining a function in JavaScript called "dartPrint".
289 */
290 static void printString(String string) {
291 if (JS('bool', r'typeof dartPrint == "function"')) {
292 // Support overriding print from JavaScript.
293 JS('void', r'dartPrint(#)', string);
294 return;
295 }
296
297 // Inside browser or nodejs.
298 if (JS('bool', r'typeof console == "object"') &&
299 JS('bool', r'typeof console.log == "function"')) {
300 JS('void', r'console.log(#)', string);
301 return;
302 }
303
304 // Don't throw inside IE, the console is only defined if dev tools is open.
305 if (JS('bool', r'typeof window == "object"')) {
306 return;
307 }
308
309 // Running in d8, the V8 developer shell, or in Firefox' js-shell.
310 if (JS('bool', r'typeof print == "function"')) {
311 JS('void', r'print(#)', string);
312 return;
313 }
314
315 // This is somewhat nasty, but we don't want to drag in a bunch of
316 // dependencies to handle a situation that cannot happen. So we
317 // avoid using Dart [:throw:] and Dart [toString].
318 JS('void', 'throw "Unable to print message: " + String(#)', string);
319 }
320
284 static _throwFormatException(String string) { 321 static _throwFormatException(String string) {
285 throw new FormatException(string); 322 throw new FormatException(string);
286 } 323 }
287 324
288 static int parseInt(String source, 325 static int parseInt(String source,
289 int radix, 326 int radix,
290 int handleError(String source)) { 327 int handleError(String source)) {
291 if (handleError == null) handleError = _throwFormatException; 328 if (handleError == null) handleError = _throwFormatException;
292 329
293 checkString(source); 330 checkString(source);
(...skipping 1705 matching lines...) Expand 10 before | Expand all | Expand 10 after
1999 } 2036 }
2000 2037
2001 /** 2038 /**
2002 * Error thrown when a runtime error occurs. 2039 * Error thrown when a runtime error occurs.
2003 */ 2040 */
2004 class RuntimeError extends Error { 2041 class RuntimeError extends Error {
2005 final message; 2042 final message;
2006 RuntimeError(this.message); 2043 RuntimeError(this.message);
2007 String toString() => "RuntimeError: $message"; 2044 String toString() => "RuntimeError: $message";
2008 } 2045 }
2046
2047 abstract class RuntimeType {
2048 const RuntimeType();
2049
2050 bool isTest(expression);
2051
2052 toRti();
2053 }
2054
2055 // TODO(ahe): Remove this class.
2056 class DummyRuntimeType extends RuntimeType {
2057 final String impl;
2058
2059 DummyRuntimeType(this.impl);
2060
2061 bool isTest(expression) {
2062 throw "<<is-test with '$impl' not implemented>>";
2063 }
2064
2065 String toString() => 'DummyRuntimeType($impl)';
2066 }
2067
2068 // TODO(ahe): Delete this method.
2069 DummyRuntimeType buildDummyType(String impl) => new DummyRuntimeType(impl);
2070
2071 class RuntimeFunctionType extends RuntimeType {
2072 final RuntimeType returnType;
2073 final List<RuntimeType> parameterTypes;
2074 final List<RuntimeType> optionalParameterTypes;
2075 final namedParameters;
2076
2077 static var /* bool */ inAssert = false;
2078
2079 RuntimeFunctionType(this.returnType,
2080 this.parameterTypes,
2081 this.optionalParameterTypes,
2082 this.namedParameters);
2083
2084 // TODO(ahe): Implement this.
2085 bool get isVoid => returnType is VoidRuntimeType;
2086
2087 /// Called from generated code. [expression] is a Dart object and this method
2088 /// returns true if [this] is a supertype of [expression].
2089 bool _isTest(expression) {
2090 // Type inferrer don't think this is called with dynamic arguments.
2091 expression = JS('', '#', expression);
2092
2093 var interceptor = getInterceptor(expression);
2094 if (!JS('bool', '# in #', JS_SIGNATURE_NAME(), interceptor)) return false;
2095 var functionTypeObject = JS('', '#[#]()', interceptor, JS_SIGNATURE_NAME());
2096 bool result = isFunctionSubtype(functionTypeObject, toRti());
2097
2098 // DEBUG REMOVE
2099 var pretty = new FunctionTypeInfoDecoderRing(functionTypeObject).toString();
2100 var self = new FunctionTypeInfoDecoderRing(toRti()).toString();
2101 Primitives.printString("<<$pretty is $this (${self}) [$result]>>");
2102
2103 return result;
2104 }
2105
2106 _asCheck(expression) {
2107 // Type inferrer don't think this is called with dynamic arguments.
2108 return _check(JS('', '#', expression), true);
2109 }
2110
2111 _assertCheck(expression) {
2112 if (inAssert) return;
2113 inAssert = true; // Don't try to check this library itself.
2114 try {
2115 // Type inferrer don't think this is called with dynamic arguments.
2116 return _check(JS('', '#', expression), false);
2117 } finally {
2118 inAssert = false;
2119 }
2120 }
2121
2122 _check(expression, bool isCast) {
2123 if (expression == null) return null;
2124 if (_isTest(expression)) return expression;
2125
2126 var self = new FunctionTypeInfoDecoderRing(toRti()).toString();
2127 if (isCast) {
2128 var interceptor = getInterceptor(expression);
2129 var pretty;
2130 if (JS('bool', '# in #', JS_SIGNATURE_NAME(), interceptor)) {
2131 var functionTypeObject =
2132 JS('', '#[#]()', interceptor, JS_SIGNATURE_NAME());
2133 pretty = new FunctionTypeInfoDecoderRing(functionTypeObject).toString();
2134 } else {
2135 pretty = Primitives.objectTypeName(expression);
2136 }
2137 throw new CastErrorImplementation(pretty, self);
2138 } else {
2139 // TODO(ahe): Pass "pretty" function-type to TypeErrorImplementation?
2140 throw new TypeErrorImplementation(expression, self);
2141 }
2142 }
2143
2144 toRti() {
2145 var result = JS('=Object', '{ #: "dynafunc" }', JS_FUNCTION_TYPE_TAG());
2146 if (isVoid) {
2147 JS('', '#[#] = true', result, JS_FUNCTION_TYPE_VOID_RETURN_TAG());
2148 } else {
2149 if (returnType is! DynamicRuntimeType) {
2150 JS('', '#[#] = #', result, JS_FUNCTION_TYPE_RETURN_TYPE_TAG(),
2151 returnType.toRti());
2152 }
2153 }
2154 if (parameterTypes.length > 0) {
2155 JS('', '#[#] = #', result, JS_FUNCTION_TYPE_REQUIRED_PARAMETERS_TAG(),
2156 listToRti(parameterTypes));
2157 }
2158
2159 if (optionalParameterTypes != null && !optionalParameterTypes.isEmpty) {
2160 JS('', '#[#] = #', result, JS_FUNCTION_TYPE_OPTIONAL_PARAMETERS_TAG(),
2161 listToRti(optionalParameterTypes));
2162 }
2163
2164 if (namedParameters != null) {
2165 var namedRti = JS('=Object', '{}');
2166 for (var name in extractKeys(namedParameters)) {
2167 var rti = JS('', '#[#]', namedParameters, name).toRti();
2168 JS('', '#[#] = #', namedRti, name, rti);
2169 }
2170 JS('', '#[#] = #', result, JS_FUNCTION_TYPE_NAMED_PARAMETERS_TAG(),
2171 namedRti);
2172 }
2173
2174 return result;
2175 }
2176
2177 static listToRti(list) {
2178 list = JS('JSFixedArray', '#', list);
2179 var result = JS('JSExtendableArray', '[]');
2180 for (var i = 0; i < list.length; i++) {
2181 JS('', '#.push(#)', result, list[i].toRti());
2182 }
2183 return result;
2184 }
2185
2186 String toString() {
2187 String result = '(';
2188 bool needsComma = false;
2189 for (RuntimeType type in parameterTypes) {
2190 if (needsComma) result += ', ';
2191 result += '$type';
2192 needsComma = true;
2193 }
2194 if (optionalParameterTypes != null && !optionalParameterTypes.isEmpty) {
2195 if (needsComma) result += ', ';
2196 needsComma = false;
2197 result += '[';
2198 for (RuntimeType type in optionalParameterTypes) {
2199 if (needsComma) result += ', ';
2200 result += '$type';
2201 needsComma = true;
2202 }
2203 result += ']';
2204 }
2205 result += ') -> $returnType';
2206 return result;
2207 }
2208 }
2209
2210 RuntimeFunctionType buildFunctionType(RuntimeType returnType,
2211 List parameterTypes,
2212 List optionalParameterTypes) {
2213 return new RuntimeFunctionType(
2214 returnType, parameterTypes, optionalParameterTypes, null);
2215 }
2216
2217 RuntimeFunctionType buildNamedFunctionType(RuntimeType returnType,
2218 List parameterTypes,
2219 namedParameters) {
2220 return new RuntimeFunctionType(
2221 returnType, parameterTypes, null, namedParameters);
2222 }
2223
2224 RuntimeType buildInterfaceType(rti, List typeArguments) {
2225 String name = JS('String|Null', r'#.name', rti);
2226 typeArguments = JS('JSFixedArray', '#', typeArguments);
2227 if (typeArguments.isEmpty) return new RuntimeTypePlain(name);
2228 return new RuntimeTypeGeneric(name, typeArguments, null);
2229 }
2230
2231 class DynamicRuntimeType extends RuntimeType {
2232 const DynamicRuntimeType();
2233
2234 String toString() => 'dynamic';
2235
2236 toRti() => null;
2237 }
2238
2239 RuntimeType getDynamicRuntimeType() => const DynamicRuntimeType();
2240
2241 class VoidRuntimeType extends RuntimeType {
2242 const VoidRuntimeType();
2243
2244 String toString() => 'void';
2245
2246 toRti() => throw 'internal error';
2247 }
2248
2249 RuntimeType getVoidRuntimeType() => const VoidRuntimeType();
2250
2251 RuntimeType convertRtiToRuntimeType(rti) {
2252 if (rti == null) {
2253 return getDynamicRuntimeType();
2254 } else if (JS('bool', 'typeof # == "function"', rti)) {
2255 return new RuntimeTypePlain(JS('String', r'rti.name'));
2256 } else if (JS('bool', '#.constructor == Array', rti)) {
2257 List list = JS('JSFixedArray', '#', rti);
2258 String name = JS('String', r'#.name', list[0]);
2259 List arguments = [];
2260 for (int i = 1; i < list.length; i++) {
2261 arguments.add(convertRtiToRuntimeType(list[i]));
2262 }
2263 return new RuntimeTypeGeneric(name, arguments, rti);
2264 } else {
2265 return new DummyRuntimeType("${JS('String', 'JSON.stringify(#)', rti)}");
2266 }
2267 }
2268
2269 class RuntimeTypePlain extends RuntimeType {
2270 final String name;
2271
2272 RuntimeTypePlain(this.name);
2273
2274 toRti() {
2275 var rti = JS('', 'init.allClasses[#]', name);
2276 if (rti == null) throw "no type for '$name'";
2277 return rti;
2278 }
2279
2280 String toString() => name;
2281 }
2282
2283 class RuntimeTypeGeneric extends RuntimeType {
2284 final String name;
2285 final List<RuntimeType> arguments;
2286 var rti;
2287
2288 RuntimeTypeGeneric(this.name, this.arguments, this.rti);
2289
2290 toRti() {
2291 if (rti != null) return rti;
2292 var result = JS('JSExtendableArray', '[init.allClasses[#]]', name);
2293 if (result[0] == null) {
2294 throw "no type for '$name<...>'";
2295 }
2296 for (RuntimeType argument in arguments) {
2297 JS('', '#.push(#)', result, argument.toRti());
2298 }
2299 return rti = result;
2300 }
2301
2302 String toString() => '$name<${arguments.join(", ")}>';
2303 }
2304
2305 class FunctionTypeInfoDecoderRing {
2306 final _typeData;
2307 String _cachedToString;
2308
2309 FunctionTypeInfoDecoderRing(this._typeData);
2310
2311 bool get _hasReturnType => JS('bool', '"ret" in #', _typeData);
2312 get _returnType => JS('', '#.ret', _typeData);
2313
2314 bool get _isVoid => JS('bool', '!!#.void', _typeData);
2315
2316 bool get _hasArguments => JS('bool', '"args" in #', _typeData);
2317 List get _arguments => JS('JSExtendableArray', '#.args', _typeData);
2318
2319 bool get _hasOptionalArguments => JS('bool', '"opt" in #', _typeData);
2320 List get _optionalArguments => JS('JSExtendableArray', '#.opt', _typeData);
2321
2322 bool get _hasNamedArguments => JS('bool', '"named" in #', _typeData);
2323 get _namedArguments => JS('=Object', '#.named', _typeData);
2324
2325 String _convert(type) {
2326 String result = runtimeTypeToString(type);
2327 if (result != null) return result;
2328 if (JS('bool', '"func" in #', type)) {
2329 return new FunctionTypeInfoDecoderRing(type).toString();
2330 } else {
2331 throw 'bad type';
2332 }
2333 }
2334
2335 String toString() {
2336 if (_cachedToString != null) return _cachedToString;
2337 var s = "(";
2338 var sep = '';
2339 if (_hasArguments) {
2340 for (var argument in _arguments) {
2341 s += sep;
2342 s += _convert(argument);
2343 sep = ', ';
2344 }
2345 }
2346 if (_hasOptionalArguments) {
2347 s += '$sep[';
2348 sep = '';
2349 for (var argument in _optionalArguments) {
2350 s += sep;
2351 s += _convert(argument);
2352 sep = ', ';
2353 }
2354 s += ']';
2355 }
2356 if (_hasNamedArguments) {
2357 s += '$sep{';
2358 sep = '';
2359 for (var name in extractKeys(_namedArguments)) {
2360 s += sep;
2361 s += '$name: ';
2362 s += _convert(JS('', '#[#]', _namedArguments, name));
2363 sep = ', ';
2364 }
2365 s += '}';
2366 }
2367 s += ') -> ';
2368 if (_isVoid) {
2369 s += 'void';
2370 } else if (_hasReturnType) {
2371 s += _convert(_returnType);
2372 } else {
2373 s += 'dynamic';
2374 }
2375 return _cachedToString = "$s";
2376 }
2377 }
OLDNEW
« no previous file with comments | « dart/sdk/lib/_internal/lib/collection_dev_patch.dart ('k') | dart/sdk/lib/_internal/lib/js_rti.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698