PageRenderTime 106ms CodeModel.GetById 43ms RepoModel.GetById 2ms app.codeStats 1ms

/src/Iterator.js

http://github.com/polygonplanet/Pot.js
JavaScript | 5493 lines | 2780 code | 27 blank | 2686 comment | 585 complexity | 8d9d63e74320019e6aa96e877f271dcb MD5 | raw file
  1. //-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
  2. // Define iteration methods. (internal)
  3. (function() {
  4. var LightIterator,
  5. QuickIteration,
  6. createLightIterateConstructor,
  7. createSyncIterator;
  8. update(PotInternal, {
  9. /**
  10. * @lends Pot.Internal
  11. */
  12. /**
  13. * LightIterator.
  14. *
  15. * Async/Sync iterator.
  16. *
  17. * @class
  18. * @private
  19. * @constructor
  20. * @ignore
  21. */
  22. LightIterator : update(function(object, callback, options) {
  23. return new LightIterator.fn.doit(
  24. object, callback, options
  25. );
  26. }, {
  27. /**@ignore*/
  28. speeds : {
  29. limp : -1,
  30. doze : 0,
  31. slow : 2,
  32. normal : 5,
  33. fast : 12,
  34. rapid : 36,
  35. ninja : 60
  36. },
  37. /**@ignore*/
  38. delays : {
  39. limp : 1000,
  40. doze : 100,
  41. slow : 13,
  42. normal : 0,
  43. fast : 0,
  44. rapid : 0,
  45. ninja : 0
  46. },
  47. /**@ignore*/
  48. types : {
  49. forLoop : 0x01,
  50. forInLoop : 0x02,
  51. repeat : 0x04,
  52. forEver : 0x08,
  53. iterate : 0x10,
  54. items : 0x20,
  55. zip : 0x40
  56. }
  57. })
  58. });
  59. // Refer the Pot properties/functions.
  60. PotInternalLightIterator = LightIterator = PotInternal.LightIterator;
  61. update(LightIterator, {
  62. /**@ignore*/
  63. defaults : {
  64. speed : LightIterator.speeds.normal
  65. },
  66. /**@ignore*/
  67. revSpeeds : {}
  68. });
  69. each(LightIterator.speeds, function(v, k) {
  70. LightIterator.revSpeeds[v] = k;
  71. });
  72. LightIterator.fn = LightIterator.prototype =
  73. update(LightIterator.prototype, {
  74. /**
  75. * @lends Pot.Internal.LightIterator.prototype
  76. */
  77. /**
  78. * @ignore
  79. */
  80. constructor : LightIterator,
  81. /**
  82. * @private
  83. * @ignore
  84. */
  85. interval : LightIterator.defaults.speed,
  86. /**
  87. * @private
  88. * @ignore
  89. */
  90. iter : null,
  91. /**
  92. * @private
  93. * @ignore
  94. */
  95. result : null,
  96. /**
  97. * @private
  98. * @ignore
  99. */
  100. deferred : null,
  101. /**
  102. * @private
  103. * @ignore
  104. */
  105. revDeferred : null,
  106. /**
  107. * @private
  108. * @ignore
  109. */
  110. isDeferStopIter : false,
  111. /**
  112. * @private
  113. * @ignore
  114. */
  115. time : {},
  116. /**
  117. * @private
  118. * @ignore
  119. */
  120. waiting : false,
  121. /**
  122. * @private
  123. * @ignore
  124. */
  125. restable : false,
  126. /**
  127. * @private
  128. * @ignore
  129. */
  130. async : false,
  131. /**
  132. * @private
  133. * @ignore
  134. */
  135. options : null,
  136. /**
  137. * @private
  138. * @ignore
  139. */
  140. doit : function(object, callback, options) {
  141. this.setOptions(options);
  142. this.execute(object, callback);
  143. this.watch();
  144. return this;
  145. },
  146. /**
  147. * Set the options.
  148. *
  149. * @private
  150. * @ignore
  151. */
  152. setOptions : function(options) {
  153. this.options = options || {};
  154. this.setInterval();
  155. this.setAsync();
  156. },
  157. /**
  158. * Set the interval option.
  159. *
  160. * @private
  161. * @ignore
  162. */
  163. setInterval : function() {
  164. var n = null;
  165. if (isNumeric(this.options.interval)) {
  166. n = this.options.interval - 0;
  167. } else if (this.options.interval in LightIterator.speeds) {
  168. n = LightIterator.speeds[this.options.interval] - 0;
  169. }
  170. if (n !== null && !isNaN(n)) {
  171. this.interval = n;
  172. }
  173. if (!isNumeric(this.interval)) {
  174. this.interval = LightIterator.defaults.speed;
  175. }
  176. },
  177. /**
  178. * Set the async option.
  179. *
  180. * @private
  181. * @ignore
  182. */
  183. setAsync : function() {
  184. var a = null;
  185. if (this.options.async !== void 0) {
  186. a = !!this.options.async;
  187. }
  188. if (a !== null) {
  189. this.async = !!a;
  190. }
  191. if (!isBoolean(this.async)) {
  192. this.async = !!this.async;
  193. }
  194. },
  195. /**
  196. * Create a new Deferred.
  197. *
  198. * @private
  199. * @ignore
  200. */
  201. createDeferred : function() {
  202. return new Deferred({ async : false });
  203. },
  204. /**
  205. * Watch the process.
  206. *
  207. * @private
  208. * @ignore
  209. */
  210. watch : function() {
  211. var that = this;
  212. if (!this.async && this.waiting === true && PotSystem.isWaitable) {
  213. Pot.XPCOM.throughout(function() {
  214. return that.waiting !== true;
  215. });
  216. }
  217. },
  218. /**
  219. * Execute process.
  220. *
  221. * @private
  222. * @ignore
  223. */
  224. execute : function(object, callback) {
  225. var d, that = this;
  226. this.waiting = true;
  227. if (!object) {
  228. this.result = {};
  229. this.waiting = false;
  230. } else {
  231. this.waiting = true;
  232. this.restable = true;
  233. this.time = {
  234. start : now(),
  235. total : null,
  236. loop : null,
  237. diff : null,
  238. risk : null,
  239. axis : null,
  240. count : 1,
  241. rest : 100,
  242. limit : 255
  243. };
  244. this.setIter(object, callback);
  245. if (!this.async && !PotSystem.isWaitable) {
  246. this.revback();
  247. this.waiting = false;
  248. } else {
  249. d = this.createDeferred();
  250. d.then(function() {
  251. var d1 = that.createDeferred(),
  252. d2 = that.createDeferred();
  253. d1.then(function() {
  254. return that.revolve().then(function() {
  255. d2.begin();
  256. });
  257. }).begin();
  258. return d2;
  259. }).ensure(function() {
  260. that.waiting = false;
  261. });
  262. if (this.async) {
  263. this.deferred = d.then(function() {
  264. if (isDeferred(that.result) &&
  265. isStopIter(Deferred.lastError(that.result))) {
  266. that.result = Deferred.lastResult(that.result);
  267. }
  268. return that.result;
  269. });
  270. }
  271. this.flush(d);
  272. }
  273. }
  274. },
  275. /**
  276. * @private
  277. * @ignore
  278. */
  279. setIter : function(object, callback) {
  280. var type = this.options.type,
  281. types = LightIterator.types,
  282. context = this.options.context;
  283. switch (true) {
  284. case ((type & types.iterate) === types.iterate):
  285. this.result = null;
  286. this.iter = this.iterate(object, callback, context);
  287. break;
  288. case ((type & types.forEver) === types.forEver):
  289. this.result = {};
  290. this.iter = this.forEver(object, context);
  291. break;
  292. case ((type & types.repeat) === types.repeat):
  293. this.result = {};
  294. this.iter = this.repeat(object, callback, context);
  295. break;
  296. case ((type & types.items) === types.items):
  297. this.result = [];
  298. this.iter = this.items(object, callback, context);
  299. break;
  300. case ((type & types.zip) === types.zip):
  301. this.result = [];
  302. this.iter = this.zip(object, callback, context);
  303. break;
  304. default:
  305. if (isArrayLike(object)) {
  306. this.result = object;
  307. this.iter = this.forLoop(object, callback, context);
  308. } else {
  309. this.result = object;
  310. this.iter = this.forInLoop(object, callback, context);
  311. }
  312. }
  313. },
  314. /**
  315. * @private
  316. * @ignore
  317. */
  318. revback : function() {
  319. var that = this, result, err, cutback = false, time;
  320. this.time.loop = now();
  321. REVOLVE: {
  322. do {
  323. try {
  324. if (this.isDeferStopIter) {
  325. this.isDeferStopIter = false;
  326. throw PotStopIteration;
  327. }
  328. result = this.iter.next();
  329. } catch (e) {
  330. err = e;
  331. if (isStopIter(err)) {
  332. break REVOLVE;
  333. }
  334. throw err;
  335. }
  336. if (this.async && isDeferred(result)) {
  337. return result.ensure(function(res) {
  338. if (res !== void 0) {
  339. if (isError(res)) {
  340. if (isStopIter(res)) {
  341. that.isDeferStopIter = true;
  342. if (isDeferred(that.result) &&
  343. isStopIter(Deferred.lastError(that.result))) {
  344. that.result = Deferred.lastResult(that.result);
  345. }
  346. } else {
  347. Deferred.lastError(this, res);
  348. }
  349. } else {
  350. Deferred.lastResult(this, res);
  351. }
  352. }
  353. that.flush(that.revback, true);
  354. });
  355. }
  356. time = now();
  357. if (PotSystem.isWaitable) {
  358. if (this.time.total === null) {
  359. this.time.total = time;
  360. } else if (time - this.time.total >= this.time.rest) {
  361. Pot.XPCOM.throughout(0);
  362. this.time.total = now();
  363. }
  364. } else if (!this.async) {
  365. if (this.restable && this.time.count >= this.time.limit) {
  366. this.restable = false;
  367. }
  368. }
  369. this.time.risk = time - this.time.start;
  370. this.time.diff = time - this.time.loop;
  371. if (this.time.diff >= this.interval) {
  372. if (this.async &&
  373. this.interval < LightIterator.speeds.normal) {
  374. cutback = true;
  375. } else if (this.async || this.restable || PotSystem.isWaitable) {
  376. if (this.time.diff < this.interval + 8) {
  377. this.time.axis = 2;
  378. } else if (this.time.diff < this.interval + 36) {
  379. this.time.axis = 5;
  380. } else if (this.time.diff < this.interval + 48) {
  381. this.time.axis = 7;
  382. } else {
  383. this.time.axis = 10;
  384. }
  385. if (this.time.axis >= 10 ||
  386. (Math.random() * 10 < this.time.axis)) {
  387. cutback = true;
  388. }
  389. }
  390. }
  391. } while (!cutback);
  392. if (this.time.count <= this.time.limit) {
  393. this.time.count++;
  394. }
  395. return this.flush(this.revback, true);
  396. }
  397. if (isDeferred(this.revDeferred)) {
  398. this.revDeferred.begin();
  399. }
  400. },
  401. /**
  402. * Revolve the process.
  403. *
  404. * @private
  405. * @ignore
  406. */
  407. revolve : function() {
  408. var that = this,
  409. d = this.createDeferred(),
  410. de = this.createDeferred();
  411. d.then(function() {
  412. var dd = that.createDeferred();
  413. that.revDeferred = that.createDeferred();
  414. dd.then(function() {
  415. return that.revback();
  416. }).begin();
  417. return that.revDeferred;
  418. }).ensure(function(er) {
  419. de.begin();
  420. if (isError(er)) {
  421. throw er;
  422. }
  423. });
  424. this.flush(d);
  425. return de;
  426. },
  427. /**
  428. * Flush the callback.
  429. *
  430. * @private
  431. * @ignore
  432. */
  433. flush : function(callback, useSpeed) {
  434. var that = this, d, lazy = false, speed, speedKey;
  435. if (this.async || PotSystem.isWaitable) {
  436. lazy = true;
  437. }
  438. if (!lazy && isFunction(callback)) {
  439. return callback.call(this);
  440. } else {
  441. d = this.createDeferred();
  442. d.then(function() {
  443. if (isDeferred(callback)) {
  444. callback.begin();
  445. } else {
  446. callback.call(that);
  447. }
  448. });
  449. if (lazy) {
  450. speed = 0;
  451. if (useSpeed) {
  452. speedKey = LightIterator.revSpeeds[this.interval];
  453. if (speedKey &&
  454. isNumeric(LightIterator.delays[speedKey])) {
  455. speed = LightIterator.delays[speedKey];
  456. }
  457. if (Math.random() * 10 < Math.max(2, (this.time.axis || 2) / 2.75)) {
  458. speed += Math.min(
  459. this.time.rest,
  460. Math.max(1,
  461. Math.ceil(
  462. (this.time.risk / (this.time.rest + this.time.diff)) +
  463. this.time.diff
  464. )
  465. )
  466. );
  467. }
  468. }
  469. PotInternalSetTimeout(function() {
  470. d.begin();
  471. }, speed);
  472. } else {
  473. d.begin();
  474. }
  475. }
  476. },
  477. /**
  478. * Return noop function.
  479. *
  480. * @private
  481. * @ignore
  482. */
  483. noop : function() {
  484. return {
  485. /**@ignore*/
  486. next : function() {
  487. throw PotStopIteration;
  488. }
  489. };
  490. },
  491. /**
  492. * forEver.
  493. *
  494. * @private
  495. * @ignore
  496. */
  497. forEver : function(callback, context) {
  498. var i = 0;
  499. if (!isFunction(callback)) {
  500. return this.noop();
  501. }
  502. return {
  503. /**@ignore*/
  504. next : function() {
  505. var result = callback.call(context, i);
  506. try {
  507. if (!isFinite(++i) || i >= Number.MAX_VALUE) {
  508. throw 0;
  509. }
  510. } catch (ex) {
  511. i = 0;
  512. }
  513. return result;
  514. }
  515. };
  516. },
  517. /**
  518. * repeat.
  519. *
  520. * @private
  521. * @ignore
  522. */
  523. repeat : function(max, callback, context) {
  524. var i, loops, n, last;
  525. if (!isFunction(callback)) {
  526. return this.noop();
  527. }
  528. if (!max || max == null) {
  529. n = 0;
  530. } else if (isNumeric(max)) {
  531. n = max - 0;
  532. } else {
  533. n = max || {};
  534. if (isNumeric(n.start)) {
  535. n.begin = n.start;
  536. }
  537. if (isNumeric(n.stop)) {
  538. n.end = n.stop;
  539. }
  540. }
  541. loops = {
  542. begin : isNumeric(n.begin) ? n.begin - 0 : 0,
  543. end : isNumeric(n.end) ? n.end - 0 : (n || 0) - 0,
  544. step : isNumeric(n.step) ? n.step - 0 : 1,
  545. last : false,
  546. prev : null
  547. };
  548. i = loops.step ? loops.begin : loops.end;
  549. last = loops.end - loops.step;
  550. return {
  551. /**@ignore*/
  552. next : function() {
  553. var result;
  554. if (i < loops.end) {
  555. loops.last = (i >= last);
  556. result = callback.call(context, i, loops.last, loops);
  557. loops.prev = result;
  558. } else {
  559. throw PotStopIteration;
  560. }
  561. i += loops.step;
  562. return result;
  563. }
  564. };
  565. },
  566. /**
  567. * forLoop.
  568. *
  569. * @private
  570. * @ignore
  571. */
  572. forLoop : function(object, callback, context) {
  573. var copy, i = 0;
  574. if (!object || !object.length || !isFunction(callback)) {
  575. return this.noop();
  576. }
  577. copy = arrayize(object);
  578. return {
  579. /**@ignore*/
  580. next : function() {
  581. var val, result;
  582. while (true) {
  583. if (i >= copy.length) {
  584. throw PotStopIteration;
  585. }
  586. if (!(i in copy)) {
  587. i++;
  588. continue;
  589. }
  590. try {
  591. val = copy[i];
  592. } catch (e) {
  593. i++;
  594. continue;
  595. }
  596. result = callback.call(context, val, i, object);
  597. i++;
  598. return result;
  599. }
  600. }
  601. };
  602. },
  603. /**
  604. * forInLoop.
  605. *
  606. * @private
  607. * @ignore
  608. */
  609. forInLoop : function(object, callback, context) {
  610. var copy, i = 0;
  611. //XXX: Should use "yield" for duplicate loops.
  612. if (isFunction(callback)) {
  613. copy = [];
  614. each(object, function(value, prop) {
  615. copy[copy.length] = [value, prop];
  616. });
  617. }
  618. if (!copy || !copy.length) {
  619. return this.noop();
  620. }
  621. return {
  622. /**@ignore*/
  623. next : function() {
  624. var result, c, key, val;
  625. while (true) {
  626. if (i >= copy.length) {
  627. throw PotStopIteration;
  628. }
  629. if (!(i in copy)) {
  630. i++;
  631. continue;
  632. }
  633. try {
  634. c = copy[i];
  635. val = c[0];
  636. key = c[1];
  637. } catch (e) {
  638. i++;
  639. continue;
  640. }
  641. result = callback.call(context, val, key, object);
  642. i++;
  643. return result;
  644. }
  645. }
  646. };
  647. },
  648. /**
  649. * iterate.
  650. *
  651. * @private
  652. * @ignore
  653. */
  654. iterate : function(object, callback, context) {
  655. var that = this, iterable;
  656. if (Pot.isIterable(object) && !Pot.isIter(object)) {
  657. // using "yield" generator.
  658. if (isFunction(callback)) {
  659. return {
  660. /**@ignore*/
  661. next : function() {
  662. var res = object.next();
  663. that.result = callback.apply(context, arrayize(res));
  664. return that.result;
  665. }
  666. };
  667. } else {
  668. return {
  669. /**@ignore*/
  670. next : function() {
  671. that.result = object.next();
  672. return that.result;
  673. }
  674. };
  675. }
  676. } else {
  677. iterable = Iter.toIter(object);
  678. if (!isIter(iterable)) {
  679. return this.noop();
  680. }
  681. if (isFunction(callback)) {
  682. return {
  683. /**@ignore*/
  684. next : function() {
  685. var results = iterable.next();
  686. results = arrayize(results);
  687. while (results.length < 2) {
  688. results.push((void 0));
  689. }
  690. results.push(object);
  691. that.result = callback.apply(context, results);
  692. return that.result;
  693. }
  694. };
  695. } else {
  696. return {
  697. /**@ignore*/
  698. next : function() {
  699. that.result = iterable.next();
  700. return that.result;
  701. }
  702. };
  703. }
  704. }
  705. },
  706. /**
  707. * items format loop.
  708. *
  709. * @private
  710. * @ignore
  711. */
  712. items : function(object, callback, context) {
  713. var that = this, copy, i = 0, isPair;
  714. if (isObject(object)) {
  715. copy = [];
  716. each(object, function(ov, op) {
  717. copy[copy.length] = [op, ov];
  718. });
  719. isPair = true;
  720. } else if (isArrayLike(object)) {
  721. copy = arrayize(object);
  722. }
  723. if (!copy || !copy.length) {
  724. return this.noop();
  725. }
  726. if (isFunction(callback)) {
  727. return {
  728. /**@ignore*/
  729. next : function() {
  730. var result, c, key, val;
  731. while (true) {
  732. if (i >= copy.length) {
  733. throw PotStopIteration;
  734. }
  735. if (!(i in copy)) {
  736. i++;
  737. continue;
  738. }
  739. try {
  740. c = copy[i];
  741. if (isPair) {
  742. key = c[0];
  743. val = c[1];
  744. } else {
  745. key = i;
  746. val = c;
  747. }
  748. } catch (e) {
  749. i++;
  750. continue;
  751. }
  752. result = callback.call(context, [key, val], object);
  753. i++;
  754. that.result[that.result.length] = result;
  755. return result;
  756. }
  757. }
  758. };
  759. } else {
  760. return {
  761. /**@ignore*/
  762. next : function() {
  763. var r, t, k, v;
  764. while (true) {
  765. if (i >= copy.length) {
  766. throw PotStopIteration;
  767. }
  768. if (!(i in copy)) {
  769. i++;
  770. continue;
  771. }
  772. try {
  773. t = copy[i];
  774. if (isPair) {
  775. k = t[0];
  776. v = t[1];
  777. } else {
  778. k = i;
  779. v = t;
  780. }
  781. } catch (e) {
  782. i++;
  783. continue;
  784. }
  785. i++;
  786. r = [k, v];
  787. that.result[that.result.length] = r;
  788. return r;
  789. }
  790. }
  791. };
  792. }
  793. },
  794. /**
  795. * zip iteration.
  796. *
  797. * @private
  798. * @ignore
  799. */
  800. zip : function(object, callback, context) {
  801. var that = this, copy, i = 0, max;
  802. if (isArrayLike(object)) {
  803. copy = arrayize(object);
  804. max = copy.length;
  805. }
  806. if (!max || !copy || !copy.length) {
  807. return this.noop();
  808. }
  809. if (isFunction(callback)) {
  810. return {
  811. /**@ignore*/
  812. next : function() {
  813. var result, zips = [], j, item;
  814. for (j = 0; j < max; j++) {
  815. item = arrayize(copy[j]);
  816. if (!item || !item.length || i >= item.length) {
  817. throw PotStopIteration;
  818. }
  819. zips[zips.length] = item[i];
  820. }
  821. result = callback.call(context, zips, object);
  822. that.result[that.result.length] = result;
  823. i++;
  824. return result;
  825. }
  826. };
  827. } else {
  828. return {
  829. /**@ignore*/
  830. next : function() {
  831. var z = [], k, t;
  832. for (k = 0; k < max; k++) {
  833. t = arrayize(copy[k]);
  834. if (!t || !t.length || i >= t.length) {
  835. throw PotStopIteration;
  836. }
  837. z[z.length] = t[i];
  838. }
  839. that.result[that.result.length] = z;
  840. i++;
  841. return z;
  842. }
  843. };
  844. }
  845. }
  846. });
  847. LightIterator.fn.doit.prototype = LightIterator.fn;
  848. // Update internal synchronous iteration.
  849. update(LightIterator, {
  850. /**
  851. * @lends Pot.Internal.LightIterator
  852. */
  853. /**
  854. * Quick iteration for synchronous.
  855. *
  856. * @type Object
  857. * @class
  858. * @private
  859. * @ignore
  860. */
  861. QuickIteration : {
  862. /**
  863. * @lends Pot.Internal.LightIterator.QuickIteration
  864. */
  865. /**
  866. * @private
  867. * @ignore
  868. */
  869. resolve : function(iter) {
  870. var err;
  871. try {
  872. while (true) {
  873. iter.next();
  874. }
  875. } catch (e) {
  876. err = e;
  877. if (!isStopIter(err)) {
  878. throw err;
  879. }
  880. }
  881. },
  882. /**
  883. * @private
  884. * @ignore
  885. */
  886. forEach : function(object, callback, context) {
  887. var result, iter, that = LightIterator.fn;
  888. if (!object) {
  889. result = {};
  890. } else {
  891. result = object;
  892. if (isArrayLike(object)) {
  893. iter = that.forLoop(object, callback, context);
  894. } else {
  895. iter = that.forInLoop(object, callback, context);
  896. }
  897. QuickIteration.resolve(iter);
  898. }
  899. return result;
  900. },
  901. /**
  902. * @private
  903. * @ignore
  904. */
  905. repeat : function(max, callback, context) {
  906. var result = {}, iter, that = LightIterator.fn;
  907. if (max) {
  908. iter = that.repeat(max, callback, context);
  909. QuickIteration.resolve(iter);
  910. }
  911. return result;
  912. },
  913. /**
  914. * @private
  915. * @ignore
  916. */
  917. forEver : function(callback, context) {
  918. var result = {}, iter, that = LightIterator.fn;
  919. if (callback) {
  920. iter = that.forEver(callback, context);
  921. QuickIteration.resolve(iter);
  922. }
  923. return result;
  924. },
  925. /**
  926. * @private
  927. * @ignore
  928. */
  929. iterate : function(object, callback, context) {
  930. var result, iter, o, that = LightIterator.fn;
  931. if (!object) {
  932. result = {};
  933. } else {
  934. result = null;
  935. o = {
  936. noop : that.noop,
  937. result : null
  938. };
  939. iter = that.iterate.call(o, object, callback, context);
  940. QuickIteration.resolve(iter);
  941. result = o.result;
  942. }
  943. return result;
  944. },
  945. /**
  946. * @private
  947. * @ignore
  948. */
  949. items : function(object, callback, context) {
  950. var result = [], iter, o, that = LightIterator.fn;
  951. if (object) {
  952. o = {
  953. noop : that.noop,
  954. result : []
  955. };
  956. iter = that.items.call(o, object, callback, context);
  957. QuickIteration.resolve(iter);
  958. result = o.result;
  959. }
  960. return result;
  961. },
  962. /**
  963. * @private
  964. * @ignore
  965. */
  966. zip : function(object, callback, context) {
  967. var result = [], iter, o, that = LightIterator.fn;
  968. if (object) {
  969. o = {
  970. noop : that.noop,
  971. result : []
  972. };
  973. iter = that.zip.call(o, object, callback, context);
  974. QuickIteration.resolve(iter);
  975. result = o.result;
  976. }
  977. return result;
  978. }
  979. }
  980. });
  981. QuickIteration = LightIterator.QuickIteration;
  982. //-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
  983. // Define the main iterators.
  984. // Temporary creation function.
  985. update(PotTmp, {
  986. /**
  987. * @lends Pot.tmp
  988. */
  989. /**
  990. * @private
  991. * @ignore
  992. */
  993. createLightIterateConstructor : function(creator) {
  994. var
  995. name,
  996. /**@ignore*/
  997. create = function(speed) {
  998. var interval;
  999. if (LightIterator.speeds[speed] === void 0) {
  1000. interval = LightIterator.defaults.speed;
  1001. } else {
  1002. interval = LightIterator.speeds[speed];
  1003. }
  1004. return creator(interval);
  1005. },
  1006. methods = {},
  1007. construct = create();
  1008. for (name in LightIterator.speeds) {
  1009. methods[name] = create(name);
  1010. }
  1011. return update(construct, methods);
  1012. }
  1013. });
  1014. createLightIterateConstructor = PotTmp.createLightIterateConstructor;
  1015. // Define the iterator functions to evaluate as synchronized.
  1016. Pot.update({
  1017. /**
  1018. * @lends Pot
  1019. */
  1020. /**
  1021. * Iterates as "for each" loop.
  1022. *
  1023. *
  1024. * @desc
  1025. * <pre>
  1026. * Unlike Deferred, speed options affect to cutback count in loop.
  1027. * Options append to after the forEach and execute it.
  1028. *
  1029. * e.g. Pot.forEach.slow(obj, function() {...})
  1030. *
  1031. * The available methods are below.
  1032. * ------------------------------------
  1033. * method name | speed
  1034. * ------------------------------------
  1035. * limp : slowest
  1036. * doze : slower
  1037. * slow : slow
  1038. * normal : normal (default)
  1039. * fast : fast
  1040. * rapid : faster
  1041. * ninja : fastest
  1042. * ------------------------------------
  1043. * </pre>
  1044. *
  1045. *
  1046. * @example
  1047. * var a = 0;
  1048. * Pot.forEach([1, 2, 3], function(value) {
  1049. * a += value;
  1050. * });
  1051. * debug(a);
  1052. * // @results 6
  1053. *
  1054. *
  1055. * @example
  1056. * var a = '';
  1057. * Pot.forEach({a:'foo', b:'bar'}, function(value, key) {
  1058. * a += key + '=' + value + ',';
  1059. * });
  1060. * debug(a);
  1061. * // @results 'a=foo,b=bar,'
  1062. *
  1063. *
  1064. * @param {Array|Object} object A target object.
  1065. * @param {Function} callback An iterable function.
  1066. * function(value, key, object)
  1067. * this == `context`.
  1068. * Throw Pot.StopIteration
  1069. * if you want to stop the loop.
  1070. * @param {*} (context) Optionally, context object. (i.e. this)
  1071. * @result {Object} Return the object.
  1072. * @class
  1073. * @function
  1074. * @static
  1075. * @name Pot.forEach
  1076. * @property {Function} limp Iterates "for each" loop with slowest speed.
  1077. * @property {Function} doze Iterates "for each" loop with slower speed.
  1078. * @property {Function} slow Iterates "for each" loop with slow speed.
  1079. * @property {Function} normal Iterates "for each" loop with default speed.
  1080. * @property {Function} fast Iterates "for each" loop with fast speed.
  1081. * @property {Function} rapid Iterates "for each" loop with faster speed.
  1082. * @property {Function} ninja Iterates "for each" loop with fastest speed.
  1083. */
  1084. forEach : createLightIterateConstructor(function(interval) {
  1085. if (PotSystem.isWaitable &&
  1086. interval < LightIterator.speeds.normal) {
  1087. return function(object, callback, context) {
  1088. var opts = {};
  1089. opts.type = LightIterator.types.forLoop |
  1090. LightIterator.types.forInLoop;
  1091. opts.interval = interval;
  1092. opts.async = false;
  1093. opts.context = context;
  1094. return (new LightIterator(object, callback, opts)).result;
  1095. };
  1096. } else {
  1097. return function(object, callback, context) {
  1098. return QuickIteration.forEach(
  1099. object, callback, context
  1100. );
  1101. };
  1102. }
  1103. }),
  1104. /**
  1105. * "repeat" loop iterates a specified number.
  1106. *
  1107. * The second argument of the callback function is
  1108. * passed the value to true only for the end of the loop.
  1109. *
  1110. * The first argument can pass as object
  1111. * that gives names "begin, end, step" any keys.
  1112. *
  1113. *
  1114. * @example
  1115. * var a = [];
  1116. * Pot.repeat(10, function(i) {
  1117. * a.push(i);
  1118. * });
  1119. * debug(a);
  1120. * // @results [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
  1121. *
  1122. *
  1123. * @example
  1124. * //
  1125. * // The second argument of the callback function is
  1126. * // passed the value to true only for the end of the loop.
  1127. * //
  1128. * var s = '', a = 'abcdef'.split('');
  1129. * Pot.repeat(a.length, function(i, last) {
  1130. * s += a[i] + '=' + i + (last ? ';' : ',');
  1131. * });
  1132. * debug(s);
  1133. * // @results 'a=0,b=1,c=2,d=3,e=4,f=5;'
  1134. *
  1135. *
  1136. * @example
  1137. * //
  1138. * // The first argument can pass as object
  1139. * // that gives names "begin, end, step" any keys.
  1140. * //
  1141. * var a = [];
  1142. * Pot.repeat({begin: 0, end: 100, step: 10}, function(i) {
  1143. * a.push(i);
  1144. * });
  1145. * debug(a);
  1146. * // @results [0, 10, 20, 30, 40, 50, 60, 70, 80, 90]
  1147. *
  1148. *
  1149. * @param {Number|Object} max The maximum number of times to loop,
  1150. * or object.
  1151. * @param {Function} callback An iterable function.
  1152. * Throw Pot.StopIteration
  1153. * if you want to stop the loop.
  1154. * @param {*} (context) Optionally, context object. (i.e. this)
  1155. * @class
  1156. * @function
  1157. * @static
  1158. * @name Pot.repeat
  1159. * @property {Function} limp Iterates "repeat" loop with slowest speed.
  1160. * @property {Function} doze Iterates "repeat" loop with slower speed.
  1161. * @property {Function} slow Iterates "repeat" loop with slow speed.
  1162. * @property {Function} normal Iterates "repeat" loop with default speed.
  1163. * @property {Function} fast Iterates "repeat" loop with fast speed.
  1164. * @property {Function} rapid Iterates "repeat" loop with faster speed.
  1165. * @property {Function} ninja Iterates "repeat" loop with fastest speed.
  1166. */
  1167. repeat : createLightIterateConstructor(function(interval) {
  1168. if (PotSystem.isWaitable &&
  1169. interval < LightIterator.speeds.normal) {
  1170. return function(max, callback, context) {
  1171. var opts = {};
  1172. opts.type = LightIterator.types.repeat;
  1173. opts.interval = interval;
  1174. opts.async = false;
  1175. opts.context = context;
  1176. return (new LightIterator(max, callback, opts)).result;
  1177. };
  1178. } else {
  1179. return function(max, callback, context) {
  1180. return QuickIteration.repeat(
  1181. max, callback, context
  1182. );
  1183. };
  1184. }
  1185. }),
  1186. /**
  1187. * Iterates indefinitely until "Pot.StopIteration" is thrown.
  1188. *
  1189. *
  1190. * @example
  1191. * var s = '', a = 'abc*';
  1192. * Pot.forEver(function(i) {
  1193. * s += i + ':' + a;
  1194. * if (s.length > 50) {
  1195. * throw Pot.StopIteration;
  1196. * }
  1197. * });
  1198. * debug(s);
  1199. * // @results
  1200. * // '0:abc*1:abc*2:abc*3:abc*4:abc*5:abc*6:abc*7:abc*8:abc*'
  1201. *
  1202. *
  1203. * @param {Function} callback An iterable function.
  1204. * Throw Pot.StopIteration
  1205. * if you want to stop the loop.
  1206. * @param {*} (context) Optionally, context object. (i.e. this)
  1207. * @class
  1208. * @function
  1209. * @static
  1210. * @name Pot.forEver
  1211. * @property {Function} limp Iterates "forEver" loop with slowest speed.
  1212. * @property {Function} doze Iterates "forEver" loop with slower speed.
  1213. * @property {Function} slow Iterates "forEver" loop with slow speed.
  1214. * @property {Function} normal Iterates "forEver" loop with default speed.
  1215. * @property {Function} fast Iterates "forEver" loop with fast speed.
  1216. * @property {Function} rapid Iterates "forEver" loop with faster speed.
  1217. * @property {Function} ninja Iterates "forEver" loop with fastest speed.
  1218. */
  1219. forEver : createLightIterateConstructor(function(interval) {
  1220. if (PotSystem.isWaitable &&
  1221. interval < LightIterator.speeds.normal) {
  1222. return function(callback, context) {
  1223. var opts = {};
  1224. opts.type = LightIterator.types.forEver;
  1225. opts.interval = interval;
  1226. opts.async = false;
  1227. opts.context = context;
  1228. return (new LightIterator(callback, null, opts)).result;
  1229. };
  1230. } else {
  1231. return function(callback, context) {
  1232. return QuickIteration.forEver(
  1233. callback, context
  1234. );
  1235. };
  1236. }
  1237. }),
  1238. /**
  1239. * Iterate an iterable object. (using Pot.Iter)
  1240. *
  1241. * @param {*} object An iterable object.
  1242. * @param {Function} callback An iterable function.
  1243. * function(value, key, object)
  1244. * this == `context`.
  1245. * Throw Pot.StopIteration
  1246. * if you want to stop the loop.
  1247. * @param {Object} (context) Optionally, context object. (i.e. this)
  1248. * @return {*} Result of iteration.
  1249. * @class
  1250. * @function
  1251. * @static
  1252. * @name Pot.iterate
  1253. * @property {Function} limp Iterates "iterate" loop with slowest speed.
  1254. * @property {Function} doze Iterates "iterate" loop with slower speed.
  1255. * @property {Function} slow Iterates "iterate" loop with slow speed.
  1256. * @property {Function} normal Iterates "iterate" loop with default speed.
  1257. * @property {Function} fast Iterates "iterate" loop with fast speed.
  1258. * @property {Function} rapid Iterates "iterate" loop with faster speed.
  1259. * @property {Function} ninja Iterates "iterate" loop with fastest speed.
  1260. */
  1261. iterate : createLightIterateConstructor(function(interval) {
  1262. if (PotSystem.isWaitable &&
  1263. interval < LightIterator.speeds.normal) {
  1264. return function(object, callback, context) {
  1265. var opts = {};
  1266. opts.type = LightIterator.types.iterate;
  1267. opts.interval = interval;
  1268. opts.async = false;
  1269. opts.context = context;
  1270. return (new LightIterator(object, callback, opts)).result;
  1271. };
  1272. } else {
  1273. return function(object, callback, context) {
  1274. return QuickIteration.iterate(
  1275. object, callback, context
  1276. );
  1277. };
  1278. }
  1279. }),
  1280. /**
  1281. * Collect the object key and value and make array as items format.
  1282. *
  1283. *
  1284. * @example
  1285. * var obj = {foo: 1, bar: 2, baz: 3};
  1286. * debug(items(obj));
  1287. * // @results [['foo', 1], ['bar', 2], ['baz', 3]]
  1288. *
  1289. *
  1290. * @example
  1291. * var array = ['foo', 'bar', 'baz'];
  1292. * debug(items(array));
  1293. * // @results [[0, 'foo'], [1, 'bar'], [2, 'baz']]
  1294. *
  1295. *
  1296. * @example
  1297. * // Example for using callback.
  1298. * var arr = ['foo', 'bar', 'baz'];
  1299. * var func = function(item) {
  1300. * return '(' + item[0] + ')' + item[1];
  1301. * };
  1302. * debug(items(arr, func));
  1303. * // @results ['(0)foo', '(1)bar', '(2)baz']
  1304. *
  1305. *
  1306. * @example
  1307. * // Example for using callback.
  1308. * var obj = {foo: 1, bar: 2, baz: 3};
  1309. * var func = function(item) {
  1310. * return [item[0] + '::' + item[1]];
  1311. * };
  1312. * debug(items(obj, func));
  1313. * // @results [['foo::1'], ['bar::2'], ['baz::3']]
  1314. *
  1315. *
  1316. * @param {Object|Array} object The target object or an array.
  1317. * @param {Function} (callback) (Optional) Callback function.
  1318. * function({Array} item[, object])
  1319. * this == `context`.
  1320. * @param {*} (context) (Optional) Object to use
  1321. * as `this` when executing callback.
  1322. * @return {Array} The collected items as an array.
  1323. *
  1324. * @class
  1325. * @function
  1326. * @static
  1327. * @name Pot.items
  1328. *
  1329. * @property {Function} limp Iterates "items" loop with slowest speed.
  1330. * @property {Function} doze Iterates "items" loop with slower speed.
  1331. * @property {Function} slow Iterates "items" loop with slow speed.
  1332. * @property {Function} normal Iterates "items" loop with default speed.
  1333. * @property {Function} fast Iterates "items" loop with fast speed.
  1334. * @property {Function} rapid Iterates "items" loop with faster speed.
  1335. * @property {Function} ninja Iterates "items" loop with fastest speed.
  1336. */
  1337. items : createLightIterateConstructor(function(interval) {
  1338. if (PotSystem.isWaitable &&
  1339. interval < LightIterator.speeds.normal) {
  1340. return function(object, callback, context) {
  1341. var opts = {};
  1342. opts.type = LightIterator.types.items;
  1343. opts.interval = interval;
  1344. opts.async = false;
  1345. opts.context = context;
  1346. return (new LightIterator(object, callback, opts)).result;
  1347. };
  1348. } else {
  1349. return function(object, callback, context) {
  1350. return QuickIteration.items(
  1351. object, callback, context
  1352. );
  1353. };
  1354. }
  1355. }),
  1356. /**
  1357. * Create a new array which has the elements at
  1358. * position ith of the provided arrays.
  1359. * This function is handled as seen from the longitudinal for array
  1360. * that is similar to the zip() function in Python.
  1361. *
  1362. * <pre>
  1363. * Example:
  1364. *
  1365. * arguments: [[1, 2, 3],
  1366. * [4, 5, 6]]
  1367. *
  1368. * results: [[1, 4],
  1369. * [2, 5],
  1370. * [3, 6]]
  1371. * </pre>
  1372. *
  1373. *
  1374. * @link http://docs.python.org/library/functions.html#zip
  1375. *
  1376. *
  1377. * @example
  1378. * var result = zip([[1, 2, 3], [4, 5, 6]]);
  1379. * debug(result);
  1380. * // @results
  1381. * // [[1, 4], [2, 5], [3, 6]]
  1382. * //
  1383. *
  1384. *
  1385. * @example
  1386. * var result = zip([[1, 2, 3], [1, 2, 3, 4, 5]]);
  1387. * debug(result);
  1388. * // @results
  1389. * // [[1, 1], [2, 2], [3, 3]]
  1390. * //
  1391. *
  1392. *
  1393. * @example
  1394. * var result = zip([[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11]]);
  1395. * debug(result);
  1396. * // @results
  1397. * // [[1, 4, 7, 10], [2, 5, 8, 11]]
  1398. * //
  1399. *
  1400. *
  1401. * @example
  1402. * var result = zip(['hoge']);
  1403. * debug(result);
  1404. * // @results
  1405. * // [['hoge']]
  1406. * //
  1407. *
  1408. *
  1409. * @example
  1410. * var result = zip([[1], [2], [3]]);
  1411. * debug(result);
  1412. * // @results
  1413. * // [[1, 2, 3]]
  1414. * //
  1415. *
  1416. *
  1417. * @example
  1418. * var result = zip([[1, 2, 3], ['foo', 'bar', 'baz'], [4, 5]]);
  1419. * debug(result);
  1420. * // @results
  1421. * // [[1, 'foo', 4], [2, 'bar', 5]]
  1422. * //
  1423. *
  1424. *
  1425. * @example
  1426. * var callback = function(items) { return items[0] + items[1]; };
  1427. * var result = zip([[1, 2, 3], [4, 5, 6]], callback);
  1428. * debug(result);
  1429. * // @results [5, 7, 9]
  1430. *
  1431. *
  1432. * @param {Array} object An array to be combined.
  1433. * @param {Function} (callback) (Optional) Callback function.
  1434. * function({Array} items[, {*} object])
  1435. * this == `context`.
  1436. * @param {*} (context) (Optional) Object to use
  1437. * as `this` when executing callback.
  1438. * @return {Array} A new array of arrays created from
  1439. * provided objects.
  1440. *
  1441. * @class
  1442. * @function
  1443. * @static
  1444. * @name Pot.zip
  1445. *
  1446. * @property {Function} limp Iterates "zip" loop with slowest speed.
  1447. * @property {Function} doze Iterates "zip" loop with slower speed.
  1448. * @property {Function} slow Iterates "zip" loop with slow speed.
  1449. * @property {Function} normal Iterates "zip" loop with default speed.
  1450. * @property {Function} fast Iterates "zip" loop with fast speed.
  1451. * @property {Function} rapid Iterates "zip" loop with faster speed.
  1452. * @property {Function} ninja Iterates "zip" loop with fastest speed.
  1453. */
  1454. zip : createLightIterateConstructor(function(interval) {
  1455. if (PotSystem.isWaitable &&
  1456. interval < LightIterator.speeds.normal) {
  1457. return function(object, callback, context) {
  1458. var opts = {};
  1459. opts.type = LightIterator.types.zip;
  1460. opts.interval = interval;
  1461. opts.async = false;
  1462. opts.context = context;
  1463. return (new LightIterator(object, callback, opts)).result;
  1464. };
  1465. } else {
  1466. return function(object, callback, context) {
  1467. return QuickIteration.zip(
  1468. object, callback, context
  1469. );
  1470. };
  1471. }
  1472. })
  1473. });
  1474. // Define iterators for Deferred (Asynchronous)
  1475. update(Deferred, {
  1476. /**
  1477. * Iterates as "for each" loop. (Asynchronous)
  1478. *
  1479. * @desc
  1480. * <pre>
  1481. * Unlike Deferred, speed options affect to cutback count in loop.
  1482. * Options append to after the forEach and execute it.
  1483. *
  1484. * e.g. Pot.Deferred.forEach.fast(obj, function() {...})
  1485. *
  1486. * The available methods are below.
  1487. * ------------------------------------
  1488. * method name | speed
  1489. * ------------------------------------
  1490. * limp : slowest
  1491. * doze : slower
  1492. * slow : slow
  1493. * normal : normal (default)
  1494. * fast : fast
  1495. * rapid : faster
  1496. * ninja : fastest
  1497. * ------------------------------------
  1498. * </pre>
  1499. *
  1500. * @param {Array|Object} object A target object.
  1501. * @param {Function} callback An iterable function.
  1502. * function(value, key, object)
  1503. * this == `context`.
  1504. * Throw Pot.StopIteration
  1505. * if you want to stop the loop.
  1506. * @param {*} (context) Optionally, context object. (i.e. this)
  1507. * @result {Deferred} Return the Deferred.
  1508. * @class
  1509. * @function
  1510. * @public
  1511. * @type Function
  1512. * @name Pot.Deferred.forEach
  1513. * @property {Function} limp Iterates "for each" loop with slowest speed.
  1514. * @property {Function} doze Iterates "for each" loop with slower speed.
  1515. * @property {Function} slow Iterates "for each" loop with slow speed.
  1516. * @property {Function} normal Iterates "for each" loop with default speed.
  1517. * @property {Function} fast Iterates "for each" loop with fast speed.
  1518. * @property {Function} rapid Iterates "for each" loop with faster speed.
  1519. * @property {Function} ninja Iterates "for each" loop with fastest speed.
  1520. */
  1521. forEach : createLightIterateConstructor(function(interval) {
  1522. return function(object, callback, context) {
  1523. var opts = {};
  1524. opts.type = LightIterator.types.forLoop |
  1525. LightIterator.types.forInLoop;
  1526. opts.interval = interval;
  1527. opts.async = true;
  1528. opts.context = context;
  1529. return (new LightIterator(object, callback, opts)).deferred;
  1530. };
  1531. }),
  1532. /**
  1533. * "repeat" loop iterates a specified number. (Asynchronous)
  1534. *
  1535. * @param {Number|Object} max The maximum number of times to loop,
  1536. * or object.
  1537. * @param {Function} callback An iterable function.
  1538. * Throw Pot.StopIteration
  1539. * if you want to stop the loop.
  1540. * @param {*} (context) Optionally, context object. (i.e. this)
  1541. * @return {Deferred} Return the Deferred.
  1542. * @class
  1543. * @function
  1544. * @public
  1545. * @type Function
  1546. * @name Pot.Deferred.repeat
  1547. * @property {Function} limp Iterates "repeat" loop with slowest speed.
  1548. * @property {Function} doze Iterates "repeat" loop with slower speed.
  1549. * @property {Function} slow Iterates "repeat" loop with slow speed.
  1550. * @property {Function} normal Iterates "repeat" loop with default speed.
  1551. * @property {Function} fast Iterates "repeat" loop with fast speed.
  1552. * @property {Function} rapid Iterates "repeat" loop with faster speed.
  1553. * @property {Function} ninja Iterates "repeat" loop with fastest speed.
  1554. */
  1555. repeat : createLightIterateConstructor(function(interval) {
  1556. return function(max, callback, context) {
  1557. var opts = {};
  1558. opts.type = LightIterator.types.repeat;
  1559. opts.interval = interval;
  1560. opts.async = true;
  1561. opts.context = context;
  1562. return (new LightIterator(max, callback, opts)).deferred;
  1563. };
  1564. }),
  1565. /**
  1566. * Iterates indefinitely until "Pot.StopIteration" is thrown. (Asynchronous)
  1567. *
  1568. * @param {Function} callback An iterable function.
  1569. * Throw Pot.StopIteration
  1570. * if you want to stop the loop.
  1571. * @param {*} (context) Optionally, context object. (i.e. this)
  1572. * @return {Deferred} Return the Deferred.
  1573. * @class
  1574. * @function
  1575. * @public
  1576. * @type Function
  1577. * @name Pot.Deferred.forEver
  1578. * @property {Function} limp Iterates "forEver" loop with slowest speed.
  1579. * @property {Function} doze Iterates "forEver" loop with slower speed.
  1580. * @property {Function} slow Iterates "forEver" loop with slow speed.
  1581. * @property {Function} normal Iterates "forEver" loop with default speed.
  1582. * @property {Function} fast Iterates "forEver" loop with fast speed.
  1583. * @property {Function} rapid Iterates "forEver" loop with faster speed.
  1584. * @property {Function} ninja Iterates "forEver" loop with fastest speed.
  1585. */
  1586. forEver : createLightIterateConstructor(function(interval) {
  1587. return function(callback, context) {
  1588. var opts = {};
  1589. opts.type = LightIterator.types.forEver;
  1590. opts.interval = interval;
  1591. opts.async = true;
  1592. opts.context = context;
  1593. return (new LightIterator(callback, null, opts)).deferred;
  1594. };
  1595. }),
  1596. /**
  1597. * Iterate an iterable object. (using Pot.Iter)
  1598. *
  1599. * @param {*} object An iterable object.
  1600. * @param {Function} callback An iterable function.
  1601. * function(value, key, object)
  1602. * this == `context`.
  1603. * Throw Pot.StopIteration
  1604. * if you want to stop the loop.
  1605. * @param {Object} (context) Optionally, context object. (i.e. this)
  1606. * @return {Deferred} Return the Deferred.
  1607. * @class
  1608. * @function
  1609. * @public
  1610. * @type Function
  1611. * @name Pot.Deferred.iterate
  1612. * @property {Function} limp Iterates "iterate" loop with slowest speed.
  1613. * @property {Function} doze Iterates "iterate" loop with slower speed.
  1614. * @property {Function} slow Iterates "iterate" loop with slow speed.
  1615. * @property {Function} normal Iterates "iterate" loop with default speed.
  1616. * @property {Function} fast Iterates "iterate" loop with fast speed.
  1617. * @property {Function} rapid Iterates "iterate" loop with faster speed.
  1618. * @property {Function} ninja Iterates "iterate" loop with fastest speed.
  1619. */
  1620. iterate : createLightIterateConstructor(function(interval) {
  1621. return function(object, callback, context) {
  1622. var opts = {};
  1623. opts.type = LightIterator.types.iterate;
  1624. opts.interval = interval;
  1625. opts.async = true;
  1626. opts.context = context;
  1627. return (new LightIterator(object, callback, opts)).deferred;
  1628. };
  1629. }),
  1630. /**
  1631. * Collect the object key and value and make array as items format.
  1632. *
  1633. * @param {Object|Array} object The target object or an array.
  1634. * @param {Function} (callback) (Optional) Callback function.
  1635. * function({Array} item[, object])
  1636. * this == `context`.
  1637. * @param {*} (context) (Optional) Object to use
  1638. * as `this` when executing callback.
  1639. * @return {Deferred} Return a new instance of Deferred that
  1640. * has the collected items as an array.
  1641. *
  1642. * @class
  1643. * @function
  1644. * @public
  1645. * @type Function
  1646. * @name Pot.Deferred.items
  1647. *
  1648. * @property {Function} limp Iterates "items" loop with slowest speed.
  1649. * @property {Function} doze Iterates "items" loop with slower speed.
  1650. * @property {Function} slow Iterates "items" loop with slow speed.
  1651. * @property {Function} normal Iterates "items" loop with default speed.
  1652. * @property {Function} fast Iterates "items" loop with fast speed.
  1653. * @property {Function} rapid Iterates "items" loop with faster speed.
  1654. * @property {Function} ninja Iterates "items" loop with fastest speed.
  1655. */
  1656. items : createLightIterateConstructor(function(interval) {
  1657. return function(object, callback, context) {
  1658. var opts = {};
  1659. opts.type = LightIterator.types.items;
  1660. opts.interval = interval;
  1661. opts.async = true;
  1662. opts.context = context;
  1663. return (new LightIterator(object, callback, opts)).deferred;
  1664. };
  1665. }),
  1666. /**
  1667. * Create a new array which has the elements at
  1668. * position ith of the provided arrays.
  1669. * This function is handled as seen from the longitudinal for array
  1670. * that is similar to the zip() function in Python.
  1671. *
  1672. * <pre>
  1673. * Example:
  1674. *
  1675. * arguments: [[1, 2, 3],
  1676. * [4, 5, 6]]
  1677. *
  1678. * results: [[1, 4],
  1679. * [2, 5],
  1680. * [3, 6]]
  1681. * </pre>
  1682. *
  1683. * @link http://docs.python.org/library/functions.html#zip
  1684. *
  1685. * @param {Array} object Objects to be combined.
  1686. * @param {Function} (callback) (Optional) Callback function.
  1687. * function({Array} items[, {*} object])
  1688. * this == `context`.
  1689. * @param {*} (context) (Optional) Object to use
  1690. * as `this` when executing callback.
  1691. * @return {Deferred} Return a new instance of Deferred that has
  1692. * a new array of arrays created from
  1693. * provided objects.
  1694. * @class
  1695. * @function
  1696. * @public
  1697. * @type Function
  1698. * @name Pot.Deferred.zip
  1699. *
  1700. * @property {Function} limp Iterates "zip" loop with slowest speed.
  1701. * @property {Function} doze Iterates "zip" loop with slower speed.
  1702. * @property {Function} slow Iterates "zip" loop with slow speed.
  1703. * @property {Function} normal Iterates "zip" loop with default speed.
  1704. * @property {Function} fast Iterates "zip" loop with fast speed.
  1705. * @property {Function} rapid Iterates "zip" loop with faster speed.
  1706. * @property {Function} ninja Iterates "zip" loop with fastest speed.
  1707. */
  1708. zip : createLightIterateConstructor(function(interval) {
  1709. return function(object, callback, context) {
  1710. var opts = {};
  1711. opts.type = LightIterator.types.zip;
  1712. opts.interval = interval;
  1713. opts.async = true;
  1714. opts.context = context;
  1715. return (new LightIterator(object, callback, opts)).deferred;
  1716. };
  1717. })
  1718. });
  1719. delete PotTmp.createLightIterateConstructor;
  1720. //-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
  1721. // Definition of Iter.
  1722. Pot.update({
  1723. /**
  1724. * @lends Pot
  1725. */
  1726. /**
  1727. * Iter.
  1728. *
  1729. * A Simple iterator.
  1730. * Constructor.
  1731. *
  1732. * @param {*} Options.
  1733. * @return {Pot.Iter} Returns an instance of Pot.Iter
  1734. *
  1735. * @name Pot.Iter
  1736. * @class
  1737. * @constructor
  1738. * @public
  1739. */
  1740. Iter : function() {
  1741. return isIter(this) ? this.init(arguments)
  1742. : new Iter.fn.init(arguments);
  1743. }
  1744. });
  1745. // Refer the Pot properties/functions.
  1746. Iter = Pot.Iter;
  1747. // Definition of the prototype
  1748. Iter.fn = Iter.prototype = update(Iter.prototype, {
  1749. /**
  1750. * @lends Pot.Iter.prototype
  1751. */
  1752. /**
  1753. * @ignore
  1754. */
  1755. constructor : Iter,
  1756. /**
  1757. * @private
  1758. * @ignore
  1759. */
  1760. id : PotInternal.getMagicNumber(),
  1761. /**
  1762. * A unique strings.
  1763. *
  1764. * @type String
  1765. * @private
  1766. * @const
  1767. */
  1768. serial : null,
  1769. /**
  1770. * @private
  1771. * @ignore
  1772. * @const
  1773. */
  1774. NAME : 'Iter',
  1775. /**
  1776. * toString.
  1777. *
  1778. * @return Return formatted string of object.
  1779. * @type Function
  1780. * @function
  1781. * @const
  1782. * @static
  1783. * @public
  1784. */
  1785. toString : PotToString,
  1786. /**
  1787. * isIter.
  1788. *
  1789. * @type Function
  1790. * @function
  1791. * @const
  1792. * @static
  1793. * @public
  1794. */
  1795. isIter : isIter,
  1796. /**
  1797. * Initialize properties.
  1798. *
  1799. * @private
  1800. * @ignore
  1801. */
  1802. init : function(args) {
  1803. if (!this.serial) {
  1804. this.serial = buildSerial(this);
  1805. }
  1806. return this;
  1807. },
  1808. /**
  1809. * Abstract function.
  1810. *
  1811. * Note: Firebug 1.7.x never shows the name of "next" method.
  1812. *
  1813. * @abstract
  1814. * @type Function
  1815. * @function
  1816. * @public
  1817. */
  1818. next : function() {
  1819. throw PotStopIteration;
  1820. }
  1821. /**
  1822. * The property that implemented since JavaScript 1.7
  1823. * as the extended ECMAScript-3rd edition.
  1824. *
  1825. * @return {Object} Return the iterator object
  1826. */
  1827. //XXX: __iterator__ unimplemented for Object.prototype.__iterator__.
  1828. //__iterator__ : function() {
  1829. // return this;
  1830. //}
  1831. });
  1832. Iter.fn.init.prototype = Iter.fn;
  1833. // Define Iter object properties.
  1834. update(Iter, {
  1835. /**
  1836. * @lends Pot.Iter
  1837. */
  1838. /**
  1839. * StopIteration.
  1840. *
  1841. * @type Object
  1842. * @static
  1843. * @const
  1844. * @public
  1845. */
  1846. StopIteration : PotStopIteration,
  1847. /**
  1848. * Assign to an iterator from the argument object value.
  1849. *
  1850. * @param {*} x An iterable object.
  1851. * @return {Pot.Iter} An iterator object instance.
  1852. * @type Function
  1853. * @function
  1854. * @static
  1855. * @public
  1856. */
  1857. toIter : function(x) {
  1858. var iter, o, arrayLike, objectLike;
  1859. if (isIter(x)) {
  1860. return x;
  1861. }
  1862. arrayLike = x && isArrayLike(x);
  1863. objectLike = x && !arrayLike && isObject(x);
  1864. if (objectLike) {
  1865. o = [];
  1866. each(x, function(xv, xp) {
  1867. o[o.length] = [xv, xp];
  1868. });
  1869. } else {
  1870. o = arrayize(x);
  1871. }
  1872. iter = new Iter();
  1873. /**@ignore*/
  1874. iter.next = (function() {
  1875. var i = 0;
  1876. if (objectLike) {
  1877. return function() {
  1878. var key, val, pair;
  1879. while (true) {
  1880. if (i >= o.length) {
  1881. throw PotStopIteration;
  1882. }
  1883. if (!(i in o)) {
  1884. i++;
  1885. continue;
  1886. }
  1887. try {
  1888. key = o[i][1];
  1889. val = o[i][0];
  1890. } catch (e) {
  1891. i++;
  1892. continue;
  1893. }
  1894. pair = [val, key];
  1895. i++;
  1896. return pair;
  1897. }
  1898. };
  1899. } else {
  1900. return function() {
  1901. var value, result;
  1902. while (true) {
  1903. if (i >= o.length) {
  1904. throw PotStopIteration;
  1905. }
  1906. if (!(i in o)) {
  1907. i++;
  1908. continue;
  1909. }
  1910. try {
  1911. value = o[i];
  1912. } catch (e) {
  1913. i++;
  1914. continue;
  1915. }
  1916. result = [value, i];
  1917. i++;
  1918. return result;
  1919. }
  1920. };
  1921. }
  1922. }());
  1923. return iter;
  1924. },
  1925. /**
  1926. * @private
  1927. * @ignore
  1928. */
  1929. forEach : function(/*object, callback[, context]*/) {
  1930. return Pot.iterate.apply(null, arguments);
  1931. },
  1932. /**
  1933. * Creates a new object with the results of calling a
  1934. * provided function on every element in object.
  1935. *
  1936. * This method like Array.prototype.map
  1937. *
  1938. *
  1939. * @example
  1940. * function fuzzyPlural(single) {
  1941. * return single.replace(/o/g, 'e');
  1942. * }
  1943. * var words = ['foot', 'goose', 'moose'];
  1944. * debug(Pot.Iter.map(words, fuzzyPlural));
  1945. * // @results ['feet', 'geese', 'meese']
  1946. *
  1947. *
  1948. * @example
  1949. * var object = {foo: 'foo1', bar: 'bar2', baz: 'baz3'};
  1950. * var result = Pot.Iter.map(object, function(value, key) {
  1951. * return value + '00';
  1952. * });
  1953. * debug(result);
  1954. * // @results {foo: 'foo100', bar: 'bar200', baz: 'baz300'}
  1955. *
  1956. *
  1957. * @param {Array|Object|*} object A target object.
  1958. * @param {Function} callback A callback function.
  1959. * @param {*} (context) (Optional) Object to use
  1960. * as `this` when executing callback.
  1961. * @return {*} Return the result of each callbacks.
  1962. * @type Function
  1963. * @function
  1964. * @static
  1965. * @public
  1966. */
  1967. map : function(object, callback, context) {
  1968. var result, arrayLike, objectLike, iterateDefer, it, iterable;
  1969. iterateDefer = this && this.iterateSpeed;
  1970. arrayLike = object && isArrayLike(object);
  1971. objectLike = object && !arrayLike && isObject(object);
  1972. if (arrayLike) {
  1973. result = [];
  1974. } else if (objectLike) {
  1975. result = {};
  1976. } else {
  1977. result = null;
  1978. }
  1979. iterable = iterateDefer || this && this.iterateSpeedSync || Pot.iterate;
  1980. /**@ignore*/
  1981. it = function() {
  1982. return iterable(object, function(val, key, obj) {
  1983. var res = callback.call(context, val, key, obj);
  1984. if (isDeferred(res)) {
  1985. return res.then(function(rv) {
  1986. if (arrayLike) {
  1987. result[result.length] = rv;
  1988. } else if (objectLike) {
  1989. result[key] = rv;
  1990. } else {
  1991. result = rv;
  1992. }
  1993. });
  1994. } else {
  1995. if (arrayLike) {
  1996. result[result.length] = res;
  1997. } else if (objectLike) {
  1998. result[key] = res;
  1999. } else {
  2000. result = res;
  2001. }
  2002. }
  2003. }, context);
  2004. };
  2005. if (iterateDefer) {
  2006. return it().then(function() {
  2007. return result;
  2008. });
  2009. } else {
  2010. it();
  2011. return result;
  2012. }
  2013. },
  2014. /**
  2015. * Creates a new object with all elements that
  2016. * pass the test implemented by the provided function.
  2017. *
  2018. * This method like Array.prototype.filter
  2019. *
  2020. *
  2021. * @example
  2022. * function isBigEnough(value, index, array) {
  2023. * return (value >= 10);
  2024. * }
  2025. * var filtered = Pot.Iter.filter([12, 5, 8, 130, 44], isBigEnough);
  2026. * debug(filtered);
  2027. * // @results [12, 130, 44]
  2028. *
  2029. *
  2030. * @example
  2031. * function isBigEnough(value, key, object) {
  2032. * return (value >= 10);
  2033. * }
  2034. * var object = {a: 1, b: 20, c: 7, d: 5, e: 27, f: 99};
  2035. * var result = Pot.Iter.filter(object, isBigEnough);
  2036. * debug(result);
  2037. * // @results {b: 20, e: 27, f: 99}
  2038. *
  2039. *
  2040. * @param {Array|Object|*} object A target object.
  2041. * @param {Function} callback A callback function.
  2042. * @param {*} (context) (Optional) Object to use
  2043. * as `this` when executing callback.
  2044. * @return {*} Return the result of each callbacks.
  2045. * @type Function
  2046. * @function
  2047. * @static
  2048. * @public
  2049. */
  2050. filter : (function() {
  2051. /**@ignore*/
  2052. var emptyFilter = function(a) { return a; };
  2053. return function(object, callback, context) {
  2054. var result, arrayLike, objectLike, iterateDefer, it, iterable, cb;
  2055. cb = callback || emptyFilter;
  2056. iterateDefer = this && this.iterateSpeed;
  2057. arrayLike = object && isArrayLike(object);
  2058. objectLike = object && !arrayLike && isObject(object);
  2059. if (arrayLike) {
  2060. result = [];
  2061. } else if (objectLike) {
  2062. result = {};
  2063. } else {
  2064. result = null;
  2065. }
  2066. iterable = iterateDefer || this && this.iterateSpeedSync || Pot.iterate;
  2067. /**@ignore*/
  2068. it = function() {
  2069. return iterable(object, function(val, key, obj) {
  2070. var res = cb.call(context, val, key, obj);
  2071. if (isDeferred(res)) {
  2072. return res.then(function(rv) {
  2073. if (rv) {
  2074. if (arrayLike) {
  2075. result[result.length] = val;
  2076. } else if (objectLike) {
  2077. result[key] = val;
  2078. } else {
  2079. result = val;
  2080. }
  2081. }
  2082. });
  2083. } else {
  2084. if (res) {
  2085. if (arrayLike) {
  2086. result[result.length] = val;
  2087. } else if (objectLike) {
  2088. result[key] = val;
  2089. } else {
  2090. result = val;
  2091. }
  2092. }
  2093. }
  2094. }, context);
  2095. };
  2096. if (iterateDefer) {
  2097. return it().then(function() {
  2098. return result;
  2099. });
  2100. } else {
  2101. it();
  2102. return result;
  2103. }
  2104. };
  2105. }()),
  2106. /**
  2107. * Apply a function against an accumulator and each value of
  2108. * the object (from left-to-right) as to reduce it to a single value.
  2109. *
  2110. * This method like Array.prototype.reduce
  2111. *
  2112. *
  2113. * @example
  2114. * var array = [1, 2, 3, 4, 5];
  2115. * var total = Pot.Iter.reduce(array, function(a, b) { return a + b; });
  2116. * debug(total);
  2117. * // @results 15
  2118. *
  2119. * @example
  2120. * var object = {a: 1, b: 2, c: 3};
  2121. * var total = Pot.Iter.reduce(object, function(a, b) { return a + b; });
  2122. * debug(total);
  2123. * // @results 6
  2124. *
  2125. *
  2126. * @param {Array|Object|*} object A target object.
  2127. * @param {Function} callback A callback function.
  2128. * @param {*} (initial) An initial value passed as `callback`
  2129. * argument that will be used on
  2130. * first iteration.
  2131. * @param {*} (context) (Optional) Object to use as
  2132. * the first argument to the
  2133. * first call of the `callback`.
  2134. * @return {*} Return the result of each callbacks.
  2135. * @type Function
  2136. * @function
  2137. * @static
  2138. * @public
  2139. */
  2140. reduce : function(object, callback, initial, context) {
  2141. var arrayLike, objectLike, value, skip, iterateDefer, it, iterable;
  2142. iterateDefer = this && this.iterateSpeed;
  2143. arrayLike = object && isArrayLike(object);
  2144. objectLike = object && !arrayLike && isObject(object);
  2145. if (initial === void 0) {
  2146. /**@ignore*/
  2147. value = (function() {
  2148. var first;
  2149. if (arrayLike || objectLike) {
  2150. each(object, function(v) {
  2151. first = v;
  2152. throw PotStopIteration;
  2153. });
  2154. }
  2155. return first;
  2156. }());
  2157. } else {
  2158. value = initial;
  2159. }
  2160. skip = true;
  2161. iterable = iterateDefer || this && this.iterateSpeedSync || Pot.iterate;
  2162. /**@ignore*/
  2163. it = function() {
  2164. return iterable(object, function(val, key, obj) {
  2165. var res;
  2166. if (skip) {
  2167. skip = false;
  2168. } else {
  2169. res = callback.call(context, value, val, key, obj);
  2170. if (isDeferred(res)) {
  2171. return res.then(function(rv) {
  2172. value = rv;
  2173. });
  2174. } else {
  2175. value = res;
  2176. }
  2177. }
  2178. }, context);
  2179. };
  2180. if (iterateDefer) {
  2181. return it().then(function() {
  2182. return value;
  2183. });
  2184. } else {
  2185. it();
  2186. return value;
  2187. }
  2188. },
  2189. /**
  2190. * Tests whether all elements in the object pass the
  2191. * test implemented by the provided function.
  2192. *
  2193. * This method like Array.prototype.every
  2194. *
  2195. * @example
  2196. * function isBigEnough(value, index, array) {
  2197. * return (value >= 10);
  2198. * }
  2199. * var passed = Pot.Iter.every([12, 5, 8, 130, 44], isBigEnough);
  2200. * debug(passed);
  2201. * // passed is false
  2202. * passed = Pot.Iter.every([12, 54, 18, 130, 44], isBigEnough);
  2203. * debug(passed);
  2204. * // passed is true
  2205. *
  2206. *
  2207. * @param {Array|Object|*} object A target object.
  2208. * @param {Function} callback A callback function.
  2209. * @param {*} (context) (Optional) Object to use
  2210. * as `this` when executing callback.
  2211. * @return {Boolean} Return the Boolean result by callback.
  2212. * @type Function
  2213. * @function
  2214. * @static
  2215. * @public
  2216. */
  2217. every : function(object, callback, context) {
  2218. var result = true, iterateDefer, it, iterable;
  2219. iterateDefer = this && this.iterateSpeed;
  2220. iterable = iterateDefer || this && this.iterateSpeedSync || Pot.iterate;
  2221. /**@ignore*/
  2222. it = function() {
  2223. return iterable(object, function(val, key, obj) {
  2224. var res = callback.call(context, val, key, obj);
  2225. if (isDeferred(res)) {
  2226. return res.then(function(rv) {
  2227. if (!rv) {
  2228. result = false;
  2229. throw PotStopIteration;
  2230. }
  2231. });
  2232. } else {
  2233. if (!res) {
  2234. result = false;
  2235. throw PotStopIteration;
  2236. }
  2237. }
  2238. }, context);
  2239. };
  2240. if (iterateDefer) {
  2241. return it().then(function() {
  2242. return result;
  2243. });
  2244. } else {
  2245. it();
  2246. return result;
  2247. }
  2248. },
  2249. /**
  2250. * Tests whether some element in the object passes the
  2251. * test implemented by the provided function.
  2252. *
  2253. * This method like Array.prototype.some
  2254. *
  2255. *
  2256. * @example
  2257. * function isBigEnough(value, index, array) {
  2258. * return (value >= 10);
  2259. * }
  2260. * var passed = Pot.Iter.some([2, 5, 8, 1, 4], isBigEnough);
  2261. * debug(passed);
  2262. * // passed is false
  2263. * passed = Pot.Iter.some([12, 5, 8, 1, 4], isBigEnough);
  2264. * debug(passed);
  2265. * // passed is true
  2266. *
  2267. *
  2268. * @param {Array|Object|*} object A target object.
  2269. * @param {Function} callback A callback function.
  2270. * @param {*} (context) (Optional) Object to use
  2271. * as `this` when executing callback.
  2272. * @return {Boolean} Return the Boolean result by callback.
  2273. * @type Function
  2274. * @function
  2275. * @static
  2276. * @public
  2277. */
  2278. some : function(object, callback, context) {
  2279. var result = false, iterateDefer, it, iterable;
  2280. iterateDefer = this && this.iterateSpeed;
  2281. iterable = iterateDefer || this && this.iterateSpeedSync || Pot.iterate;
  2282. /**@ignore*/
  2283. it = function() {
  2284. return iterable(object, function(val, key, obj) {
  2285. var res = callback.call(context, val, key, obj);
  2286. if (isDeferred(res)) {
  2287. return res.then(function(rv) {
  2288. if (rv) {
  2289. result = true;
  2290. throw PotStopIteration;
  2291. }
  2292. });
  2293. } else {
  2294. if (res) {
  2295. result = true;
  2296. throw PotStopIteration;
  2297. }
  2298. }
  2299. }, context);
  2300. };
  2301. if (iterateDefer) {
  2302. return it().then(function() {
  2303. return result;
  2304. });
  2305. } else {
  2306. it();
  2307. return result;
  2308. }
  2309. },
  2310. /**
  2311. * Create continuously array that
  2312. * has numbers between start number and end number.
  2313. *
  2314. * First argument can given an object that has "begin, end, step" any keys.
  2315. *
  2316. * This function can be a letter rather than just numbers.
  2317. *
  2318. * @example
  2319. * var numbers = Pot.Iter.range(1, 5);
  2320. * debug(numbers); // @results [1, 2, 3, 4, 5]
  2321. * var chars = Pot.Iter.range('a', 'f');
  2322. * debug(chars); // @results ['a', 'b', 'c', 'd', 'e', 'f']
  2323. * var ranges = Pot.Iter.range({begin: 0, step: 10, end: 50});
  2324. * debug(ranges); // @results [0, 10, 20, 30, 40, 50]
  2325. *
  2326. *
  2327. * @param {Number|Object} end/begin The end number or object.
  2328. * @param {Number} (end) (optinal) The end number.
  2329. * @param {Number} (step) (optinal) The step number.
  2330. * @return {Array} Return an array result.
  2331. * @type Function
  2332. * @function
  2333. * @static
  2334. * @public
  2335. */
  2336. range : function(/*[begin,] end[, step]*/) {
  2337. var args = arguments, arg, result = [],
  2338. begin = 0,
  2339. end = 0,
  2340. step = 1,
  2341. n, string, iter;
  2342. switch (args.length) {
  2343. case 0:
  2344. return;
  2345. case 1:
  2346. arg = args[0];
  2347. if (isObject(arg)) {
  2348. if ('begin' in arg) {
  2349. begin = arg.begin;
  2350. } else if ('start' in arg) {
  2351. begin = arg.start;
  2352. }
  2353. if ('end' in arg) {
  2354. end = arg.end;
  2355. } else if ('stop' in arg) {
  2356. end = arg.stop;
  2357. }
  2358. if ('step' in arg) {
  2359. step = arg.step;
  2360. }
  2361. } else {
  2362. end = arg;
  2363. }
  2364. break;
  2365. case 2:
  2366. begin = args[0];
  2367. end = args[1];
  2368. break;
  2369. default:
  2370. begin = args[0];
  2371. end = args[1];
  2372. step = args[2];
  2373. }
  2374. if (isString(begin) && begin.length === 1 &&
  2375. isString(end) && end.length === 1) {
  2376. begin = begin.charCodeAt(0) || 0;
  2377. end = end.charCodeAt(0) || 0;
  2378. string = true;
  2379. } else {
  2380. begin = begin - 0;
  2381. end = end - 0;
  2382. string = false;
  2383. }
  2384. step = step - 0;
  2385. if (isNaN(begin) || isNaN(end) || isNaN(step) || step == 0) {
  2386. return result;
  2387. }
  2388. if ((step > 0 && begin > end) ||
  2389. (step < 0 && begin < end)) {
  2390. n = begin;
  2391. begin = end;
  2392. end = n;
  2393. }
  2394. iter = new Iter();
  2395. /**@ignore*/
  2396. iter.next = function() {
  2397. if ((step > 0 && begin > end) ||
  2398. (step < 0 && begin < end)) {
  2399. throw PotStopIteration;
  2400. }
  2401. result[result.length] = string ? fromUnicode(begin) : begin;
  2402. begin += step;
  2403. };
  2404. Pot.iterate(iter);
  2405. return result;
  2406. },
  2407. /**
  2408. * Returns the first index at which a
  2409. * given element can be found in the object, or -1 if it is not present.
  2410. *
  2411. * This method like Array.prototype.indexOf
  2412. *
  2413. *
  2414. * @example
  2415. * var array = [2, 5, 9];
  2416. * var index = Pot.Iter.indexOf(array, 2);
  2417. * // index is 0
  2418. * index = Pot.Iter.indexOf(array, 7);
  2419. * // index is -1
  2420. * var object = {a: 2, b: 5, c: 9};
  2421. * index = Pot.Iter.indexOf(object, 2);
  2422. * // index is 'a'
  2423. * index = Pot.Iter.indexOf(object, 7);
  2424. * // index is -1
  2425. *
  2426. *
  2427. * @param {Array|Object|*} object A target object.
  2428. * @param {*} subject A subject object.
  2429. * @param {*} (from) (Optional) The index at
  2430. * which to begin the search.
  2431. * Defaults to 0.
  2432. * @return {Number|String} Return the index of result, or -1.
  2433. * @type Function
  2434. * @function
  2435. * @static
  2436. * @public
  2437. */
  2438. indexOf : function(object, subject, from) {
  2439. var result = -1, i, len, val, passed,
  2440. args = arguments, argn = args.length,
  2441. arrayLike = object && isArrayLike(object),
  2442. objectLike = object && !arrayLike && isObject(object);
  2443. if (arrayLike) {
  2444. try {
  2445. if (PotSystem.isBuiltinArrayIndexOf) {
  2446. i = indexOf.apply(object, arrayize(args, 1));
  2447. if (isNumeric(i)) {
  2448. result = i;
  2449. } else {
  2450. throw i;
  2451. }
  2452. } else {
  2453. throw i;
  2454. }
  2455. } catch (err) {
  2456. len = (object && object.length) || 0;
  2457. i = (+from) || 0;
  2458. i = (i < 0) ? Math.ceil(i) : Math.floor(i);
  2459. if (i < 0) {
  2460. i += len;
  2461. }
  2462. for (; i < len; i++) {
  2463. try {
  2464. if (i in object) {
  2465. val = object[i];
  2466. if (val === subject) {
  2467. result = i;
  2468. break;
  2469. }
  2470. }
  2471. } catch (e) {
  2472. continue;
  2473. }
  2474. }
  2475. }
  2476. } else if (objectLike) {
  2477. passed = false;
  2478. each(object, function(ov, op) {
  2479. if (!passed && argn >= 3 && from !== op) {
  2480. return;
  2481. } else {
  2482. passed = true;
  2483. }
  2484. if (ov === subject) {
  2485. result = op;
  2486. }
  2487. });
  2488. } else if (object != null) {
  2489. try {
  2490. val = (object.toString && object.toString()) || String(object);
  2491. result = StringProto.indexOf.apply(val, arrayize(args, 1));
  2492. } catch (e) {
  2493. result = -1;
  2494. }
  2495. } else {
  2496. result = -1;
  2497. }
  2498. return result;
  2499. },
  2500. /**
  2501. * Returns the last index at which a
  2502. * given element can be found in the object, or -1 if it is not present.
  2503. *
  2504. * This method like Array.prototype.lastIndexOf
  2505. *
  2506. *
  2507. * @example
  2508. * debug('array');
  2509. * var index, array = [2, 5, 9, 2];
  2510. * index = Pot.Iter.lastIndexOf(array, 2);
  2511. * debug('index is 3 : result = ' + index); // 3
  2512. * index = Pot.Iter.lastIndexOf(array, 7);
  2513. * debug('index is -1 : result = ' + index); // -1
  2514. * index = Pot.Iter.lastIndexOf(array, 2, 3);
  2515. * debug('index is 3 : result = ' + index); // 3
  2516. * index = Pot.Iter.lastIndexOf(array, 2, 2);
  2517. * debug('index is 0 : result = ' + index); // 0
  2518. * index = Pot.Iter.lastIndexOf(array, 2, -2);
  2519. * debug('index is 0 : result = ' + index); // 0
  2520. * index = Pot.Iter.lastIndexOf(array, 2, -1);
  2521. * debug('index is 3 : result = ' + index); // 3
  2522. * debug('object');
  2523. * var object = {a: 2, b: 5, c: 9, d: 2};
  2524. * index = Pot.Iter.lastIndexOf(object, 2);
  2525. * debug('index is d : result = ' + index); // 'd'
  2526. * index = Pot.Iter.lastIndexOf(object, 7);
  2527. * debug('index is -1 : result = ' + index); // -1
  2528. * index = Pot.Iter.lastIndexOf(object, 2, 'd'); // 'd'
  2529. * debug('index is d : result = ' + index);
  2530. * index = Pot.Iter.lastIndexOf(object, 2, 'c'); // 'a'
  2531. * debug('index is a : result = ' + index);
  2532. *
  2533. *
  2534. * @param {Array|Object|*} object A target object.
  2535. * @param {*} subject A subject object.
  2536. * @param {*} (from) (Optional) The index at which to
  2537. * start searching backwards.
  2538. * Defaults to the array's length.
  2539. * @return {Number|String} Return the index of result, or -1.
  2540. * @type Function
  2541. * @function
  2542. * @static
  2543. * @public
  2544. */
  2545. lastIndexOf : function(object, subject, from) {
  2546. var result = -1, i, len, key, val, passed, pairs,
  2547. args = arguments,
  2548. arrayLike = object && isArrayLike(object),
  2549. objectLike = object && !arrayLike && isObject(object);
  2550. if (arrayLike) {
  2551. try {
  2552. if (PotSystem.isBuiltinArrayLastIndexOf) {
  2553. i = lastIndexOf.apply(object, arrayize(args, 1));
  2554. if (isNumeric(i)) {
  2555. result = i;
  2556. } else {
  2557. throw i;
  2558. }
  2559. } else {
  2560. throw i;
  2561. }
  2562. } catch (err) {
  2563. len = (object && object.length) || 0;
  2564. i = (+from);
  2565. if (isNaN(i)) {
  2566. i = len - 1;
  2567. } else {
  2568. i = (i < 0) ? Math.ceil(i) : Math.floor(i);
  2569. if (i < 0) {
  2570. i += len;
  2571. } else if (i >= len) {
  2572. i = len - 1;
  2573. }
  2574. }
  2575. for (; i > -1; i--) {
  2576. try {
  2577. if (i in object) {
  2578. val = object[i];
  2579. if (val === subject) {
  2580. result = i;
  2581. break;
  2582. }
  2583. }
  2584. } catch (e) {
  2585. continue;
  2586. }
  2587. }
  2588. }
  2589. } else if (objectLike) {
  2590. pairs = [];
  2591. passed = false;
  2592. each(object, function(ov, op) {
  2593. pairs[pairs.length] = [op, ov];
  2594. if (ov === subject) {
  2595. result = op;
  2596. }
  2597. if (op === from) {
  2598. passed = true;
  2599. throw PotStopIteration;
  2600. }
  2601. });
  2602. if (passed) {
  2603. result = -1;
  2604. len = pairs.length;
  2605. while (--len >= 0) {
  2606. key = pairs[len][0];
  2607. val = pairs[len][1];
  2608. if (val === subject) {
  2609. result = key;
  2610. break;
  2611. }
  2612. }
  2613. }
  2614. } else if (object != null) {
  2615. try {
  2616. val = (object.toString && object.toString()) || String(object);
  2617. result = StringProto.lastIndexOf.apply(val, arrayize(args, 1));
  2618. } catch (e) {
  2619. result = -1;
  2620. }
  2621. } else {
  2622. result = -1;
  2623. }
  2624. return result;
  2625. }
  2626. });
  2627. // Update methods for reference.
  2628. Pot.update({
  2629. toIter : Iter.toIter
  2630. });
  2631. //-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
  2632. // Update the Pot.Deferred object for iterators.
  2633. // Extends the Pot.Deferred object for iterators with speed.
  2634. update(PotTmp, {
  2635. /**
  2636. * @private
  2637. * @ignore
  2638. */
  2639. createIterators : function(iters) {
  2640. each(iters, function(iter) {
  2641. var o = {};
  2642. /**@ignore*/
  2643. o[iter.NAME] = function() {
  2644. var me = {}, args = arrayize(arguments);
  2645. me.iterateSpeed = (this && this.iterateSpeed) || Deferred.iterate;
  2646. return Deferred.begin(function() {
  2647. var d = new Deferred();
  2648. iter.method.apply(me, args).then(function(res) {
  2649. d.begin(res);
  2650. }, function(err) {
  2651. d.raise(err);
  2652. });
  2653. return d;
  2654. });
  2655. };
  2656. update(Deferred, o);
  2657. Deferred.extendSpeeds(Deferred, iter.NAME, function(opts) {
  2658. var me = {}, args = arrayize(arguments, 1);
  2659. me.iterateSpeed = Deferred.iterate[opts.speedName];
  2660. return Deferred.begin(function() {
  2661. var d = new Deferred();
  2662. iter.method.apply(me, args).then(function(res) {
  2663. d.begin(res);
  2664. }, function(err) {
  2665. d.raise(err);
  2666. });
  2667. return d;
  2668. });
  2669. }, LightIterator.speeds);
  2670. });
  2671. },
  2672. /**
  2673. * @private
  2674. * @ignore
  2675. */
  2676. createProtoIterators : function(iters) {
  2677. each(iters, function(iter) {
  2678. var o = {}, sp = {};
  2679. /**@ignore*/
  2680. o[iter.NAME] = function() {
  2681. var args = arrayize(arguments), options = update({}, this.options);
  2682. return this.then(function(value) {
  2683. var d = new Deferred();
  2684. args = iter.args(value, args);
  2685. iter.method.apply(iter.context, args).ensure(function(res) {
  2686. extendDeferredOptions(d, options);
  2687. if (isError(res)) {
  2688. d.raise(res);
  2689. } else {
  2690. d.begin(res);
  2691. }
  2692. });
  2693. return d;
  2694. });
  2695. };
  2696. update(Deferred.fn, o);
  2697. if (iter.speed) {
  2698. if (iter.iterable) {
  2699. /**@ignore*/
  2700. sp.methods = function(speed) {
  2701. return {
  2702. iter : iter.iterable[speed],
  2703. context : iter.context
  2704. };
  2705. };
  2706. } else {
  2707. /**@ignore*/
  2708. sp.methods = function(speed) {
  2709. return {
  2710. iter : iter.method,
  2711. context : {iterateSpeed : iter.context.iterateSpeed[speed]}
  2712. };
  2713. };
  2714. }
  2715. Deferred.extendSpeeds(Deferred.fn, iter.NAME, function(opts) {
  2716. var args = arrayize(arguments, 1),
  2717. iterable = sp.methods(opts.speedName),
  2718. options = update({}, this.options);
  2719. return this.then(function(value) {
  2720. var d = new Deferred();
  2721. args = iter.args(value, args);
  2722. iterable.iter.apply(iterable.context, args).ensure(function(res) {
  2723. extendDeferredOptions(d, options);
  2724. if (isError(res)) {
  2725. d.raise(res);
  2726. } else {
  2727. d.begin(res);
  2728. }
  2729. });
  2730. return d;
  2731. });
  2732. }, LightIterator.speeds);
  2733. }
  2734. });
  2735. },
  2736. /**
  2737. * @private
  2738. * @ignore
  2739. */
  2740. createSyncIterator : function(creator) {
  2741. var methods, construct,
  2742. /**@ignore*/
  2743. create = function(speed) {
  2744. var key = speed;
  2745. if (!key) {
  2746. each(LightIterator.speeds, function(v, k) {
  2747. if (v === LightIterator.defaults.speed) {
  2748. key = k;
  2749. throw PotStopIteration;
  2750. }
  2751. });
  2752. }
  2753. return creator(key);
  2754. };
  2755. construct = create();
  2756. methods = {};
  2757. each(LightIterator.speeds, function(v, k) {
  2758. methods[k] = create(k);
  2759. });
  2760. return update(construct, methods);
  2761. }
  2762. });
  2763. // Create iterators to Pot.Deferred.
  2764. PotTmp.createIterators([{
  2765. /**
  2766. * Creates a new object with the results of calling a
  2767. * provided function on every element in object.
  2768. *
  2769. * Iteration will use the results of the previous chain.
  2770. *
  2771. * This method like Array.prototype.map
  2772. *
  2773. *
  2774. * @example
  2775. * var words = ['foot', 'goose', 'moose'];
  2776. * Pot.Deferred.map(words, function(word) {
  2777. * return word.replace(/o/g, 'e');
  2778. * }).then(function(result) {
  2779. * debug(result);
  2780. * });
  2781. * // @results result = ['feet', 'geese', 'meese']
  2782. *
  2783. *
  2784. * @param {Array|Object|*} object A target object.
  2785. * @param {Function} callback A callback function.
  2786. * @param {*} (context) (Optional) Object to use
  2787. * as `this` when executing callback.
  2788. * @return {*} Return the result of each callbacks.
  2789. * @name Pot.Deferred.map
  2790. * @type Function
  2791. * @class
  2792. * @function
  2793. * @static
  2794. * @public
  2795. *
  2796. * @property {Function} limp Iterates "map" loop with slowest speed.
  2797. * @property {Function} doze Iterates "map" loop with slower speed.
  2798. * @property {Function} slow Iterates "map" loop with slow speed.
  2799. * @property {Function} normal Iterates "map" loop with default speed.
  2800. * @property {Function} fast Iterates "map" loop with fast speed.
  2801. * @property {Function} rapid Iterates "map" loop with faster speed.
  2802. * @property {Function} ninja Iterates "map" loop with fastest speed.
  2803. */
  2804. NAME : 'map',
  2805. /**@ignore*/
  2806. method : Iter.map
  2807. }, {
  2808. /**
  2809. * Creates a new object with all elements that
  2810. * pass the test implemented by the provided function.
  2811. *
  2812. * Iteration will use the results of the previous chain.
  2813. *
  2814. * This method like Array.prototype.filter
  2815. *
  2816. *
  2817. * @example
  2818. * var numbers = [12, 5, 8, 130, 44];
  2819. * Pot.Deferred.filter(numbers, function(value, index, array) {
  2820. * return (value >= 10);
  2821. * }).then(function(result) {
  2822. * debug(result);
  2823. * });
  2824. * // @results result = [12, 130, 44]
  2825. *
  2826. *
  2827. * @param {Array|Object|*} object A target object.
  2828. * @param {Function} callback A callback function.
  2829. * @param {*} (context) (Optional) Object to use
  2830. * as `this` when executing callback.
  2831. * @return {*} Return the result of each callbacks.
  2832. * @name Pot.Deferred.filter
  2833. * @type Function
  2834. * @class
  2835. * @function
  2836. * @static
  2837. * @public
  2838. *
  2839. * @property {Function} limp Iterates "filter" loop with slowest speed.
  2840. * @property {Function} doze Iterates "filter" loop with slower speed.
  2841. * @property {Function} slow Iterates "filter" loop with slow speed.
  2842. * @property {Function} normal Iterates "filter" loop with default speed.
  2843. * @property {Function} fast Iterates "filter" loop with fast speed.
  2844. * @property {Function} rapid Iterates "filter" loop with faster speed.
  2845. * @property {Function} ninja Iterates "filter" loop with fastest speed.
  2846. */
  2847. NAME : 'filter',
  2848. /**@ignore*/
  2849. method : Iter.filter
  2850. }, {
  2851. /**
  2852. * Apply a function against an accumulator and each value of
  2853. * the object (from left-to-right) as to reduce it to a single value.
  2854. *
  2855. * Iteration will use the results of the previous chain.
  2856. *
  2857. * This method like Array.prototype.reduce
  2858. *
  2859. *
  2860. * @example
  2861. * var numbers = [1, 2, 3, 4, 5];
  2862. * Pot.Deferred.reduce(numbers, function(a, b) {
  2863. * return a + b;
  2864. * }).then(function(result) {
  2865. * debug(result);
  2866. * });
  2867. * // @results result = 15
  2868. *
  2869. *
  2870. * @param {Array|Object|*} object A target object.
  2871. * @param {Function} callback A callback function.
  2872. * @param {*} initial An initial value passed as
  2873. * `callback` argument that
  2874. * will be used on
  2875. * first iteration.
  2876. * @param {*} (context) (Optional) Object to use as
  2877. * the first argument to the
  2878. * first call of the `callback`.
  2879. * @return {*} Return the result of each callbacks.
  2880. * @name Pot.Deferred.reduce
  2881. * @type Function
  2882. * @class
  2883. * @function
  2884. * @static
  2885. * @public
  2886. *
  2887. * @property {Function} limp Iterates "reduce" loop with slowest speed.
  2888. * @property {Function} doze Iterates "reduce" loop with slower speed.
  2889. * @property {Function} slow Iterates "reduce" loop with slow speed.
  2890. * @property {Function} normal Iterates "reduce" loop with default speed.
  2891. * @property {Function} fast Iterates "reduce" loop with fast speed.
  2892. * @property {Function} rapid Iterates "reduce" loop with faster speed.
  2893. * @property {Function} ninja Iterates "reduce" loop with fastest speed.
  2894. */
  2895. NAME : 'reduce',
  2896. /**@ignore*/
  2897. method : Iter.reduce
  2898. }, {
  2899. /**
  2900. * Tests whether all elements in the object pass the
  2901. * test implemented by the provided function.
  2902. *
  2903. * Iteration will use the results of the previous chain.
  2904. *
  2905. * This method like Array.prototype.every
  2906. *
  2907. * @example
  2908. * var numbers = [12, 5, 8, 130, 44];
  2909. * Pot.Deferred.every(numbers, function(value, index, array) {
  2910. * return (value >= 10);
  2911. * }).then(function(result) {
  2912. * debug(result);
  2913. * // @results false
  2914. * });
  2915. *
  2916. * @example
  2917. * var numbers = [12, 54, 18, 130, 44];
  2918. * Pot.Deferred.every(numbers, function(value, index, array) {
  2919. * return (value >= 10);
  2920. * }).then(function(result) {
  2921. * debug(result);
  2922. * // @results true
  2923. * });
  2924. *
  2925. * @param {Array|Object|*} object A target object.
  2926. * @param {Function} callback A callback function.
  2927. * @param {*} (context) (Optional) Object to use as
  2928. * `this` when executing callback.
  2929. * @return {Boolean} Return the Boolean result
  2930. * by callback.
  2931. * @name Pot.Deferred.every
  2932. * @type Function
  2933. * @class
  2934. * @function
  2935. * @static
  2936. * @public
  2937. *
  2938. * @property {Function} limp Iterates "every" loop with slowest speed.
  2939. * @property {Function} doze Iterates "every" loop with slower speed.
  2940. * @property {Function} slow Iterates "every" loop with slow speed.
  2941. * @property {Function} normal Iterates "every" loop with default speed.
  2942. * @property {Function} fast Iterates "every" loop with fast speed.
  2943. * @property {Function} rapid Iterates "every" loop with faster speed.
  2944. * @property {Function} ninja Iterates "every" loop with fastest speed.
  2945. */
  2946. NAME : 'every',
  2947. /**@ignore*/
  2948. method : Iter.every
  2949. }, {
  2950. /**
  2951. * Tests whether some element in the object passes the
  2952. * test implemented by the provided function.
  2953. *
  2954. * Iteration will use the results of the previous chain.
  2955. *
  2956. * This method like Array.prototype.some
  2957. *
  2958. *
  2959. * @example
  2960. * var numbers = [2, 5, 8, 1, 4];
  2961. * Pot.Deferred.some(numbers, function(value, index, array) {
  2962. * return (value >= 10);
  2963. * }).then(function(result) {
  2964. * debug(result);
  2965. * // @results false
  2966. * });
  2967. *
  2968. * @example
  2969. * var numbers = [12, 5, 8, 1, 4];
  2970. * Pot.Deferred.some(numbers, function(value, index, array) {
  2971. * return (value >= 10);
  2972. * }).then(function(result) {
  2973. * debug(result);
  2974. * // @results true
  2975. * });
  2976. *
  2977. *
  2978. * @param {Array|Object|*} object A target object.
  2979. * @param {Function} callback A callback function.
  2980. * @param {*} (context) (Optional) Object to use as
  2981. * `this` when executing callback.
  2982. * @return {Boolean} Return the Boolean result by
  2983. * callback.
  2984. * @name Pot.Deferred.some
  2985. * @type Function
  2986. * @class
  2987. * @function
  2988. * @static
  2989. * @public
  2990. *
  2991. * @property {Function} limp Iterates "some" loop with slowest speed.
  2992. * @property {Function} doze Iterates "some" loop with slower speed.
  2993. * @property {Function} slow Iterates "some" loop with slow speed.
  2994. * @property {Function} normal Iterates "some" loop with default speed.
  2995. * @property {Function} fast Iterates "some" loop with fast speed.
  2996. * @property {Function} rapid Iterates "some" loop with faster speed.
  2997. * @property {Function} ninja Iterates "some" loop with fastest speed.
  2998. */
  2999. NAME : 'some',
  3000. /**@ignore*/
  3001. method : Iter.some
  3002. }]);
  3003. // Create iterators to Pot.Deferred.prototype.
  3004. PotTmp.createProtoIterators([{
  3005. /**
  3006. * Iterates as "for each" loop. (Asynchronous)
  3007. *
  3008. * Iteration will use the results of the previous chain.
  3009. *
  3010. * @desc
  3011. * <pre>
  3012. * Unlike Deferred, speed options affect to cutback count in loop.
  3013. * Options append to after the forEach and execute it.
  3014. *
  3015. * e.g. d.forEach.slow(function() {...}).then(function() {...})
  3016. *
  3017. * The available methods are below.
  3018. * ------------------------------------
  3019. * method name | speed
  3020. * ------------------------------------
  3021. * limp : slowest
  3022. * doze : slower
  3023. * slow : slowly
  3024. * normal : normal (default)
  3025. * fast : fast
  3026. * rapid : faster
  3027. * ninja : fastest
  3028. * ------------------------------------
  3029. * </pre>
  3030. *
  3031. *
  3032. * @example
  3033. * var elems = document.getElementsByTagName('*');
  3034. * var defer = new Pot.Deferred();
  3035. * var alpha = 1;
  3036. * defer.forEach.slow(function(elem, i, elems) {
  3037. * alpha -= 0.02;
  3038. * if (alpha < 0.02) {
  3039. * alpha = 0.02;
  3040. * }
  3041. * elem.style.opacity = alpha;
  3042. * }).wait(5).forEach(function(elem, i, elems) {
  3043. * elem.style.opacity = 1;
  3044. * }).then(function() {
  3045. * debug('end');
  3046. * }).begin(elems);
  3047. *
  3048. *
  3049. * @param {Function} callback An iterable function.
  3050. * function(value, key, object)
  3051. * this == `context`.
  3052. * Throw Pot.StopIteration
  3053. * if you want to stop the loop.
  3054. * @param {*} (context) Optionally, context object. (i.e. this)
  3055. * @result {Deferred} Return the Deferred.
  3056. *
  3057. * @name Pot.Deferred.prototype.forEach
  3058. * @class
  3059. * @public
  3060. *
  3061. * @property {Function} limp Iterates "for each" loop with slowest speed.
  3062. * @property {Function} doze Iterates "for each" loop with slower speed.
  3063. * @property {Function} slow Iterates "for each" loop with slow speed.
  3064. * @property {Function} normal Iterates "for each" loop with default speed.
  3065. * @property {Function} fast Iterates "for each" loop with fast speed.
  3066. * @property {Function} rapid Iterates "for each" loop with faster speed.
  3067. * @property {Function} ninja Iterates "for each" loop with fastest speed.
  3068. */
  3069. NAME : 'forEach',
  3070. /**
  3071. * @ignore
  3072. */
  3073. method : Deferred.forEach,
  3074. /**
  3075. * @ignore
  3076. */
  3077. context : null,
  3078. /**
  3079. * @ignore
  3080. */
  3081. speed : true,
  3082. /**
  3083. * @ignore
  3084. */
  3085. iterable : Deferred.forEach,
  3086. /**
  3087. * @ignore
  3088. */
  3089. args : function(arg, args) {
  3090. return [arg].concat(args);
  3091. }
  3092. }, {
  3093. /**
  3094. * "repeat" loop iterates a specified number. (Asynchronous)
  3095. *
  3096. * If you specify the first argument as a function
  3097. * then the results of the previous chain will be used.
  3098. *
  3099. *
  3100. * @example
  3101. * var d = new Pot.Deferred();
  3102. * var p = document.getElementsByTagName('p');
  3103. * d.repeat(p.length, function(i, last) {
  3104. * p[i].innerHTML += last ? 'end' : i;
  3105. * }).then(function() {
  3106. * debug('finish');
  3107. * }).begin();
  3108. *
  3109. *
  3110. * @param {Number|Object} (max) The maximum number of times to loop,
  3111. * or object.
  3112. * @param {Function} callback An iterable function.
  3113. * Throw Pot.StopIteration
  3114. * if you want to stop the loop.
  3115. * @param {*} (context) Optionally, context object. (i.e. this)
  3116. * @return {Deferred} Return the Deferred.
  3117. *
  3118. * @name Pot.Deferred.prototype.repeat
  3119. * @class
  3120. * @public
  3121. *
  3122. * @property {Function} limp Iterates "repeat" loop with slowest speed.
  3123. * @property {Function} doze Iterates "repeat" loop with slower speed.
  3124. * @property {Function} slow Iterates "repeat" loop with slow speed.
  3125. * @property {Function} normal Iterates "repeat" loop with default speed.
  3126. * @property {Function} fast Iterates "repeat" loop with fast speed.
  3127. * @property {Function} rapid Iterates "repeat" loop with faster speed.
  3128. * @property {Function} ninja Iterates "repeat" loop with fastest speed.
  3129. */
  3130. NAME : 'repeat',
  3131. /**
  3132. * @ignore
  3133. */
  3134. method : Deferred.repeat,
  3135. /**
  3136. * @ignore
  3137. */
  3138. context : null,
  3139. /**
  3140. * @ignore
  3141. */
  3142. speed : true,
  3143. /**
  3144. * @ignore
  3145. */
  3146. iterable : Deferred.repeat,
  3147. /**
  3148. * @ignore
  3149. */
  3150. args : function(arg, args) {
  3151. if (isNumeric(arg)) {
  3152. return [arg - 0].concat(args);
  3153. }
  3154. if (arg && isNumber(arg.length)) {
  3155. return [arg.length].concat(args);
  3156. }
  3157. if (arg && isObject(arg) &&
  3158. ('end' in arg || 'begin' in arg || 'step' in arg ||
  3159. 'stop' in arg || 'start' in arg)) {
  3160. return [arg].concat(args);
  3161. }
  3162. return args;
  3163. }
  3164. }, {
  3165. /**
  3166. * Iterates indefinitely until "Pot.StopIteration" is thrown. (Asynchronous)
  3167. *
  3168. *
  3169. * @example
  3170. * var d = new Pot.Deferred();
  3171. * var s = '';
  3172. * d.forEver(function(i) {
  3173. * s += 'i=' + i + ',';
  3174. * if (s.length > 25) {
  3175. * throw Pot.StopIteration;
  3176. * }
  3177. * }).then(function() {
  3178. * debug(s);
  3179. * }).begin();
  3180. * // @results s = 'i=0,i=1,i=2,i=3,i=4,i=5,i=6,'
  3181. *
  3182. *
  3183. * @param {Function} callback An iterable function.
  3184. * Throw Pot.StopIteration
  3185. * if you want to stop the loop.
  3186. * @param {*} (context) Optionally, context object. (i.e. this)
  3187. * @return {Deferred} Return the Deferred.
  3188. *
  3189. * @name Pot.Deferred.prototype.forEver
  3190. * @class
  3191. * @public
  3192. *
  3193. * @property {Function} limp Iterates "forEver" loop with slowest speed.
  3194. * @property {Function} doze Iterates "forEver" loop with slower speed.
  3195. * @property {Function} slow Iterates "forEver" loop with slow speed.
  3196. * @property {Function} normal Iterates "forEver" loop with default speed.
  3197. * @property {Function} fast Iterates "forEver" loop with fast speed.
  3198. * @property {Function} rapid Iterates "forEver" loop with faster speed.
  3199. * @property {Function} ninja Iterates "forEver" loop with fastest speed.
  3200. */
  3201. NAME : 'forEver',
  3202. /**
  3203. * @ignore
  3204. */
  3205. method : Deferred.forEver,
  3206. /**
  3207. * @ignore
  3208. */
  3209. context : null,
  3210. /**
  3211. * @ignore
  3212. */
  3213. speed : true,
  3214. /**
  3215. * @ignore
  3216. */
  3217. iterable : Deferred.forEver,
  3218. /**
  3219. * @ignore
  3220. */
  3221. args : function(arg, args) {
  3222. return args;
  3223. }
  3224. }, {
  3225. /**
  3226. * Iterate an iterable object that is previous chain result.
  3227. *
  3228. * Iteration will use the results of the previous chain.
  3229. *
  3230. * @param {Function} callback An iterable function.
  3231. * function(value, key, object)
  3232. * this == `context`.
  3233. * Throw Pot.StopIteration
  3234. * if you want to stop the loop.
  3235. * @param {Object} (context) Optionally, context object. (i.e. this)
  3236. * @return {Deferred} Return the Deferred.
  3237. *
  3238. * @name Pot.Deferred.prototype.iterate
  3239. * @class
  3240. * @public
  3241. *
  3242. * @property {Function} limp Iterates "iterate" loop with slowest speed.
  3243. * @property {Function} doze Iterates "iterate" loop with slower speed.
  3244. * @property {Function} slow Iterates "iterate" loop with slow speed.
  3245. * @property {Function} normal Iterates "iterate" loop with default speed.
  3246. * @property {Function} fast Iterates "iterate" loop with fast speed.
  3247. * @property {Function} rapid Iterates "iterate" loop with faster speed.
  3248. * @property {Function} ninja Iterates "iterate" loop with fastest speed.
  3249. */
  3250. NAME : 'iterate',
  3251. /**
  3252. * @ignore
  3253. */
  3254. method : Deferred.iterate,
  3255. /**
  3256. * @ignore
  3257. */
  3258. context : null,
  3259. /**
  3260. * @ignore
  3261. */
  3262. speed : true,
  3263. /**
  3264. * @ignore
  3265. */
  3266. iterable : Deferred.iterate,
  3267. /**
  3268. * @ignore
  3269. */
  3270. args : function(arg, args) {
  3271. return [arg].concat(args);
  3272. }
  3273. }, {
  3274. /**
  3275. * Collect the object key and value and make array as items format.
  3276. *
  3277. *
  3278. * @example
  3279. * var obj = {foo: 1, bar: 2, baz: 3};
  3280. * var d = new Deferred();
  3281. * d.items().then(function(res) {
  3282. * debug(res);
  3283. * // @results [['foo', 1], ['bar', 2], ['baz', 3]]
  3284. * }).begin(obj);
  3285. *
  3286. *
  3287. * @example
  3288. * var array = ['foo', 'bar', 'baz'];
  3289. * var d = new Deferred();
  3290. * d.items().then(function(res) {
  3291. * debug(res);
  3292. * // @results [[0, 'foo'], [1, 'bar'], [2, 'baz']]
  3293. * }).begin(array);
  3294. *
  3295. *
  3296. * @example
  3297. * // Example for using callback.
  3298. * var arr = ['foo', 'bar', 'baz'];
  3299. * var func = function(item) {
  3300. * return '(' + item[0] + ')' + item[1];
  3301. * };
  3302. * var d = new Deferred();
  3303. * d.items(func).then(function(res) {
  3304. * debug(res);
  3305. * // @results ['(0)foo', '(1)bar', '(2)baz']
  3306. * }).begin(arr);
  3307. *
  3308. *
  3309. * @example
  3310. * // Example for using callback.
  3311. * var obj = {foo: 1, bar: 2, baz: 3};
  3312. * var func = function(item) {
  3313. * return [item[0] + '::' + item[1]];
  3314. * };
  3315. * var d = new Deferred();
  3316. * d.items(func).then(function(res) {
  3317. * debug(res);
  3318. * // @results [['foo::1'], ['bar::2'], ['baz::3']]
  3319. * }).begin(obj);
  3320. *
  3321. *
  3322. * @param {Function} (callback) (Optional) Callback function.
  3323. * function({Array} item[, object])
  3324. * this == `context`.
  3325. * @param {*} (context) (Optional) Object to use
  3326. * as `this` when executing callback.
  3327. * @return {Array} The collected items as an array.
  3328. *
  3329. * @name Pot.Deferred.prototype.items
  3330. * @class
  3331. * @public
  3332. *
  3333. * @property {Function} limp Iterates "items" loop with slowest speed.
  3334. * @property {Function} doze Iterates "items" loop with slower speed.
  3335. * @property {Function} slow Iterates "items" loop with slow speed.
  3336. * @property {Function} normal Iterates "items" loop with default speed.
  3337. * @property {Function} fast Iterates "items" loop with fast speed.
  3338. * @property {Function} rapid Iterates "items" loop with faster speed.
  3339. * @property {Function} ninja Iterates "items" loop with fastest speed.
  3340. */
  3341. NAME : 'items',
  3342. /**
  3343. * @ignore
  3344. */
  3345. method : Deferred.items,
  3346. /**
  3347. * @ignore
  3348. */
  3349. context : null,
  3350. /**
  3351. * @ignore
  3352. */
  3353. speed : true,
  3354. /**
  3355. * @ignore
  3356. */
  3357. iterable : Deferred.items,
  3358. /**
  3359. * @ignore
  3360. */
  3361. args : function(arg, args) {
  3362. return [arg].concat(args);
  3363. }
  3364. }, {
  3365. /**
  3366. * Create a new array which has the elements at
  3367. * position ith of the provided arrays.
  3368. * This function is handled as seen from the longitudinal for array
  3369. * that is similar to the zip() function in Python.
  3370. *
  3371. * <pre>
  3372. * Example:
  3373. *
  3374. * arguments: [[1, 2, 3],
  3375. * [4, 5, 6]]
  3376. *
  3377. * results: [[1, 4],
  3378. * [2, 5],
  3379. * [3, 6]]
  3380. * </pre>
  3381. *
  3382. *
  3383. * @link http://docs.python.org/library/functions.html#zip
  3384. *
  3385. *
  3386. * @example
  3387. * var d = new Deferred();
  3388. * d.then(function() {
  3389. * return [[1, 2, 3], [4, 5, 6]];
  3390. * }).zip().then(function(res) {
  3391. * debug(res);
  3392. * // @results
  3393. * // [[1, 4], [2, 5], [3, 6]]
  3394. * //
  3395. * }).begin();
  3396. *
  3397. *
  3398. * @example
  3399. * var d = new Deferred();
  3400. * d.then(function() {
  3401. * return [[1, 2, 3], [1, 2, 3, 4, 5]];
  3402. * }).zip().then(function(res) {
  3403. * debug(res);
  3404. * // @results
  3405. * // [[1, 1], [2, 2], [3, 3]]
  3406. * //
  3407. * }).begin();
  3408. *
  3409. *
  3410. * @example
  3411. * var d = new Deferred();
  3412. * d.then(function() {
  3413. * return [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11]];
  3414. * }).zip().then(function(res) {
  3415. * debug(res);
  3416. * // @results
  3417. * // [[1, 4, 7, 10], [2, 5, 8, 11]]
  3418. * //
  3419. * }).begin();
  3420. *
  3421. *
  3422. * @example
  3423. * begin(function() {
  3424. * return ['hoge'];
  3425. * }).zip().then(function(res) {
  3426. * debug(res);
  3427. * // @results
  3428. * // [['hoge']]
  3429. * //
  3430. * });
  3431. *
  3432. *
  3433. * @example
  3434. * begin(function() {
  3435. * return [[1], [2], [3]];
  3436. * }).zip().then(function(res) {
  3437. * debug(res);
  3438. * // @results
  3439. * // [[1, 2, 3]]
  3440. * //
  3441. * });
  3442. *
  3443. *
  3444. * @example
  3445. * begin(function() {
  3446. * return [[1, 2, 3], ['foo', 'bar', 'baz'], [4, 5]];
  3447. * }).zip().then(function(res) {
  3448. * debug(res);
  3449. * // @results
  3450. * // [[1, 'foo', 4], [2, 'bar', 5]]
  3451. * //
  3452. * });
  3453. *
  3454. *
  3455. * @example
  3456. * var callback = function(items) { return items[0] + items[1]; };
  3457. * begin(function() {
  3458. * return [[1, 2, 3], [4, 5, 6]];
  3459. * }).zip(callback).then(function(res) {
  3460. * debug(res);
  3461. * // @results [5, 7, 9]
  3462. * });
  3463. *
  3464. *
  3465. * @param {Function} (callback) (Optional) Callback function.
  3466. * function({Array} items[, {*} object])
  3467. * this == `context`.
  3468. * @param {*} (context) (Optional) Object to use
  3469. * as `this` when executing callback.
  3470. * @return {Array} A new array of arrays created from
  3471. * provided objects.
  3472. *
  3473. * @name Pot.Deferred.prototype.zip
  3474. * @class
  3475. * @public
  3476. *
  3477. * @property {Function} limp Iterates "zip" loop with slowest speed.
  3478. * @property {Function} doze Iterates "zip" loop with slower speed.
  3479. * @property {Function} slow Iterates "zip" loop with slow speed.
  3480. * @property {Function} normal Iterates "zip" loop with default speed.
  3481. * @property {Function} fast Iterates "zip" loop with fast speed.
  3482. * @property {Function} rapid Iterates "zip" loop with faster speed.
  3483. * @property {Function} ninja Iterates "zip" loop with fastest speed.
  3484. */
  3485. NAME : 'zip',
  3486. /**
  3487. * @ignore
  3488. */
  3489. method : Deferred.zip,
  3490. /**
  3491. * @ignore
  3492. */
  3493. context : null,
  3494. /**
  3495. * @ignore
  3496. */
  3497. speed : true,
  3498. /**
  3499. * @ignore
  3500. */
  3501. iterable : Deferred.zip,
  3502. /**
  3503. * @ignore
  3504. */
  3505. args : function(arg, args) {
  3506. return [arg].concat(args);
  3507. }
  3508. }, {
  3509. /**
  3510. * Creates a new object with the results of calling a
  3511. * provided function on every element in chains result.
  3512. *
  3513. * Iteration will use the results of the previous chain.
  3514. *
  3515. * This method like Array.prototype.map
  3516. *
  3517. *
  3518. * @example
  3519. * var d = new Pot.Deferred();
  3520. * d.then(function() {
  3521. * return ['foot', 'goose', 'moose'];
  3522. * }).map(function(word) {
  3523. * return word.replace(/o/g, 'e');
  3524. * }).then(function(result) {
  3525. * debug(result);
  3526. * }).begin();
  3527. * // @results result = ['feet', 'geese', 'meese']
  3528. *
  3529. *
  3530. * @param {Function} callback A callback function.
  3531. * @param {*} (context) (Optional) Object to use
  3532. * as `this` when executing callback.
  3533. * @return {*} Return the result of each callbacks.
  3534. *
  3535. * @name Pot.Deferred.prototype.map
  3536. * @class
  3537. * @public
  3538. *
  3539. * @property {Function} limp Iterates "map" loop with slowest speed.
  3540. * @property {Function} doze Iterates "map" loop with slower speed.
  3541. * @property {Function} slow Iterates "map" loop with slow speed.
  3542. * @property {Function} normal Iterates "map" loop with default speed.
  3543. * @property {Function} fast Iterates "map" loop with fast speed.
  3544. * @property {Function} rapid Iterates "map" loop with faster speed.
  3545. * @property {Function} ninja Iterates "map" loop with fastest speed.
  3546. */
  3547. NAME : 'map',
  3548. /**
  3549. * @ignore
  3550. */
  3551. method : Iter.map,
  3552. /**
  3553. * @ignore
  3554. */
  3555. context : {iterateSpeed : Deferred.iterate},
  3556. /**
  3557. * @ignore
  3558. */
  3559. speed : true,
  3560. /**
  3561. * @ignore
  3562. */
  3563. iterable : null,
  3564. /**
  3565. * @ignore
  3566. */
  3567. args : function(arg, args) {
  3568. return [arg].concat(args);
  3569. }
  3570. }, {
  3571. /**
  3572. * Creates a new object with all elements that
  3573. * pass the test implemented by the provided function.
  3574. *
  3575. * Iteration will use the results of the previous chain.
  3576. *
  3577. * This method like Array.prototype.filter
  3578. *
  3579. *
  3580. * @example
  3581. * var d = new Pot.Deferred();
  3582. * d.then(function() {
  3583. * return [12, 5, 8, 130, 44];
  3584. * }).filter(function(value, index, array) {
  3585. * return (value >= 10);
  3586. * }).then(function(result) {
  3587. * debug(result);
  3588. * }).begin();
  3589. * // @results [12, 130, 44]
  3590. *
  3591. *
  3592. * @param {Function} callback A callback function.
  3593. * @param {*} (context) (Optional) Object to use
  3594. * as `this` when executing callback.
  3595. * @return {*} Return the result of each callbacks.
  3596. *
  3597. * @name Pot.Deferred.prototype.filter
  3598. * @class
  3599. * @public
  3600. *
  3601. * @property {Function} limp Iterates "filter" loop with slowest speed.
  3602. * @property {Function} doze Iterates "filter" loop with slower speed.
  3603. * @property {Function} slow Iterates "filter" loop with slow speed.
  3604. * @property {Function} normal Iterates "filter" loop with default speed.
  3605. * @property {Function} fast Iterates "filter" loop with fast speed.
  3606. * @property {Function} rapid Iterates "filter" loop with faster speed.
  3607. * @property {Function} ninja Iterates "filter" loop with fastest speed.
  3608. */
  3609. NAME : 'filter',
  3610. /**
  3611. * @ignore
  3612. */
  3613. method : Iter.filter,
  3614. /**
  3615. * @ignore
  3616. */
  3617. context : {iterateSpeed : Deferred.iterate},
  3618. /**
  3619. * @ignore
  3620. */
  3621. speed : true,
  3622. /**
  3623. * @ignore
  3624. */
  3625. iterable : null,
  3626. /**
  3627. * @ignore
  3628. */
  3629. args : function(arg, args) {
  3630. return [arg].concat(args);
  3631. }
  3632. }, {
  3633. /**
  3634. * Apply a function against an accumulator and each value of
  3635. * the object (from left-to-right) as to reduce it to a single value.
  3636. *
  3637. * Iteration will use the results of the previous chain.
  3638. *
  3639. * This method like Array.prototype.reduce
  3640. *
  3641. *
  3642. * @example
  3643. * Pot.Deferred.begin(function() {
  3644. * return [1, 2, 3, 4, 5];
  3645. * }).reduce(function(a, b) {
  3646. * return a + b;
  3647. * }).then(function(result) {
  3648. * debug(result);
  3649. * });
  3650. * // @results 15
  3651. *
  3652. *
  3653. * @param {Function} callback A callback function.
  3654. * @param {*} initial An initial value passed as `callback`
  3655. * argument that will be used on
  3656. * first iteration.
  3657. * @param {*} (context) (Optional) Object to use as
  3658. * the first argument to the
  3659. * first call of the `callback`.
  3660. * @return {*} Return the result of each callbacks.
  3661. *
  3662. * @name Pot.Deferred.prototype.reduce
  3663. * @class
  3664. * @public
  3665. *
  3666. * @property {Function} limp Iterates "reduce" loop with slowest speed.
  3667. * @property {Function} doze Iterates "reduce" loop with slower speed.
  3668. * @property {Function} slow Iterates "reduce" loop with slow speed.
  3669. * @property {Function} normal Iterates "reduce" loop with default speed.
  3670. * @property {Function} fast Iterates "reduce" loop with fast speed.
  3671. * @property {Function} rapid Iterates "reduce" loop with faster speed.
  3672. * @property {Function} ninja Iterates "reduce" loop with fastest speed.
  3673. */
  3674. NAME : 'reduce',
  3675. /**
  3676. * @ignore
  3677. */
  3678. method : Iter.reduce,
  3679. /**
  3680. * @ignore
  3681. */
  3682. context : {iterateSpeed : Deferred.iterate},
  3683. /**
  3684. * @ignore
  3685. */
  3686. speed : true,
  3687. /**
  3688. * @ignore
  3689. */
  3690. iterable : null,
  3691. /**
  3692. * @ignore
  3693. */
  3694. args : function(arg, args) {
  3695. return [arg].concat(args);
  3696. }
  3697. }, {
  3698. /**
  3699. * Tests whether all elements in the object pass the
  3700. * test implemented by the provided function.
  3701. *
  3702. * Iteration will use the results of the previous chain.
  3703. *
  3704. * This method like Array.prototype.every
  3705. *
  3706. * @example
  3707. * var d = new Pot.Deferred();
  3708. * d.then(function() {
  3709. * return [12, 5, 8, 130, 44];
  3710. * }).every(function(value, index, array) {
  3711. * return (value >= 10);
  3712. * }).then(function(result) {
  3713. * debug(result);
  3714. * // @results false
  3715. * }).then(function() {
  3716. * return [12, 54, 18, 130, 44];
  3717. * }).every(function(value, index, array) {
  3718. * return (value >= 10);
  3719. * }).then(function(result) {
  3720. * debug(result);
  3721. * // @results true
  3722. * });
  3723. * d.begin();
  3724. *
  3725. *
  3726. * @param {Function} callback A callback function.
  3727. * @param {*} (context) (Optional) Object to use
  3728. * as `this` when executing callback.
  3729. * @return {Boolean} Return the Boolean result by callback.
  3730. *
  3731. * @name Pot.Deferred.prototype.every
  3732. * @class
  3733. * @public
  3734. *
  3735. * @property {Function} limp Iterates "every" loop with slowest speed.
  3736. * @property {Function} doze Iterates "every" loop with slower speed.
  3737. * @property {Function} slow Iterates "every" loop with slow speed.
  3738. * @property {Function} normal Iterates "every" loop with default speed.
  3739. * @property {Function} fast Iterates "every" loop with fast speed.
  3740. * @property {Function} rapid Iterates "every" loop with faster speed.
  3741. * @property {Function} ninja Iterates "every" loop with fastest speed.
  3742. */
  3743. NAME : 'every',
  3744. /**
  3745. * @ignore
  3746. */
  3747. method : Iter.every,
  3748. /**
  3749. * @ignore
  3750. */
  3751. context : {iterateSpeed : Deferred.iterate},
  3752. /**
  3753. * @ignore
  3754. */
  3755. speed : true,
  3756. /**
  3757. * @ignore
  3758. */
  3759. iterable : null,
  3760. /**
  3761. * @ignore
  3762. */
  3763. args : function(arg, args) {
  3764. return [arg].concat(args);
  3765. }
  3766. }, {
  3767. /**
  3768. * Tests whether some element in the object passes the
  3769. * test implemented by the provided function.
  3770. *
  3771. * Iteration will use the results of the previous chain.
  3772. *
  3773. * This method like Array.prototype.some
  3774. *
  3775. *
  3776. * @example
  3777. * Pot.Deferred.begin(function() {
  3778. * return [2, 5, 8, 1, 4];
  3779. * }).some(function(value, index, array) {
  3780. * return (value >= 10);
  3781. * }).then(function(result) {
  3782. * debug(result);
  3783. * // @results false
  3784. * }).then(function() {
  3785. * return [12, 5, 8, 1, 4];
  3786. * }).some(function(value, index, array) {
  3787. * return (value >= 10);
  3788. * }).then(function(result) {
  3789. * debug(result);
  3790. * // @results true;
  3791. * });
  3792. *
  3793. *
  3794. * @param {Function} callback A callback function.
  3795. * @param {*} (context) (Optional) Object to use
  3796. * as `this` when executing callback.
  3797. * @return {Boolean} Return the Boolean result by callback.
  3798. *
  3799. * @name Pot.Deferred.prototype.some
  3800. * @class
  3801. * @public
  3802. *
  3803. * @property {Function} limp Iterates "some" loop with slowest speed.
  3804. * @property {Function} doze Iterates "some" loop with slower speed.
  3805. * @property {Function} slow Iterates "some" loop with slow speed.
  3806. * @property {Function} normal Iterates "some" loop with default speed.
  3807. * @property {Function} fast Iterates "some" loop with fast speed.
  3808. * @property {Function} rapid Iterates "some" loop with faster speed.
  3809. * @property {Function} ninja Iterates "some" loop with fastest speed.
  3810. */
  3811. NAME : 'some',
  3812. /**
  3813. * @ignore
  3814. */
  3815. method : Iter.some,
  3816. /**
  3817. * @ignore
  3818. */
  3819. context : {iterateSpeed : Deferred.iterate},
  3820. /**
  3821. * @ignore
  3822. */
  3823. speed : true,
  3824. /**
  3825. * @ignore
  3826. */
  3827. iterable : null,
  3828. /**
  3829. * @ignore
  3830. */
  3831. args : function(arg, args) {
  3832. return [arg].concat(args);
  3833. }
  3834. }]);
  3835. createSyncIterator = PotTmp.createSyncIterator;
  3836. // Update iterator methods for Pot
  3837. Pot.update({
  3838. /**
  3839. * @lends Pot
  3840. */
  3841. /**
  3842. * Creates a new object with the results of calling a
  3843. * provided function on every element in object.
  3844. *
  3845. * This method like Array.prototype.map
  3846. *
  3847. *
  3848. * @example
  3849. * function fuzzyPlural(single) {
  3850. * return single.replace(/o/g, 'e');
  3851. * }
  3852. * var words = ['foot', 'goose', 'moose'];
  3853. * debug(Pot.map(words, fuzzyPlural));
  3854. * // @results ['feet', 'geese', 'meese']
  3855. *
  3856. * @example
  3857. * var object = {foo: 'foo1', bar: 'bar2', baz: 'baz3'};
  3858. * var result = Pot.map(object, function(value, key) {
  3859. * return value + '00';
  3860. * });
  3861. * debug(result);
  3862. * // @results {foo: 'foo100', bar: 'bar200', baz: 'baz300'}
  3863. *
  3864. *
  3865. * @param {Array|Object|*} object A target object.
  3866. * @param {Function} callback A callback function.
  3867. * @param {*} (context) (Optional) Object to use
  3868. * as `this` when executing callback.
  3869. * @return {*} Return the result of each callbacks.
  3870. * @name Pot.map
  3871. * @class
  3872. * @function
  3873. * @static
  3874. * @public
  3875. */
  3876. map : createSyncIterator(function(speedKey) {
  3877. return function() {
  3878. var context = {iterateSpeedSync : Pot.iterate[speedKey]};
  3879. return Iter.map.apply(context, arguments);
  3880. };
  3881. }),
  3882. /**
  3883. * Creates a new object with all elements that
  3884. * pass the test implemented by the provided function.
  3885. *
  3886. * This method like Array.prototype.filter
  3887. *
  3888. *
  3889. * @example
  3890. * function isBigEnough(value, index, array) {
  3891. * return (value >= 10);
  3892. * }
  3893. * var filtered = Pot.filter([12, 5, 8, 130, 44], isBigEnough);
  3894. * debug(filtered);
  3895. * // @results [12, 130, 44]
  3896. *
  3897. *
  3898. * @example
  3899. * function isBigEnough(value, key, object) {
  3900. * return (value >= 10);
  3901. * }
  3902. * var object = {a: 1, b: 20, c: 7, d: 5, e: 27, f: 99};
  3903. * var result = Pot.filter(object, isBigEnough);
  3904. * debug(result);
  3905. * // @results {b: 20, e: 27, f: 99}
  3906. *
  3907. *
  3908. * @param {Array|Object|*} object A target object.
  3909. * @param {Function} callback A callback function.
  3910. * @param {*} (context) (Optional) Object to use
  3911. * as `this` when executing callback.
  3912. * @return {*} Return the result of each callbacks.
  3913. * @name Pot.filter
  3914. * @class
  3915. * @function
  3916. * @static
  3917. * @public
  3918. */
  3919. filter : createSyncIterator(function(speedKey) {
  3920. return function() {
  3921. var context = {iterateSpeedSync : Pot.iterate[speedKey]};
  3922. return Iter.filter.apply(context, arguments);
  3923. };
  3924. }),
  3925. /**
  3926. * Apply a function against an accumulator and each value of
  3927. * the object (from left-to-right) as to reduce it to a single value.
  3928. *
  3929. * This method like Array.prototype.reduce
  3930. *
  3931. *
  3932. * @example
  3933. * var array = [1, 2, 3, 4, 5];
  3934. * var total = Pot.reduce(array, function(a, b) { return a + b; });
  3935. * debug(total);
  3936. * // @results 15
  3937. *
  3938. * @example
  3939. * var object = {a: 1, b: 2, c: 3};
  3940. * var total = Pot.reduce(object, function(a, b) { return a + b; });
  3941. * debug(total);
  3942. * // @results 6
  3943. *
  3944. *
  3945. * @param {Array|Object|*} object A target object.
  3946. * @param {Function} callback A callback function.
  3947. * @param {*} initial An initial value passed as `callback`
  3948. * argument that will be used on
  3949. * first iteration.
  3950. * @param {*} (context) (Optional) Object to use as
  3951. * the first argument to the
  3952. * first call of the `callback`.
  3953. * @return {*} Return the result of each callbacks.
  3954. * @name Pot.reduce
  3955. * @class
  3956. * @function
  3957. * @static
  3958. * @public
  3959. */
  3960. reduce : createSyncIterator(function(speedKey) {
  3961. return function() {
  3962. var context = {iterateSpeedSync : Pot.iterate[speedKey]};
  3963. return Iter.reduce.apply(context, arguments);
  3964. };
  3965. }),
  3966. /**
  3967. * Tests whether all elements in the object pass the
  3968. * test implemented by the provided function.
  3969. *
  3970. * This method like Array.prototype.every
  3971. *
  3972. * @example
  3973. * function isBigEnough(value, index, array) {
  3974. * return (value >= 10);
  3975. * }
  3976. * var passed = Pot.every([12, 5, 8, 130, 44], isBigEnough);
  3977. * // passed is false
  3978. * passed = Pot.every([12, 54, 18, 130, 44], isBigEnough);
  3979. * // passed is true
  3980. *
  3981. *
  3982. * @param {Array|Object|*} object A target object.
  3983. * @param {Function} callback A callback function.
  3984. * @param {*} (context) (Optional) Object to use
  3985. * as `this` when executing callback.
  3986. * @return {Boolean} Return the Boolean result by callback.
  3987. * @name Pot.every
  3988. * @class
  3989. * @function
  3990. * @static
  3991. * @public
  3992. */
  3993. every : createSyncIterator(function(speedKey) {
  3994. return function() {
  3995. var context = {iterateSpeedSync : Pot.iterate[speedKey]};
  3996. return Iter.every.apply(context, arguments);
  3997. };
  3998. }),
  3999. /**
  4000. * Tests whether some element in the object passes the
  4001. * test implemented by the provided function.
  4002. *
  4003. * This method like Array.prototype.some
  4004. *
  4005. *
  4006. * @example
  4007. * function isBigEnough(value, index, array) {
  4008. * return (value >= 10);
  4009. * }
  4010. * var passed = Pot.some([2, 5, 8, 1, 4], isBigEnough);
  4011. * // passed is false
  4012. * passed = Pot.some([12, 5, 8, 1, 4], isBigEnough);
  4013. * // passed is true
  4014. *
  4015. *
  4016. * @param {Array|Object|*} object A target object.
  4017. * @param {Function} callback A callback function.
  4018. * @param {*} (context) (Optional) Object to use
  4019. * as `this` when executing callback.
  4020. * @return {Boolean} Return the Boolean result by callback.
  4021. * @name Pot.some
  4022. * @class
  4023. * @function
  4024. * @static
  4025. * @public
  4026. */
  4027. some : createSyncIterator(function(speedKey) {
  4028. return function() {
  4029. var context = {iterateSpeedSync : Pot.iterate[speedKey]};
  4030. return Iter.some.apply(context, arguments);
  4031. };
  4032. }),
  4033. /**
  4034. * Create continuously array that
  4035. * has numbers between start number and end number.
  4036. *
  4037. * First argument can given an object that has "begin, end, step" any keys.
  4038. *
  4039. * This function can be a letter rather than just numbers.
  4040. *
  4041. * @example
  4042. * var numbers = Pot.range(1, 5);
  4043. * debug(numbers); // @results [1, 2, 3, 4, 5]
  4044. * var chars = Pot.range('a', 'f');
  4045. * debug(chars); // @results ['a', 'b', 'c', 'd', 'e', 'f']
  4046. * var ranges = Pot.range({begin: 0, step: 10, end: 50});
  4047. * debug(ranges); // @results [0, 10, 20, 30, 40, 50]
  4048. *
  4049. *
  4050. * @param {Number|Object} end/begin The end number or object.
  4051. * @param {Number} (end) (optinal) The end number.
  4052. * @param {Number} (step) (optinal) The step number.
  4053. * @return {Array} Return an array result.
  4054. * @function
  4055. * @static
  4056. * @public
  4057. */
  4058. range : function(/*[begin,] end[, step]*/) {
  4059. return Iter.range.apply(null, arguments);
  4060. },
  4061. /**
  4062. * Returns the first index at which a
  4063. * given element can be found in the object, or -1 if it is not present.
  4064. *
  4065. * This method like Array.prototype.indexOf
  4066. *
  4067. *
  4068. * @example
  4069. * var array = [2, 5, 9];
  4070. * var index = Pot.indexOf(array, 2);
  4071. * // index is 0
  4072. * index = Pot.indexOf(array, 7);
  4073. * // index is -1
  4074. * var object = {a: 2, b: 5, c: 9};
  4075. * index = Pot.indexOf(object, 2);
  4076. * // index is 'a'
  4077. * index = Pot.indexOf(object, 7);
  4078. * // index is -1
  4079. *
  4080. *
  4081. * @param {Array|Object|*} object A target object.
  4082. * @param {*} subject A subject object.
  4083. * @param {*} (from) (Optional) The index at
  4084. * which to begin the search.
  4085. * Defaults to 0.
  4086. * @return Return the index of result, or -1.
  4087. * @function
  4088. * @static
  4089. * @public
  4090. */
  4091. indexOf : function() {
  4092. return Iter.indexOf.apply(null, arguments);
  4093. },
  4094. /**
  4095. * Returns the last index at which a
  4096. * given element can be found in the object, or -1 if it is not present.
  4097. *
  4098. * This method like Array.prototype.lastIndexOf
  4099. *
  4100. *
  4101. * @example
  4102. * debug('array');
  4103. * var index, array = [2, 5, 9, 2];
  4104. * index = Pot.lastIndexOf(array, 2);
  4105. * debug('index is 3 : result = ' + index); // 3
  4106. * index = Pot.lastIndexOf(array, 7);
  4107. * debug('index is -1 : result = ' + index); // -1
  4108. * index = Pot.lastIndexOf(array, 2, 3);
  4109. * debug('index is 3 : result = ' + index); // 3
  4110. * index = Pot.lastIndexOf(array, 2, 2);
  4111. * debug('index is 0 : result = ' + index); // 0
  4112. * index = Pot.lastIndexOf(array, 2, -2);
  4113. * debug('index is 0 : result = ' + index); // 0
  4114. * index = Pot.lastIndexOf(array, 2, -1);
  4115. * debug('index is 3 : result = ' + index); // 3
  4116. * debug('object');
  4117. * var object = {a: 2, b: 5, c: 9, d: 2};
  4118. * index = Pot.lastIndexOf(object, 2);
  4119. * debug('index is d : result = ' + index); // 'd'
  4120. * index = Pot.lastIndexOf(object, 7);
  4121. * debug('index is -1 : result = ' + index); // -1
  4122. * index = Pot.lastIndexOf(object, 2, 'd'); // 'd'
  4123. * debug('index is d : result = ' + index);
  4124. * index = Pot.lastIndexOf(object, 2, 'c'); // 'a'
  4125. * debug('index is a : result = ' + index);
  4126. *
  4127. *
  4128. * @param {Array|Object|*} object A target object.
  4129. * @param {*} subject A subject object.
  4130. * @param {*} (from) (Optional) The index at which to
  4131. * start searching backwards.
  4132. * Defaults to the array's length.
  4133. * @return Return the index of result, or -1.
  4134. * @function
  4135. * @static
  4136. * @public
  4137. */
  4138. lastIndexOf : function() {
  4139. return Iter.lastIndexOf.apply(null, arguments);
  4140. }
  4141. });
  4142. update(PotInternal, {
  4143. defineDeferrater : createSyncIterator
  4144. });
  4145. // Definition of deferreed function.
  4146. (function() {
  4147. /**@ignore*/
  4148. var Deferrizer = function(func) {
  4149. return new Deferrizer.prototype.init(func);
  4150. },
  4151. SPEED = buildSerial({NAME : '.\u0000[~`{{*@:SPEED:@*}}`~]\u0001'}),
  4152. CACHE = {},
  4153. CACHE_COUNT = 0,
  4154. CACHE_LIMIT = 0x2000;
  4155. Deferrizer.prototype = update(Deferrizer.prototype, {
  4156. /**
  4157. * @private
  4158. * @ignore
  4159. * @internal
  4160. */
  4161. constructor : Deferrizer,
  4162. /**
  4163. * @private
  4164. * @ignore
  4165. */
  4166. id : PotInternal.getMagicNumber(),
  4167. /**
  4168. * @ignore
  4169. * @private
  4170. */
  4171. func : null,
  4172. /**
  4173. * @ignore
  4174. * @private
  4175. */
  4176. code : null,
  4177. /**
  4178. * @ignore
  4179. * @private
  4180. */
  4181. tokens : [],
  4182. /**
  4183. * @ignore
  4184. * @private
  4185. */
  4186. uniqs : {},
  4187. /**
  4188. * @ignore
  4189. * @private
  4190. */
  4191. tails : [],
  4192. /**
  4193. * @ignore
  4194. * @private
  4195. */
  4196. iteration : {},
  4197. /**
  4198. * Initialize properties.
  4199. *
  4200. * @private
  4201. * @ignore
  4202. */
  4203. init : function(func) {
  4204. this.func = func;
  4205. this.code = this.toCode(this.func);
  4206. this.tokens = [];
  4207. this.iteration = {};
  4208. this.tails = [];
  4209. return this;
  4210. },
  4211. /**
  4212. * Execute.
  4213. *
  4214. * @private
  4215. * @ignore
  4216. */
  4217. execute : function() {
  4218. var that = this, result = '';
  4219. if (this.code) {
  4220. if (this.code in CACHE) {
  4221. result = CACHE[this.code];
  4222. } else {
  4223. this.uniqs = {};
  4224. each('key val ret rev err nxt'.split(' '), function(v) {
  4225. that.uniqs[v] = that.generateUniqName({
  4226. NAME : '$_' + v + '_'
  4227. });
  4228. });
  4229. this.tokens = this.tokenize(this.code);
  4230. if (!this.hasIteration(this.tokens)) {
  4231. result = this.func;
  4232. } else {
  4233. this.parseLoop();
  4234. result = this.deferrizeFunction();
  4235. if (result) {
  4236. if (CACHE_COUNT < CACHE_LIMIT) {
  4237. CACHE[this.code] = result;
  4238. CACHE_COUNT++;
  4239. }
  4240. }
  4241. }
  4242. }
  4243. }
  4244. return result;
  4245. },
  4246. /**
  4247. * @internal
  4248. * @private
  4249. * @ignore
  4250. */
  4251. hasIteration : function(tokens) {
  4252. var result = false, i, len, token;
  4253. if (tokens) {
  4254. len = tokens.length;
  4255. for (i = 0; i < len; i++) {
  4256. token = tokens[i];
  4257. if (token === 'for' || token === 'while' || token === 'do') {
  4258. result = true;
  4259. break;
  4260. }
  4261. }
  4262. }
  4263. return result;
  4264. },
  4265. /**
  4266. * @internal
  4267. * @private
  4268. * @ignore
  4269. */
  4270. toCode : function(func) {
  4271. return Pot.getFunctionCode(func);
  4272. },
  4273. /**
  4274. * @internal
  4275. * @private
  4276. * @ignore
  4277. */
  4278. isWord : (function() {
  4279. var RE = {
  4280. SPACE : /\s/,
  4281. WORDS : /[$\w\u0100-\uFFFF]/
  4282. };
  4283. return function(c) {
  4284. return c != null && !RE.SPACE.test(c) && RE.WORDS.test(c);
  4285. };
  4286. }()),
  4287. /**
  4288. * @internal
  4289. * @private
  4290. * @ignore
  4291. */
  4292. isNL : (function() {
  4293. var RE = /\r\n|\r|\n/;
  4294. return function(c) {
  4295. return c != null && RE.test(c);
  4296. };
  4297. }()),
  4298. /**
  4299. * @internal
  4300. * @private
  4301. * @ignore
  4302. */
  4303. format : function(/*format[, ...args]*/) {
  4304. var args = arrayize(arguments);
  4305. return args[0].replace(/#(\d+)/g, function(a, i) {
  4306. return args[+i];
  4307. });
  4308. },
  4309. /**
  4310. * @internal
  4311. * @private
  4312. * @ignore
  4313. */
  4314. joinTokens : function(tokens) {
  4315. var result = [], len = tokens.length,
  4316. prev, prevSuf, pre, suf, i, token;
  4317. for (i = 0; i < len; i++) {
  4318. token = tokens[i];
  4319. if (!prev) {
  4320. result[result.length] = token;
  4321. } else {
  4322. pre = '';
  4323. suf = '';
  4324. if (token === '+' || token === '-' ||
  4325. token === '++' || token === '--' ||
  4326. token === 'in'
  4327. ) {
  4328. pre = ' ';
  4329. suf = ' ';
  4330. } else if (this.isWord(prev.slice(-1)) &&
  4331. this.isWord(token.charAt(0))) {
  4332. pre = ' ';
  4333. }
  4334. if (prevSuf === ' ') {
  4335. pre = '';
  4336. }
  4337. result[result.length] = pre + token + suf;
  4338. }
  4339. prev = token;
  4340. prevSuf = suf;
  4341. }
  4342. return result.join('');
  4343. },
  4344. /**
  4345. * @internal
  4346. * @private
  4347. * @ignore
  4348. */
  4349. toEnd : function(code) {
  4350. var s;
  4351. if (isArray(code)) {
  4352. s = this.joinTokens(code);
  4353. } else {
  4354. s = stringify(code);
  4355. }
  4356. if (trim(s).slice(-1) === ';') {
  4357. return s;
  4358. }
  4359. return s ? s + ';' : s;
  4360. },
  4361. /**
  4362. * @internal
  4363. * @private
  4364. * @ignore
  4365. */
  4366. generateUniqName : function(prefix) {
  4367. var result;
  4368. do {
  4369. result = buildSerial(prefix || Pot, '');
  4370. } while (~Pot.indexOf(this.tokens, result));
  4371. return result;
  4372. },
  4373. /**
  4374. * @internal
  4375. * @private
  4376. * @ignore
  4377. */
  4378. tokenize : (function() {
  4379. var RE = {
  4380. TOKEN : new RegExp(
  4381. '(' + '^\\s*function\\b[^{]*[{]' + // function prefix
  4382. '|' + '[}][^}]*$' + // function suffix
  4383. '|' + '/[*][\\s\\S]*?[*]/' + // multiline comment
  4384. '|' + '/{2,}[^\\r\\n]*(?:\\r\\n|\\r|\\n|)' + // single line comment
  4385. '|' + '"(?:\\\\[\\s\\S]|[^"\\r\\n\\\\])*"' + // string literal
  4386. '|' + "'(?:\\\\[\\s\\S]|[^'\\r\\n\\\\])*'" + // string literal
  4387. '|' + '/(?![*])(?:\\\\.|[^/\\r\\n\\\\])+/' +
  4388. '[gimy]{0,4}' +
  4389. '|' + '<([^\\s>]*)[^>]*>[\\s\\S]*?</\\2>' + // e4x
  4390. '|' + '>>>=?|<<=|===|!==|>>=' + // operators
  4391. '|' + '[+][+](?=[+])|[-][-](?=[-])' +
  4392. '|' + '[=!<>*+/&|^-]=' +
  4393. '|' + '[&][&]|[|][|]|[+][+]|[-][-]|<<|>>' +
  4394. '|' + '0(?:[xX][0-9a-fA-F]+|[0-7]+)' + // number literal
  4395. '|' + '\\d+(?:[.]\\d+)?(?:[eE][+-]?\\d+)?' +
  4396. '|' + '[1-9]\\d*' +
  4397. '|' + '[-+/%*=&|^~<>!?:,;@()\\\\[\\].{}]' + // operator
  4398. '|' + '(?![\\r\\n])\\s+' + // white space
  4399. '|' + '(?:\\r\\n|\\r|\\n)' + // nl
  4400. '|' + '[^\\s+/%*=&|^~<>!?:,;@()\\\\[\\].{}\'"-]+' + // token
  4401. ')',
  4402. 'g'
  4403. ),
  4404. NOTSPACE : /[\S\r\n]/,
  4405. COMMENTS : /^\/{2,}[\s\S]*$|^\/[*][\s\S]*?[*]\/$/
  4406. };
  4407. return function(func) {
  4408. var r = [], m, token, s = this.toCode(func);
  4409. if (s) {
  4410. RE.TOKEN.lastIndex = 0;
  4411. while ((m = RE.TOKEN.exec(s)) != null) {
  4412. token = m[1];
  4413. if (!RE.NOTSPACE.test(token) || RE.COMMENTS.test(token)) {
  4414. continue;
  4415. } else {
  4416. r[r.length] = token;
  4417. }
  4418. }
  4419. }
  4420. return r;
  4421. };
  4422. }()),
  4423. /**
  4424. * @internal
  4425. * @private
  4426. * @ignore
  4427. */
  4428. parseLoop : function() {
  4429. var result, max = 0, loops = [], offsets = [], index = 0, nest = 0,
  4430. level = 0, inLoop, i, token, len = this.tokens.length;
  4431. for (i = 0; i < len; i++) {
  4432. token = this.tokens[i];
  4433. switch (token) {
  4434. case 'for':
  4435. case 'while':
  4436. case 'do':
  4437. if (!inLoop) {
  4438. inLoop = {
  4439. token : token,
  4440. org : {
  4441. level : level,
  4442. nest : nest
  4443. },
  4444. cur : {
  4445. level : level,
  4446. nest : nest
  4447. }
  4448. };
  4449. }
  4450. break;
  4451. case '(':
  4452. nest++;
  4453. if (inLoop) {
  4454. inLoop.cur.nest++;
  4455. }
  4456. break;
  4457. case ')':
  4458. nest--;
  4459. if (inLoop) {
  4460. if (--inLoop.cur.nest === inLoop.org.nest &&
  4461. inLoop.cur.level === inLoop.org.level &&
  4462. inLoop.token === 'do'
  4463. ) {
  4464. inLoop.last = true;
  4465. }
  4466. }
  4467. break;
  4468. case '{':
  4469. level++;
  4470. if (inLoop) {
  4471. inLoop.cur.level++;
  4472. }
  4473. break;
  4474. case '}':
  4475. level--;
  4476. if (inLoop) {
  4477. if (--inLoop.cur.level === inLoop.org.level &&
  4478. inLoop.cur.nest === inLoop.org.nest &&
  4479. inLoop.token !== 'do'
  4480. ) {
  4481. inLoop.last = true;
  4482. }
  4483. }
  4484. break;
  4485. }
  4486. if (inLoop) {
  4487. if (!(index in loops)) {
  4488. loops[index] = [];
  4489. offsets[index] = {
  4490. start : i
  4491. };
  4492. }
  4493. loops[index][loops[index].length] = token;
  4494. if (inLoop.last) {
  4495. offsets[index].end = i;
  4496. inLoop = null;
  4497. index++;
  4498. }
  4499. }
  4500. }
  4501. len = loops.length;
  4502. for (i = 0; i < len; i++) {
  4503. if (loops[i].length > max) {
  4504. max = i;
  4505. }
  4506. }
  4507. this.iteration = {
  4508. loops : loops[max],
  4509. start : offsets[max].start,
  4510. end : offsets[max].end
  4511. };
  4512. return result;
  4513. },
  4514. /**
  4515. * @internal
  4516. * @private
  4517. * @ignore
  4518. */
  4519. deferrizeLoop : function() {
  4520. var tokens = this.iteration.loops,
  4521. state = tokens.shift();
  4522. switch (state) {
  4523. case 'for' : return this.parseFor(tokens);
  4524. case 'while' : return this.parseWhile(tokens);
  4525. case 'do' : return this.parseDoWhile(tokens);
  4526. }
  4527. },
  4528. /**
  4529. * @internal
  4530. * @private
  4531. * @ignore
  4532. */
  4533. deferrizeFunction : function() {
  4534. var result, next, looped, token, i, len = this.tokens.length,
  4535. key = 'before', enclose,
  4536. states = {
  4537. level : 0,
  4538. block : 0
  4539. },
  4540. parts = {
  4541. before : [],
  4542. loop : [],
  4543. after : [],
  4544. result : []
  4545. },
  4546. /**@ignore*/
  4547. openBlock = function(k) {
  4548. if (!states[k]) {
  4549. states[k] = {
  4550. block : states.block,
  4551. level : states.level
  4552. };
  4553. }
  4554. },
  4555. /**@ignore*/
  4556. closeBlock = function(kv) {
  4557. each(kv ? arrayize(kv) : ['func', 'cond'], function(k) {
  4558. if (states[k] &&
  4559. states[k].block === states.block &&
  4560. states[k].level === states.level) {
  4561. states[k] = null;
  4562. }
  4563. });
  4564. };
  4565. for (i = 1; i < len - 1; i++) {
  4566. if (i >= this.iteration.start &&
  4567. i <= this.iteration.end
  4568. ) {
  4569. if (!looped) {
  4570. looped = true;
  4571. i = this.iteration.end - 1;
  4572. parts.loop = arrayize(this.deferrizeLoop());
  4573. key = 'after';
  4574. if (states.cond) {
  4575. enclose = true;
  4576. }
  4577. }
  4578. continue;
  4579. }
  4580. token = this.tokens[i];
  4581. next = this.tokens[i + 1];
  4582. switch (token) {
  4583. case '{':
  4584. states.block++;
  4585. break;
  4586. case '}':
  4587. states.block--;
  4588. closeBlock();
  4589. break;
  4590. case '(':
  4591. states.level++;
  4592. break;
  4593. case ')':
  4594. states.level--;
  4595. if (states.cond && states.cond.expr && next === '{') {
  4596. states.cond.expr = null;
  4597. closeBlock('func');
  4598. } else {
  4599. closeBlock();
  4600. }
  4601. break;
  4602. case ';':
  4603. closeBlock('result');
  4604. break;
  4605. case 'function':
  4606. openBlock('func');
  4607. break;
  4608. case 'if':
  4609. openBlock('cond');
  4610. states.cond.expr = true;
  4611. break;
  4612. case 'return':
  4613. if (!states.func && !states.result) {
  4614. if (!next || next === ';' || this.isNL(next)) {
  4615. token = this.format('#1 #2=void 0#3',
  4616. token,
  4617. this.uniqs.ret,
  4618. (next === ';' || this.isNL(next)) ? '' : ';'
  4619. );
  4620. } else {
  4621. token = this.format('#1(#2!==#3)?#2:#2=',
  4622. token,
  4623. this.uniqs.ret,
  4624. this.uniqs.rev
  4625. );
  4626. }
  4627. parts.result = [];
  4628. openBlock('result');
  4629. }
  4630. break;
  4631. default:
  4632. if (states.result && this.isNL(token)) {
  4633. closeBlock('result');
  4634. }
  4635. break;
  4636. }
  4637. parts[key][parts[key].length] = token;
  4638. if (states.result) {
  4639. parts.result[parts.result.length] = token;
  4640. }
  4641. }
  4642. result = this.format(
  4643. '#1' +
  4644. 'var #2={},#3=#2,#4={};' +
  4645. 'return Pot.Deferred.begin(function(){' +
  4646. '#5' +
  4647. '#6' +
  4648. '#9' +
  4649. '});' +
  4650. '#7' +
  4651. '#8' +
  4652. '}).then(function(r){' +
  4653. 'return(#2===#3)?r:#2;' +
  4654. '});' +
  4655. '#10',
  4656. this.tokens.shift(),
  4657. this.uniqs.ret,
  4658. this.uniqs.rev,
  4659. this.uniqs.nxt,
  4660. this.toEnd(this.joinTokens(parts.before)),
  4661. this.joinTokens(parts.loop),
  4662. this.joinTokens(this.tails),
  4663. this.joinTokens(enclose ? parts.after : []),
  4664. this.joinTokens(enclose ? parts.result : parts.after),
  4665. this.tokens.pop()
  4666. );
  4667. return result;
  4668. },
  4669. /**
  4670. * @internal
  4671. * @private
  4672. * @ignore
  4673. */
  4674. parseWhile : function(tokens) {
  4675. var result = '', level = 0, nest = 0, started = false,
  4676. prev, next, skip, key = 'cond', inLoop, token, i,
  4677. len = tokens.length, isEnd = false,
  4678. states = {
  4679. cond : [],
  4680. body : []
  4681. };
  4682. for (i = 0; i < len; i++) {
  4683. token = tokens[i];
  4684. next = tokens[i + 1];
  4685. skip = false;
  4686. switch (token) {
  4687. case '(':
  4688. nest++;
  4689. if (inLoop) {
  4690. inLoop.cur.nest++;
  4691. }
  4692. if (i === 0 && nest === 1) {
  4693. skip = true;
  4694. }
  4695. break;
  4696. case ')':
  4697. nest--;
  4698. if (inLoop) {
  4699. if (--inLoop.cur.nest === inLoop.org.nest &&
  4700. inLoop.cur.level === inLoop.org.level &&
  4701. inLoop.token === 'do'
  4702. ) {
  4703. inLoop = null;
  4704. }
  4705. }
  4706. if (!started && nest === 0 &&
  4707. level === 0 && next === '{') {
  4708. skip = true;
  4709. }
  4710. break;
  4711. case '{':
  4712. level++;
  4713. if (inLoop) {
  4714. inLoop.cur.level++;
  4715. }
  4716. if (level === 1 && nest === 0 && prev === ')') {
  4717. skip = true;
  4718. started = true;
  4719. key = 'body';
  4720. }
  4721. break;
  4722. case '}':
  4723. level--;
  4724. if (inLoop) {
  4725. if (--inLoop.cur.level === inLoop.org.level &&
  4726. inLoop.cur.nest === inLoop.org.nest &&
  4727. inLoop.token !== 'do'
  4728. ) {
  4729. inLoop = null;
  4730. }
  4731. }
  4732. if (started && nest === 0 && level === 0) {
  4733. states.body.unshift(this.format(
  4734. 'if(#1!==#2||!(#3)){' +
  4735. 'throw Pot.StopIteration;' +
  4736. '}' +
  4737. 'try{',
  4738. this.uniqs.ret,
  4739. this.uniqs.rev,
  4740. this.joinTokens(states.cond) || 'false'
  4741. ));
  4742. states.body.push(this.format(
  4743. '}catch(#1){' +
  4744. 'if(Pot.isError(#1)||Pot.isStopIter(#1)){' +
  4745. 'throw #1;' +
  4746. '}' +
  4747. 'if(#1!==#2){' +
  4748. 'throw #1;' +
  4749. '}' +
  4750. '}',
  4751. this.uniqs.err,
  4752. this.uniqs.nxt
  4753. ));
  4754. token += ').then(function(){';
  4755. isEnd = true;
  4756. }
  4757. break;
  4758. case 'for':
  4759. case 'while':
  4760. case 'do':
  4761. inLoop = {
  4762. token : token,
  4763. org : {
  4764. level : level,
  4765. nest : nest
  4766. },
  4767. cur : {
  4768. level : level,
  4769. nest : nest
  4770. }
  4771. };
  4772. break;
  4773. case 'break':
  4774. if (!inLoop && started && !this.isWord(next)) {
  4775. token = 'throw Pot.StopIteration';
  4776. }
  4777. break;
  4778. case 'continue':
  4779. if (!inLoop && started && !this.isWord(next)) {
  4780. token = 'throw ' + this.uniqs.nxt;
  4781. }
  4782. break;
  4783. case 'return':
  4784. if (started) {
  4785. if (!next || next === ';' || this.isNL(next)) {
  4786. token = this.format('#1 #2=void 0#3',
  4787. token,
  4788. this.uniqs.ret,
  4789. (next === ';' || this.isNL(next)) ? '' : ';'
  4790. );
  4791. } else {
  4792. token = this.format('#1 #2=',
  4793. token,
  4794. this.uniqs.ret
  4795. );
  4796. }
  4797. }
  4798. break;
  4799. }
  4800. if (!skip) {
  4801. states[key][states[key].length] = token;
  4802. }
  4803. prev = token;
  4804. }
  4805. result = '';
  4806. if (!isEnd) {
  4807. throw new Error("Parse error, expect 'while(...)'");
  4808. }
  4809. result = this.format(
  4810. 'return Pot.Deferred.forEver.#1(function(){' +
  4811. '#2',
  4812. SPEED,
  4813. this.joinTokens(states.body)
  4814. );
  4815. return result;
  4816. },
  4817. /**
  4818. * @internal
  4819. * @private
  4820. * @ignore
  4821. */
  4822. parseDoWhile : function(tokens) {
  4823. var result = '', level = 0, nest = 0, prev, next, skip,
  4824. key = 'body', inLoop, token, i, len = tokens.length, isEnd = false,
  4825. states = {
  4826. cond : [],
  4827. body : [],
  4828. after : []
  4829. };
  4830. for (i = 0; i < len; i++) {
  4831. token = tokens[i];
  4832. next = tokens[i + 1];
  4833. skip = false;
  4834. switch (token) {
  4835. case '(':
  4836. nest++;
  4837. if (inLoop) {
  4838. inLoop.cur.nest++;
  4839. }
  4840. if (level === 0 && nest === 1 && prev === 'while') {
  4841. skip = true;
  4842. key = 'cond';
  4843. }
  4844. break;
  4845. case ')':
  4846. nest--;
  4847. if (inLoop) {
  4848. if (--inLoop.cur.nest === inLoop.org.nest &&
  4849. inLoop.cur.level === inLoop.org.level &&
  4850. inLoop.token === 'do'
  4851. ) {
  4852. inLoop = null;
  4853. }
  4854. }
  4855. if (nest === 0 && level === 0 && key === 'cond') {
  4856. skip = true;
  4857. }
  4858. break;
  4859. case '{':
  4860. level++;
  4861. if (inLoop) {
  4862. inLoop.cur.level++;
  4863. }
  4864. if (i === 0 && level === 1) {
  4865. skip = true;
  4866. }
  4867. break;
  4868. case '}':
  4869. level--;
  4870. if (inLoop) {
  4871. if (--inLoop.cur.level === inLoop.org.level &&
  4872. inLoop.cur.nest === inLoop.org.nest &&
  4873. inLoop.token !== 'do'
  4874. ) {
  4875. inLoop = null;
  4876. }
  4877. }
  4878. if (nest === 0 && level === 0 && next === 'while') {
  4879. isEnd = true;
  4880. skip = true;
  4881. }
  4882. break;
  4883. case 'while':
  4884. if (level === 0 && nest === 0) {
  4885. skip = true;
  4886. break;
  4887. }
  4888. // FALLTHROUGH
  4889. case 'for':
  4890. case 'do':
  4891. inLoop = {
  4892. token : token,
  4893. org : {
  4894. level : level,
  4895. nest : nest
  4896. },
  4897. cur : {
  4898. level : level,
  4899. nest : nest
  4900. }
  4901. };
  4902. break;
  4903. case 'break':
  4904. if (!inLoop && !this.isWord(next)) {
  4905. token = 'throw Pot.StopIteration';
  4906. }
  4907. break;
  4908. case 'continue':
  4909. if (!inLoop && !this.isWord(next)) {
  4910. token = 'throw ' + this.uniqs.nxt;
  4911. }
  4912. break;
  4913. case 'return':
  4914. if (!next || next === ';' || this.isNL(next)) {
  4915. token = this.format('#1 #2=void 0#3',
  4916. token,
  4917. this.uniqs.ret,
  4918. (next === ';' || this.isNL(next)) ? '' : ';'
  4919. );
  4920. } else {
  4921. token = this.format('#1 #2=',
  4922. token,
  4923. this.uniqs.ret
  4924. );
  4925. }
  4926. break;
  4927. }
  4928. if (!skip) {
  4929. states[key][states[key].length] = token;
  4930. }
  4931. prev = token;
  4932. }
  4933. result = '';
  4934. if (!isEnd) {
  4935. throw new Error("Parse error, expect 'do...while()'");
  4936. }
  4937. states.body.unshift(this.format(
  4938. 'if(#1!==#2){' +
  4939. 'throw Pot.StopIteration;' +
  4940. '}' +
  4941. 'try{',
  4942. this.uniqs.ret,
  4943. this.uniqs.rev
  4944. ));
  4945. states.body.push(this.format(
  4946. '}catch(#1){' +
  4947. 'if(Pot.isError(#1)||Pot.isStopIter(#1)){' +
  4948. 'throw #1;' +
  4949. '}' +
  4950. 'if(#1!==#2){' +
  4951. 'throw #1;' +
  4952. '}' +
  4953. '}finally{' +
  4954. 'if(!(#3)){' +
  4955. 'throw Pot.StopIteration;' +
  4956. '}' +
  4957. '}' +
  4958. '}).then(function(){',
  4959. this.uniqs.err,
  4960. this.uniqs.nxt,
  4961. this.joinTokens(states.cond) || 'false'
  4962. ));
  4963. result = this.format(
  4964. 'return Pot.Deferred.forEver.#1(function(){' +
  4965. '#2',
  4966. SPEED,
  4967. this.joinTokens(states.body)
  4968. );
  4969. return result;
  4970. },
  4971. /**
  4972. * @internal
  4973. * @private
  4974. * @ignore
  4975. */
  4976. parseFor : function(tokens) {
  4977. var result = '', level = 0, nest = 0, isInOrOf = null, started = false,
  4978. prev, next, skip, key = 'before', varType, inLoop, i, len, token,
  4979. isEnd = false,
  4980. states = {
  4981. prefix : [],
  4982. suffix : [],
  4983. before : [],
  4984. cond : [],
  4985. after : [],
  4986. key : [],
  4987. target : [],
  4988. body : []
  4989. };
  4990. len = tokens.length;
  4991. for (i = 0; i < len; i++) {
  4992. token = tokens[i];
  4993. next = tokens[i + 1];
  4994. skip = false;
  4995. switch (token) {
  4996. case '(':
  4997. nest++;
  4998. if (inLoop) {
  4999. inLoop.cur.nest++;
  5000. }
  5001. if (i === 0 && nest === 1) {
  5002. skip = true;
  5003. }
  5004. break;
  5005. case ')':
  5006. nest--;
  5007. if (inLoop) {
  5008. if (--inLoop.cur.nest === inLoop.org.nest &&
  5009. inLoop.cur.level === inLoop.org.level &&
  5010. inLoop.token === 'do'
  5011. ) {
  5012. inLoop = null;
  5013. }
  5014. }
  5015. if (!started && nest === 0 &&
  5016. level === 0 && next === '{') {
  5017. skip = true;
  5018. }
  5019. break;
  5020. case '{':
  5021. level++;
  5022. if (inLoop) {
  5023. inLoop.cur.level++;
  5024. }
  5025. if (level === 1 && nest === 0 && prev === ')') {
  5026. skip = true;
  5027. started = true;
  5028. key = 'body';
  5029. }
  5030. break;
  5031. case '}':
  5032. level--;
  5033. if (inLoop) {
  5034. if (--inLoop.cur.level === inLoop.org.level &&
  5035. inLoop.cur.nest === inLoop.org.nest &&
  5036. inLoop.token !== 'do'
  5037. ) {
  5038. inLoop = null;
  5039. }
  5040. }
  5041. if (started && nest === 0 && level === 0) {
  5042. states.body.unshift(this.format(
  5043. 'if(#1!==#2){' +
  5044. 'throw Pot.StopIteration;' +
  5045. '}' +
  5046. 'try{',
  5047. this.uniqs.ret,
  5048. this.uniqs.rev
  5049. ));
  5050. if (states.suffix.length) {
  5051. states.body.push(
  5052. this.toEnd(this.joinTokens(states.suffix))
  5053. );
  5054. }
  5055. states.body.push(this.format(
  5056. '}catch(#1){' +
  5057. 'if(Pot.isError(#1)||Pot.isStopIter(#1)){' +
  5058. 'throw #1;' +
  5059. '}' +
  5060. 'if(#1!==#2){' +
  5061. 'throw #1;' +
  5062. '}' +
  5063. '}finally{' +
  5064. '#3' +
  5065. '}',
  5066. this.uniqs.err,
  5067. this.uniqs.nxt,
  5068. this.toEnd(this.joinTokens(states.after))
  5069. ));
  5070. token += ').then(function(){';
  5071. isEnd = true;
  5072. }
  5073. break;
  5074. case 'each':
  5075. if (i === 0) {
  5076. throw new Error("Not supported 'for each'");
  5077. }
  5078. break;
  5079. case 'in':
  5080. case 'of':
  5081. if (!started && isInOrOf === null &&
  5082. nest === 1 && level === 0
  5083. ) {
  5084. skip = true;
  5085. isInOrOf = true;
  5086. if (states.before.length > 2) {
  5087. throw new Error(
  5088. "Invalid keys, expect 'for(var [...] in ...);'"
  5089. );
  5090. }
  5091. if (varType) {
  5092. states.before.push(';');
  5093. unshift.apply(states.prefix, states.before);
  5094. states.before.shift();
  5095. states.before.pop();
  5096. if (varType === 'let') {
  5097. states.prefix.unshift('{');
  5098. this.tails.push('}');
  5099. }
  5100. }
  5101. states.before.push('=' + this.uniqs.key);
  5102. states.before.push(';');
  5103. states.key = states.before;
  5104. unshift.apply(states.body, states.key);
  5105. key = 'target';
  5106. }
  5107. break;
  5108. case 'var':
  5109. case 'let':
  5110. if (!varType && i === 1 && nest === 1) {
  5111. varType = token;
  5112. }
  5113. break;
  5114. case ',':
  5115. if (!started && nest === 1 && level === 0 &&
  5116. !varType &&
  5117. (key === 'before' || key === 'after')
  5118. ) {
  5119. token = ';';
  5120. }
  5121. break;
  5122. case ';':
  5123. if (!started && nest === 1 && level === 0) {
  5124. skip = true;
  5125. if (isInOrOf === null) {
  5126. isInOrOf = false;
  5127. }
  5128. if (key === 'before') {
  5129. key = 'cond';
  5130. states.prefix.push(
  5131. this.toEnd(this.joinTokens(states.before))
  5132. );
  5133. if (varType === 'let') {
  5134. states.prefix.unshift('{');
  5135. this.tails.push('}');
  5136. }
  5137. } else if (key === 'cond') {
  5138. key = 'after';
  5139. if (states.cond.length) {
  5140. states.cond.unshift('if(');
  5141. states.cond.push('){');
  5142. states.suffix.push('}else{throw Pot.StopIteration;}');
  5143. }
  5144. push.apply(states.body, states.cond);
  5145. }
  5146. }
  5147. break;
  5148. case 'for':
  5149. case 'while':
  5150. case 'do':
  5151. inLoop = {
  5152. token : token,
  5153. org : {
  5154. level : level,
  5155. nest : nest
  5156. },
  5157. cur : {
  5158. level : level,
  5159. nest : nest
  5160. }
  5161. };
  5162. break;
  5163. case 'break':
  5164. if (!inLoop && started && !this.isWord(next)) {
  5165. token = 'throw Pot.StopIteration';
  5166. }
  5167. break;
  5168. case 'continue':
  5169. if (!inLoop && started && !this.isWord(next)) {
  5170. token = 'throw ' + this.uniqs.nxt;
  5171. }
  5172. break;
  5173. case 'return':
  5174. if (started) {
  5175. if (!next || next === ';' || this.isNL(next)) {
  5176. token = this.format('#1 #2=void 0#3',
  5177. token,
  5178. this.uniqs.ret,
  5179. (next === ';' || this.isNL(next)) ? '' : ';'
  5180. );
  5181. } else {
  5182. token = this.format('#1 #2=',
  5183. token,
  5184. this.uniqs.ret
  5185. );
  5186. }
  5187. }
  5188. break;
  5189. }
  5190. if (!skip) {
  5191. states[key][states[key].length] = token;
  5192. }
  5193. prev = token;
  5194. }
  5195. result = '';
  5196. if (!isEnd) {
  5197. throw new Error("Parse error, expect 'for(...)'");
  5198. }
  5199. if (isInOrOf) {
  5200. result = this.format(
  5201. '#1return Pot.Deferred.forEach.#2(#3,function(#4,#5){' +
  5202. '#6',
  5203. this.toEnd(this.joinTokens(states.prefix)),
  5204. SPEED,
  5205. this.joinTokens(states.target),
  5206. this.uniqs.val,
  5207. this.uniqs.key,
  5208. this.joinTokens(states.body)
  5209. );
  5210. } else {
  5211. result = this.format(
  5212. '#1return Pot.Deferred.forEver.#2(function(){' +
  5213. '#3',
  5214. this.toEnd(this.joinTokens(states.prefix)),
  5215. SPEED,
  5216. this.joinTokens(states.body)
  5217. );
  5218. }
  5219. return result;
  5220. }
  5221. });
  5222. Deferrizer.prototype.init.prototype = Deferrizer.prototype;
  5223. update(PotInternal, {
  5224. /**
  5225. * @lends Pot.Internal
  5226. */
  5227. /**
  5228. * @type Function
  5229. * @internal
  5230. * @ignore
  5231. */
  5232. deferrate : function(func) {
  5233. return (new Deferrizer(func)).execute();
  5234. }
  5235. });
  5236. // Update Pot/Pot.Deferred.
  5237. update(Deferred, {
  5238. /**
  5239. * @lends Pot.Deferred
  5240. */
  5241. /**
  5242. * Create new defer function with speeds from static function.
  5243. * That returns a new instance of Pot.Deferred that
  5244. * has already ".begin()" called.
  5245. * This function works like 'deferrize'.
  5246. * This function will redefine the function that converts the
  5247. * synchronous loop block (i.e. for, for-in, do, while) to the
  5248. * asynchronous iteration by Pot.Deferred.xxx.
  5249. *
  5250. *
  5251. * @example
  5252. * var toCharCode = function(string) {
  5253. * var result = [];
  5254. * for (var i = 0; i < string.length; i++) {
  5255. * result.push(string.charCodeAt(i));
  5256. * }
  5257. * return result;
  5258. * };
  5259. * var toCharCodeDefer = Pot.deferreed(toCharCode);
  5260. * // Note:
  5261. * // toCharCodeDefer like below.
  5262. * //
  5263. * // function(string) {
  5264. * // var result = [];
  5265. * // return Pot.Deferred.repeat(string.length, function(i) {
  5266. * // result.push(string.charCodeAt(i));
  5267. * // }).then(function() {
  5268. * // return result;
  5269. * // });
  5270. * // };
  5271. * //
  5272. * toCharCodeDefer('abc').then(function(res) {
  5273. * Pot.debug(res); // @results [97, 98, 99]
  5274. * });
  5275. * // Large string.
  5276. * var largeString = new Array(100000).join('abcdef');
  5277. * // Specify speed 'slow'.
  5278. * toCharCodeDefer.slow(largeString).then(function(res) {
  5279. * Pot.debug(res.length); // @results 599994
  5280. * });
  5281. *
  5282. *
  5283. * @example
  5284. * // Compress/Decompress string by LZ77 algorithm.
  5285. * // http://polygon-planet.blogspot.com/2011/02/lz77javascript.html
  5286. * var TinyLz77 = {
  5287. * // compress (synchronous)
  5288. * compress : function(s) {
  5289. * var a = 53300, b, c, d, e, f, g = -1,
  5290. * h, i, r = [], x = String.fromCharCode;
  5291. * if (!s) {
  5292. * return '';
  5293. * }
  5294. * s = new Array(a--).join(' ') + s;
  5295. * while ((b = s.substr(a, 256))) {
  5296. * for (c = 2, i = b.length; c <= i; ++c) {
  5297. * d = s.substring(
  5298. * a - 52275,
  5299. * a + c - 1
  5300. * ).lastIndexOf(b.substring(0, c));
  5301. * if (!~d) {
  5302. * break;
  5303. * }
  5304. * e = d;
  5305. * }
  5306. * if (c === 2 || c === 3 && f === g) {
  5307. * f = g;
  5308. * h = s.charCodeAt(a++);
  5309. * r.push(
  5310. * x(h >> 8 & 255),
  5311. * x(h & 255)
  5312. * );
  5313. * } else {
  5314. * r.push(
  5315. * x((e >> 8 & 255) | 65280),
  5316. * x(e & 255),
  5317. * x(c - 3)
  5318. * );
  5319. * a += c - 1;
  5320. * }
  5321. * }
  5322. * return r.join('');
  5323. * },
  5324. * // decompress (synchronous)
  5325. * decompress : function(s) {
  5326. * var a = 53300, b = 0, c, d, e, f, g,
  5327. * h, r = new Array(a--).join(' '),
  5328. * x = String.fromCharCode;
  5329. * if (s && s.length) {
  5330. * do {
  5331. * c = s.charCodeAt(b++);
  5332. * if (c <= 255) {
  5333. * r += x((c << 8) | s.charCodeAt(b++));
  5334. * } else {
  5335. * e = ((c & 255) << 8) | s.charCodeAt(b++);
  5336. * f = e + s.charCodeAt(b++) + 2;
  5337. * h = r.slice(-52275);
  5338. * g = h.substring(e, f);
  5339. * if (g) {
  5340. * while (h.length < f) {
  5341. * h += g;
  5342. * }
  5343. * r += h.substring(e, f);
  5344. * }
  5345. * }
  5346. * } while (b < s.length);
  5347. * }
  5348. * return r.slice(a);
  5349. * }
  5350. * };
  5351. * // create asynchronous iteration functions.
  5352. * var compressDefer = Pot.deferreed(TinyLz77, 'compress');
  5353. * var decompressDefer = Pot.deferreed(TinyLz77, 'decompress');
  5354. * // original string.
  5355. * var string = 'foooooooooo baaaaaaaaaaaaar baaaaaaazzzzzzzzzzzz';
  5356. * Pot.debug(string.length); // 48
  5357. * // execute compress with asynchronous iterator.
  5358. * compressDefer(string).then(function(res) {
  5359. * Pot.debug(res.length); // 26
  5360. * return decompressDefer(res).then(function(res) {
  5361. * Pot.debug(res.length); // 48
  5362. * });
  5363. * });
  5364. *
  5365. *
  5366. * @param {Object|Function} object The context object.
  5367. * or the target function.
  5368. * @param {String|Function} (method) The target function name.
  5369. * or the target function.
  5370. * @return {Function} The defer function that
  5371. * returns Deferred object.
  5372. * Returns new asynchronous
  5373. * function that has
  5374. * each speeds below.
  5375. * <pre>
  5376. * ----------------------------------
  5377. * method name | speed
  5378. * ----------------------------------
  5379. * limp : slowest
  5380. * doze : slower
  5381. * slow : slow
  5382. * normal : normal (default)
  5383. * fast : fast
  5384. * rapid : faster
  5385. * ninja : fastest
  5386. * ----------------------------------
  5387. * You can control speed by
  5388. * specify key.
  5389. * e.g.
  5390. * var f = deferreed(func);
  5391. * f(); // normal
  5392. * f.slow(); // slow
  5393. * </pre>
  5394. * @type Function
  5395. * @function
  5396. * @public
  5397. * @static
  5398. */
  5399. deferreed : function(object, method) {
  5400. var result, func, context, err, code, proc;
  5401. try {
  5402. switch (arguments.length) {
  5403. case 0:
  5404. throw false;
  5405. case 1:
  5406. func = object;
  5407. if (!isFunction(func)) {
  5408. throw func;
  5409. }
  5410. proc = func;
  5411. break;
  5412. case 2:
  5413. default:
  5414. if (isObject(method)) {
  5415. context = method;
  5416. func = object;
  5417. } else {
  5418. func = method;
  5419. context = object;
  5420. }
  5421. if (!isFunction(context[func])) {
  5422. throw func;
  5423. }
  5424. proc = context[func];
  5425. break;
  5426. }
  5427. if (!proc || !isFunction(proc) || Pot.isBuiltinMethod(proc)) {
  5428. throw proc;
  5429. }
  5430. code = PotInternal.deferrate(proc);
  5431. if (!code) {
  5432. throw code;
  5433. }
  5434. if (code === proc) {
  5435. result = Deferred.deferrize(proc);
  5436. } else {
  5437. if (!isString(code)) {
  5438. throw code;
  5439. }
  5440. result = PotInternal.defineDeferrater(function(speedKey) {
  5441. var c = code.replace(SPEED, speedKey),
  5442. f = Pot.localEval(c, context);
  5443. return function() {
  5444. return f.apply(context, arguments);
  5445. };
  5446. });
  5447. }
  5448. if (!result || !isFunction(result)) {
  5449. throw result;
  5450. }
  5451. } catch (e) {
  5452. err = e;
  5453. throw isError(err) ? err : new Error(err);
  5454. }
  5455. return result;
  5456. }
  5457. });
  5458. // Refer Pot object.
  5459. Pot.update({
  5460. deferreed : Deferred.deferreed
  5461. });
  5462. }());
  5463. delete PotTmp.createIterators;
  5464. delete PotTmp.createProtoIterators;
  5465. delete PotTmp.createSyncIterator;
  5466. }());