From 7f5190a44de15c5e7b14b4702e00700bebd1bdb7 Mon Sep 17 00:00:00 2001 From: Stefan Penner Date: Sat, 11 Mar 2017 13:46:22 -0800 Subject: [PATCH] [Fixes #15001] Remove internal EmptyObject usage --- packages/container/lib/registry.js | 8 ++++---- packages/ember-application/lib/system/engine.js | 6 +++--- .../ember-glimmer/lib/components/text_field.js | 3 +-- packages/ember-glimmer/lib/utils/iterable.js | 8 ++++---- packages/ember-glimmer/lib/utils/process-args.js | 7 +++---- packages/ember-glimmer/lib/utils/references.js | 5 ++--- packages/ember-glimmer/lib/views/outlet.js | 4 ++-- .../ember-glimmer/tests/unit/layout-cache-test.js | 3 +-- packages/ember-metal/lib/cache.js | 5 ++--- packages/ember-metal/lib/chains.js | 5 ++--- packages/ember-metal/lib/map.js | 12 ++++++------ packages/ember-metal/lib/meta.js | 9 ++++----- packages/ember-routing/lib/system/cache.js | 5 ++--- packages/ember-routing/lib/system/router.js | 15 +++++++-------- .../lib/computed/reduce_computed_macros.js | 4 ++-- packages/ember-runtime/lib/mixins/enumerable.js | 4 ++-- packages/ember-runtime/lib/system/each_proxy.js | 3 +-- packages/ember-utils/lib/dictionary.js | 9 +-------- packages/ember-utils/lib/empty-object.js | 11 ++++++----- 19 files changed, 55 insertions(+), 71 deletions(-) diff --git a/packages/container/lib/registry.js b/packages/container/lib/registry.js index 5d6476c24ab..909fb3f0a30 100644 --- a/packages/container/lib/registry.js +++ b/packages/container/lib/registry.js @@ -1,4 +1,4 @@ -import { dictionary, EmptyObject, assign, intern } from 'ember-utils'; +import { dictionary, assign, intern } from 'ember-utils'; import { assert, deprecate } from 'ember-metal'; import Container from './container'; @@ -35,7 +35,7 @@ export default function Registry(options) { this._factoryTypeInjections = dictionary(null); this._factoryInjections = dictionary(null); - this._localLookupCache = new EmptyObject(); + this._localLookupCache = Object.create(null); this._normalizeCache = dictionary(null); this._resolveCache = dictionary(null); this._failCache = dictionary(null); @@ -205,7 +205,7 @@ Registry.prototype = { let normalizedName = this.normalize(fullName); - this._localLookupCache = new EmptyObject(); + this._localLookupCache = Object.create(null); delete this.registrations[normalizedName]; delete this._resolveCache[normalizedName]; @@ -811,7 +811,7 @@ function expandLocalLookup(registry, normalizedName, normalizedSource) { let normalizedNameCache = cache[normalizedName]; if (!normalizedNameCache) { - normalizedNameCache = cache[normalizedName] = new EmptyObject(); + normalizedNameCache = cache[normalizedName] = Object.create(null); } let cached = normalizedNameCache[normalizedSource]; diff --git a/packages/ember-application/lib/system/engine.js b/packages/ember-application/lib/system/engine.js index a2b2f01eb1e..3146bc1fe32 100644 --- a/packages/ember-application/lib/system/engine.js +++ b/packages/ember-application/lib/system/engine.js @@ -2,7 +2,7 @@ @module ember @submodule ember-application */ -import { canInvoke, EmptyObject } from 'ember-utils'; +import { canInvoke } from 'ember-utils'; import { Namespace, RegistryProxyMixin, @@ -168,8 +168,8 @@ const Engine = Namespace.extend(RegistryProxyMixin, { }); Engine.reopenClass({ - initializers: new EmptyObject(), - instanceInitializers: new EmptyObject(), + initializers: Object.create(null), + instanceInitializers: Object.create(null), /** The goal of initializers should be to register dependencies and injections. diff --git a/packages/ember-glimmer/lib/components/text_field.js b/packages/ember-glimmer/lib/components/text_field.js index 49c24bbe58e..84e0306c49d 100644 --- a/packages/ember-glimmer/lib/components/text_field.js +++ b/packages/ember-glimmer/lib/components/text_field.js @@ -2,7 +2,6 @@ @module ember @submodule ember-views */ -import { EmptyObject } from 'ember-utils'; import { computed } from 'ember-metal'; import { environment } from 'ember-environment'; import Component from '../component'; @@ -10,7 +9,7 @@ import layout from '../templates/empty'; import { TextSupport } from 'ember-views'; let inputTypeTestElement; -const inputTypes = new EmptyObject(); +const inputTypes = Object.create(null); function canSetTypeOfInput(type) { if (type in inputTypes) { return inputTypes[type]; diff --git a/packages/ember-glimmer/lib/utils/iterable.js b/packages/ember-glimmer/lib/utils/iterable.js index 368e7a71f99..e026da6055b 100644 --- a/packages/ember-glimmer/lib/utils/iterable.js +++ b/packages/ember-glimmer/lib/utils/iterable.js @@ -1,4 +1,4 @@ -import { guidFor, EmptyObject } from 'ember-utils'; +import { guidFor } from 'ember-utils'; import { get, tagForProperty, tagFor, isProxy } from 'ember-metal'; import { objectAt, @@ -84,7 +84,7 @@ class ArrayIterator { this.length = array.length; this.keyFor = keyFor; this.position = 0; - this.seen = new EmptyObject(); + this.seen = Object.create(null); } isEmpty() { @@ -112,7 +112,7 @@ class EmberArrayIterator { this.length = get(array, 'length'); this.keyFor = keyFor; this.position = 0; - this.seen = new EmptyObject(); + this.seen = Object.create(null); } isEmpty() { @@ -140,7 +140,7 @@ class ObjectKeysIterator { this.values = values; this.keyFor = keyFor; this.position = 0; - this.seen = new EmptyObject(); + this.seen = Object.create(null); } isEmpty() { diff --git a/packages/ember-glimmer/lib/utils/process-args.js b/packages/ember-glimmer/lib/utils/process-args.js index e7fcc4ca11c..625e15c63ec 100644 --- a/packages/ember-glimmer/lib/utils/process-args.js +++ b/packages/ember-glimmer/lib/utils/process-args.js @@ -1,7 +1,6 @@ import { assign, - symbol, - EmptyObject + symbol } from 'ember-utils'; import { CONSTANT_TAG @@ -88,8 +87,8 @@ export class ComponentArgs { let { namedArgs } = this; let keys = namedArgs.keys; let attrs = namedArgs.value(); - let props = new EmptyObject(); - let args = new EmptyObject(); + let props = Object.create(null); + let args = Object.create(null); props[ARGS] = args; diff --git a/packages/ember-glimmer/lib/utils/references.js b/packages/ember-glimmer/lib/utils/references.js index 7ef1529970b..94e0149be60 100644 --- a/packages/ember-glimmer/lib/utils/references.js +++ b/packages/ember-glimmer/lib/utils/references.js @@ -1,7 +1,6 @@ import { HAS_NATIVE_WEAKMAP, - symbol, - EmptyObject + symbol } from 'ember-utils'; import { get, @@ -72,7 +71,7 @@ export class CachedReference extends EmberPathReference { export class RootReference extends ConstReference { constructor(value) { super(value); - this.children = new EmptyObject(); + this.children = Object.create(null); } get(propertyKey) { diff --git a/packages/ember-glimmer/lib/views/outlet.js b/packages/ember-glimmer/lib/views/outlet.js index 0b3e51c7c7a..aa5ed5e916c 100644 --- a/packages/ember-glimmer/lib/views/outlet.js +++ b/packages/ember-glimmer/lib/views/outlet.js @@ -2,7 +2,7 @@ @module ember @submodule ember-glimmer */ -import { assign, EmptyObject } from 'ember-utils'; +import { assign } from 'ember-utils'; import { DirtyableTag } from '@glimmer/reference'; import { environment } from 'ember-environment'; import { OWNER } from 'ember-utils'; @@ -56,7 +56,7 @@ class OrphanedOutletStateReference extends OutletStateReference { return null; } - let state = new EmptyObject(); + let state = Object.create(null); state[matched.render.outlet] = matched; matched.wasUsed = true; return { outlets: state }; diff --git a/packages/ember-glimmer/tests/unit/layout-cache-test.js b/packages/ember-glimmer/tests/unit/layout-cache-test.js index d069de8dc70..4becd1d5bec 100644 --- a/packages/ember-glimmer/tests/unit/layout-cache-test.js +++ b/packages/ember-glimmer/tests/unit/layout-cache-test.js @@ -1,4 +1,3 @@ -import { EmptyObject } from 'ember-utils'; import { RenderingTest, moduleFor } from '../utils/test-case'; import { CompiledBlock } from '@glimmer/runtime'; import { OWNER } from 'ember-utils'; @@ -19,7 +18,7 @@ class Counter { reset() { this.total = 0; - this.counts = new EmptyObject(); + this.counts = Object.create(null); } } diff --git a/packages/ember-metal/lib/cache.js b/packages/ember-metal/lib/cache.js index 9b82c57eaab..e54ac2fa194 100644 --- a/packages/ember-metal/lib/cache.js +++ b/packages/ember-metal/lib/cache.js @@ -1,4 +1,3 @@ -import { EmptyObject } from 'ember-utils'; import { UNDEFINED } from './meta'; export default class Cache { @@ -57,7 +56,7 @@ export default class Cache { class DefaultStore { constructor() { - this.data = new EmptyObject(); + this.data = Object.create(null); } get(key) { @@ -69,6 +68,6 @@ class DefaultStore { } clear() { - this.data = new EmptyObject(); + this.data = Object.create(null); } } diff --git a/packages/ember-metal/lib/chains.js b/packages/ember-metal/lib/chains.js index d4a343dac9c..044ee484207 100644 --- a/packages/ember-metal/lib/chains.js +++ b/packages/ember-metal/lib/chains.js @@ -1,4 +1,3 @@ -import { EmptyObject } from 'ember-utils'; import { get } from './property_get'; import { meta as metaFor, peekMeta } from './meta'; import { watchKey, unwatchKey } from './watch_key'; @@ -23,7 +22,7 @@ class ChainWatchers { // chain nodes that reference a key in this obj by key // we only create ChainWatchers when we are going to add them // so create this upfront - this.chains = new EmptyObject(); + this.chains = Object.create(null); } add(key, node) { @@ -231,7 +230,7 @@ class ChainNode { let chains = this._chains; let node; if (chains === undefined) { - chains = this._chains = new EmptyObject(); + chains = this._chains = Object.create(null); } else { node = chains[key]; } diff --git a/packages/ember-metal/lib/map.js b/packages/ember-metal/lib/map.js index 8e3d285ef91..08b63af5fe4 100644 --- a/packages/ember-metal/lib/map.js +++ b/packages/ember-metal/lib/map.js @@ -20,7 +20,7 @@ Map is mocked out to look like an Ember object, so you can do `Ember.Map.create()` for symmetry with other Ember classes. */ -import { EmptyObject, guidFor } from 'ember-utils'; +import { guidFor } from 'ember-utils'; function missingFunction(fn) { throw new TypeError(`${Object.prototype.toString.call(fn)} is not a function`); @@ -31,10 +31,10 @@ function missingNew(name) { } function copyNull(obj) { - let output = new EmptyObject(); + let output = Object.create(null); for (let prop in obj) { - // hasOwnPropery is not needed because obj is new EmptyObject(); + // hasOwnPropery is not needed because obj is Object.create(null); output[prop] = obj[prop]; } @@ -90,7 +90,7 @@ OrderedSet.prototype = { @private */ clear() { - this.presenceSet = new EmptyObject(); + this.presenceSet = Object.create(null); this.list = []; this.size = 0; }, @@ -242,7 +242,7 @@ function Map() { if (this instanceof Map) { this._keys = OrderedSet.create(); this._keys._silenceRemoveDeprecation = true; - this._values = new EmptyObject(); + this._values = Object.create(null); this.size = 0; } else { missingNew('Map'); @@ -394,7 +394,7 @@ Map.prototype = { */ clear() { this._keys.clear(); - this._values = new EmptyObject(); + this._values = Object.create(null); this.size = 0; }, diff --git a/packages/ember-metal/lib/meta.js b/packages/ember-metal/lib/meta.js index 5b6ed781c97..adc5bb01b1c 100644 --- a/packages/ember-metal/lib/meta.js +++ b/packages/ember-metal/lib/meta.js @@ -1,6 +1,5 @@ import { HAS_NATIVE_WEAKMAP, - EmptyObject, lookupDescriptor, symbol } from 'ember-utils'; @@ -202,7 +201,7 @@ export class Meta { } _getOrCreateOwnMap(key) { - return this[key] || (this[key] = new EmptyObject()); + return this[key] || (this[key] = Object.create(null)); } _getInherited(key) { @@ -238,7 +237,7 @@ export class Meta { let outerMap = this._getOrCreateOwnMap('_deps'); let innerMap = outerMap[subkey]; if (!innerMap) { - innerMap = outerMap[subkey] = new EmptyObject(); + innerMap = outerMap[subkey] = Object.create(null); } innerMap[itemkey] = value; } @@ -277,7 +276,7 @@ export class Meta { _forEachIn(key, subkey, fn) { let pointer = this; - let seen = new EmptyObject(); + let seen = Object.create(null); let calls = []; while (pointer !== undefined) { let map = pointer[key]; @@ -368,7 +367,7 @@ function inheritedMap(name, Meta) { Meta.prototype[`forEach${capitalized}`] = function(fn) { let pointer = this; - let seen = new EmptyObject(); + let seen = Object.create(null); while (pointer !== undefined) { let map = pointer[key]; if (map) { diff --git a/packages/ember-routing/lib/system/cache.js b/packages/ember-routing/lib/system/cache.js index 57ff2c0f945..699e85a6ccf 100644 --- a/packages/ember-routing/lib/system/cache.js +++ b/packages/ember-routing/lib/system/cache.js @@ -1,4 +1,3 @@ -import { EmptyObject } from 'ember-utils'; import { Object as EmberObject } from 'ember-runtime'; /** @@ -10,7 +9,7 @@ import { Object as EmberObject } from 'ember-runtime'; */ export default EmberObject.extend({ init() { - this.cache = new EmptyObject(); + this.cache = Object.create(null); }, has(bucketKey) { @@ -21,7 +20,7 @@ export default EmberObject.extend({ let bucket = this.cache[bucketKey]; if (!bucket) { - bucket = this.cache[bucketKey] = new EmptyObject(); + bucket = this.cache[bucketKey] = Object.create(null); } bucket[key] = value; diff --git a/packages/ember-routing/lib/system/router.js b/packages/ember-routing/lib/system/router.js index c49ec5fa8ee..a11a0a452c8 100644 --- a/packages/ember-routing/lib/system/router.js +++ b/packages/ember-routing/lib/system/router.js @@ -1,5 +1,4 @@ import { - EmptyObject, assign, guidFor, dictionary, @@ -144,11 +143,11 @@ const EmberRouter = EmberObject.extend(Evented, { this.currentRouteName = null; this.currentPath = null; - this._qpCache = new EmptyObject(); + this._qpCache = Object.create(null); this._resetQueuedQueryParameterChanges(); this._handledErrors = dictionary(null); - this._engineInstances = new EmptyObject(); - this._engineInfoByRoute = new EmptyObject(); + this._engineInstances = Object.create(null); + this._engineInfoByRoute = Object.create(null) }, /* @@ -571,7 +570,7 @@ const EmberRouter = EmberObject.extend(Evented, { }, _getHandlerFunction() { - let seen = new EmptyObject(); + let seen = Object.create(null); let owner = getOwner(this); return name => { @@ -1024,7 +1023,7 @@ const EmberRouter = EmberObject.extend(Evented, { let engineInstances = this._engineInstances; if (!engineInstances[name]) { - engineInstances[name] = new EmptyObject(); + engineInstances[name] = Object.create(null); } let engineInstance = engineInstances[name][instanceId]; @@ -1483,7 +1482,7 @@ function appendLiveRoute(liveRoutes, defaultParentState, renderOptions) { let target; let myState = { render: renderOptions, - outlets: new EmptyObject(), + outlets: Object.create(null), wasUsed: false }; if (renderOptions.into) { @@ -1528,7 +1527,7 @@ function appendOrphan(liveRoutes, into, myState) { render: { name: '__ember_orphans__' }, - outlets: new EmptyObject() + outlets: Object.create(null) }; } liveRoutes.outlets.__ember_orphans__.outlets[into] = myState; diff --git a/packages/ember-runtime/lib/computed/reduce_computed_macros.js b/packages/ember-runtime/lib/computed/reduce_computed_macros.js index c32cff4094d..889dbfad494 100644 --- a/packages/ember-runtime/lib/computed/reduce_computed_macros.js +++ b/packages/ember-runtime/lib/computed/reduce_computed_macros.js @@ -3,7 +3,7 @@ @submodule ember-runtime */ -import { EmptyObject, guidFor } from 'ember-utils'; +import { guidFor } from 'ember-utils'; import { assert, get, @@ -433,7 +433,7 @@ export function uniq(...args) { export function uniqBy(dependentKey, propertyKey) { return computed(`${dependentKey}.[]`, function() { let uniq = emberA(); - let seen = new EmptyObject(); + let seen = Object.create(null); let list = get(this, dependentKey); if (isArray(list)) { list.forEach(item => { diff --git a/packages/ember-runtime/lib/mixins/enumerable.js b/packages/ember-runtime/lib/mixins/enumerable.js index c3e344b23b1..af9075c29e6 100644 --- a/packages/ember-runtime/lib/mixins/enumerable.js +++ b/packages/ember-runtime/lib/mixins/enumerable.js @@ -7,7 +7,7 @@ // HELPERS // -import { guidFor, EmptyObject } from 'ember-utils'; +import { guidFor } from 'ember-utils'; import { get, set, @@ -1086,7 +1086,7 @@ const Enumerable = Mixin.create({ uniqBy(key) { let ret = emberA(); - let seen = new EmptyObject(); + let seen = Object.create(null); this.forEach((item) => { let guid = guidFor(get(item, key)); diff --git a/packages/ember-runtime/lib/system/each_proxy.js b/packages/ember-runtime/lib/system/each_proxy.js index 590d903dc52..85afe31d06a 100644 --- a/packages/ember-runtime/lib/system/each_proxy.js +++ b/packages/ember-runtime/lib/system/each_proxy.js @@ -1,4 +1,3 @@ -import { EmptyObject } from 'ember-utils'; import { assert, get, @@ -74,7 +73,7 @@ EachProxy.prototype = { beginObservingContentKey(keyName) { let keys = this._keys; if (!keys) { - keys = this._keys = new EmptyObject(); + keys = this._keys = Object.create(null); } if (!keys[keyName]) { diff --git a/packages/ember-utils/lib/dictionary.js b/packages/ember-utils/lib/dictionary.js index c78271adfbd..b5e4be0b521 100644 --- a/packages/ember-utils/lib/dictionary.js +++ b/packages/ember-utils/lib/dictionary.js @@ -1,17 +1,10 @@ -import EmptyObject from './empty-object'; - // the delete is meant to hint at runtimes that this object should remain in // dictionary mode. This is clearly a runtime specific hack, but currently it // appears worthwhile in some usecases. Please note, these deletes do increase // the cost of creation dramatically over a plain Object.create. And as this // only makes sense for long-lived dictionaries that aren't instantiated often. export default function makeDictionary(parent) { - let dict; - if (parent === null) { - dict = new EmptyObject(); - } else { - dict = Object.create(parent); - } + let dict = Object.create(parent); dict['_dict'] = null; delete dict['_dict']; return dict; diff --git a/packages/ember-utils/lib/empty-object.js b/packages/ember-utils/lib/empty-object.js index 5585df6fead..a7efd663744 100644 --- a/packages/ember-utils/lib/empty-object.js +++ b/packages/ember-utils/lib/empty-object.js @@ -1,8 +1,9 @@ -// This exists because `Object.create(null)` is absurdly slow compared -// to `new EmptyObject()`. In either case, you want a null prototype -// when you're treating the object instances as arbitrary dictionaries -// and don't want your keys colliding with build-in methods on the -// default object prototype. +// This exists because `Object.create(null)` WAS slow compared to `new +// EmptyObject()`. In either case, you want a null prototype when you're +// treating the object instances as arbitrary dictionaries and don't want your +// keys colliding with build-in methods on the default object prototype. +// +// This has been resolved: https://github.com/emberjs/ember.js/issues/15001 const proto = Object.create(null, { // without this, we will always still end up with (new