From 6954ade6203f1d7b9dd8d83b95c0d8fa319fe58b Mon Sep 17 00:00:00 2001 From: Matthew Beale Date: Sat, 17 Dec 2016 14:08:01 -0800 Subject: [PATCH] [BUGFIX] Only freeze empty array/dict with weakmap When arrays and objects are frozen in JavaScript, it is impossible to attach meta-data (like Ember's own `meta`) to them without using a WeakMap. Ember does adopt the WeakMap strategy in browsers that support it, however there are still supported environments (IE9, IE10) where `Object.freeze` is supported but WeakMap is not. But not freezing these empty arrays and object if WeakMap is missing, legacy meta-data strategies are permitted on those instances. See: * https://github.com/emberjs/ember.js/issues/14264 * https://github.com/emberjs/ember.js/pull/14244 --- packages/glimmer-runtime/lib/utils.ts | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/packages/glimmer-runtime/lib/utils.ts b/packages/glimmer-runtime/lib/utils.ts index 67cb6b039b..21e310bbfc 100644 --- a/packages/glimmer-runtime/lib/utils.ts +++ b/packages/glimmer-runtime/lib/utils.ts @@ -1,7 +1,18 @@ import { Dict, dict } from 'glimmer-util'; -export const EMPTY_ARRAY = Object.freeze([]); -export const EMPTY_DICT: Dict = Object.freeze(dict()); +const HAS_NATIVE_WEAKMAP = (function() { + // detect if `WeakMap` is even present + let hasWeakMap = typeof WeakMap === 'function'; + if (!hasWeakMap) { return false; } + + let instance = new WeakMap(); + // use `Object`'s `.toString` directly to prevent us from detecting + // polyfills as native weakmaps + return Object.prototype.toString.call(instance) === '[object WeakMap]'; +})(); + +export const EMPTY_ARRAY = HAS_NATIVE_WEAKMAP ? Object.freeze([]) : []; +export const EMPTY_DICT: Dict = HAS_NATIVE_WEAKMAP ? Object.freeze(dict()) : dict(); export interface EnumerableCallback { (item: T): void;