@@ -342,19 +342,80 @@ if (isEnabled('mandatory-setter')) {
342342 } ;
343343}
344344
345+ const HAS_NATIVE_WEAKMAP = ( function ( ) {
346+ // detect if `WeakMap` is even present
347+ let hasWeakMap = typeof WeakMap === 'function' ;
348+ if ( ! hasWeakMap ) { return false ; }
349+
350+ let instance = new WeakMap ( ) ;
351+ // use `Object`'s `.toString` directly to prevent us from detecting
352+ // polyfills as native weakmaps
353+ return Object . prototype . toString . call ( instance ) === '[object WeakMap]' ;
354+ } ) ( ) ;
355+
356+ let setMeta , peekMeta , deleteMeta ;
357+
345358// choose the one appropriate for given platform
346- let setMeta = function ( obj , meta ) {
347- // if `null` already, just set it to the new value
348- // otherwise define property first
349- if ( obj [ META_FIELD ] !== null ) {
350- if ( obj . __defineNonEnumerable ) {
351- obj . __defineNonEnumerable ( EMBER_META_PROPERTY ) ;
352- } else {
353- Object . defineProperty ( obj , META_FIELD , META_DESC ) ;
359+ if ( HAS_NATIVE_WEAKMAP ) {
360+ let getPrototypeOf = Object . getPrototypeOf ;
361+ let metaStore = new WeakMap ( ) ;
362+
363+ setMeta = function WeakMap_setMeta ( obj , meta ) {
364+ metaStore . set ( obj , meta ) ;
365+ } ;
366+
367+ peekMeta = function WeakMap_peekMeta ( obj ) {
368+ let pointer = obj ;
369+ let meta ;
370+ while ( pointer ) {
371+ meta = metaStore . get ( pointer ) ;
372+ // stop if we find a `null` value, since
373+ // that means the meta was deleted
374+ // any other truthy value is a "real" meta
375+ if ( meta === null || meta ) {
376+ return meta ;
377+ }
378+
379+ pointer = getPrototypeOf ( pointer ) ;
354380 }
355- }
381+ } ;
356382
357- obj [ META_FIELD ] = meta ;
383+ deleteMeta = function WeakMap_deleteMeta ( obj ) {
384+ // set value to `null` so that we can detect
385+ // a deleted meta in peekMeta later
386+ metaStore . set ( obj , null ) ;
387+ } ;
388+ } else {
389+ setMeta = function Fallback_setMeta ( obj , meta ) {
390+ // if `null` already, just set it to the new value
391+ // otherwise define property first
392+ if ( obj [ META_FIELD ] !== null ) {
393+ if ( obj . __defineNonEnumerable ) {
394+ obj . __defineNonEnumerable ( EMBER_META_PROPERTY ) ;
395+ } else {
396+ Object . defineProperty ( obj , META_FIELD , META_DESC ) ;
397+ }
398+ }
399+
400+ obj [ META_FIELD ] = meta ;
401+ } ;
402+
403+ peekMeta = function Fallback_peekMeta ( obj ) {
404+ return obj [ META_FIELD ] ;
405+ } ;
406+
407+ deleteMeta = function Fallback_deleteMeta ( obj ) {
408+ if ( typeof obj [ META_FIELD ] !== 'object' ) {
409+ return ;
410+ }
411+ obj [ META_FIELD ] = null ;
412+ } ;
413+ }
414+
415+ export {
416+ peekMeta ,
417+ setMeta ,
418+ deleteMeta
358419} ;
359420
360421/**
@@ -391,14 +452,3 @@ export function meta(obj) {
391452 setMeta ( obj , newMeta ) ;
392453 return newMeta ;
393454}
394-
395- export function peekMeta ( obj ) {
396- return obj [ META_FIELD ] ;
397- }
398-
399- export function deleteMeta ( obj ) {
400- if ( typeof obj [ META_FIELD ] !== 'object' ) {
401- return ;
402- }
403- obj [ META_FIELD ] = null ;
404- }
0 commit comments