polyfill_EntryStore.js.html 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="utf-8">
  5. <title>JSDoc: Source: polyfill/EntryStore.js</title>
  6. <script src="scripts/prettify/prettify.js"> </script>
  7. <script src="scripts/prettify/lang-css.js"> </script>
  8. <!--[if lt IE 9]>
  9. <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
  10. <![endif]-->
  11. <link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
  12. <link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
  13. </head>
  14. <body>
  15. <div id="main">
  16. <h1 class="page-title">Source: polyfill/EntryStore.js</h1>
  17. <section>
  18. <article>
  19. <pre class="prettyprint source linenums"><code>// Licensed Materials - Property of IBM
  20. //
  21. // IBM Watson Analytics
  22. //
  23. // (C) Copyright IBM Corp. 2015
  24. //
  25. // US Government Users Restricted Rights - Use, duplication or
  26. // disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
  27. module.exports = ( function( ObjectPolyfill )
  28. {
  29. "use strict";
  30. /**
  31. * EntryStore provides the actual Map (and Set) implementation. Its implementation is shaped by two features:
  32. * 1. Attempt to achieve the O(1) lookup time of the native Map and Set types (for String and Number values).
  33. * 2. Support iterators according to the spec.
  34. *
  35. * Since we don't want to track iterators (as that would keep them alive indefinitely if iteration is aborted before end),
  36. * the EntryStore never re-uses or changes an entry index.
  37. * This allows iterators to keep pointing at a specific entry index, and look at the actual situation during the next call.
  38. * @class module:barejs/polyfill.EntryStore
  39. * @param {*} [_iterable] Optional: an iterable whose values will be added to the EntryStore.
  40. * @param {boolean} [_pair] Optional: if the EntryStore is used for a Map, this should be true
  41. * (iterable's values should be interpreted as key-value pairs, not as single values).
  42. */
  43. function EntryStore( _iterable, _pair )
  44. {
  45. this.entries = Object.create( null );
  46. // Note: skip index 0 so it is safe to use the entry index in boolean expressions.
  47. this.entries.start = this.entries.end = 1;
  48. this.clear();
  49. if ( _iterable )
  50. {
  51. // Use Array.from for iteration, as it normalizes iterables for us.
  52. // Only downside is that we're creating an array that is thrown away
  53. Array.from( _iterable, _pair === true ? this._setPair : this._setValue, this );
  54. }
  55. }
  56. ObjectPolyfill.polyfill( EntryStore, null,
  57. /** @lends module:barejs/polyfill.EntryStore# */
  58. {
  59. _setPair: function( _value )
  60. {
  61. if ( typeof _value !== "object" )
  62. throw new TypeError( "Iterator value " + String( _value ) + " is not an entry object" );
  63. this.set( _value[0], _value[1] );
  64. },
  65. _setValue: function( _value )
  66. {
  67. this.set( _value, _value );
  68. },
  69. /**
  70. * Find the next valid index, starting at _start
  71. * @param {number} _start The index to start looking at. If _start is in entries, start is returned.
  72. * @returns {number} The next valid index, or -1 if there is no next entry.
  73. */
  74. _nxt: function( _start )
  75. {
  76. for ( var i = Math.max( _start || 0, this.entries.start ), end = this.entries.end; i &lt; end; ++i )
  77. if ( i in this.entries )
  78. return i;
  79. return -1;
  80. },
  81. /**
  82. * Find the entry index for a key
  83. * @param _key The key to get the entry index for
  84. * @param _key The key to get the entry index for
  85. * @returns {number} The entry index, or -1
  86. */
  87. indexOf: function( _key )
  88. {
  89. switch ( typeof _key )
  90. {
  91. case "string":
  92. return this._stringKeys[ _key ] || -1;
  93. case "number":
  94. return this._numberKeys[ String( _key ) ] || -1;
  95. default:
  96. return this._otherKeyIds[ this._otherKeys.indexOf( _key ) ] || -1;
  97. }
  98. },
  99. /**
  100. * Set the entry for a key
  101. * @param {*} _key The key for the value.
  102. * @param {*} _value The value to set.
  103. */
  104. "set": function( _key, _value )
  105. {
  106. var idx = this.indexOf( _key );
  107. if ( idx &lt; 0 )
  108. {
  109. idx = this.entries.end++;
  110. ++this.size;
  111. switch ( typeof _key )
  112. {
  113. case "string":
  114. this._stringKeys[ _key ] = idx;
  115. break;
  116. case "number":
  117. this._numberKeys[ String( _key ) ] = idx;
  118. break;
  119. default:
  120. this._otherKeys.push( _key );
  121. this._otherKeyIds.push( idx );
  122. break;
  123. }
  124. this.entries[idx] = [_key, _value];
  125. }
  126. else
  127. {
  128. this.entries[idx][1] = _value;
  129. }
  130. },
  131. /**
  132. * Remove _key from the EntryStore
  133. * @param {*} _key The key to remove the value for
  134. * @returns {boolean} True if the value for _key got removed, false otherwise.
  135. */
  136. remove: function( _key )
  137. {
  138. var idx;
  139. switch ( typeof _key )
  140. {
  141. case "string":
  142. if ( ( idx = this._stringKeys[ _key ] || -1 ) >= 0 )
  143. delete this._stringKeys[ _key ];
  144. break;
  145. case "number":
  146. if ( ( idx = this._numberKeys[ String( _key ) ] || -1 ) >= 0 )
  147. delete this._numberKeys[ String( _key ) ];
  148. break;
  149. default:
  150. if ( ( idx = this._otherKeys.indexOf( _key ) ) >= 0 )
  151. {
  152. // Remove key
  153. this._otherKeys.splice( idx, 1 );
  154. // Remove index mapping, and update idx to the entry index
  155. idx = this._otherKeyIds.splice( idx, 1 )[0];
  156. }
  157. break;
  158. }
  159. var remove = idx >= 0;
  160. if ( remove )
  161. {
  162. // We already moved the key mapping, but we still need to drop the entry
  163. // (and potentially update the start value)
  164. delete this.entries[idx];
  165. --this.size;
  166. if ( idx === this.entries.start )
  167. {
  168. // If we removed the "start" value, update it
  169. idx = this._nxt( idx + 1 );
  170. this.entries.start = idx &lt; 0 ? this.entries.end : idx;
  171. }
  172. }
  173. return remove;
  174. },
  175. /**
  176. * Clear the EntryStore, removing all keys and associated values.
  177. */
  178. clear: function()
  179. {
  180. this._numberKeys = Object.create( null );
  181. this._stringKeys = Object.create( null );
  182. this._otherKeys = [];
  183. this._otherKeyIds = [];
  184. this.size = 0;
  185. // drop all entries
  186. for ( var i = this.entries.start, end = this.entries.end; i &lt; end; ++i )
  187. delete this.entries[i];
  188. // Update start to end
  189. this.entries.start = this.entries.end;
  190. },
  191. /**
  192. * Iterate the EntryStore (on behalf of _iterated)
  193. * @param {module:barejs/polyfill.EntryStore} _iterated The object to report as being iterated.
  194. * Since the EntryStore is an internal object to be used by a Set or Map it has to report the correct object.
  195. * @param {function} Callback: the iterator callback to call for every entry. Called with ( &amp;lt;key&amp;gt;, &amp;lt;value&amp;gt;, _iterated ).
  196. * @param {object} [_thisArg] Optional: object to use as context for the callback function
  197. */
  198. forEach: function( _iterated, _callback, _thisArg )
  199. {
  200. // Do NOT cache end, adding entries during iteration is allowed
  201. for ( var o = ObjectPolyfill.ensureCallable( _callback, _thisArg &amp;&amp; Object( _thisArg ) ), i = this._nxt(), entry; i >= 0; i = this._nxt( i + 1 ) )
  202. {
  203. entry = this.entries[i];
  204. _callback.call( o, entry[1], entry[0], _iterated );
  205. }
  206. }
  207. }, null, "EntryStore" );
  208. // This is NOT the native Iterator...
  209. //jshint -W121
  210. /**
  211. * @class module:barejs/polyfill.EntryStore.Iterator
  212. * @classdesc Base class Iterator for a class using the EntryStore
  213. */
  214. function Iterator( _kind, _store )
  215. {
  216. this._kind = _kind;
  217. this._next = _store._nxt();
  218. if ( this._next >= 0 )
  219. this._store = _store;
  220. }
  221. ObjectPolyfill.polyfill( Iterator, null,
  222. /** @lends module:barejs/polyfill.EntryStore.Iterator# */
  223. {
  224. /**
  225. * Get the next value
  226. * @returns {object} An object containing a done and value property.
  227. */
  228. next: function next()
  229. {
  230. var entry, // Note: entry is used to get an undefined value (minification optimisation)
  231. result = { value: entry, done: this._next &lt; 0 };
  232. if ( !result.done )
  233. {
  234. var store = this._store,
  235. // use _nxt to check if there is still an entry at _next
  236. next = this._next = store._nxt( this._next );
  237. // If we're done iterating, remove the reference to _store
  238. if ( next &lt; 0 )
  239. {
  240. // All entries at next (and possibly afterwards) got removed, mark the iterator done
  241. result.done = true;
  242. // Clear link to _store since we don't need it anymore
  243. this._store = null;
  244. }
  245. else
  246. {
  247. entry = store.entries[next];
  248. switch ( this._kind )
  249. {
  250. case "key":
  251. result.value = entry[0];
  252. break;
  253. case "value":
  254. result.value = entry[1];
  255. break;
  256. default:
  257. // Don't expose our inner array, make a copy
  258. result.value = entry.slice( 0, 2 );
  259. break;
  260. }
  261. this._next = store._nxt( next + 1 );
  262. }
  263. }
  264. return result;
  265. }
  266. }, null, "Iterator" );
  267. ObjectPolyfill.defineProperty( EntryStore, "Iterator", { value: Iterator } );
  268. ObjectPolyfill.setIterator( Iterator.prototype, /*istanbul ignore next*/ function()
  269. {
  270. //jshint validthis:true
  271. return this;
  272. } );
  273. return EntryStore;
  274. }( require( "./Object" ) ) );
  275. </code></pre>
  276. </article>
  277. </section>
  278. </div>
  279. <nav>
  280. <h2><a href="index.html">Home</a></h2><h3>Modules</h3><ul><li><a href="module-barejs.html">barejs</a></li><li><a href="module-barejs_polyfill.html">barejs/polyfill</a></li><li><a href="module-barejs_polyfill_Intl.html">barejs/polyfill/Intl</a></li></ul><h3>Classes</h3><ul><li><a href="module-barejs.decl.html">decl</a></li><li><a href="module-barejs.decl-Enum.html">Enum</a></li><li><a href="module-barejs.decl-Interface.html">Interface</a></li><li><a href="module-barejs.decl-SpecialType.html">SpecialType</a></li><li><a href="module-barejs.Destroyable.html">Destroyable</a></li><li><a href="module-barejs.EventArgs.html">EventArgs</a></li><li><a href="module-barejs.Evented.html">Evented</a></li><li><a href="module-barejs.Evented-EventedHandle.html">EventedHandle</a></li><li><a href="module-barejs.Exception.html">Exception</a></li><li><a href="module-barejs_polyfill.Array.html">Array</a></li><li><a href="module-barejs_polyfill.Date.html">Date</a></li><li><a href="module-barejs_polyfill.EntryStore.html">EntryStore</a></li><li><a href="module-barejs_polyfill.EntryStore.Iterator.html">Iterator</a></li><li><a href="module-barejs_polyfill.Function.html">Function</a></li><li><a href="module-barejs_polyfill.Map.html">Map</a></li><li><a href="module-barejs_polyfill.Map-MapIterator.html">MapIterator</a></li><li><a href="module-barejs_polyfill.Math.html">Math</a></li><li><a href="module-barejs_polyfill.Number.html">Number</a></li><li><a href="module-barejs_polyfill.Object.html">Object</a></li><li><a href="module-barejs_polyfill.Promise.html">Promise</a></li><li><a href="module-barejs_polyfill.Set.html">Set</a></li><li><a href="module-barejs_polyfill.Set-SetIterator.html">SetIterator</a></li><li><a href="module-barejs_polyfill.String.html">String</a></li><li><a href="module-barejs_polyfill.Symbol.html">Symbol</a></li><li><a href="module-barejs_polyfill.WeakMap.html">WeakMap</a></li><li><a href="module-barejs_polyfill.WeakSet.html">WeakSet</a></li><li><a href="module-barejs_polyfill_Intl.DateTimeFormat.html">DateTimeFormat</a></li><li><a href="module-barejs_polyfill_Intl.DateTimeFormat-DateTimeFormatOptions.html">DateTimeFormatOptions</a></li><li><a href="module-barejs_polyfill_Intl.NumberFormat.html">NumberFormat</a></li><li><a href="module-barejs_polyfill_Intl.NumberFormat-NumberFormatOptions.html">NumberFormatOptions</a></li><li><a href="module-barejs_polyfill_Intl-Format.html">Format</a></li></ul>
  281. </nav>
  282. <br class="clear">
  283. <footer>
  284. Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.5.5</a> on Wed Oct 03 2018 15:59:34 GMT+0200 (W. Europe Daylight Time)
  285. </footer>
  286. <script> prettyPrint(); </script>
  287. <script src="scripts/linenumber.js"> </script>
  288. </body>
  289. </html>