| Index: lib/runtime/dart_runtime.js
|
| diff --git a/lib/runtime/dart_runtime.js b/lib/runtime/dart_runtime.js
|
| index b1d2f0012055b5bea48be84451d6563f56f32f10..01791fdc06a5c9cc1c9e6bc0251e7edd0d6cdf44 100644
|
| --- a/lib/runtime/dart_runtime.js
|
| +++ b/lib/runtime/dart_runtime.js
|
| @@ -11,6 +11,10 @@ var dart, _js_helper;
|
| let getOwnPropertyNames = Object.getOwnPropertyNames;
|
| let getOwnPropertySymbols = Object.getOwnPropertySymbols;
|
|
|
| + function getOwnNamesAndSymbols(obj) {
|
| + return getOwnPropertyNames(obj).concat(getOwnPropertySymbols(obj));
|
| + }
|
| +
|
| // Adapted from Angular.js
|
| let FN_ARGS = /^function\s*[^\(]*\(\s*([^\)]*)\)/m;
|
| let FN_ARG_SPLIT = /,/;
|
| @@ -24,8 +28,7 @@ var dart, _js_helper;
|
| argDecl = fnText.match(FN_ARGS);
|
|
|
| let r = argDecl[1].split(FN_ARG_SPLIT);
|
| - for(let a in r) {
|
| - let arg = r[a];
|
| + for (let arg of r) {
|
| arg.replace(FN_ARG, function(all, underscore, name){
|
| args.push(name);
|
| });
|
| @@ -324,14 +327,14 @@ var dart, _js_helper;
|
|
|
| if (type instanceof AbstractFunctionType) {
|
| if (!_isTop(type.returnType, false)) return false;
|
| - for (var i = 0; i < type.args.length; ++i) {
|
| + for (let i = 0; i < type.args.length; ++i) {
|
| if (!_isBottom(type.args[i], true)) return false;
|
| }
|
| - for (var i = 0; i < type.optionals.length; ++i) {
|
| + for (let i = 0; i < type.optionals.length; ++i) {
|
| if (!_isBottom(type.optionals[i], true)) return false;
|
| }
|
| - var names = Object.getOwnPropertyNames(type.named);
|
| - for (var i = 0; i < names.length; ++i) {
|
| + var names = getOwnPropertyNames(type.named);
|
| + for (let i = 0; i < names.length; ++i) {
|
| if (!_isBottom(type.named[names[i]], true)) return false;
|
| }
|
| return true;
|
| @@ -382,7 +385,7 @@ var dart, _js_helper;
|
| if (this._stringValue) return this._stringValue;
|
|
|
| var buffer = '(';
|
| - for (var i = 0; i < this.args.length; ++i) {
|
| + for (let i = 0; i < this.args.length; ++i) {
|
| if (i > 0) {
|
| buffer += ', ';
|
| }
|
| @@ -391,7 +394,7 @@ var dart, _js_helper;
|
| if (this.optionals.length > 0) {
|
| if (this.args.length > 0) buffer += ', ';
|
| buffer += '[';
|
| - for (var i = 0; i < this.optionals.length; ++i) {
|
| + for (let i = 0; i < this.optionals.length; ++i) {
|
| if (i > 0) {
|
| buffer += ', ';
|
| }
|
| @@ -401,8 +404,8 @@ var dart, _js_helper;
|
| } else if (this.named.length > 0) {
|
| if (this.args.length > 0) buffer += ', ';
|
| buffer += '{';
|
| - let names = Object.getOwnPropertyNames(this.named).sort();
|
| - for (var i = 0; i < names.length; ++i) {
|
| + let names = getOwnPropertyNames(this.named).sort();
|
| + for (let i = 0; i < names.length; ++i) {
|
| if (i > 0) {
|
| buffer += ', ';
|
| }
|
| @@ -523,7 +526,7 @@ var dart, _js_helper;
|
| return false;
|
| }
|
|
|
| - for (var i = 0; i < args1.length; ++i) {
|
| + for (let i = 0; i < args1.length; ++i) {
|
| if (!isSubtype_(args2[i], args1[i], true)) {
|
| return false;
|
| }
|
| @@ -537,13 +540,13 @@ var dart, _js_helper;
|
| }
|
|
|
| var j = 0;
|
| - for (var i = args1.length; i < args2.length; ++i, ++j) {
|
| + for (let i = args1.length; i < args2.length; ++i, ++j) {
|
| if (!isSubtype_(args2[i], optionals1[j], true)) {
|
| return false;
|
| }
|
| }
|
|
|
| - for (var i = 0; i < optionals2.length; ++i, ++j) {
|
| + for (let i = 0; i < optionals2.length; ++i, ++j) {
|
| if (!isSubtype_(optionals2[i], optionals1[j], true)) {
|
| return false;
|
| }
|
| @@ -552,10 +555,10 @@ var dart, _js_helper;
|
| let named1 = ft1.named;
|
| let named2 = ft2.named;
|
|
|
| - let names = Object.getOwnPropertyNames(named2);
|
| - for (var i = 0; i < names.length; ++i) {
|
| + let names = getOwnPropertyNames(named2);
|
| + for (let i = 0; i < names.length; ++i) {
|
| let name = names[i];
|
| - let n1 = named1[name]
|
| + let n1 = named1[name];
|
| let n2 = named2[name];
|
| if (n1 === void 0) {
|
| return false;
|
| @@ -599,9 +602,7 @@ var dart, _js_helper;
|
| }
|
|
|
| function defineLazy(to, from) {
|
| - let names = getOwnPropertyNames(from);
|
| - for (let i = 0; i < names.length; i++) {
|
| - let name = names[i];
|
| + for (let name of getOwnNamesAndSymbols(from)) {
|
| defineLazyProperty(to, name, getOwnPropertyDescriptor(from, name));
|
| }
|
| }
|
| @@ -615,14 +616,9 @@ var dart, _js_helper;
|
| * This operation is commonly called `mixin` in JS.
|
| */
|
| function copyProperties(to, from) {
|
| - function copyPropertiesHelper(names) {
|
| - for (let i = 0; i < names.length; i++) {
|
| - let name = names[i];
|
| - defineProperty(to, name, getOwnPropertyDescriptor(from, name));
|
| - }
|
| + for (let name of getOwnNamesAndSymbols(from)) {
|
| + defineProperty(to, name, getOwnPropertyDescriptor(from, name));
|
| }
|
| - copyPropertiesHelper(getOwnPropertyNames(from));
|
| - copyPropertiesHelper(getOwnPropertySymbols(from));
|
| return to;
|
| }
|
| dart.copyProperties = copyProperties;
|
| @@ -716,7 +712,7 @@ var dart, _js_helper;
|
| map.set(key, value);
|
| }
|
| } else if (typeof values === 'object') {
|
| - for (let key of Object.getOwnPropertyNames(values)) {
|
| + for (let key of getOwnPropertyNames(values)) {
|
| map.set(key, values[key]);
|
| }
|
| }
|
| @@ -796,6 +792,59 @@ var dart, _js_helper;
|
| }
|
| dart.generic = generic;
|
|
|
| + let _value = Symbol('_value');
|
| + /**
|
| + * Looks up a sequence of [keys] in [map], recursively, and
|
| + * returns the result. If the value is not found, [valueFn] will be called to
|
| + * add it. For example:
|
| + *
|
| + * var map = new Map();
|
| + * putIfAbsent(map, [1, 2, 'hi ', 'there '], () => 'world');
|
| + *
|
| + * ... will create a Map with a structure like:
|
| + *
|
| + * { 1: { 2: { 'hi ': { 'there ': 'world' } } } }
|
| + */
|
| + function multiKeyPutIfAbsent(map, keys, valueFn) {
|
| + for (let k of keys) {
|
| + let value = map.get(k);
|
| + if (!value) {
|
| + // TODO(jmesserly): most of these maps are very small (e.g. 1 item),
|
| + // so it may be worth optimizing for that.
|
| + map.set(k, value = new Map());
|
| + }
|
| + map = value;
|
| + }
|
| + if (map.has(_value)) return map.get(_value);
|
| + let value = valueFn();
|
| + map.set(_value, value);
|
| + return value;
|
| + }
|
| +
|
| + /** The global constant table. */
|
| + let constants = new Map();
|
| +
|
| + /**
|
| + * Canonicalize a constant object.
|
| + *
|
| + * Preconditions:
|
| + * - `obj` is an objects or array, not a primitive.
|
| + * - nested values of the object are themselves already canonicalized.
|
| + */
|
| + function constant(obj) {
|
| + let objectKey = [getRuntimeType(obj)];
|
| + // There's no guarantee in JS that names/symbols are returned in the same
|
| + // order. We could probably get the same order if we're judicious about
|
| + // initializing them, but easier to not depend on that.
|
| + for (let name of getOwnNamesAndSymbols(obj)) {
|
| + // TODO(jmesserly): we can make this faster if needed.
|
| + objectKey.push(name);
|
| + objectKey.push(obj[name]);
|
| + }
|
| + return multiKeyPutIfAbsent(constants, objectKey, () => obj);
|
| + }
|
| + dart.const = constant;
|
| +
|
| /** Sets the runtime type of `obj` to be `type` */
|
| function setType(obj, type) {
|
| obj[runtimeType] = type;
|
|
|