@@ -354,19 +354,80 @@ if (isEnabled('mandatory-setter')) {
354354 } ;
355355}
356356
357+ const HAS_NATIVE_WEAKMAP = ( function ( ) {
358+ // detect if `WeakMap` is even present
359+ let hasWeakMap = typeof WeakMap === 'function' ;
360+ if ( ! hasWeakMap ) { return false ; }
361+
362+ let instance = new WeakMap ( ) ;
363+ // use `Object`'s `.toString` directly to prevent us from detecting
364+ // polyfills as native weakmaps
365+ return Object . prototype . toString . call ( instance ) === '[object WeakMap]' ;
366+ } ) ( ) ;
367+
368+ let setMeta , peekMeta , deleteMeta ;
369+
357370// choose the one appropriate for given platform
358- let setMeta = function ( obj , meta ) {
359- // if `null` already, just set it to the new value
360- // otherwise define property first
361- if ( obj [ META_FIELD ] !== null ) {
362- if ( obj . __defineNonEnumerable ) {
363- obj . __defineNonEnumerable ( EMBER_META_PROPERTY ) ;
364- } else {
365- Object . defineProperty ( obj , META_FIELD , META_DESC ) ;
371+ if ( HAS_NATIVE_WEAKMAP ) {
372+ let getPrototypeOf = Object . getPrototypeOf ;
373+ let metaStore = new WeakMap ( ) ;
374+
375+ setMeta = function WeakMap_setMeta ( obj , meta ) {
376+ metaStore . set ( obj , meta ) ;
377+ } ;
378+
379+ peekMeta = function WeakMap_peekMeta ( obj ) {
380+ let pointer = obj ;
381+ let meta ;
382+ while ( pointer ) {
383+ meta = metaStore . get ( pointer ) ;
384+ // stop if we find a `null` value, since
385+ // that means the meta was deleted
386+ // any other truthy value is a "real" meta
387+ if ( meta === null || meta ) {
388+ return meta ;
389+ }
390+
391+ pointer = getPrototypeOf ( pointer ) ;
366392 }
367- }
393+ } ;
368394
369- obj [ META_FIELD ] = meta ;
395+ deleteMeta = function WeakMap_deleteMeta ( obj ) {
396+ // set value to `null` so that we can detect
397+ // a deleted meta in peekMeta later
398+ metaStore . set ( obj , null ) ;
399+ } ;
400+ } else {
401+ setMeta = function Fallback_setMeta ( obj , meta ) {
402+ // if `null` already, just set it to the new value
403+ // otherwise define property first
404+ if ( obj [ META_FIELD ] !== null ) {
405+ if ( obj . __defineNonEnumerable ) {
406+ obj . __defineNonEnumerable ( EMBER_META_PROPERTY ) ;
407+ } else {
408+ Object . defineProperty ( obj , META_FIELD , META_DESC ) ;
409+ }
410+ }
411+
412+ obj [ META_FIELD ] = meta ;
413+ } ;
414+
415+ peekMeta = function Fallback_peekMeta ( obj ) {
416+ return obj [ META_FIELD ] ;
417+ } ;
418+
419+ deleteMeta = function Fallback_deleteMeta ( obj ) {
420+ if ( typeof obj [ META_FIELD ] !== 'object' ) {
421+ return ;
422+ }
423+ obj [ META_FIELD ] = null ;
424+ } ;
425+ }
426+
427+ export {
428+ peekMeta ,
429+ setMeta ,
430+ deleteMeta
370431} ;
371432
372433/**
@@ -403,14 +464,3 @@ export function meta(obj) {
403464 setMeta ( obj , newMeta ) ;
404465 return newMeta ;
405466}
406-
407- export function peekMeta ( obj ) {
408- return obj [ META_FIELD ] ;
409- }
410-
411- export function deleteMeta ( obj ) {
412- if ( typeof obj [ META_FIELD ] !== 'object' ) {
413- return ;
414- }
415- obj [ META_FIELD ] = null ;
416- }
0 commit comments