Chromium Code Reviews| Index: sdk/lib/_internal/compiler/js_lib/js_names.dart |
| diff --git a/sdk/lib/_internal/compiler/js_lib/js_names.dart b/sdk/lib/_internal/compiler/js_lib/js_names.dart |
| index 87cc6c04eea97bdddc5e4322a1513dcacf728283..a1358935d86057819d2b44616b07d742b750e200 100644 |
| --- a/sdk/lib/_internal/compiler/js_lib/js_names.dart |
| +++ b/sdk/lib/_internal/compiler/js_lib/js_names.dart |
| @@ -26,55 +26,103 @@ preserveNames() {} |
| /// A map from mangled names to "reflective" names, that is, unmangled names |
| /// with some additional information, such as, number of required arguments. |
| /// This map is for mangled names used as instance members. |
| -final Map<String, String> mangledNames = |
| - computeMangledNames( |
| - JS_EMBEDDED_GLOBAL('=Object', MANGLED_NAMES), |
| - false); |
| +final _LazyMangledNamesMap mangledNames = new _LazyMangledInstanceNamesMap( |
| + JS_EMBEDDED_GLOBAL('=Object', MANGLED_NAMES)); |
| /// A map from "reflective" names to mangled names (the reverse of |
| /// [mangledNames]). |
| -final Map<String, String> reflectiveNames = |
| - computeReflectiveNames(mangledNames); |
| +final _LazyReflectiveNamesMap reflectiveNames = |
| + new _LazyReflectiveNamesMap(JS_EMBEDDED_GLOBAL('=Object', MANGLED_NAMES), |
| + true); |
| /// A map from mangled names to "reflective" names (see [mangledNames]). This |
| /// map is for globals, that is, static and top-level members. |
| -final Map<String, String> mangledGlobalNames = computeMangledNames( |
| - JS_EMBEDDED_GLOBAL('=Object', MANGLED_GLOBAL_NAMES), |
| - true); |
| +final _LazyMangledNamesMap mangledGlobalNames = new _LazyMangledNamesMap( |
| + JS_EMBEDDED_GLOBAL('=Object', MANGLED_GLOBAL_NAMES)); |
| /// A map from "reflective" names to mangled names (the reverse of |
| /// [mangledGlobalNames]). |
| -final Map<String, String> reflectiveGlobalNames = |
| - computeReflectiveNames(mangledGlobalNames); |
| +final _LazyReflectiveNamesMap reflectiveGlobalNames = |
| + new _LazyReflectiveNamesMap( |
| + JS_EMBEDDED_GLOBAL('=Object', MANGLED_GLOBAL_NAMES), false); |
| /// [jsMangledNames] is a JavaScript object literal. The keys are the mangled |
| /// names, and the values are the "reflective" names. |
| -Map<String, String> computeMangledNames(jsMangledNames, bool isGlobal) { |
| - preserveNames(); |
| - var keys = extractKeys(jsMangledNames); |
| - var result = <String, String>{}; |
| - String getterPrefix = JS_GET_NAME('GETTER_PREFIX'); |
| - int getterPrefixLength = getterPrefix.length; |
| - String setterPrefix = JS_GET_NAME('SETTER_PREFIX'); |
| - for (String key in keys) { |
| - String value = JS('String', '#[#]', jsMangledNames, key); |
| - result[key] = value; |
| - if (!isGlobal) { |
| - if (key.startsWith(getterPrefix)) { |
| - result['$setterPrefix${key.substring(getterPrefixLength)}'] = '$value='; |
| - } |
| +class _LazyMangledNamesMap { |
| + var _jsMangledNames; |
| + |
| + _LazyMangledNamesMap(this._jsMangledNames); |
| + |
| + String operator[](String key) { |
| + String result = JS('var', '#[#]', _jsMangledNames, key); |
| + // Filter out all non-string values to protect against polution from |
| + // anciliary fields in [_jsMangledNames]. |
| + bool filter = |
| + JS('bool', '# == null || typeof # !== "string"', result, result); |
|
sra1
2015/03/05 18:23:25
typeof is sufficient
herhut
2015/03/06 12:36:45
True, thanks!
|
| + return filter ? null : result; |
| + } |
| +} |
| + |
| +class _LazyMangledInstanceNamesMap extends _LazyMangledNamesMap { |
| + _LazyMangledInstanceNamesMap(_jsMangledNames) : super(_jsMangledNames); |
| + |
| + String operator[](String key) { |
| + var result = super[key]; |
|
floitsch
2015/03/06 14:54:10
Use type.
herhut
2015/03/09 14:28:35
Done.
|
| + String setterPrefix = JS_GET_NAME('SETTER_PREFIX'); |
| + if (result == null && key.startsWith(setterPrefix)) { |
|
floitsch
2015/03/06 14:54:10
Isn't this handled by the "_updateReflectiveNames
herhut
2015/03/09 14:28:35
_updateReflectiveNames is the inverse mapping. Thi
floitsch
2015/03/09 16:35:06
Explain in a comment.
|
| + String getterPrefix = JS_GET_NAME('GETTER_PREFIX'); |
| + int setterPrefixLength = getterPrefix.length; |
|
floitsch
2015/03/09 16:35:06
getterPrefixLength
|
| + |
| + // Generate the setter name from the getter name. |
| + key = '$getterPrefix${key.substring(setterPrefixLength)}'; |
| + result = super[key]; |
| + return (result != null) ? "${result}=" : null; |
|
floitsch
2015/03/06 14:54:10
You don't need the curly braces.
herhut
2015/03/09 14:28:35
I actually find this easier to read. Unless you re
|
| } |
| + return result; |
| } |
| - return result; |
| } |
| -Map<String, String> computeReflectiveNames(Map<String, String> map) { |
| - preserveNames(); |
| - var result = <String, String>{}; |
| - map.forEach((String mangledName, String reflectiveName) { |
| - result[reflectiveName] = mangledName; |
| - }); |
| - return result; |
| +class _LazyReflectiveNamesMap { |
| + final _jsMangledNames; |
| + final bool _isInstance; |
| + var _cacheLength = 0; |
|
floitsch
2015/03/06 14:54:10
types.
herhut
2015/03/09 14:28:35
Done.
|
| + var _cache; |
| + |
| + _LazyReflectiveNamesMap(this._jsMangledNames, this._isInstance); |
| + |
| + Map<String, String> _updateReflectiveNames() { |
| + preserveNames(); |
| + var result = <String, String>{}; |
|
floitsch
2015/03/06 14:54:10
Use types.
herhut
2015/03/09 14:28:35
Done.
|
| + var keys = JS('List', 'Object.keys(#)', _jsMangledNames); |
| + for (String key in keys) { |
| + var reflectiveName = JS('var', '#[#]', _jsMangledNames, key); |
| + // Filter out all non-string values to protect against polution from |
| + // anciliary fields in [_jsMangledNames]. |
| + bool filter = JS('bool', '# == null || typeof # !== "string"', |
| + reflectiveName, reflectiveName); |
| + if (filter) continue; |
| + result[reflectiveName] = key; |
| + |
| + String getterPrefix = JS_GET_NAME('GETTER_PREFIX'); |
| + if (_isInstance && key.startsWith(getterPrefix)) { |
| + int getterPrefixLength = getterPrefix.length; |
| + String setterPrefix = JS_GET_NAME('SETTER_PREFIX'); |
| + result['$reflectiveName='] = |
| + '$setterPrefix${key.substring(getterPrefixLength)}'; |
| + } |
| + } |
| + return result; |
| + } |
| + |
| + int get _jsMangledNamesLength => JS('int', '#.length', _jsMangledNames); |
| + |
| + String operator[](String key) { |
| + if (_cache == null || _jsMangledNamesLength != _cacheLength) { |
| + _cache = _updateReflectiveNames(); |
| + _cacheLength = _jsMangledNamesLength; |
| + } |
| + return _cache[key]; |
| + } |
| } |
| @NoInline() |