Compare commits

..

485 Commits
0.9.2 ... 1.1.1

Author SHA1 Message Date
Benjamin Tan
3bdc4f19d4 Update v1.1.1 docs 2015-01-23 16:15:04 +08:00
John-David Dalton
1acca0278c Bump to v1.1.1.
Former-commit-id: 1eaebbcedcd925ef2994d8e9a2c9b00c6a23c4b3
2013-03-27 08:03:09 -07:00
John-David Dalton
639c8d4171 Add _.forEach thisArg unit test to test.js.
Former-commit-id: b3d16d90789e76df778ac3457f68fdcbc3f6f4ad
2013-03-27 07:55:19 -07:00
John-David Dalton
d77c9d3fca Ensure underscore build internal forOwn will accept a thisArg argument. [closes #220].
Former-commit-id: a7818db29e81b64556232bfe44b2e1275d3dada1
2013-03-27 07:29:27 -07:00
John-David Dalton
2c7cc2c191 Update vendor/tar for Node v0.10.0+. [closes #218]
Former-commit-id: 9b35d27127dbd85dd56808e50bf255bbd3413c62
2013-03-26 20:15:06 -07:00
John-David Dalton
d7c74b8004 Bump to v1.1.0.
Former-commit-id: 7d103159263b2ad339cd1e2dba90df0d6c42a61d
2013-03-26 00:18:12 -07:00
John-David Dalton
aaa8003418 Update Benchmark.js to work in PhantomJS.
Former-commit-id: 9145f027f58a3c9f0c8b57b6e340f500ba4c7131
2013-03-25 23:23:15 -07:00
John-David Dalton
86890b13c6 Ensure consistent unit test count depending on build.
Former-commit-id: 390020635374f6fb1165a6adef0648847ec9cb9e
2013-03-25 22:12:25 -07:00
John-David Dalton
39158b0eb6 Add missing semicolons. [ci skip]
Former-commit-id: 7c9c39e84600f41d1a4f94224dfe5b2be8791d20
2013-03-25 20:37:54 -07:00
John-David Dalton
87f1d55bc2 Update docs and builds.
Former-commit-id: 21791e052114af5907d76251c58c3ba2ca138873
2013-03-25 08:35:20 -07:00
John-David Dalton
14343b5410 Make object iteration that uses _.keys work correctly in IE < 9 and _.isPlainObject work correctly in IE < 8.
Former-commit-id: ad9a3c36acb38e36cd21fe82a29b7e65a767e049
2013-03-25 08:22:40 -07:00
John-David Dalton
ffdac30b3c Make _.toArray work in legacy build.
Former-commit-id: 36866e65670f563b587af51168db9f95f01ed248
2013-03-25 08:21:43 -07:00
John-David Dalton
244c8dc391 Add dist/lodash.backbone.js. [ci skip]
Former-commit-id: c9abf959bbc0e30dd5da728e3c7903905d4e751a
2013-03-24 00:11:57 -07:00
John-David Dalton
e593344461 Add copyright header to minified Underscore file. [ci skip]
Former-commit-id: dce520ee6e1e2a175e4671ddcf7c2408efdff69f
2013-03-23 23:51:42 -07:00
John-David Dalton
74c46f6e93 Reduce the lodash underscore build.
Former-commit-id: 2f928d053faf4b8e45d5ef26e2697c25426b7a90
2013-03-23 23:46:40 -07:00
John-David Dalton
bbfd8aa249 Update Backbone method dependencies.
Former-commit-id: 031a5f31c289ad32c8ef0d30272a02c756a341ce
2013-03-23 23:24:25 -07:00
John-David Dalton
2705a488ad Update vendors.
Former-commit-id: b1b94d80548df89b3ce0ddd71b1e938f31666052
2013-03-23 23:23:57 -07:00
John-David Dalton
850c253e08 Use _.contains instead of indexOf in build/test files.
Former-commit-id: b0947f4f24c23e011f3ac781d400ee3ebbc94609
2013-03-23 22:49:28 -07:00
John-David Dalton
80e0e3fcd7 Optimize _.pluck for modern environments.
Former-commit-id: 1a6bbb9866b8ac20faaa707be5f33814579e1df8
2013-03-23 12:21:43 -07:00
John-David Dalton
2cc2d696f1 _.bind should throw a TypeError if func is not a function. [closes #213]
Former-commit-id: b6035736d9cb042b7fa4a9d0b7b4d9c6cb0ea4f8
2013-03-23 09:00:24 -07:00
John-David Dalton
8a83a6b5be Add AMD exports to the dist/lodash.underscore.js builds. [closes #214]
Former-commit-id: 4635d0c4f1ff315b08fb459ab64ef2b9ac6cbaa8
2013-03-23 00:40:06 -07:00
John-David Dalton
002d5338a0 Correct build.
Former-commit-id: 360983e61c6c6460f344d53dbda5c68e21530e32
2013-03-23 00:36:12 -07:00
John-David Dalton
743aa472f0 Ensure _.keys use in createIterator is consistent per build.
Former-commit-id: a4e0aef177d4d1c26ed5ce088574b591a6666d0d
2013-03-19 23:50:56 -07:00
John-David Dalton
ba85d5d351 Remove the _.isEqual dependency from createCallback in the underscore build and avoid potentially unnecessary string coercion in the underscore build _.isEqual method.
Former-commit-id: 1e8ce4fd9a35ad36c2b24457e519cb587c49c93b
2013-03-18 03:08:12 -06:00
John-David Dalton
4e2ef908dc Limit the category build option to adding only those methods available for specific builds (i.e. underscore and backbone builds).
Former-commit-id: 63a5509cd953b20376723335d42fb5a136eb3a5c
2013-03-18 02:43:02 -06:00
John-David Dalton
f5dd05ba8e Fix _.findIndex and _.findKey doc typos.
Former-commit-id: 7d4ae05db116e324b4b143e77bca67787476030f
2013-03-18 01:49:36 -06:00
John-David Dalton
17eda2a4cc Rebuild files and docs.
Former-commit-id: a3948db17af507d28d568d07d3e1a2afbd2c70ad
2013-03-17 19:43:23 -05:00
John-David Dalton
d219c6e019 Avoid creating intermediate strings when not needed.
Former-commit-id: 1e7457ff131f867adbf799e20af11cf714f5da7e
2013-03-17 19:31:37 -05:00
John-David Dalton
2dc539747b Add _.findIndex and _.findKey. [closes #199]
Former-commit-id: 5ac98b559e074082d4019cd30c27bface063f9c9
2013-03-17 19:28:46 -05:00
John-David Dalton
e941de50e8 Add fast path for callback back to _.forEach and ensure createCallback is called from lodash.
Former-commit-id: 5d589344897878d529d59ebba987a163b9704b37
2013-03-15 06:34:13 -07:00
John-David Dalton
63052257a2 Adjust large array size for _.difference and cleanup large array optimization code.
Former-commit-id: c3623ce2e0639a9e98d77e36e4dae51063c76e92
2013-03-14 14:38:48 -07:00
John-David Dalton
ac5d2a714e Make modern build pass unit tests again.
Former-commit-id: 6269bdbaa7cd96217568504921da097c2352cef8
2013-03-13 10:13:59 -07:00
John-David Dalton
59f78c16b1 Remove internal each for modern and underscore builds.
Former-commit-id: d090f9d0a21f8086d9e34d1171dc046a93327bb8
2013-03-13 07:56:15 -07:00
John-David Dalton
3f7f8133df Make pref.'s work for various lodash builds.
Former-commit-id: cdde1730e7b402c1f6475fc796af683faf6a8e88
2013-03-13 07:54:46 -07:00
John-David Dalton
fef5e1ce2c Simplify "Collections" methods for the modern and underscore builds.
Former-commit-id: 4ee5052537f7aed6816a886bee6da4e75c17099c
2013-03-12 07:32:02 -07:00
John-David Dalton
0b97b3864f Add isHostType to perf.js.
Former-commit-id: 36a1818a5272966ac9bd7f2394f2bd466fe6a4d4
2013-03-11 01:10:31 -07:00
John-David Dalton
3d1330c85d Remove assignment to undeclared variable in perf.js.
Former-commit-id: 6c8c6bd2db9a3ab137f6a705e2dabb2c07ccdc34
2013-03-10 23:51:17 -07:00
John-David Dalton
041c0cc322 Make pref.js work in Rhino, Narwhal, and Ringo again.
Former-commit-id: 1969153262cbc3ac134018aa021de92a86d6d7ef
2013-03-10 23:40:33 -07:00
John-David Dalton
e72712640c Allow lodash underscore plus=cloneDeep without also needing to include clone.
Former-commit-id: 90f89296ab47eff635c3c30ed34466e347ea13d3
2013-03-10 22:32:57 -07:00
John-David Dalton
6830195127 Cleanup build and docs.
Former-commit-id: 7e0719bb11e3f22ab09d51b52ab930699cbecf17
2013-03-10 11:05:07 -07:00
John-David Dalton
f9b5d6644d Ensure _.isPlainObject returns false for objects without a [[Class]] of "Object".
Former-commit-id: ce034f55733cd1929f09bf80e4a461c6e1502d1b
2013-03-10 04:27:45 -07:00
John-David Dalton
40f9eeda36 Remove reLeadingZeros from lodash underscore build.
Former-commit-id: 289d53be5b6af17ace4118ea0e6d9784667d09d3
2013-03-10 03:28:59 -07:00
John-David Dalton
0fa0b0b1ea Remove Closure Compiler escape from eachIteratorOptions.
Former-commit-id: 532e73f570bed2bc5941d0a6d1cb13618da0441b
2013-03-10 00:55:50 -08:00
John-David Dalton
ff0b23f200 Update vendor/platform.js again.
Former-commit-id: 39d31dcc7ef75a2bc62d9147f39c7adab2f2369f
2013-03-10 00:43:31 -08:00
John-David Dalton
5456d4081b Move regexp used in _.parseInt to outside the method.
Former-commit-id: 5b93dcdff39089ed5467ba52040f2e352716c49e
2013-03-10 00:30:58 -08:00
John-David Dalton
8948fae780 Update vendor/platform.js but remove it from test.'s.
Former-commit-id: 4f72d2b4454e7de42754c98c7b17f47f1f30718c
2013-03-09 23:52:20 -08:00
John-David Dalton
ee4542a699 Optimize lodash function to avoid slow path for arrays.
Former-commit-id: 24e2c4ac2525ae38e214fdb0ea8e3ab664d784b7
2013-03-09 18:24:29 -08:00
John-David Dalton
31e4e631f9 Cleanup test.js and perf.js and add _(array) benchmark.
Former-commit-id: bcd120c9ee332db39c7b637894751f2861bac069
2013-03-09 18:15:32 -08:00
John-David Dalton
cbf20b3271 Update vendors.
Former-commit-id: 7b8fe528a3e3887321505cf68b61cc3d774ef60b
2013-03-09 17:15:35 -08:00
John-David Dalton
a65fd50723 Add note to _.createCallback docs.
Former-commit-id: 0e5dfa9b4dc9aeea1c821b47d2f3d755678ea1aa
2013-03-09 13:32:15 -08:00
John-David Dalton
63a6aac2d8 Expanded _.createCallback and _.after docs and ensure _.times calls lodash.createCallback.
Former-commit-id: 2d6a480a5ee449295ec40acd5e8bbef6fe955473
2013-03-09 12:22:19 -08:00
John-David Dalton
afde4804c9 Fix build test and add extra "Arrays" and "Functions" method category tests.
Former-commit-id: 924e034ec6ec8d05d573dff969f064f1bb32ea33
2013-03-09 01:30:45 -08:00
John-David Dalton
bc8ec9cd3e Make _.times use _.createCallback and rebuild docs and dist/builds.
Former-commit-id: 62393b4833b64cea226abdbb6f1488369de46677
2013-03-09 01:29:42 -08:00
John-David Dalton
b63ab18e29 Rebuild docs and custom builds.
Former-commit-id: 6fea0c6b4c7bb28ee3d55b4af27874e40cd9813f
2013-03-08 22:57:20 -08:00
John-David Dalton
e7325f58c3 Correct unit test for rhino -require support.
Former-commit-id: 83c076f881daccd18d7e11006e3fab75ecea27ea
2013-03-08 09:00:20 -08:00
John-David Dalton
7b35bb8c96 Correct support.nonEnumArgs.
Former-commit-id: 69b09827404bae997846daa681d96d8c9264af78
2013-03-08 08:56:30 -08:00
John-David Dalton
e84671ce5d Correct _.result docs and cleanup _.support docs.
Former-commit-id: 6edb1956885d61408188d2809eeacd3aa975f283
2013-03-08 08:32:50 -08:00
John-David Dalton
b01d50fe05 Add _.support unit tests and remove _.support from the lodash underscore build.
Former-commit-id: 986c02d5363329f16cde720430b26edb6bc865f0
2013-03-08 00:53:27 -08:00
John-David Dalton
3f163051b1 Avoid hardcoded indents in build.js.
Former-commit-id: ece1e6a32f5d308e4674774f8875ee34c06b4d43
2013-03-08 00:20:07 -08:00
John-David Dalton
4f1d03e1d4 Cleanup the inlined iteratorTemplate.
Former-commit-id: 0964f0fda4a21a2009ebfd022e9d9c33bd78bbee
2013-03-08 00:03:57 -08:00
John-David Dalton
fc39e4a225 Fix build.
Former-commit-id: 17c97c9e2cad21ea6eb0af3d7b93ebb5caa89720
2013-03-07 23:20:25 -08:00
John-David Dalton
bf88ad7fc8 Update builds and docs.
Former-commit-id: 104839a253a7f3711dad357899128ccf839b01cf
2013-03-07 23:09:35 -08:00
John-David Dalton
11ba02067e Ensure _.times doesn't error when passed negative numbers.
Former-commit-id: 5d694743fbda0f477250fe3c90cf29168834ac6f
2013-03-07 09:05:27 -08:00
John-David Dalton
952afa05ce Add the _.support object.
Former-commit-id: b81ec9e5dbd41c729b3ad71187cb5e77e0755b9f
2013-03-07 09:02:44 -08:00
John-David Dalton
3131cc3160 Replace createWrapper references with new lodashWrapper references and refine Closure Compiler fix.
Former-commit-id: 552b98a4e9ccd42a00a980dd850e3b154cb7cd32
2013-03-05 02:05:44 -08:00
John-David Dalton
792f768479 Update vendor/requirejs.
Former-commit-id: 90bd5bc12f9159b65d485c540474404a61cad7ef
2013-03-05 00:22:03 -08:00
John-David Dalton
ff312a15dd Update minifiers, fix new Closure Compiler issue, and re-minify builds.
Former-commit-id: fb9993cb39c5c43d430e038253ab717ceb4c705f
2013-03-05 00:21:41 -08:00
John-David Dalton
36207c9a98 Modify the Lo-Dash description.
Former-commit-id: 910b51eb69b12df04345f8e97d7c288aee1525f7
2013-03-04 22:15:29 -08:00
John-David Dalton
b92105e888 Simplify the lodash wrapper.
Former-commit-id: 389c9ca8aa8414b04f7f99caf955862a1925d42e
2013-03-04 22:03:34 -08:00
John-David Dalton
35bd7c55d0 Move lodash instance check up in lodash function and tweak chaining benchmark.
Former-commit-id: 799ae05e5180ee87bb2a5249be3e442ed0425ef7
2013-03-04 01:40:55 -08:00
John-David Dalton
9f19c302d8 Cleanup _.bind benchmarks and add chaining benchmarks. [ci skip]
Former-commit-id: 9198c34679709610a440f71856a3869eaa83090e
2013-03-04 00:43:02 -08:00
John-David Dalton
87b1ac776f Remove extraneous spaces from non-minified builds.
Former-commit-id: ec8e18d00884cab96031c061ed32002f41edc0e5
2013-03-03 23:29:54 -08:00
John-David Dalton
41e401b05e Add callback and thisArg arguments to _.flatten. [closes #204]
Former-commit-id: 166d6af35c3905c87498ee74abd143f6fdba451d
2013-03-03 23:26:28 -08:00
John-David Dalton
d88da3589d Update docs and builds.
Former-commit-id: 1f7bfb21276f1c871f4e6ce8a6bf168784509994
2013-03-03 20:12:06 -08:00
John-David Dalton
9638c393bb Expose createCallback.
Former-commit-id: d0c0b02a68e33a2bf220a1605a6fe62eb4a11a83
2013-03-03 19:46:27 -08:00
John-David Dalton
9961ddc2a8 Ensure callback shorthands work with _.uniq. [\ht @jden, @motowilliams]
Former-commit-id: d9a0e688414edc4167b5f8e9ca123bab587f8264
2013-03-03 14:40:15 -08:00
John-David Dalton
2d40dfd8d4 Merge branch 'master' of github.com:bestiejs/lodash
Former-commit-id: e3d0b12d132d3eee4490575e5b18beb8faaf69c6
2013-03-03 13:46:57 -08:00
John-David Dalton
99c9bdf71d Fix misspellings in the docs.
Former-commit-id: 5c318a9fd6b624dbd9befb314644cb7967dc4fe9
2013-03-03 13:46:45 -08:00
John-David Dalton
4fcd25ec88 Merge pull request #202 from drewish/master
Fixing some misspellings.

Former-commit-id: 5315bcc098e909972d93312cf8c14889d17efef0
2013-03-03 13:44:10 -08:00
John-David Dalton
440218da67 Fix build.
Former-commit-id: 9d57351081959276735f8f3df81ecde71c4b9344
2013-03-03 13:36:10 -08:00
andrew morton
fefdb9fc8d Fix some misspellings in the docs.
Former-commit-id: 38ec1d19f1e5ea1fbb05306e5b5cfc9fac550562
2013-03-03 13:08:01 -08:00
John-David Dalton
21a0eff593 Fix build, and rebuild files & docs.
Former-commit-id: af57dd1de6b20e93caa79f05cb9b43647a1de578
2013-03-03 01:37:33 -08:00
John-David Dalton
8825a094ae Use native Object.create when available, optimize the creation of lodash instances, and ensure methods like forEach return the existing wrapper object when chaining, instead of creating a new one.
Former-commit-id: fa9ec371ba23ce8c35c15a66dd9b1f09f183b3a9
2013-03-03 01:21:19 -08:00
John-David Dalton
aa49ce5c56 Tweak platform placement in test.js and runner.
Former-commit-id: a261884dfda6f046431007bef6d9fe109fb1d887
2013-03-02 20:48:42 -08:00
John-David Dalton
1522d3385d Rename _.object to _.zipObject and make _.object an alias of _.zipObject.
Former-commit-id: 7ae3c9d8be32b1430945ffeafc20c740f1d7f409
2013-03-02 20:48:04 -08:00
John-David Dalton
510c41440a Rebuild docs and files.
Former-commit-id: ae6f8f4117b7baab2a47e7c8302edc1fa8dfdb07
2013-03-01 00:39:02 -08:00
John-David Dalton
aa0c34ba1c If _.cloneDeep callback result is not undefined then return the result instead of going deeper.
Former-commit-id: 6a0588dbe158211061ec88badf4d4e3b89b02aa5
2013-03-01 00:36:19 -08:00
John-David Dalton
af87e6ef62 Correct _.cloneDeep docs.
Former-commit-id: 93849f67b49fbba0d91ea8693a4d0b324f55352c
2013-03-01 00:24:48 -08:00
John-David Dalton
30291ce6e6 Make setting context work in older ES3 environments that will use values, named after built-in constructors, for the creation of literals.
Former-commit-id: 981139db2a30f9c69d3e616021f697b8403dee26
2013-02-28 20:34:14 -08:00
John-David Dalton
890c2eb564 Remove unneeded contextProp value.
Former-commit-id: f73bf05faece643fea8b1b67edfa240ba47beec5
2013-02-28 03:26:02 -08:00
John-David Dalton
67a269b89c Update builds and docs.
Former-commit-id: 57709d874ed5b6855daf536c2a0977738665c3c1
2013-02-28 02:53:09 -08:00
John-David Dalton
4b9ee81a78 Adjust build for renamed variables and _.runInContext dependencies, and cleanup build.js and build/pre-compile.js.
Former-commit-id: 0d813bc111617e9b8cd922b505ec8c90ce09063b
2013-02-28 02:51:43 -08:00
John-David Dalton
4343f4d229 Tweak _.parseInt docs.
Former-commit-id: 960256bab36fbecb8aa06679c10d8033e2013de2
2013-02-28 02:49:54 -08:00
John-David Dalton
2162baa6c0 Add contextProps to make _.runInContext work in older IEs.
Former-commit-id: 208f25296d35ed29a283fb1598de0052a5a2703d
2013-02-28 02:49:26 -08:00
John-David Dalton
7e7f792710 Add _.parseInt and _.runInContext to the underscore build tests.
Former-commit-id: a5f8d936e912d0bd53f689d23c3393731fe97f47
2013-02-28 02:48:11 -08:00
John-David Dalton
1bbd9e24b0 Fix and cleanup [[DontEnum]] unit test.
Former-commit-id: 9e47eeb03c88a52d2e1d6dd2c0373c2df2f576fe
2013-02-28 02:47:14 -08:00
John-David Dalton
6435aaa64f Ensure the exports object is not a DOM element. [closes #197]
Former-commit-id: 3adb679f7f4d7a64e0bc37ed80a443c211a17510
2013-02-27 09:10:13 -08:00
John-David Dalton
999aae0a33 Add _.parseInt.
Former-commit-id: 0c0f10af3dc50a4d1b684523f19d02e423d738f5
2013-02-27 08:54:15 -08:00
John-David Dalton
ba795639b4 Fix iife build tests.
Former-commit-id: 0fa103c21297672c018d66fba16ef376d3599b41
2013-02-27 02:17:19 -08:00
John-David Dalton
4c4b205721 Use setImmediate reference of the context object.
Former-commit-id: 28c11df25ceb1a414caaa61eaee54fae27a2ff03
2013-02-27 01:15:59 -08:00
John-David Dalton
b3c550b7c0 Make _.runInContext not require a fully populated context object.
Former-commit-id: 11bf3cad2bfd3e922e7701eb7b0f48028f522ba6
2013-02-27 01:03:45 -08:00
John-David Dalton
eb8953e784 Remove isJSC in mobile and underscore builds. [closes #196]
Former-commit-id: 77ddbbcfcf17b5074a7fba137dc426f20a6ab5dd
2013-02-26 21:08:35 -08:00
John-David Dalton
b88b292d5d Fix lodash.underscore usage example in README.md. [ci skip] [closes #194]
Former-commit-id: 5df59e98d58dc13eeff1ff9a4a76c7ef6811a0a7
2013-02-25 21:59:05 -08:00
John-David Dalton
5f42c3b319 Add rhino -require to the run-test.sh.
Former-commit-id: 105f76b6058b8a1493d1a56716df7f22391e4bdd
2013-02-24 22:51:11 -08:00
John-David Dalton
5b27ae0371 Cleanup comments in various source files.
Former-commit-id: 02e8223692e4678e78a0eadc4ffaed3e27b5a49f
2013-02-24 22:50:10 -08:00
John-David Dalton
f26b1da1b5 Simplify build/mkdirp-sync.js.
Former-commit-id: b49bbea9e565dbf1d23f601af74443b33fe9fc7d
2013-02-24 17:49:47 -08:00
John-David Dalton
7a853e2dcb Update vendors.
Former-commit-id: 92fe8e8ceacd0993fadd35c5feffddcbe319d6c7
2013-02-24 15:35:56 -08:00
John-David Dalton
9b22748bd0 Cleanup perf/perf.js and test/test.js.
Former-commit-id: fba43c75aa25227e771a3cdd0cce0ee8ee9cdba6
2013-02-24 15:25:56 -08:00
John-David Dalton
c1e9dd3373 Ensure relative paths work with --output and template=… build options.
Former-commit-id: 2447466a006dc8d968969bba70a0e44f91610154
2013-02-24 11:40:56 -08:00
John-David Dalton
8cbbc47043 Ensure all temp folders made during the --output build tests are removed.
Former-commit-id: d5c98deebd879f594aac73d4b835c97516ee4e89
2013-02-24 09:48:33 -08:00
John-David Dalton
81b3567133 Add path.sep for older versions of Node.js.
Former-commit-id: 1a058681fc5c6aae426902a7d6dd76b3a5849837
2013-02-24 09:29:23 -08:00
John-David Dalton
fc6568f390 Cleanup build tests and inline _.mixin when it's removed to preserve chaining behavior.
Former-commit-id: ed24a9acfabb70fb7093479a5c3484d966cbc5bb
2013-02-24 03:05:49 -08:00
John-David Dalton
8e30fe2946 Fix build.
Former-commit-id: 41b9584b63962a71f146c61fda056d15a2be4e14
2013-02-24 01:54:35 -08:00
John-David Dalton
6c811a3261 Move mkdir -p functionality to its own module and cleanup --output build tests.
Former-commit-id: b7ea2a41c60357e780e10bd3d665db3d50e7f044
2013-02-24 01:24:47 -08:00
John-David Dalton
afbe5aa540 Merge pull request #192 from phated/master
Implement `mkdir -p` for `--output` build option.

Former-commit-id: cb7a6753d15f495a1ab8b0016edd34d5626727de
2013-02-23 22:55:18 -08:00
John-David Dalton
324afd2d6c Add doc not for chaining support in custom builds and tweak support rules in build.js. [closes #193]
Former-commit-id: c87f6bfe28f00d9228f4112463635d555e138a41
2013-02-23 22:52:21 -08:00
John-David Dalton
58d94ef61e Clarify docs for callback use in _.first, _.initial, _.last, and _.rest. [ci skip] [closes #189]
Former-commit-id: 12ee5f957fa67e93e40630e627d90b9aaa7eff37
2013-02-23 21:49:02 -08:00
John-David Dalton
39974b0982 Make optionsToArray remove falsey values.
Former-commit-id: 5c82f8ab92f67bd35030320fae06811dbb8f442b
2013-02-23 20:30:14 -08:00
John-David Dalton
323d7306e2 Add QUnit.config.noglobals to build tests.
Former-commit-id: 4519f5322a51632ce23dc4c574365472338a18e0
2013-02-23 20:29:23 -08:00
John-David Dalton
251e228ce4 Remove isFunction fallback from modern builds
Former-commit-id: 21f51b3041b60136bb07ca775abfe91df7687639
2013-02-23 19:07:19 -08:00
Blaine Bublitz
a99f3f217a really basic version of mkdir -p for -o option
Former-commit-id: 0fb635efd2043ee901c4f4eae7c6670d5b44a068
2013-02-23 19:37:46 -07:00
John-David Dalton
e2acbee113 Adjust iife build test and add strict build tests.
Former-commit-id: 1422311e7c7106e7def75b7b75800975c59127ff
2013-02-23 16:19:52 -08:00
John-David Dalton
37b69eddf2 Tweak detection of the Node.js executable in command-line arguments.
Former-commit-id: 74047748237f8defe36aea2a27e54ac72a648c93
2013-02-23 15:58:43 -08:00
John-David Dalton
f0322e6f2c Rebuild files, adding lodash.legacy and lodash.mobile builds, and update docs. [closes #190]
Former-commit-id: 6167b81d8baf1e491b8cbb3e3c68c01ae6ddd865
2013-02-23 14:56:50 -08:00
John-David Dalton
756587d080 Remove undefined from the IIFE to allow easier customizations with the iife build option.
Former-commit-id: a496b1fba74fdab3b2819d27b769371f73364684
2013-02-23 14:08:48 -08:00
John-David Dalton
1ad2c92324 Fix lodash underscore build.
Former-commit-id: 017208b28865b10b068ba4ae5e4a7baa9c01a80f
2013-02-22 03:33:15 -08:00
John-David Dalton
e5433adf78 Rebuild files and docs.
Former-commit-id: 1a834e5811525e9fb99def149cb4c455b3d4367d
2013-02-22 02:02:51 -08:00
John-David Dalton
ed765f75d8 Fix alais -> alias typo in README.md.
Former-commit-id: 7c919c834f729d03d26c0b3eb14203585099333b
2013-02-22 02:01:36 -08:00
John-David Dalton
4136f1b377 Fix build indenting.
Former-commit-id: 87a7793799ee3ed28fe67cb894aa2876be103c50
2013-02-22 02:00:42 -08:00
John-David Dalton
860339b90e Fix failing tests in Narwhal.
Former-commit-id: 986262a14784d94f616663724e52d11a0e11a56d
2013-02-21 23:33:23 -08:00
John-David Dalton
03254a0c0f Make isKeysFast true for Firefox too.
Former-commit-id: cf14455782375eccc4c32c5bfca41c3f918db2e8
2013-02-21 23:19:26 -08:00
John-David Dalton
a76081c979 Add require call to compiled templates.
Former-commit-id: 3d97f6cc71a3c7e6ac9b12cc876ace4790efbae8
2013-02-21 22:08:09 -08:00
John-David Dalton
71a207079f Update vendors.
Former-commit-id: 25cce48fee2dfb010eb6a9c2e4235890f20b19aa
2013-02-21 08:40:09 -08:00
John-David Dalton
f6e724c4c5 Update build to work with _.runInContext.
Former-commit-id: da4a9da0e2c74bbcbd142c077794486d0ac45835
2013-02-21 08:39:25 -08:00
John-David Dalton
4251b36b25 Add _.runInContext.
Former-commit-id: f427f7d4704fb1b6af578b095e417ee25ca029e7
2013-02-21 00:47:19 -08:00
John-David Dalton
b8f39cbfdf Cleanup _.template comments.
Former-commit-id: cff1c86d3a7e9c5ee32e00762ce522690726ef09
2013-02-19 08:08:31 -08:00
John-David Dalton
088c621862 Tweak _.defer and _.delay docs. [ci skip]
Former-commit-id: 921eec8f2e8e7701f14095d221a5e72a2c45f470
2013-02-19 01:53:21 -08:00
John-David Dalton
2459a53350 Bump to v1.0.1.
Former-commit-id: b2536f9a226c7418ad3aaa7b5fb88282b77d20e5
2013-02-18 02:13:39 -08:00
John-David Dalton
7093e9c0d4 Add PhantomJS not to CONTRIBUTING.md.
Former-commit-id: e7c81af0fb6e1ede8f89d50ffdc5ec671e124252
2013-02-17 23:54:19 -08:00
John-David Dalton
4bc49978d1 Avoid using setImmediate in IE because it cannot be cleared with clearTimeout.
Former-commit-id: 836d49c6440b2313f1885456645ed4a00ab82ae6
2013-02-17 23:45:26 -08:00
John-David Dalton
96bac9c149 Add legacy underscore build test.
Former-commit-id: f56e254f7c2fb4c4adeac16b56c789dd8af8a986
2013-02-17 20:44:28 -08:00
John-David Dalton
8dcc15f4d3 Ensure setImmediate is not minified by the Closure Compiler.
Former-commit-id: 74c121d45854dba2aaaa65558c3e1ca8effd3096
2013-02-17 18:15:41 -08:00
John-David Dalton
8183740c04 Update vendors.
Former-commit-id: 6ab66f9ea6fd881e8c5ed18e84b9a24656496e10
2013-02-17 16:38:23 -08:00
John-David Dalton
25e4231d7b Update _.defer build dependencies.
Former-commit-id: 159f541373b01f259c9509e16c3fc0c2018e6d51
2013-02-17 16:13:42 -08:00
John-David Dalton
3ed9e0e905 Add support for specifying a source map URL in the to the -p/--source-map build options.
Former-commit-id: 2098da69d7902497e2e67210d778b8f99a5ff8f0
2013-02-17 16:02:53 -08:00
John-David Dalton
45bec0c440 Remove setImmediate use in the lodash legacy build and cleanup patterns.
Former-commit-id: a3c942e3545c278b7cac2112ed1a5417212048d9
2013-02-17 14:30:22 -08:00
John-David Dalton
5133e39d45 Make _.defer use setImmediate if available.
Former-commit-id: b3898d78725a4b203856916b1b071ab9c6f40b83
2013-02-17 14:29:40 -08:00
John-David Dalton
cb3b4e446e Ensure _.isEqual returns boolean values even if callback doesn't.
Former-commit-id: b2c31ee1711a436e5400c8e80c9f54a9680301b7
2013-02-17 10:41:05 -08:00
John-David Dalton
9829a2f3b4 Rebuild files.
Former-commit-id: c381088f55093f25067d0284319975c868e6e3bf
2013-02-16 23:18:05 -08:00
John-David Dalton
7eadf11145 Optimize the ES6 template delimiter regexp and regexp to detect strings.
Former-commit-id: 6177f2b32f27515cf8edcac6036d0adb58ebfcd0
2013-02-16 23:17:17 -08:00
John-David Dalton
2a2bc44f43 Make _.where search arrays for values.
Former-commit-id: b942c6a44680c78fae1a41f2cf994be09ffcfbb9
2013-02-16 00:39:45 -08:00
John-David Dalton
9ccfa5cec9 Convert map files via JSON.parse instead of using string manipulation in minify.js.
Former-commit-id: 185b77d45995f17c586f35d6ad447074d677a6ae
2013-02-15 08:58:20 -08:00
John-David Dalton
02687f3c78 Ensure the second argument passed to _.assign is not treated as a callback. [closes #184]
Former-commit-id: 1254e11ab02d1d5055c08400cd0a4786ed71aef2
2013-02-15 08:11:19 -08:00
John-David Dalton
7ea7a6cbb1 Automatically set a source map's "sources" key based on the build performed.
Former-commit-id: c02c88dfd1db097a3f98113ee57c3da850da5abb
2013-02-15 00:23:03 -08:00
John-David Dalton
a15a28fe5b Add -p and --source-map unit tests.
Former-commit-id: c7416ca507ce9376adb31e91a294e2e40073788c
2013-02-14 20:47:23 -08:00
Kit Cambridge
265dedfae1 Fix typo that caused sourceMappingURL to be undefined in source map builds.
Former-commit-id: ff3b22a7965c15a1ae072f8e9d51009e095ec443
2013-02-14 17:36:43 -08:00
John-David Dalton
5ddbb8bc56 Remove unneeded __d variable from _.template.
Former-commit-id: 4ff32444d7e96f8b9cc39e61c1ce17fb34fa357c
2013-02-14 09:21:06 -08:00
John-David Dalton
4101b8e937 Remove reInsertVariable cleanup in build/pre-compile.js.
Former-commit-id: 1fa75107e8c43362b57021292e26397145e62e39
2013-02-14 09:03:47 -08:00
John-David Dalton
56b6d50479 Tweak _.at docs.
Former-commit-id: 505e34b0a151287d78da73a1140d4aefdf45b43b
2013-02-14 09:03:06 -08:00
John-David Dalton
506f585d78 Bump to v1.0.0.
Former-commit-id: 623103d8c34c2e3c260c481da83cb94c888402d3
2013-02-14 08:58:11 -08:00
John-David Dalton
577dfb7220 Make Jam package use the compat build by default.
Former-commit-id: 8c371e59bd4796cfe42d0e0d9d07b85372b6d5b1
2013-02-13 23:48:13 -08:00
John-David Dalton
7e4286adde Add another unit test for precompiled templates with AMD support.
Former-commit-id: 68d1b7b0aa8cd8b1d4b27a9374095b8cebbfb386
2013-02-13 20:06:34 -08:00
John-David Dalton
1090228628 Add _.groupBy test for passing numbers for the callback argument.
Former-commit-id: 6ce29f81f8688495a8a756e464b32e9e825c7857
2013-02-13 19:54:39 -08:00
John-David Dalton
aeea861b73 Tweak docs for "_.pluck" and "_.where" style callbacks.
Former-commit-id: 8ee7906ac1839c2675a5e82749c9a2c86cf6f49a
2013-02-13 19:50:59 -08:00
John-David Dalton
997c43bbdd Add _.extend and _.defaults underscore build tests.
Former-commit-id: f9244ddd7c81f65d2f0a01a18fa6e821e8f2705b
2013-02-13 02:49:12 -08:00
John-David Dalton
958d4dbd2e Remove more unused variables in debug builds.
Former-commit-id: dd50d5d0b855a85ca8099d92288f2ca621a532fa
2013-02-13 01:52:12 -08:00
John-David Dalton
f2b350eb62 Change _.defaults to not overwrite null values.
Former-commit-id: 4a85aefc3eaf2180fb0e8cd0f6efb1524a9d7caa
2013-02-13 01:51:15 -08:00
John-David Dalton
a3464780a1 Add "customization callback" support to _.assign.
Former-commit-id: 5f0c7b72942ba0c40960072b11936f0683909043
2013-02-13 01:17:51 -08:00
John-David Dalton
fe1eb92196 Ensure _.first, _.initial, _.last, and _.rest work with string and objects for callback.
Former-commit-id: f587a5d11164c1c6fa050feccfb05956fd82a0d0
2013-02-12 08:45:10 -08:00
John-David Dalton
0b2d26ec92 Simplify AMD checks in test/test.js.
Former-commit-id: db2f72020e6171f30770c7ecc7caf1619b78ac88
2013-02-12 00:33:09 -08:00
John-David Dalton
8024a25f2b Update vendors.
Former-commit-id: aff34ccd5d3c6e3e78aeb5832e694171fca35412
2013-02-12 00:24:55 -08:00
John-David Dalton
d287ecbb34 Remove unused snippet from pre-compile.js.
Former-commit-id: d52c35eed1ccd611f728febfca5b5154440e9fb0
2013-02-12 00:24:37 -08:00
John-David Dalton
d9c95e7730 Escape } in regexes used in lodash.js. [closes #179]
Former-commit-id: 7b4687f3967079e19025fccc3f54b7fc5fcc4ff9
2013-02-12 00:24:08 -08:00
John-David Dalton
c3b1af31ce Add PhantomJS to .travis.yml.
Former-commit-id: 82ea6081046ee285538876572e5a42547ffffa61
2013-02-11 08:51:58 -08:00
John-David Dalton
465576b5cb Update vendors.
Former-commit-id: 4ffc3f5b267f8fdf1ac074f9f9ab44b0a7c4c3dd
2013-02-10 23:51:46 -08:00
John-David Dalton
9ecbcd0075 Update vendor/qunit-clib and tests to work with Ringo 0.9 and PhantomJS.
Former-commit-id: e6906e4b9f6afdee598902d6939356bf33302909
2013-02-10 23:42:09 -08:00
John-David Dalton
c1f62d72ae Ensure the csp build is an alias of the mobile.
Former-commit-id: defb0a7d28cb3ff9d799dcbaceef3175f78531e9
2013-02-10 01:14:49 -08:00
John-David Dalton
1b27834c41 Move _.isArguments fallback noArgsClass work into removeNoArgsClass in build.js.
Former-commit-id: 3627e59c65b67a61fc5ee04166004e400d816d13
2013-02-09 19:36:10 -08:00
John-David Dalton
77804907b6 Make whereIndicator check strict and make the _.where deep object comparison unit test deeper.
Former-commit-id: b9c59ff56b3ab7acd519888407de5dd02d6475cf
2013-02-09 10:10:36 -08:00
John-David Dalton
9dfa2609be Cleanup _.isEqual.
Former-commit-id: 83dd17b62fc86b870ca44aa4a54387343fd14cb2
2013-02-08 22:47:43 -08:00
John-David Dalton
8ffb3ab3c4 Simplify _.unescape unit test.
Former-commit-id: 113ee8e94a5a6a7d72b4e39672c60d67342def49
2013-02-08 19:04:02 -08:00
John-David Dalton
65e1da34fa Add custom build header comment to builds when only using --output.
Former-commit-id: adef2798bd590c0dc0c14b253f0d450ec5bb5394
2013-02-08 16:57:46 -08:00
John-David Dalton
282110807c Merge pull request #175 from timmywil/single_quote
_.escape("'") => &#x27; hex escaped not recognized by some html parsers

Former-commit-id: 0e55d8994a1919f5d5dd5806732cbe4711dae22a
2013-02-08 12:46:49 -08:00
Timmy Willison
25e5f43d1c Add lodash.compat builds
Former-commit-id: 5edfef23bb5d55c8efaf21a1cb345dc2b0d9488b
2013-02-08 15:45:08 -05:00
Timmy Willison
ce0441694d Escape single quote with numerical html character code rather than hex.
Former-commit-id: aef76d2662a065affc21ff735de526a177b50546
2013-02-08 14:54:12 -05:00
John-David Dalton
db29699927 Reduced _.pluck.
Former-commit-id: e413c1a6d0df383cb1ca51ab2203d3e380f71177
2013-02-08 08:42:04 -08:00
John-David Dalton
9a4e2d7617 Reduce the travis-ci time limit by 5 seconds.
Former-commit-id: 9653f4fee2bbfd8d77a228504795f3ef13df92dc
2013-02-08 08:13:57 -08:00
John-David Dalton
fbf64585b7 Fix --output build unit test.
Former-commit-id: fafafe88dfec9d777418c9eb95a7643c0061ee23
2013-02-08 07:18:55 -08:00
John-David Dalton
6d1c6dfd16 Update test and perf scripts.
Former-commit-id: 434935e332ec03dfd370efcd191b3f9aff5a9387
2013-02-08 00:58:26 -08:00
John-David Dalton
e78df4d981 Create a debug build if --output is passed.
Former-commit-id: 7571d238cf00fd9a7c72f65313e3807483067ace
2013-02-07 23:36:09 -08:00
John-David Dalton
a757b4d5dc Tweak docs for _.cloneDeep, _.bindAll, _.reduce, and _.sortBy.
Former-commit-id: a5d73e6ef174a743e05c0ef85414b899deea7815
2013-02-07 23:35:34 -08:00
John-David Dalton
d28036ee91 Add another _.size string value unit test.
Former-commit-id: 01c3bc51259c04a04f07d0e60398a0b2aa781641
2013-02-06 08:42:22 -08:00
John-David Dalton
d2ba0d4e7a Ensure _.merge doesn't iterate over a passed callback arg.
Former-commit-id: 2ed55922c2f5b4e47ac7e9763f3d76b4bec142da
2013-02-06 00:38:28 -08:00
John-David Dalton
5787436177 Don't remove nonEnumArgs fixes for mobile builds and cleanup debug builds.
Former-commit-id: b1fbb7ed362d0c94a92e4b12e0385c77973654b3
2013-02-05 22:54:18 -08:00
John-David Dalton
f5ab24b8d2 Fix legacy build.
Former-commit-id: 27bbe3ec6e025185daf73f9589e034e82097c313
2013-02-05 01:05:45 -08:00
John-David Dalton
05c0f32a24 Rebuild docs and files.
Former-commit-id: daf0b29cbcca43d7fa975e1ddb52f8c8b58cb31f
2013-02-04 23:56:57 -08:00
John-David Dalton
7b918f77a9 Clarify browsers affected by nonEnumArgs and reduce code around hasEnumPrototype.
Former-commit-id: 587f755332accbca26dc1eb357a66d4f898aad88
2013-02-04 23:55:52 -08:00
John-David Dalton
d87929d61c Remove "use strict" directive from the "modern" builds.
Former-commit-id: 7d1d5dd8cb91deb51fbdf7cfda04f3e49c96c204
2013-02-04 23:55:38 -08:00
John-David Dalton
a926829c33 Add _.bindAll unit test for passing just object.
Former-commit-id: 62f90c1dc7429610fb4bfaec3c5bb64d5a63dc9e
2013-02-04 08:36:15 -08:00
John-David Dalton
d58e366c40 Update docs and rebuild files.
Former-commit-id: 6265fed04ac7d6da6c6ded82095c22c1a60d9193
2013-02-04 01:21:22 -08:00
John-David Dalton
0fb4f7e1c4 Simplify _.where but don't make it an official alias of _.filter.
Former-commit-id: 794ab4eb814e8872443e282beb32cc636dedc43a
2013-02-04 00:55:12 -08:00
John-David Dalton
6ee606e3e2 Fix failing unit test in older IE.
Former-commit-id: 2de10b6bc3b9720a14fba86d9fe2638b30a7d0ef
2013-02-03 21:43:17 -08:00
John-David Dalton
22d4a7690f Make Closure Compiler bug fix to work with !1.
Former-commit-id: 2d82a0a8d71d8fc3907bf5f71b5ab41ed4142c04
2013-02-03 21:42:06 -08:00
John-David Dalton
f3a2f5018a Update vendor/uglifyjs.
Former-commit-id: 36cfce5048198ccb9f0a24a9021742afe60316b5
2013-02-03 01:48:11 -08:00
John-David Dalton
d2a7589f7c Fix failing build test and add another build test.
Former-commit-id: dccae3f43f55dda764750880e37c5e0682f32095
2013-02-03 01:23:40 -08:00
John-David Dalton
f87b4e04f1 Update test configs and move builds.
Former-commit-id: dc14112821f14101f107f90e9aeb5abec55b18a6
2013-02-02 19:33:29 -08:00
John-David Dalton
b5aa4c1f0c Add modern build option.
Former-commit-id: 4d8c791f8024eefec40c17b6efb708d989e78f34
2013-02-02 19:22:40 -08:00
John-David Dalton
0c1eb6d288 Update npm test. [ci skip]
Former-commit-id: f28a9229e700648926b933e3bc9d9ce371b9c556
2013-02-02 01:18:57 -08:00
John-David Dalton
8a03c5f998 Make travis-ci tests go right up to the max run time.
Former-commit-id: 15124a63d530c416ad1974898b7c1e3ee53c58a6
2013-02-02 01:14:06 -08:00
John-David Dalton
60aa50ae45 Add env and script to .travis.yml.
Former-commit-id: 700479d45f2c0683a877bddc15cd33d804aec00a
2013-02-02 00:16:11 -08:00
John-David Dalton
aae6bbbb66 Ensure build tests pass the correct exit code when their time limit is hit.
Former-commit-id: ead1bcc0448a639d5310ceb63e2efcf81e64a0c3
2013-02-01 23:41:44 -08:00
John-David Dalton
5ca903c428 Remove unnecessary _.template benchmarks.
Former-commit-id: ba9af8212673c7dfa109cb1e3f33bafec068dcdf
2013-02-01 23:20:16 -08:00
John-David Dalton
e86b07f760 Add node_js 0.8 back to .travis.yml now that they've fixed their issues.
Former-commit-id: 480cb02695ca5e3290bc9bf95f61e098b79ce988
2013-02-01 09:30:34 -08:00
John-David Dalton
d7fea5dc78 Update lodash underscore build _.findWhere to follow v1.4.4 null behavior.
Former-commit-id: 7b6ce7e9d7cf032171f43835bbf907cf3ffeb908
2013-02-01 09:29:56 -08:00
John-David Dalton
c1eff5aebb Cleanup comment blocks explaining old browser bugs.
Former-commit-id: e420cc9237565da01f60ed204fb6767bbe2cb9b4
2013-02-01 01:36:16 -08:00
John-David Dalton
f2dc490d6f Cleanup docs for _.omit, _.every, and _.template.
Former-commit-id: a2810a5db94ef1de4bb530a56b0f9f121688de05
2013-02-01 01:31:08 -08:00
John-David Dalton
b296e1b340 Add _.isNumber unit test for Firefox [xpconnect wrapped native prototype] issues.
Former-commit-id: d81b0bb7807139d14796c2a952294d1fd581f73a
2013-02-01 01:25:10 -08:00
John-David Dalton
8adb060edb Add hasEnumPrototype to avoid including the fix if not needed.
Former-commit-id: f826b725180a95d41b66612919c8b3fddfe568a0
2013-02-01 01:24:34 -08:00
John-David Dalton
c3b984fea7 Make callback behavior consistent for _.clone, _.cloneDeep, _.isEqual, and _.merge and add more doc examples.
Former-commit-id: 7a53ea18e4512dfcab5649c937db0f90d7649373
2013-01-31 00:28:47 -08:00
John-David Dalton
afbb2c338b Add _.findWhere benchmark and removenew bound benchmark.
Former-commit-id: baef485421cf6419450e3bc2a14f36e7e7c437c3
2013-01-30 08:58:55 -08:00
John-David Dalton
6632241ab5 Ensure the lodash underscore version of _.result matches v1.4.4 behavior.
Former-commit-id: c4c1946e49f12ddc4ba2f0f65a9ef7c9727d79ca
2013-01-30 08:57:28 -08:00
John-David Dalton
be50df81db Update builds and docs.
Former-commit-id: c0e38666fb1aee210c3dbd6401b040d8a2bee23d
2013-01-30 01:27:10 -08:00
John-David Dalton
9763b6e2cf Update build to add _.findWhere as an alias of _.find for the underscore build.
Former-commit-id: 0b772c30749c9af6ddc20b7b786f282ea93b63ce
2013-01-30 00:39:33 -08:00
John-David Dalton
812b848daf Update tests to work with QUnit v1.11.0.
Former-commit-id: ce6d6fb1756eb606e8106ac7e93816dffb48624e
2013-01-30 00:38:31 -08:00
John-David Dalton
4907a7389f Fix test.js for browsers.
Former-commit-id: e334ab595fa78a59b8371b755ce8dc54706a6630
2013-01-29 22:59:09 -08:00
John-David Dalton
17dff36b65 Update vendors.
Former-commit-id: 55a30b9cbfe7c513dd13d709aa4552fe715c262b
2013-01-29 22:43:56 -08:00
John-David Dalton
904921d8c4 Add a --time-limit option to test-build.js so travis-ci can complete its test runs.
Former-commit-id: 742b17208d6c9316efea33c106e7689b9290f48d
2013-01-28 23:34:27 -08:00
John-David Dalton
ac4c075d32 Add support for loading different Lo-Dash builds in test.js for Narwhal, Rhino, and Ringo.
Former-commit-id: 936b2f246540b2456c78a6087266ba9d39f48f91
2013-01-28 23:31:52 -08:00
John-David Dalton
ddde64ece9 Add lodash.min.js support to test.js.
Former-commit-id: c5c6cc47631752862c8f7b3b0f3d7b004493c01b
2013-01-28 21:12:06 -08:00
John-David Dalton
91c097e88d Cleanup unit tests and tests for _.clone, _.cloneDeep, and _.isEqual support of callback and thisArg arguments.
Former-commit-id: a53b5f4295cfc3e2f06ebed878c7c876acd64e6a
2013-01-27 23:34:18 -08:00
John-David Dalton
894658a3f5 Add underscore build replacement for _.isEqual and ensure legacy cannot be used with backbone or underscore commands.
Former-commit-id: 09340411bf3c4a0e4432d9b134b0aefb1f19183e
2013-01-27 23:32:21 -08:00
John-David Dalton
a4454ea5f9 Simplify regexp that escapes special regexp characters for reNative, and add callback and thisArg arguments to _.clone, _.cloneDeep, and _.isEqual.
Former-commit-id: 86715543147d2965a562016cf0b08f945fa38fe6
2013-01-27 23:29:38 -08:00
John-David Dalton
8ea8fa3a8a Add deep comparison note to the _.where docs. [ci skip]
Former-commit-id: 223d3a45832238b9ce39d4321636b971abde9b46
2013-01-27 15:12:20 -08:00
John-David Dalton
7480603295 Simplify regexp that escapes regexp special characters.
Former-commit-id: dde89b0f7d9cd31768eecd4ef92c0ae9d1b5d581
2013-01-27 14:57:32 -08:00
John-David Dalton
079b749d5d Add more _.isEqual benchmarks.
Former-commit-id: e0eee615e593eb9be627da52be158bf7b590fd2a
2013-01-27 11:24:55 -08:00
John-David Dalton
4815600e85 Continue dependency map tweaking, and simplify how _.isArguments is handled in the underscore build.
Former-commit-id: 568887e067d6463f102b3b866195f3a173fc6d4f
2013-01-27 11:23:02 -08:00
John-David Dalton
1c63e2d295 Update method dependencies and add more mobile and underscore build tests.
Former-commit-id: fa10d8c7bef9700ec59e4e38e730e0ad4963d812
2013-01-27 03:06:24 -08:00
John-David Dalton
cf13eca58c Cleanup deep _.clone and _.where unit tests.
Former-commit-id: b7106461640259ca3bf60c1fabb91b59b241e35f
2013-01-27 02:39:18 -08:00
John-David Dalton
3cf4607870 Add support for deep clone via _.clone(object, true) back.
Former-commit-id: cc9b6bb81848b6a98d6f413485845e2e0407e3ac
2013-01-27 02:38:43 -08:00
John-David Dalton
23c3ba6ad7 Ensure _.where works correctly for nested properties and give indicator arguments more meaningful names.
Former-commit-id: c35e2817125cd852a66066ccdef44bcc40c93e61
2013-01-26 23:47:47 -08:00
John-David Dalton
17fc3c2317 Reduce doc examples, simplify iteratorTemplate, remove deep argument support from _.clone, and ensure _.merge and _.pick exit early for non-objects.
Former-commit-id: d3fbd9a8ff9cd0c8201beb7180e3e7190e2a7cf8
2013-01-26 20:37:26 -08:00
John-David Dalton
af234cbe54 Finish renaming iteratee to iterable. [closes #170]
Former-commit-id: 0ac6cecaec0a779cb29c21b5fc3caa90c84479eb
2013-01-25 20:10:53 -08:00
John-David Dalton
c8517c0ec9 Merge pull request #170 from paulmillr/topics/iteratee
Fix naming: use “iterable” instead of “iteratee”.

Former-commit-id: 199757631f0c941898e1dcb8f5ae9f9d8c517337
2013-01-25 19:40:13 -08:00
Paul Miller
20b226454b Use “iterable” instead of “iteratee”.
Iteratee is a monad that provides functional way of handling I/O,
when iterable is a representation of series of elements that can be iterated over.


Former-commit-id: 94e58614ba9c2ebdd2aad1848a8b4d0ceef55023
2013-01-26 03:21:41 +02:00
John-David Dalton
98eccf223a Simplify null/undefined check in _.isEqual and edit _.cloneDeep docs.
Former-commit-id: 62455ba83df04318856fbc889743f44101b24fe3
2013-01-25 00:20:55 -08:00
John-David Dalton
0fc2ab4d41 Fix lodash settings=… documentation example. [ci skip]
Former-commit-id: 671683d4e77b8fa27903e30d938f665548311b3f
2013-01-25 00:07:21 -08:00
John-David Dalton
641b6efe7f Remove auto with statement removal optimization from _.template. [closes #166]
Former-commit-id: da27942b109844d44327914631b7c5681489b04b
2013-01-24 01:14:07 -08:00
John-David Dalton
4c83435b4b Clarify the -d and -m build options. [closes #167]
Former-commit-id: d3ee420b982291632785d6583a6f2981ab07a635
2013-01-24 00:08:52 -08:00
John-David Dalton
9f7319cff4 Revert to compiling _.assign and _.defaults, using isKeysFast, and tweak large array size in _.without.
Former-commit-id: 275d453f49e762ac499a9328ddb8e156b8c9c22d
2013-01-23 23:59:41 -08:00
John-David Dalton
dd9baa1502 Add doc note about wrapper Array methods. [closes #162] [ci skip]
Former-commit-id: 9d83e9b4c0298469d926325b35dee5566071f48c
2013-01-23 00:23:57 -08:00
John-David Dalton
41b4d0daa1 Update method dependencies in build.js.
Former-commit-id: 6cb368b6f440faa31c8f06cba347dcb755c95179
2013-01-22 23:54:52 -08:00
John-David Dalton
e41b181163 Ensure _.where deep compares properties values.
Former-commit-id: f3f29abf024f87a947fef6df1e3db9d9d1de99bf
2013-01-22 23:54:09 -08:00
John-David Dalton
288ac115d0 Avoid buggy Travis-CI Node version in travis.yml. [ci skip]
Former-commit-id: be10d0a5144628a98aafdc974febd08592cad30b
2013-01-22 23:08:09 -08:00
John-David Dalton
6774d46a6f Simplify sourceURL code and ensure source maps work avoid compat issues.
Former-commit-id: 5b64703eaebc65c443d6b9d3699d448c253e70c1
2013-01-22 21:51:10 -08:00
John-David Dalton
607abf89f7 Move generic Closure Compiler fixes into build/minify.js.
Former-commit-id: 8492f60a67cbf7a2d7d3118f9653e6997ab1d15b
2013-01-21 01:13:51 -08:00
John-David Dalton
27f1e5e2f2 Fix _.partialRight doc typo. [ci skip]
Former-commit-id: 871aa8f8c89a226e89988995926f8a6946757321
2013-01-20 12:21:57 -08:00
John-David Dalton
a457675ce1 Move deep _.defaults implementation unit test to _.partialRight.
Former-commit-id: 7e5c6184d24b47170ef148122ef5c7428f8b2da9
2013-01-20 12:09:44 -08:00
John-David Dalton
82049096e6 More build fixes.
Former-commit-id: 8b97cd56c4b5530d03ba89d192be7df989e96655
2013-01-20 12:02:47 -08:00
John-David Dalton
6c965e0223 Cleanup strict build.
Former-commit-id: c34b2e7e2810e8bc35bde3e0f962d925b3f5ba1b
2013-01-20 03:56:35 -08:00
John-David Dalton
8b4d952929 Fix build.
Former-commit-id: e930621f522aae7c15502ac56fe9983943d2dc80
2013-01-20 03:40:44 -08:00
John-David Dalton
873cc63f94 Add _.partialRight and make _.assign and _.defaults work with arrays.
Former-commit-id: 6d9fea855de53e9ccb5ac6f58db68239ef08e9de
2013-01-19 22:17:14 -08:00
John-David Dalton
39fc839ff2 Fix test/test-build.js to work with build.js modifications.
Former-commit-id: 9df41ae02627557a21f282f70a73a447497b8984
2013-01-19 16:42:16 -08:00
John-David Dalton
4edef4c959 Update license and copyright.
Former-commit-id: 16ded758d08c66dcc9585e75848dec5420ddbbf2
2013-01-19 16:07:15 -08:00
John-David Dalton
1d9ced8037 Remove resolved Underscore issues from README.md.
Former-commit-id: 16f60867355adc5f528274838d3526ab7821b553
2013-01-19 01:00:15 -08:00
John-David Dalton
4cb77d1429 Avoid extreme &nbsp; use in the README.md.
Former-commit-id: 3ff1aca436ed040a6ffb0335f92b8b44f80137be
2013-01-19 00:36:22 -08:00
John-David Dalton
b52d9d1bdd Add --source-map build option. [closes #161]
Former-commit-id: e0cac11fda86671d944de5c157d3df3146d6def1
2013-01-18 02:37:22 -08:00
John-David Dalton
5fe7ca5e70 Update vendor/backbone.
Former-commit-id: faf9ed71356e1ae8b5c4f65e7084243571cb7d82
2013-01-17 00:40:49 -08:00
John-David Dalton
62fb440de2 Update closure compiler.
Former-commit-id: 20934c3606c88b0c108f89a01bcc7703dfbe2179
2013-01-17 00:18:41 -08:00
John-David Dalton
96fbd7c7ba Fix closure compiler bug.
Former-commit-id: 6b61f095fa26d2dee0d70b666e630e4ca0fa7be6
2013-01-16 23:59:24 -08:00
John-David Dalton
c9bec8e636 Fix typo in _.merge unit test.
Former-commit-id: 15b2389bca12cb1655a07a51525624f7af9caa6c
2013-01-16 23:22:07 -08:00
John-David Dalton
769e03e7f2 Update Closure Compiler and UglifyJS.
Former-commit-id: 8e20f30f84b01ed6df593136c2d081e9d05acbca
2013-01-16 23:21:08 -08:00
John-David Dalton
ab83f2d5e2 Ensure _.first and _.last have the correct chaining behavior when passing a callback and thisArg.
Former-commit-id: 4d54fd677fa48bf8de033696c58ee66babd77a81
2013-01-16 01:39:58 -08:00
John-David Dalton
b60d0cdb17 Added support for _.merge to accept callback and thisArg arguments. [closes #154]
Former-commit-id: 5d641ae4ba1d120d776a895f8bc9b8c1a7def0b6
2013-01-16 01:11:39 -08:00
John-David Dalton
677503dbf1 Remove Travis-CI build status until they resolve their issues.
Former-commit-id: 2d5607771e148b3010906452a9dc86f25f18ed3f
2013-01-15 21:28:14 -08:00
John-David Dalton
25efa29470 Remove metadata from tar.gz files.
Former-commit-id: 2cd702d72e9f2ff441fc7f8c8e22bef3f2784cbe
2013-01-15 21:16:18 -08:00
John-David Dalton
21a90f8f8f Avoid travis-ci downloading the included minifiers.
Former-commit-id: d8558ea8295a9c7e7d28c1a1740edf63daa81933
2013-01-15 20:50:25 -08:00
John-David Dalton
64e8d6ae99 Update .travis.yml with git and branch options.
Former-commit-id: 51abc02eb378332b15d525fdab62d82f8d70b62b
2013-01-15 02:18:40 -08:00
John-David Dalton
16a204335e Ensure _.merge produces dense arrays and revert accepting arrays of arguments for _.compose, _.defaults, _.extend, and _.merge.
Former-commit-id: a02772f8be04e187cbbfeb324cd4fb4318098162
2013-01-15 01:32:21 -08:00
John-David Dalton
0a53f762fe Update tested environments in README.md.
Former-commit-id: 9ce4d74e664acdd3acee27b7a127a6d7d4577ac4
2013-01-14 01:28:39 -08:00
John-David Dalton
6ba4778c1b Make methods capable of accepting unlimited arguments consistently accept either individual arguments or arrays of arguments.
Former-commit-id: b9f0c744f79e74889323f4fd7f737d10acd32ada
2013-01-14 01:11:46 -08:00
John-David Dalton
0404c2266c Use strictEqual when the expected result is 0 or 1.
Former-commit-id: ff439b0e7252351663b754267056ad09e0f89838
2013-01-13 15:12:02 -08:00
John-David Dalton
e5e914282f Allow _.first, _.last, _.initial, and _.rest to accept callback and thisArg arguments. [closes #155]
Former-commit-id: b921ae0ccc188c5544480f397216ce3b2479989e
2013-01-13 14:58:53 -08:00
John-David Dalton
9867d4bdc3 Add unit test for passing an object as callback to _.find.
Former-commit-id: 36da6e95473e85ac799180618e1a546d87f0686f
2013-01-12 20:42:54 -08:00
John-David Dalton
e4cb7112cf Update vendors, minified builds, and rebuild docs.
Former-commit-id: 9be99ca3c78a1a35fd13138398c48ab4a4b35f11
2013-01-12 20:12:38 -08:00
John-David Dalton
2d202e90b7 Add unofficial _.where like support for methods like _.find. [closes #159]
Former-commit-id: c6106035af3f3d676cbd3f0a5c785b2c00ad1e9d
2013-01-12 19:02:06 -08:00
John-David Dalton
016391e442 Add capitalize and getCategoryDependencies method to build.js
Former-commit-id: d939fbb482926a1673c5841f0c08b280ddca18e5
2013-01-12 16:46:52 -08:00
John-David Dalton
1eff48a429 Ensure iterator options are minified correctly.
Former-commit-id: ae7b617051d91d99bad899d82df195d3c41bf76a
2013-01-12 16:18:17 -08:00
John-David Dalton
ce33af6bb5 Cleanup _.merge.
Former-commit-id: 4227c403f89a1085ce88ca992106b7ed0a3c210c
2013-01-12 13:47:13 -08:00
John-David Dalton
fb9d4303f1 Correct _#tap doc example. [closes #156]
Former-commit-id: d1f6982e824a97db73546b8594c074b735580f8e
2013-01-08 22:21:46 -08:00
John-David Dalton
4e631c9e8f Flip noNodeClass check to avoid breaking when Firebug's "break on all errors" option is enabled. [closes #85]
Former-commit-id: f98c3af700279cb688c5df6c696b141bf626e26b
2013-01-05 22:11:14 -08:00
John-David Dalton
766d67d80d Remove isKeysFast guard.
Former-commit-id: 38a63ed31d652fd198ebf30dbb0f1546160c30c1
2013-01-05 12:07:29 -08:00
John-David Dalton
e2c2a37221 Make _.merge assign null values. [closes #151]
Former-commit-id: 5a839996db9475182d5957d2f8cb4b3c265b0d9f
2013-01-05 00:12:33 -08:00
John-David Dalton
2b23020695 Merge branch 'master' of github.com:bestiejs/lodash
Former-commit-id: fe8531c316e040e71dd8f58d509dcee9c137d985
2013-01-04 06:20:36 -08:00
John-David Dalton
8d43c6b1a8 Merge pull request #152 from terinjokes/docs
Fix typo in `_.range` docs.

Former-commit-id: 1fd6134d1809dcd59119740f0a115f0b5e819734
2013-01-04 06:15:27 -08:00
Terin Stock
7362dd1a7c Update _.range docs to consistently reference 'end'
Former-commit-id: a8ee760eb86e67eb898715ee9719fa8981eeda17
2013-01-04 02:20:06 -08:00
John-David Dalton
316caf7e8c Tweak UglifyJS "comments" option and update vendor/benchmark.js.
Former-commit-id: 6f09f27936f9453c58138e216399a51732a00173
2013-01-02 23:35:38 -08:00
John-David Dalton
87dc6631ee Cleanup "imports" template option.
Former-commit-id: f9f52b1f63908bcb7db7837a9bda067f2855acbb
2012-12-31 14:52:16 -06:00
John-David Dalton
62246d7d43 Update platform.js.
Former-commit-id: 5e5170b0c29175469d4b80010297d31afa14b5c8
2012-12-31 14:45:53 -06:00
John-David Dalton
a14be3a42c Add "imports" option to _.templateSettings. [closes #148]
Former-commit-id: 16a019d27aea2e7a72665f62adf4c4c35e29b4bf
2012-12-30 12:23:51 -06:00
John-David Dalton
7fdf00d5e9 Workaround UglifyJS comments option bug.
Former-commit-id: 705510311c4eee0739e85054c6d8edded427efe3
2012-12-30 11:14:10 -06:00
John-David Dalton
99e02f30fb Simplify createIterator. and remove whitespace between else { in template text.
Former-commit-id: a673f0edbe9b8655cbe1e91d9063e58130172495
2012-12-30 00:41:00 -06:00
John-David Dalton
716a5b9b5a Update _.random docs and add unit tests.
Former-commit-id: d4a033bf83ad5fce7bb3b09467305730a89adc01
2012-12-28 20:22:04 -06:00
John-David Dalton
87f880ca52 Update vendors.
Former-commit-id: baf89d2c3bd7077462995bffa7f8bff1e1cf28f9
2012-12-28 19:47:44 -06:00
John-David Dalton
8ec7b84a78 Remove unneeded default ran value from _.once.
Former-commit-id: 4d4fc057c0cf9108183e7e7158f305214eed4323
2012-12-27 14:17:09 -06:00
John-David Dalton
05cf5bc8db Defer downloading required minifies until the lodash command-line executable is used for the first time.
Former-commit-id: 83df0ac5875e8647168fffb7043a4cc197d27d79
2012-12-27 14:17:01 -06:00
John-David Dalton
ac25e21a0c Avoid minifying typeof x == 'undefined' checks into x === void 0.
Former-commit-id: 23c998b48a1d2e1bca19dad6bf16fa94aeebed31
2012-12-27 00:44:57 -06:00
John-David Dalton
cc1e0daaa4 Update vendor/underscore.
Former-commit-id: 9a00fa6c531e8cf0990526b7034cbde67ef335b3
2012-12-27 00:08:19 -06:00
John-David Dalton
f4120a9c8c Consistently coerce keys to strings before passing them to hasOwnProperty and init Array lengths when possible.
Former-commit-id: 5bd397eafbae888c7e6c76e62a7021b85796e65a
2012-12-25 23:12:19 -06:00
John-David Dalton
e3b80a5e09 Simplify _.toArray and wrapper methods.
Former-commit-id: b0440d401bd58cfa2d7aaf213549a824963474c3
2012-12-25 17:06:51 -06:00
John-David Dalton
ef7cb26b01 Update vendor/underscore and continue to tweak _.throttle unit tests to avoid false fails.
Former-commit-id: b5ba7b53e3bbebb3fa42da7e197f746515c8efb0
2012-12-24 09:49:46 -06:00
John-David Dalton
408a5c168f Optimize _.max and _.min for gzip.
Former-commit-id: e4d6eb949824718aa967208203b7c487df7e02f5
2012-12-23 16:49:00 -06:00
John-David Dalton
0ad6ac95b2 Avoid setTimeout inconsistencies in the unit tests.
Former-commit-id: fdbe08fcb381bf7771a1a7e474882d82e5bdbdf2
2012-12-23 10:10:28 -06:00
John-David Dalton
bda4747e9c Use @license in the copyright/license header. [closes #138]
Former-commit-id: 3b924dad24d56e0fd33e4df1341b09c6165521a1
2012-12-22 15:18:14 -06:00
John-David Dalton
bd8f882c94 Tweak _.reduce documentation.
Former-commit-id: 58d8a724dbf53594420e355c3d29ae28b53a7886
2012-12-22 11:57:14 -06:00
John-David Dalton
32b5b5b1c4 Catch module load errors in build/post-install.js.
Former-commit-id: 6671d4925749d8b4d6da9ddd732bc7f436b6740d
2012-12-22 11:56:52 -06:00
John-David Dalton
c1e543c9fe Cleanup .npmignore. [ci skip]
Former-commit-id: bca4d773ba803c28a128ec162b41e033998b5d0a
2012-12-21 20:08:16 -06:00
John-David Dalton
3908fa5c57 Simplify build/post-install.js.
Former-commit-id: a3f657f9721b18cef3c43b36a64e83b77d63eeea
2012-12-21 19:29:46 -06:00
John-David Dalton
1b347fc185 Tweak _.uniqueId to avoid problems with buggy minifiers.
Former-commit-id: e940c336b227ce89661cd6ada5f3e722a0204318
2012-12-21 12:38:55 -06:00
John-David Dalton
282a5e0b01 Correct href value in post-install.js.
Former-commit-id: 63b220d6dfecad7c1ebb5079efef603145e97392
2012-12-20 02:43:16 -05:00
John-David Dalton
e9d23cc1ea Use child_process.execFile instead of child_process.exec in post-install.js.
Former-commit-id: 2f6b0827641ceb1c6b418af9de87ef3c70243d5f
2012-12-20 02:29:21 -05:00
John-David Dalton
34173fd60f Upgrade to UglifyJS2.
Former-commit-id: dd326a5f401d8359f92f46552e2f59c1accf7cc1
2012-12-20 02:17:38 -05:00
John-David Dalton
d0d3c8ef57 Remove unused variable, index, in _.isEqual.
Former-commit-id: 21f364b6fa0505f9ccb579660f1bda4e38cbe3d3
2012-12-18 23:28:28 -08:00
John-David Dalton
11912008dd Account for at in an underscore build test.
Former-commit-id: 7222681ef1e5ec17e940789efc38e99be97c0116
2012-12-18 22:41:50 -08:00
John-David Dalton
c122007e17 Rebuild minified files and docs. [ci skip]
Former-commit-id: 161ba27aa3bd38c48d8f15057343944dc6a674c2
2012-12-18 21:53:30 -08:00
John-David Dalton
69dfa1a175 Clarify _.merge documentation. [closes #143] [ci skip]
Former-commit-id: efcec739bf2682da9b3dde27a43ff3b76aa4d6e8
2012-12-18 21:35:43 -08:00
John-David Dalton
bfea443e55 Cleanup _.at and add build tests.
Former-commit-id: 7648376e1ef447ae83d621b449b73acec355bb67
2012-12-18 21:16:10 -08:00
John-David Dalton
680798c28f Merge branch 'master' of github.com:bestiejs/lodash
Former-commit-id: 4241085b99e4df0991946a18f66990209e05ee31
2012-12-18 19:14:15 -08:00
John-David Dalton
9f0cc45c45 Merge pull request #142 from danheberden/pluckByArray
Add `at` method to get elements from a collection.

Former-commit-id: 99e4d651afe760f952398e5119d03c6caff0fc44
2012-12-18 19:14:00 -08:00
John-David Dalton
0ac97f467f Merge branch 'master' of github.com:bestiejs/lodash
Former-commit-id: 53ef1ba726cff56a98b739190957565c27bd253f
2012-12-18 19:09:33 -08:00
John-David Dalton
647746ea72 Update vendors, builds, and docs.
Former-commit-id: 8e6ca9a1334c73671aba1b4c974d738dbd7d72e1
2012-12-18 19:07:39 -08:00
John-David Dalton
7bea30b2e6 Optimize _.invert, _.pairs, and _.values.
Former-commit-id: d2725dc8c75254784d450f2a7e997e079b8c3183
2012-12-18 19:07:38 -08:00
John-David Dalton
12bc852c89 Update Chrome extension sandboxing link in README.md. [ci skip]
Former-commit-id: 17363260102ec1e874309eeea62bb077e2479303
2012-12-18 19:07:38 -08:00
John-David Dalton
0d42e84045 Add a benchmark for _.some with thisArg and avoid corrupting the aggregate score if a single benchmark errors. [ci skip]
Former-commit-id: 2042fdaab870ad2de2fb4938f5033d21f3dd1ae3
2012-12-18 19:07:38 -08:00
John-David Dalton
897b85b607 Merge branch 'master' of github.com:bestiejs/lodash
Former-commit-id: b5d52b6bbb4b5312fdf5d9da82fc15a4abef2b84
2012-12-18 19:05:59 -08:00
John-David Dalton
5c55cf0efb Make path convention consistent in package.json.
Former-commit-id: bf1bde8a2e78a520dca92ddd7b95f9fce12eb446
2012-12-18 19:05:39 -08:00
Dan Heberden
eccd6463f6 update dependency for at method
Former-commit-id: 600a1079d3591880654df0b861810b7c070047e9
2012-12-18 15:30:38 -08:00
Dan Heberden
4a0897c734 build in functionality to at, add string support, optimize, and add more tests
Former-commit-id: 951ef27e55fff5a70d09916b55b85f9e725f751a
2012-12-18 15:10:10 -08:00
Dan Heberden
c86a16df7f change .grab to .at, add unlimited args or numbers or arrays and simplify function call to use values and pick
Former-commit-id: 3deb82ad9f55cd7261453a40bb0f046a5340790d
2012-12-18 12:52:44 -08:00
Dan Heberden
2ae0e9d902 add grab method to get elements in a collection that match the indexes in the provided list array
Former-commit-id: 18df81c229cab4acde8f8157df9bb1001a51e9db
2012-12-18 10:00:24 -08:00
John-David Dalton
bba18cd56b Update vendors, builds, and docs.
Former-commit-id: 488762bd908dca5538767e4b4210ca0079560520
2012-12-18 07:41:34 -08:00
John-David Dalton
2f20781e16 Optimize _.invert, _.pairs, and _.values.
Former-commit-id: 7df68977c0a99b48e8989101228432c3db55c460
2012-12-18 02:45:56 -08:00
John-David Dalton
3bee212876 Update Chrome extension sandboxing link in README.md. [ci skip]
Former-commit-id: c093d1d8356b5ef4129e91b820478c25c5224798
2012-12-18 01:49:50 -08:00
John-David Dalton
6c8893a550 Add a benchmark for _.some with thisArg and avoid corrupting the aggregate score if a single benchmark errors. [ci skip]
Former-commit-id: 10dae73eb07e610a7752fc3f9035e71e696ce93d
2012-12-18 01:08:55 -08:00
John-David Dalton
9c52ecc19b Tweak regexp in post-compile.js.
Former-commit-id: 8c6933944703a17582696fb10b45f12926fe1030
2012-12-17 08:36:02 -08:00
John-David Dalton
692c884ca2 Ensure test count is the same for dev and prod builds.
Former-commit-id: 00e24fdd70d52bc6be4ae53fed43933fcf2c35da
2012-12-17 08:21:13 -08:00
John-David Dalton
3ef51d7fae Refactor previous commit.
Former-commit-id: ad5408ad8a9e5b2caa9667994fe6748760b40fbe
2012-12-17 08:20:37 -08:00
John-David Dalton
73d95de122 Reduce _.forEach and optimize the minified builds for Safari.
Former-commit-id: d4366f1a3c5fd0751558f714384600c3bcf0f49b
2012-12-17 00:06:59 -08:00
John-David Dalton
04a568ac9b Update vendors and docs. [ci skip]
Former-commit-id: 9ca377423f4714fdf0e3fa428711e8dfe75e2e44
2012-12-16 21:41:01 -08:00
John-David Dalton
a45499cf04 Cleanup build.js and README.md.
Former-commit-id: abf5c3e3f1b0a04b8f9eeb132366f51c92c9a450
2012-12-16 14:47:00 -08:00
John-David Dalton
b847d672ab Bump to v1.0.0-rc.3.
Former-commit-id: d00d4d948fc0e2597e4ee2f2d15a9bee2dc27440
2012-12-16 12:22:04 -08:00
John-David Dalton
3ffefdf6b5 Avoid _.isArray returning true for arguments objects in browsers that report arguments.constructor as Array.
Former-commit-id: 9fccc5219e7cb6a007138f1f474d9e68504a0260
2012-12-16 10:47:22 -08:00
John-David Dalton
cca4c4be80 Fix hasObjectSpliceBug implementations of _#pop, _#shift, and _#splice.
Former-commit-id: 91a3bc259c85bd269c3d895b66204bdc4d158827
2012-12-16 00:14:08 -08:00
John-David Dalton
cb9e044cb3 Prepare v1.0.0-rc.3 bump.
Former-commit-id: d4b08cd58a7effb9e6107fe16c11ccdea032cb00
2012-12-16 00:12:01 -08:00
John-David Dalton
fd25dd83bd Coerce value to a string once in _.intersection and _.uniq.
Former-commit-id: 5cb0f0034c473ec62c3b342f45d22c0abe6c5fb3
2012-12-15 14:32:55 -08:00
John-David Dalton
584bb00cfc Use the indicatorObject instead of a boolean in the internals of _.reduce and _.reduceRight.
Former-commit-id: b83d1ef428941f15a6633c1b16b9373210149318
2012-12-15 13:01:43 -08:00
John-David Dalton
5b9369d344 Update tested Node version and reduce emphasis on performance in README.md.
Former-commit-id: 12a57f39409fa5bb5a18e3535c56c50ef767289a
2012-12-15 13:00:22 -08:00
John-David Dalton
a64506a0de More clearly label lodash underscore compatibility builds. [ci skip]
Former-commit-id: 169559848f08a5ce9228e18e647e2e26eabe8341
2012-12-14 01:55:39 -08:00
John-David Dalton
2fc83ef80b Tweak _.cloneDeep docs.
Former-commit-id: 992471067498a0be795f473fabaaf8e45581f291
2012-12-14 01:06:00 -08:00
John-David Dalton
8bee3ebd65 Update backbone method dependencies.
Former-commit-id: 1b030f0a7b2f4065ec1dfc9ef911de77ebd7d842
2012-12-14 00:54:36 -08:00
John-David Dalton
99686fdd73 Revert @license doc tag addition of #138.
Former-commit-id: a66d22c952b3a0bb45e049a80ee80aa54c4e6a33
2012-12-14 00:41:56 -08:00
John-David Dalton
33bc3d6a1e Update vendors, builds, and docs.
Former-commit-id: d57931d657ac0e73d91ac1bd1b33e24be5a16f35
2012-12-14 00:32:58 -08:00
John-David Dalton
90597530a4 Add _.cloneDeep alias of _.clone(…, true). [closes #140]
Former-commit-id: b71397d5c5b71cb28a60eb4656cbaf12f6b03d1a
2012-12-14 00:24:02 -08:00
John-David Dalton
b2af8da9a2 Merge branch 'master' of github.com:bestiejs/lodash
Former-commit-id: 502c65ac38876c5fe42c9c652ef4cb237e9c631a
2012-12-13 23:49:38 -08:00
John-David Dalton
05dbf41fdc Optimize _.intersection.
Former-commit-id: 017b20ad958a9dd7be09872456b1d26a59361c5a
2012-12-13 23:48:19 -08:00
John-David Dalton
c56bb56708 Cleanup benchmarks.
Former-commit-id: 805c0091cd6cec85729ee7511005c233545a9899
2012-12-13 23:47:48 -08:00
Kit Cambridge
4def1ea1dc Fix installation mode detection on Windows. Closes #139.
The global `node_modules` directory does not exist if no modules have been
installed globally, causing `realpathSync` to throw an exception.


Former-commit-id: 5a59e6b53c7afe5d5c5728352e9cd722744b2247
2012-12-13 10:35:29 -08:00
John-David Dalton
0ba05e4de0 Add @license to minified copyright header to preserve it in case of double minification. [closes #138]
Former-commit-id: 6c9b72f9c807daac613ff2d4339c0e3c4e7cafe3
2012-12-12 00:37:56 -08:00
John-David Dalton
24fce89155 Remove "Collections" method _.forEach dependency from "Arrays" method _.intersection.
Former-commit-id: 83197c7ac47654c6fc2d2f37df8ff77d4adb9096
2012-12-12 00:34:58 -08:00
John-David Dalton
1a3c20f91d Tweak _.throttle unit test pass more consistently.
Former-commit-id: 91063b5c6ae0c9beb2c86cc21153d75f060afef1
2012-12-11 01:10:52 -08:00
John-David Dalton
fe3e78cc1c Update vendors, rebuild minified files, update docs/license.
Former-commit-id: 689793b6e5c4bbae917e726dc646902c697ce3a7
2012-12-11 01:09:52 -08:00
John-David Dalton
749f49b1a0 Add instanceof memory leak warning to _.isArray.
Former-commit-id: f90b1ad1850fb21c1d976f037a382c7388496d1c
2012-12-11 00:54:09 -08:00
John-David Dalton
f14010a09d Make a private each function to be used by _.forEach.
Former-commit-id: da9e22a66aef1ad9f4688f4fbb07e0806f8f0445
2012-12-11 00:44:02 -08:00
John-David Dalton
0b48b9c7d4 Optimize _.isArray fallback, _.isDate, _.isFunction, and _.isRegExp.
Former-commit-id: a3e350bf1fa91a9582ba6a0effe61d4589cc8afe
2012-12-10 00:29:26 -08:00
John-David Dalton
13d62b01d1 Ensure utf-8 encoding and tweak text in CONTRIBUTING.md.
Former-commit-id: 67a3e585c0a3b815e916e0d38ed2bc113de3220d
2012-12-10 00:05:43 -08:00
John-David Dalton
4e7b71db1d Cleanup CONTRIBUTING.md and README.md.
Former-commit-id: f0dca3ffc6a23128a877ae4d7d7f409d2e6adb69
2012-12-09 22:36:19 -08:00
John-David Dalton
069fc1f97b Merge branch 'master' of github.com:bestiejs/lodash
Former-commit-id: e30fbcc10d6a5ea2bde762d91b9dd11a6f8a0dfc
2012-12-09 21:59:42 -08:00
John-David Dalton
8684f75254 Cleanup lib and build unit tests.
Former-commit-id: 96171aa70fee408f5237e0615ace4faa6541caa7
2012-12-09 21:59:05 -08:00
John-David Dalton
11cd924ce1 Rework the chaining behavior of Array wrapper methods.
Former-commit-id: fb8add58a861a19a2df63d6ff377c2a9537a38b6
2012-12-09 21:58:31 -08:00
Kit Cambridge
e2fd0cfc4e Add contributing guidelines.
Former-commit-id: 0e613d3b5136a980284b3ba3de738ba664cb7fe5
2012-12-09 14:16:15 -08:00
John-David Dalton
5eb3106706 Updating Backbone/Underscore unit tests to avoid failing tests due to different chaining implementations.
Former-commit-id: d797a3547368faae04806d61818327e7d2319309
2012-12-09 00:23:02 -08:00
John-David Dalton
1831efbe9d Cleanup build and doc comments.
Former-commit-id: 861145621113c0b6719b24d00ce0e359360ee1eb
2012-12-08 21:37:40 -08:00
John-David Dalton
38edbadca5 Update Lo-Dash description.
Former-commit-id: 75703b13b95399107b11f109dcc6d3b3dfd9eabe
2012-12-08 18:53:45 -08:00
John-David Dalton
6fcd80b979 Update builds and docs.
Former-commit-id: 647fe24574fc9bab2d32abb6e95f74d1cdd593f4
2012-12-08 18:52:59 -08:00
John-David Dalton
cf5e5dbe55 Update build to add _.chain and _#chain for backbone and underscore builds.
Former-commit-id: 2c910de419904a1285d246a3b08d87cb4daafa18
2012-12-08 18:46:09 -08:00
John-David Dalton
a451861bf1 Make "Functions" methods return wrapped values when chaining and remove _.chain and _#chain methods.
Former-commit-id: a507f9a1b76b933a7d558d2cc20177e6995dcf0d
2012-12-08 18:42:48 -08:00
John-David Dalton
7313dd74a6 Allow compiled templates loaded via AMD to set and use the private _ variable.
Former-commit-id: 746e6d8275f08dbb628e92c146fffba84df0f8c0
2012-12-08 01:26:08 -08:00
John-David Dalton
32b9de05f2 Cleanup test/test-build.js.
Former-commit-id: 4edb24bf22b8e8f9aa45b08a97289c1b83461e16
2012-12-08 01:24:25 -08:00
Kit Cambridge
c79bed22f8 Ensure that passing settings=... does not clobber the default moduleId.
Precompiling a template with `settings` previously generated a snippet
resembling `define(["undefined"], function(lodash) { ... })` if the `settings`
object did not contain a `moduleId` property. You can now pass `settings` and
`moduleId` options simultaneously; the builder will always use the `moduleId`
property in `settings` if it is provided, and default to `moduleId` otherwise.


Former-commit-id: 711b4f167dc08ce3d42029e9001ebdb2d8d60a56
2012-12-07 19:41:11 -08:00
John-David Dalton
cdeb50132d Optimize _.reduce and _.reduceRight.
Former-commit-id: 6f281aae7f285458feafb02957fcd90fb09c10bd
2012-12-07 00:20:09 -08:00
John-David Dalton
090fb09955 Optimize _.union.
Former-commit-id: 0cba8cac81a621b1fdbe8868ab406a30eb1d743f
2012-12-06 23:09:41 -08:00
John-David Dalton
54b862bd79 Bump to v1.0.0-rc.2.
Former-commit-id: 55bca6a70e127152329deeff509a72a73436f40e
2012-12-05 02:24:46 -08:00
John-David Dalton
e37e1c109a Tweak method's chaining behavior.
Former-commit-id: 3bfdd8d004fbdcb839843748b907cad5a5003446
2012-12-05 01:37:28 -08:00
John-David Dalton
939123785b Specify more method's chaining behavior.
Former-commit-id: 7b8c18f6058bb279ab25f7e8b94e7418951e3ded
2012-12-05 01:36:18 -08:00
John-David Dalton
221b347bd9 Update vendor/underscore to v1.4.3 and update the Underscore build compatibility.
Former-commit-id: ebcaad4a92848bef3bbf65bb8eb3a0c1553e005c
2012-12-05 01:03:10 -08:00
John-David Dalton
af9bf3e852 Cleanup comments/docs/descriptions. [ci skip]
Former-commit-id: 4d6a0a54abbaa6607cc5897a09e5a7c0fc884a1a
2012-12-04 09:14:59 -08:00
John-David Dalton
ed8746df77 Rebuild update vendors, minified files, and adjust README.md changelog.
Former-commit-id: a01567b3d8e88da0cb20e12c864703e633b86fc6
2012-12-04 01:29:24 -08:00
John-David Dalton
bb187db49d Tweak _.throttle unit test and add _.bind test.
Former-commit-id: b863194c661d97177bbcda9676699e9753f0db22
2012-12-03 22:37:09 -08:00
John-David Dalton
081e72b3ea Fix typo in _.clone documentation. [closes #130]
Former-commit-id: 81e17c992848c5d0ac9d30fb64eef3163bac6598
2012-12-03 22:10:08 -08:00
John-David Dalton
6188c38053 Move bound inheritance hookup inside bound.
Former-commit-id: 7f95fffa14ef42f8f065aad124ac883740baac64
2012-12-03 22:07:45 -08:00
John-David Dalton
12b0186f5a Make _.isEqual work with arguments objects in older versions of Opera.
Former-commit-id: 860a27e7f81e14781eb371cadf24bb812eb31718
2012-12-03 01:54:46 -08:00
John-David Dalton
9bccc9c53c Ensured _.throttle nulls the timeoutId. [closes #129]
Former-commit-id: 24242f513e01adb2827cc3a5af6c8904098a9280
2012-12-03 01:04:54 -08:00
John-David Dalton
351b2b320e Bump to version 1.0.0-rc.1.
Former-commit-id: 8867f4ddfab62435d0c2c685d67e68555d146545
2012-12-02 22:09:56 -08:00
John-David Dalton
94258feb09 Make _#bind return non-wrapped values and cleanup a _.template unit test.
Former-commit-id: 351e4ae8b346a69a795c6d2bfe6a55b306515af6
2012-12-02 21:19:34 -08:00
John-David Dalton
8b0f033a78 Update vendor/underscore.
Former-commit-id: 8bb0b59d367ab2600a85a4442789eb41d9d97cb6
2012-12-02 21:18:46 -08:00
John-David Dalton
f58f255fc8 Make the custom build message work with -rc.1 and fix build.
Former-commit-id: 96f31fff906fa978a0d10fad90d9322c761e1d26
2012-12-02 02:21:55 -08:00
John-David Dalton
e3eabcf648 Fix isBindFast and isKeysFast.
Former-commit-id: 59e6cfa0669f28139a7036a172995d7f7f8a64ef
2012-12-02 00:01:29 -08:00
John-David Dalton
9aa506cbd7 Cleanup build.js.
Former-commit-id: 91bb957cef2efd3aefd3c196374841efbd3ffd1d
2012-12-01 23:32:26 -08:00
John-David Dalton
d8cff7b90f Remove script injection and simplify createFunction.
Former-commit-id: cc466c8ea05210b2238ee72a624628c7454eb1ee
2012-12-01 23:32:02 -08:00
John-David Dalton
07e7bca9eb Merge branch 'master' of github.com:bestiejs/lodash
Former-commit-id: a1f2773afba4c885385e601e656c6ee461a6fb24
2012-12-01 18:49:46 -08:00
John-David Dalton
e1f442be90 Ensure Lo-Dash works in the JS engine embedded in Adobe products.
Former-commit-id: 860665d3735aef1dff75149b49b78c1615f38fa0
2012-12-01 18:47:38 -08:00
John-David Dalton
c5d579e0e3 Update vendors, minified files, and docs.
Former-commit-id: b29e9f8a497153408ba6266bf44412004e63c1af
2012-12-01 17:16:50 -08:00
John-David Dalton
5271c2e08f Update vendors, minified files, and docs.
Former-commit-id: 018dfcade1386aa84492f60c8404ea00c01cbe11
2012-12-01 13:24:40 -08:00
John-David Dalton
9010a7ddbc Fix typo in _.toArray and tweak _.forEach documentation.
Former-commit-id: 6417e50be9381a4ecede54868a9c2c41dabca4f2
2012-12-01 13:23:15 -08:00
John-David Dalton
bb95fb7d07 Reduce _.pluck.
Former-commit-id: 91db56f95d258070a0d25e4e4b74917e52b8cefe
2012-12-01 10:47:00 -08:00
John-David Dalton
2edb11376d Avoid script injection unless the JS engine is inferred to be Firefox's.
Former-commit-id: 1e267374fe85a858197609b35b85670394c0b66d
2012-12-01 01:08:38 -08:00
John-David Dalton
e7f5ebf912 Rebuild minified files and docs.
Former-commit-id: 18a7f085459a08c6440be3e14d3f663fa181032d
2012-11-30 23:17:00 -08:00
John-David Dalton
da9758c2f3 Ensure bound result of _.bind(func, …) is an instance of bound and func.
Former-commit-id: d8176ad5eb45a3d675617676fc1eee4d9cbd6ebc
2012-11-30 23:16:39 -08:00
John-David Dalton
3e11d58d73 Ensure _.toArray returns a dence array.
Former-commit-id: 534091d4d200208b8aa831d86801d5e9d73410fe
2012-11-30 22:51:15 -08:00
John-David Dalton
6b35c097d6 Make deep _.clone copy array properties assigned by RegExp#exec.
Former-commit-id: b465457babfc04e8204048dfaeff6e5d37e5e43c
2012-11-30 00:40:32 -08:00
John-David Dalton
619ba13265 Make _.uniqueId consistently return a string value.
Former-commit-id: 5a5c626df83b0fc78e9bae37510680383f112c0b
2012-11-29 22:38:15 -08:00
John-David Dalton
529c5b8abf Use forIn in _.isEqual instead of forOwn.
Former-commit-id: dd057e421be029d67cd293b733ee1cfee2b7715f
2012-11-29 20:57:13 -08:00
John-David Dalton
3a5ed6e800 Ensure revised _.isEqual works correctly in Underscore build.
Former-commit-id: 24c01405f08f8925bfe473d5d7e9ad0a270382b6
2012-11-29 08:54:33 -08:00
John-David Dalton
52cddc015b Make _.clone follow the structured cloning algorithm's behavior for cloning objects created by constructors other than Object and make _.isEqual equate objects to arguments objects.
Former-commit-id: a387c6444694d8d550ab463ea5290088d3356d8b
2012-11-29 02:04:16 -08:00
John-David Dalton
4a01f4f65f Update vendor/underscore.js
Former-commit-id: d74b9331b5547cfde6c04bd1b915e983187b2ec0
2012-11-27 19:25:55 -08:00
John-David Dalton
f9768cb5a3 Use typeof x == 'undefined' checks instead of x === undefined for consistency with other typeof checks.
Former-commit-id: 8ab7d3efe54aa7017b52295b0598b75c297a6277
2012-11-26 09:24:51 -06:00
John-David Dalton
221e0e550c Optimize _.forEach, _.forIn, and _.forOwn.
Former-commit-id: 5d3b83ec0d5240ee14a86421994de86f311089fd
2012-11-24 23:21:30 -06:00
John-David Dalton
d2d1d42d0f Optimize _.isNumber and _.isString. [closes #126]
Former-commit-id: 633dfe2e9c2c0ff7e54d5bbb4bf95f9adcca83c4
2012-11-24 09:46:20 -06:00
John-David Dalton
faf018a097 Rebuild minified files and docs.
Former-commit-id: b3e87e12dfa55dcaa813d31b2ef0749a83b652aa
2012-11-24 01:49:56 -06:00
John-David Dalton
a2a71a107e Fix onerror typo.
Former-commit-id: 61ba70537963824f396496cc59e7cfac1e9f8c8a
2012-11-24 01:36:18 -06:00
John-David Dalton
fc9c937e67 Simplify iteratorTemplate and support for minifying double quoted strings in source.
Former-commit-id: d18cbd6dc380001fe3617f6891c84a794a13c8d1
2012-11-24 01:34:00 -06:00
John-David Dalton
b4f2e9b442 Fix build.
Former-commit-id: dba1a3fa7526001d0062dc6e0b44f3c6e3d3d8db
2012-11-23 13:26:12 -06:00
John-David Dalton
1672645e73 Avoid engine slow path for primitives in _(…). [closes #123]
Former-commit-id: 32e33b0c0d192915e6d5a83001b85645829ca0ab
2012-11-23 10:19:10 -06:00
John-David Dalton
4a42c44101 Use createFunction in _.template.
Former-commit-id: c996d94c7002bf4a89092b9cf7f4e5e80f70d9fd
2012-11-23 10:05:15 -06:00
John-David Dalton
383b1a5769 Avoid Firefox's unoptimized Function constructor.
Former-commit-id: 7cc5fc63c0cebd1410edde47c88e580c64fa2b98
2012-11-23 01:14:44 -06:00
John-David Dalton
77bac4cf9e Narrow the scope of regexes used in build.js to the functions they relate to.
Former-commit-id: 6d838b24778d5e2107f4f5b25613ae40f363e969
2012-11-20 16:20:06 -06:00
John-David Dalton
e2b8e530c9 Merge pull request #119 from bestiejs/no-chain
Make `_(...)` wrapped values chainable without the need to call `chain`

Former-commit-id: 2e133540c0bedb41440bab592f1bacb75d426687
2012-11-20 07:52:11 -08:00
John-David Dalton
e9f752bd67 Merge /master into /no-chain
Former-commit-id: 59e5a4b13eb8bddd39bd37d917344715d62bf385
2012-11-20 07:47:48 -08:00
John-David Dalton
4b31921eb4 Rebuild minified files and docs.
Former-commit-id: 9565bb8c27577b72cf42d79cc7a1569a496d8bdc
2012-11-20 07:44:25 -08:00
John-David Dalton
3df9fc6225 Ensure _.reduce and _.reduceRight pass the correct number of callback arguments.
Former-commit-id: fec2d28b5a69ceb590e0ef1d8a0792b25b53c7e9
2012-11-20 07:43:09 -08:00
John-David Dalton
b57fe466ce Make _(…) wrapper versions of _.first and _.last capable of returning wrapped and unwrapped values.
Former-commit-id: b30704c1ce359213aa09069b290ee55edfb3e33e
2012-11-20 07:32:51 -08:00
John-David Dalton
bd4bff3b6b Add lodash.prototype methods that return non-wrapped values.
Former-commit-id: b7ecb8c91ec9647827a80a297b966639c6580ef0
2012-11-19 23:02:35 -08:00
John-David Dalton
9d4618a223 Merge /master into /no-chain
Former-commit-id: fcef4ca54be1907762e92ee528b650bea9759c1d
2012-11-19 21:52:25 -08:00
John-David Dalton
93636180df Fallback to the local npm install if there are problems resolving the npm -g root path. [closes #122]
Former-commit-id: 1cbf807877e51198853950e5ebd1b49a6e20d123
2012-11-19 21:42:54 -08:00
John-David Dalton
fcceaa168f Update v0.10.0 changelog in README.md.
Former-commit-id: daf4501ee97420d93bb02d7c1dfd5498d6618bb9
2012-11-19 21:12:57 -08:00
John-David Dalton
2639cc6138 Update vendors.
Former-commit-id: e109c9ffd436610d066493b07bd38293e1ec01a7
2012-11-19 20:54:23 -08:00
John-David Dalton
4a99c2e928 Add support for NodeLists in _.toArray for IE < 9.
Former-commit-id: 67b26fe6fe60d77c0b38c48865bfd2ca56f7b470
2012-11-19 20:47:16 -08:00
John-David Dalton
7d5af3df05 Remove deprecated indicators from _.isFinite, _.isNaN, _.isNull, _.isUndefined, and _.result docs. [ci skip]
Former-commit-id: 39a6e1a4a948469993afb90c6303f1f6faa661fd
2012-11-18 22:37:47 -08:00
John-David Dalton
c88b80d2a0 Add documentation note to _#chain. [ci skip]
Former-commit-id: 90b50a50b6b104cd9e2bbccc4412346dfd6a6bba
2012-11-18 22:35:23 -08:00
John-David Dalton
819d4abaa2 Add _#toString and _#valueOf.
Former-commit-id: adb194b6270fc72f794c69343891a2e891b90051
2012-11-18 21:50:41 -08:00
John-David Dalton
20630aeb47 Remove the need to call chain on _(…) wrapped values.
Former-commit-id: 21861c88e3ec9af955d844c025b50cb32c322809
2012-11-18 21:06:24 -08:00
John-David Dalton
0c0db3babb Remove deprecated indicators from _.isFinite, _.isNaN, _.isNull, _.isUndefined, and _.result docs. [ci skip]
Former-commit-id: 597001cfe5ef71d40b3254344eb5dbbe9905430a
2012-11-18 15:41:07 -08:00
John-David Dalton
e7761f7e57 Minor cleanup to README.md.
Former-commit-id: a4ded5a5b2f41016fad5e4c7491dd96704e9d69a
2012-11-18 14:38:04 -08:00
John-David Dalton
064fd497ae Bump version to v0.10.0 in package.json.
Former-commit-id: 0be4f584b19bc6d53bd6bce61e8ac3cc249f2003
2012-11-18 13:39:43 -08:00
John-David Dalton
49c60b6b75 Add link to ES6 draft spec for Object.assign and add more notes to the v0.10.0 changelog to README.md.
Former-commit-id: c0f5d00e506f6b4a03d0844e7cc8379d462f9fff
2012-11-18 13:31:50 -08:00
John-David Dalton
ca7f36506c Update vendors.
Former-commit-id: cdd10877e964b62eb73747fbaec5f7eda6ace599
2012-11-18 00:00:51 -08:00
John-David Dalton
155f0a9736 Bump to v0.10.0.
Former-commit-id: fd251fd13dfda3120569d3d284aa55ded0b806af
2012-11-17 23:48:57 -08:00
John-David Dalton
25e1eb3ce9 Rename _.lateBind to _.bindKey. [closes #114]
Former-commit-id: 971e56cb86b5298ba2a9f92365f0463665d27230
2012-11-17 00:06:55 -08:00
John-David Dalton
f2f980928b Update vendors to replace CRLF with LF.
Former-commit-id: 65f8982b6cfe965808ef97acba49c4d1cef6cd18
2012-11-16 22:09:41 -08:00
John-David Dalton
1d121a97a7 Convert resolve real paths of npm -g root. [closes #116]
Former-commit-id: 0379fdf33da465fbb9ac78ddaa9e820b9b3e9987
2012-11-16 21:59:36 -08:00
John-David Dalton
211d13da09 Cleanup build/post-install.js.
Former-commit-id: efb35fab14fa62b79caec2ba806173415b217207
2012-11-16 21:06:48 -08:00
John-David Dalton
11343d469e Merge branch 'master' of github.com:bestiejs/lodash
Former-commit-id: 08347b0f4b7c5853e28557d482424b63028505b6
2012-11-15 23:58:35 -08:00
John-David Dalton
d7c8041aa1 Update Backbone build method dependencies.
Former-commit-id: 808b991f6cebc72c182ce8d0def370778cce0b05
2012-11-15 23:51:49 -08:00
Kit Cambridge
9587e30af8 post-install: Show instructions for manually downloading the minifiers. [#113]
Former-commit-id: d9b794bc51057216f922f43c5bb6d8c9dc38f570
2012-11-15 22:21:34 -08:00
John-David Dalton
76fa7affaf Add @cascadiajs video link to README.md. [ci skip]
Former-commit-id: 72fbf780e0727ce751090b09cf783e5a88752614
2012-11-14 23:55:52 -08:00
John-David Dalton
2971dd8672 Cleanup npm note in README.md.
Former-commit-id: d1cd290edb316116c69cf9b7b79a10498fd6df3c
2012-11-14 22:13:22 -08:00
John-David Dalton
2a33fe3564 Add .gitattributes.
Former-commit-id: 4a4ecefda83fb408200dfb106ea5b0a837af43c0
2012-11-14 21:59:18 -08:00
Kit Cambridge
46cdf5da70 Encourage users to update to the latest npm version.
Former-commit-id: bbcab6e7338039fb3343cfaca09c17ae0ea293a1
2012-11-14 20:03:40 -08:00
John-David Dalton
28c801bfd4 Add more info about the csp build to README.md. [skip ci]
Former-commit-id: ceb0cb3588bff9cadd791b091390799b506874ca
2012-11-14 08:17:43 -08:00
John-David Dalton
c22cd40293 Move Underscore build _.template replacement within build.js.
Former-commit-id: 3c2971a67986e69a9ea0952056e2cdf95f73435f
2012-11-14 00:31:48 -08:00
John-David Dalton
56bd430983 Cleanup and comment _.merge's _.reduce support.
Former-commit-id: 2cfc41f1c00a7a3981c51be7e8005f0cc95ac692
2012-11-12 07:41:31 -08:00
John-David Dalton
d873890e46 Remove alternative _.where for Underscore build.
Former-commit-id: 4e42a26d4c16157957fa43dbb31ae9706e2641b8
2012-11-12 07:35:33 -08:00
John-David Dalton
d29b8eca3c Ensure _.merge works with _.reduce.
Former-commit-id: de53bfd024c7a088c98ee94c95d0c57fb00ed032
2012-11-12 07:35:05 -08:00
John-David Dalton
6f258000fe Add the build commands used to the custom build's copyright/license header. [via @phated]
Former-commit-id: 2e1ff0c6a83e3c4c404ad4bac968f12d34afaa6e
2012-11-11 21:42:52 -08:00
John-David Dalton
255211cd07 Update vendor/underscore.
Former-commit-id: 3e8a169e8cb81fd852e41420ad317ee12ae486f9
2012-11-11 20:00:48 -08:00
John-David Dalton
f6d28a90e3 Make _.where iterate over only own properties.
Former-commit-id: 29b4cafe5271cad70c711c2d401cea627fa97e33
2012-11-11 20:00:20 -08:00
John-David Dalton
ed66ff88a1 Update minified and doc builds.
Former-commit-id: 5d6d8ee0538a2502eef6c38d77e58d31e8026e53
2012-11-11 16:20:16 -08:00
John-David Dalton
82e58f2bf9 Make _.defaults follow _.assign and only assign own properties of source.
Former-commit-id: 114dc47bbfa6db6a53a2fa03dd477fe86c3395cb
2012-11-11 16:16:11 -08:00
John-David Dalton
797a87ca26 Make _.extend and alias of _.assign and make _.assign iterate only own enumerable source props to align with ES6.
Former-commit-id: 37ba7c3066c1ea70210346a9bf598e8587e907db
2012-11-11 15:52:43 -08:00
John-David Dalton
ec6a709393 Add ES6 _.assign alias of _.extend.
Former-commit-id: 20a0e0d295cb90a1756a5831b0b6684b97477170
2012-11-11 14:03:10 -08:00
John-David Dalton
07cbfdb424 Optimize _.contains.
Former-commit-id: b50628adedd21fe2c099f4dcab1aa9f0036a22ed
2012-11-10 23:09:23 -08:00
John-David Dalton
3b9bd944fb Ensure _.find works correctly in the Underscore build.
Former-commit-id: c22b91ffcab34b75415f126582c48c168a7cc759
2012-11-10 22:42:13 -08:00
John-David Dalton
934e585cb3 Optimize _.filter.
Former-commit-id: 565c1b0159207e9d9413d82b5827ed685564efff
2012-11-10 21:15:25 -08:00
John-David Dalton
3a68f4cf54 Cleanup build/post-install.js.
Former-commit-id: 5e289381b90e764b38bf5a3ba1866b6658766f52
2012-11-10 21:09:50 -08:00
Kit Cambridge
bd00fcb875 Improve zlib error handling. [#109]
Former-commit-id: f6d7dd9afb630125d55188401da037ed97d6e5c5
2012-11-09 14:24:57 -08:00
John-David Dalton
905dd5a70f Add template precompiler unit test for ES6 delimiters.
Former-commit-id: dc4561afa74844294bf38ecff7dadd43c0b0b99f
2012-11-09 11:13:46 -08:00
79 changed files with 39242 additions and 20458 deletions

1
.gitattributes vendored Normal file
View File

@@ -0,0 +1 @@
* text=auto

View File

@@ -1,6 +1,7 @@
.* .*
*.custom.* *.custom.*
*.d.ts *.d.ts
CONTRIBUTING.md
doc/*.php doc/*.php
node_modules/ node_modules/
perf/*.html perf/*.html
@@ -12,14 +13,15 @@ test/*.sh
vendor/*.gz vendor/*.gz
vendor/backbone/ vendor/backbone/
vendor/benchmark.js/*.jar vendor/benchmark.js/*.jar
vendor/closure-compiler vendor/closure-compiler/
vendor/docdown vendor/docdown/
vendor/firebug-lite/ vendor/firebug-lite/
vendor/json3/ vendor/json3/
vendor/jquery/ vendor/jquery/
vendor/platform.js/
vendor/qunit/qunit/*.css vendor/qunit/qunit/*.css
vendor/qunit/qunit/*-1.8.0.js vendor/qunit/qunit/*-1.8.0.js
vendor/requirejs/ vendor/requirejs/
vendor/underscore/*-min.js vendor/underscore/*-min.js
vendor/uglifyjs vendor/uglifyjs/
vendor/underscore/test/ vendor/underscore/test/

View File

@@ -1,7 +1,20 @@
language: node_js language: node_js
node_js: node_js:
- 0.6 - 0.6
- 0.8 - 0.9
env:
- TEST_COMMAND="phantomjs ./test/test.js ../dist/lodash.compat.js"
- TEST_COMMAND="phantomjs ./test/test.js ../dist/lodash.compat.min.js"
- TEST_COMMAND="node ./test/test.js ../dist/lodash.js"
- TEST_COMMAND="node ./test/test.js ../dist/lodash.min.js"
- TEST_COMMAND="node ./test/test-build.js --time-limit 49m40s"
git:
depth: 1
branches:
only:
- master
before_script: before_script:
- "curl -H 'Accept: application/vnd.github.v3.raw' https://api.github.com/repos/bestiejs/lodash/git/blobs/aa29a2ecf6f51d4da5a2a418c0d4ea0e368ee80d | tar xvz -C vendor" - "tar -xzvf vendor/closure-compiler.tar.gz -C vendor"
- "curl -H 'Accept: application/vnd.github.v3.raw' https://api.github.com/repos/bestiejs/lodash/git/blobs/9869c4443fb22598235d1019fcc8245be41e8889 | tar xvz -C vendor" - "tar -xzvf vendor/uglifyjs.tar.gz -C vendor"
script:
$TEST_COMMAND

35
CONTRIBUTING.md Normal file
View File

@@ -0,0 +1,35 @@
# Contributing to Lo-Dash
If youd like to contribute a feature or bug fix, you can [fork](https://help.github.com/articles/fork-a-repo) Lo-Dash, commit your changes, and [send a pull request](https://help.github.com/articles/using-pull-requests).
Please make sure to [search the issue tracker](https://github.com/bestiejs/lodash/issues) first; your issue may have already been discussed or fixed in `master`.
## Tests
Include updated unit tests in the `test` directory as part of your pull request.
You can run the tests from the command line via `npm test`, or open `test/index.html` in a web browser.
The `test/run-test.sh` script attempts to run the tests in [Rhino](https://developer.mozilla.org/en-US/docs/Rhino), [Narwhal](https://github.com/280north/narwhal), [RingoJS](http://ringojs.org/), [PhantomJS](http://phantomjs.org/), and [Node](http://nodejs.org/), before running them in your default browser.
The [Backbone](http://backbonejs.org/) and [Underscore](http://http://underscorejs.org/) test suites are included as well.
## Contributor License Agreement
Lo-Dash is a member of the [Dojo Foundation](http://dojofoundation.org/).
As such, we request that all contributors sign the Dojo Foundation [contributor license agreement](http://dojofoundation.org/about/claForm).
For more information about CLAs, please check out Alex Russells excellent post, ["Why Do I Need to Sign This?"](http://infrequently.org/2008/06/why-do-i-need-to-sign-this/).
## Coding Guidelines
In addition to the following guidelines, please follow the conventions already established in the code.
- **Spacing**:<br>
Use two spaces for indentation. No tabs.
- **Naming**:<br>
Keep variable and method names concise and descriptive.<br>
Variable names `index`, `collection`, and `callback` are preferable to `i`, `arr`, and `fn`.
- **Quotes**:<br>
Single-quoted strings are preferred to double-quoted strings; however, please use a double-quoted string if the value contains a single-quote character to avoid unnecessary escaping.
- **Comments**:<br>
Please use single-line comments to annotate significant additions, and [JSDoc-style](http://www.2ality.com/2011/08/jsdoc-intro.html) comments for new methods.

View File

@@ -1,6 +1,6 @@
Copyright 2012 John-David Dalton <http://allyoucanleet.com/> Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
Based on Underscore.js 1.3.3, copyright 2009-2012 Jeremy Ashkenas, Based on Underscore.js 1.4.3, copyright 2009-2013 Jeremy Ashkenas,
DocumentCloud Inc. <http://documentcloud.github.com/underscore> DocumentCloud Inc. <http://underscorejs.org/>
Permission is hereby granted, free of charge, to any person obtaining Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the a copy of this software and associated documentation files (the

165
README.md
View File

@@ -1,56 +1,84 @@
# Lo-Dash <sup>v0.9.2</sup> # Lo-Dash <sup>v1.1.1</sup>
[![build status](https://secure.travis-ci.org/bestiejs/lodash.png)](http://travis-ci.org/bestiejs/lodash) [![build status](https://secure.travis-ci.org/bestiejs/lodash.png)](http://travis-ci.org/bestiejs/lodash)
A drop-in replacement<sup>[*](https://github.com/bestiejs/lodash/wiki/Drop-in-Disclaimer)</sup> for Underscore.js, from the devs behind [jsPerf.com](http://jsperf.com), delivering [performance](http://lodash.com/benchmarks), [bug fixes](https://github.com/bestiejs/lodash#resolved-underscorejs-issues), and [additional features](http://lodash.com/#features). A low-level utility library delivering consistency, [customization](https://github.com/bestiejs/lodash#custom-builds), [performance](http://lodash.com/benchmarks), and [extra features](https://github.com/bestiejs/lodash#features).
Lo-Dashs performance is gained by avoiding slower native methods, instead opting for simplified non-ES5 compliant methods optimized for common usage, and by leveraging function compilation to reduce the number of overall function calls.
## Download ## Download
* [Development build](https://raw.github.com/bestiejs/lodash/v0.9.2/lodash.js) * Lo-Dash builds (for modern environments):<br>
* [Production build](https://raw.github.com/bestiejs/lodash/v0.9.2/lodash.min.js) [Development](https://raw.github.com/bestiejs/lodash/v1.1.1/dist/lodash.js) and
* [Underscore build](https://raw.github.com/bestiejs/lodash/v0.9.2/lodash.underscore.min.js) tailored for projects already using Underscore [Production](https://raw.github.com/bestiejs/lodash/v1.1.1/dist/lodash.min.js)
* CDN copies of ≤ v0.9.2s [Production](http://cdnjs.cloudflare.com/ajax/libs/lodash.js/0.9.2/lodash.min.js), [Underscore](http://cdnjs.cloudflare.com/ajax/libs/lodash.js/0.9.2/lodash.underscore.min.js), and [Development](http://cdnjs.cloudflare.com/ajax/libs/lodash.js/0.9.2/lodash.js) builds are available on [cdnjs](http://cdnjs.com/) thanks to [CloudFlare](http://www.cloudflare.com/)
* For optimal file size, [create a custom build](https://github.com/bestiejs/lodash#custom-builds) with only the features you need * Lo-Dash compatibility builds (for legacy and modern environments):<br>
[Development](https://raw.github.com/bestiejs/lodash/v1.1.1/dist/lodash.compat.js) and
[Production](https://raw.github.com/bestiejs/lodash/v1.1.1/dist/lodash.compat.min.js)
* Underscore compatibility builds:<br>
[Development](https://raw.github.com/bestiejs/lodash/v1.1.1/dist/lodash.underscore.js) and
[Production](https://raw.github.com/bestiejs/lodash/v1.1.1/dist/lodash.underscore.min.js)
* CDN copies of ≤ v1.1.1s builds are available on [cdnjs](http://cdnjs.com/) thanks to [CloudFlare](http://www.cloudflare.com/):<br>
[Lo-Dash dev](http://cdnjs.cloudflare.com/ajax/libs/lodash.js/1.1.1/lodash.js),
[Lo-Dash prod](http://cdnjs.cloudflare.com/ajax/libs/lodash.js/1.1.1/lodash.min.js),<br>
[Lo-Dash compat-dev](http://cdnjs.cloudflare.com/ajax/libs/lodash.js/1.1.1/lodash.compat.js),
[Lo-Dash compat-prod](http://cdnjs.cloudflare.com/ajax/libs/lodash.js/1.1.1/lodash.compat.min.js),<br>
[Underscore compat-dev](http://cdnjs.cloudflare.com/ajax/libs/lodash.js/1.1.1/lodash.underscore.js), and
[Underscore compat-prod](http://cdnjs.cloudflare.com/ajax/libs/lodash.js/1.1.1/lodash.underscore.min.js)
* For optimal file size, [create a custom build](https://github.com/bestiejs/lodash#custom-builds) with only the features you need
## Dive in ## Dive in
Weve got [API docs](http://lodash.com/docs), [benchmarks](http://lodash.com/benchmarks), and [unit tests](http://lodash.com/tests). Weve got [API docs](http://lodash.com/docs), [benchmarks](http://lodash.com/benchmarks), and [unit tests](http://lodash.com/tests).
Create your own benchmarks at [jsPerf](http://jsperf.com), or [search](http://jsperf.com/search?q=lodash) for existing ones.
For a list of upcoming features, check out our [roadmap](https://github.com/bestiejs/lodash/wiki/Roadmap). For a list of upcoming features, check out our [roadmap](https://github.com/bestiejs/lodash/wiki/Roadmap).
## Screencasts ## Resources
For more information check out these screencasts over Lo-Dash: For more information check out these articles, screencasts, and other videos over Lo-Dash:
* [Introducing Lo-Dash](https://vimeo.com/44154599) * Posts
* [Lo-Dash optimizations and custom builds](https://vimeo.com/44154601) - [Say “Hello” to Lo-Dash](http://kitcambridge.be/blog/say-hello-to-lo-dash/)
* [Lo-Dashs origin and why its a better utility belt](https://vimeo.com/44154600)
* [Unit testing in Lo-Dash](https://vimeo.com/45865290) * Videos
* [Lo-Dashs approach to native method use](https://vimeo.com/48576012) - [Introducing Lo-Dash](https://vimeo.com/44154599)
- [Lo-Dash optimizations and custom builds](https://vimeo.com/44154601)
- [Lo-Dashs origin and why its a better utility belt](https://vimeo.com/44154600)
- [Unit testing in Lo-Dash](https://vimeo.com/45865290)
- [Lo-Dashs approach to native method use](https://vimeo.com/48576012)
- [CascadiaJS: Lo-Dash for a better utility belt](http://www.youtube.com/watch?v=dpPy4f_SeEk)
## Features ## Features
* AMD loader support ([RequireJS](http://requirejs.org/), [curl.js](https://github.com/cujojs/curl), etc.) * AMD loader support ([RequireJS](http://requirejs.org/), [curl.js](https://github.com/cujojs/curl), etc.)
* [_.clone](http://lodash.com/docs#clone) supports *“deep”* cloning * [_(…)](http://lodash.com/docs#_) supports intuitive chaining
* [_.at](http://lodash.com/docs#at) for cherry-picking collection values
* [_.bindKey](http://lodash.com/docs#bindKey) for binding [*“lazy”* defined](http://michaux.ca/articles/lazy-function-definition-pattern) methods
* [_.cloneDeep](http://lodash.com/docs#cloneDeep) for deep cloning arrays and objects
* [_.contains](http://lodash.com/docs#contains) accepts a `fromIndex` argument * [_.contains](http://lodash.com/docs#contains) accepts a `fromIndex` argument
* [_.createCallback](http://lodash.com/docs#createCallback) to customize how callback arguments are handled and support callback shorthands in mixins
* [_.findIndex](http://lodash.com/docs#findIndex) and [_.findKey](http://lodash.com/docs#findKey) for finding indexes and keys of collections
* [_.forEach](http://lodash.com/docs#forEach) is chainable and supports exiting iteration early * [_.forEach](http://lodash.com/docs#forEach) is chainable and supports exiting iteration early
* [_.forIn](http://lodash.com/docs#forIn) for iterating over an objects own and inherited properties * [_.forIn](http://lodash.com/docs#forIn) for iterating over an objects own and inherited properties
* [_.forOwn](http://lodash.com/docs#forOwn) for iterating over an objects own properties * [_.forOwn](http://lodash.com/docs#forOwn) for iterating over an objects own properties
* [_.isPlainObject](http://lodash.com/docs#isPlainObject) checks if values are created by the `Object` constructor * [_.isPlainObject](http://lodash.com/docs#isPlainObject) checks if values are created by the `Object` constructor
* [_.lateBind](http://lodash.com/docs#lateBind) for late binding * [_.merge](http://lodash.com/docs#merge) for a deep [_.extend](http://lodash.com/docs#extend)
* [_.merge](http://lodash.com/docs#merge) for a *“deep”* [_.extend](http://lodash.com/docs#extend) * [_.parseInt](http://lodash.com/docs#parseInt) for consistent cross-environment behavior
* [_.partial](http://lodash.com/docs#partial) for partial application without `this` binding * [_.partial](http://lodash.com/docs#partial) and [_.partialRight](http://lodash.com/docs#partialRight) for partial application without `this` binding
* [_.pick](http://lodash.com/docs#pick) and [_.omit](http://lodash.com/docs#omit) accepts `callback` and `thisArg` arguments * [_.runInContext](http://lodash.com/docs#runInContext) for easier mocking and extended environment support
* [_.template](http://lodash.com/docs#template) supports [ES6 delimiters](http://people.mozilla.org/~jorendorff/es6-draft.html#sec-7.8.6) and utilizes [sourceURLs](http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl) for easier debugging * [_.support](http://lodash.com/docs#support) to flag environment features
* [_.template](http://lodash.com/docs#template) supports [*“imports”* options](http://lodash.com/docs#templateSettings_imports), [ES6 template delimiters](http://people.mozilla.org/~jorendorff/es6-draft.html#sec-7.8.6), and [sourceURLs](http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl)
* [_.where](http://lodash.com/docs#where) supports deep object comparisons
* [_.clone](http://lodash.com/docs#clone), [_.omit](http://lodash.com/docs#omit), [_.pick](http://lodash.com/docs#pick),
[and more…](http://lodash.com/docs "_.assign, _.cloneDeep, _.first, _.initial, _.isEqual, _.last, _.merge, _.rest") accept `callback` and `thisArg` arguments
* [_.contains](http://lodash.com/docs#contains), [_.size](http://lodash.com/docs#size), [_.toArray](http://lodash.com/docs#toArray), * [_.contains](http://lodash.com/docs#contains), [_.size](http://lodash.com/docs#size), [_.toArray](http://lodash.com/docs#toArray),
[and more…](http://lodash.com/docs "_.countBy, _.every, _.filter, _.find, _.forEach, _.groupBy, _.invoke, _.map, _.max, _.min, _.pluck, _.reduce, _.reduceRight, _.reject, _.shuffle, _.some, _.sortBy, _.where") accept strings [and more…](http://lodash.com/docs "_.at, _.countBy, _.every, _.filter, _.find, _.forEach, _.groupBy, _.invoke, _.map, _.max, _.min, _.pluck, _.reduce, _.reduceRight, _.reject, _.shuffle, _.some, _.sortBy, _.where") accept strings
* [_.filter](http://lodash.com/docs#filter), [_.find](http://lodash.com/docs#find), [_.map](http://lodash.com/docs#map),
[and more…](http://lodash.com/docs "_.countBy, _.every, _.first, _.groupBy, _.initial, _.last, _.max, _.min, _.reject, _.rest, _.some, _.sortBy, _.sortedIndex, _.uniq") support *“_.pluck”* and *“_.where”* `callback` shorthands
## Support ## Support
Lo-Dash has been tested in at least Chrome 5~23, Firefox 1~16, IE 6-10, Opera 9.25-12, Safari 3-6, Node.js 0.4.8-0.8.14, Narwhal 0.3.2, RingoJS 0.8, and Rhino 1.7RC5. Lo-Dash has been tested in at least Chrome 5~25, Firefox 2~19, IE 6-10, Opera 9.25-12, Safari 3-6, Node.js 0.4.8-0.10.1, Narwhal 0.3.2, PhantomJS 1.8.1, RingoJS 0.9, and Rhino 1.7RC5.
## Custom builds ## Custom builds
@@ -62,17 +90,23 @@ To top it off, we handle all method dependency and alias mapping for you.
lodash backbone lodash backbone
``` ```
* CSP builds, supporting default Content Security Policy restrictions, may be created using the `csp` modifier argument. * CSP builds, supporting default [Content Security Policy](https://dvcs.w3.org/hg/content-security-policy/raw-file/tip/csp-specification.dev.html) restrictions, may be created using the `csp` modifier argument.
The `csp` modifier is an alias of the `mobile` modifier. Lo-Dash may be used in Chrome extensions by using either the `csp`, `mobile`, or `underscore` build and using precompiled templates, or loading Lo-Dash in a [sandbox](http://developer.chrome.com/stable/extensions/sandboxingEval.html).
```bash ```bash
lodash csp lodash csp
``` ```
* Legacy builds, tailored for older browsers without [ES5 support](http://es5.github.com/), may be created using the `legacy` modifier argument. * Legacy builds, tailored for older environments without [ES5 support](http://es5.github.com/), may be created using the `legacy` modifier argument.
```bash ```bash
lodash legacy lodash legacy
``` ```
* Mobile builds, with IE < 9 bug fixes and method compilation removed, may be created using the `mobile` modifier argument. * Modern builds, tailored for newer environments with ES5 support, may be created using the `modern` modifier argument.
```bash
lodash modern
```
* Mobile builds, without method compilation and most bug fixes for old browsers, may be created using the `mobile` modifier argument.
```bash ```bash
lodash mobile lodash mobile
``` ```
@@ -133,7 +167,7 @@ lodash template="./*.jst"
* Use the `settings` argument to pass the template settings used when precompiling templates. * Use the `settings` argument to pass the template settings used when precompiling templates.
```bash ```bash
lodash settings="{interpolate:/\\{\\{([\\s\\S]+?)\\}\\}/g}" lodash settings="{interpolate:/\{\{([\s\S]+?)\}\}/g}"
``` ```
* Use the `moduleId` argument to specify the AMD module ID of Lo-Dash, which defaults to “lodash”, used by precompiled templates. * Use the `moduleId` argument to specify the AMD module ID of Lo-Dash, which defaults to “lodash”, used by precompiled templates.
@@ -141,18 +175,19 @@ lodash settings="{interpolate:/\\{\\{([\\s\\S]+?)\\}\\}/g}"
lodash moduleId="underscore" lodash moduleId="underscore"
``` ```
All arguments, except `legacy` with `csp` or `mobile`, may be combined.<br> All arguments, except `legacy` with `csp`, `mobile`, `modern`, or `underscore`, may be combined.<br>
Unless specified by `-o` or `--output`, all files created are saved to the current working directory. Unless specified by `-o` or `--output`, all files created are saved to the current working directory.
The following options are also supported: The following options are also supported:
* `-c`, `--stdout`&nbsp;&nbsp;&nbsp;&nbsp; Write output to standard output * `-c`, `--stdout` ......... Write output to standard output
* `-d`, `--debug`&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Write only the debug output * `-d`, `--debug` ........... Write only the non-minified development output
* `-h`, `--help`&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Display help information * `-h`, `--help` ............. Display help information
* `-m`, `--minify`&nbsp;&nbsp;&nbsp;&nbsp; Write only the minified output * `-m`, `--minify` ......... Write only the minified production output
* `-o`, `--output`&nbsp;&nbsp;&nbsp;&nbsp; Write output to a given path/filename * `-o`, `--output` ......... Write output to a given path/filename
* `-s`, `--silent`&nbsp;&nbsp;&nbsp;&nbsp; Skip status updates normally logged to the console * `-p`, `--source-map` .. Generate a source map for the minified output, using an optional source map URL
* `-V`, `--version`&nbsp;&nbsp; Output current version of Lo-Dash * `-s`, `--silent` ......... Skip status updates normally logged to the console
* `-V`, `--version` ....... Output current version of Lo-Dash
The `lodash` command-line utility is available when Lo-Dash is installed as a global package (i.e. `npm install -g lodash`). The `lodash` command-line utility is available when Lo-Dash is installed as a global package (i.e. `npm install -g lodash`).
@@ -164,7 +199,7 @@ In browsers:
<script src="lodash.js"></script> <script src="lodash.js"></script>
``` ```
Using [npm](http://npmjs.org/): Using [`npm`](http://npmjs.org/):
```bash ```bash
npm install lodash npm install lodash
@@ -173,15 +208,24 @@ npm install -g lodash
npm link lodash npm link lodash
``` ```
In [Node.js](http://nodejs.org/) and [RingoJS v0.8.0+](http://ringojs.org/): To avoid potential issues, update `npm` before installing Lo-Dash:
```bash
npm install npm -g
```
In [Node.js](http://nodejs.org/) and [RingoJS ≥ v0.8.0](http://ringojs.org/):
```js ```js
var _ = require('lodash'); var _ = require('lodash');
// or as a drop-in replacement for Underscore
var _ = require('lodash/dist/lodash.underscore');
``` ```
**Note:** If Lo-Dash is installed globally, [run `npm link lodash`](http://blog.nodejs.org/2011/03/23/npm-1-0-global-vs-local-installation/) in your projects root directory before requiring it. **Note:** If Lo-Dash is installed globally, run [`npm link lodash`](http://blog.nodejs.org/2011/03/23/npm-1-0-global-vs-local-installation/) in your projects root directory before requiring it.
In [RingoJS v0.7.0-](http://ringojs.org/): In [RingoJS v0.7.0](http://ringojs.org/):
```js ```js
var _ = require('lodash')._; var _ = require('lodash')._;
@@ -206,33 +250,32 @@ require({
}); });
``` ```
## Resolved Underscore.js issues
* Allow iteration of objects with a `length` property [[#799](https://github.com/documentcloud/underscore/pull/799), [test](https://github.com/bestiejs/lodash/blob/v0.9.2/test/test.js#L545-551)]
* Fix cross-browser object iteration bugs [[#60](https://github.com/documentcloud/underscore/issues/60), [#376](https://github.com/documentcloud/underscore/issues/376), [test](https://github.com/bestiejs/lodash/blob/v0.9.2/test/test.js#L558-582)]
* Methods should work on pages with incorrectly shimmed native methods [[#7](https://github.com/documentcloud/underscore/issues/7), [#742](https://github.com/documentcloud/underscore/issues/742), [test](https://github.com/bestiejs/lodash/blob/v0.9.2/test/test.js#L140-146)]
* `_.isEmpty` should support jQuery/MooTools DOM query collections [[#690](https://github.com/documentcloud/underscore/pull/690), [test](https://github.com/bestiejs/lodash/blob/v0.9.2/test/test.js#L747-752)]
* `_.isObject` should avoid V8 bug [#2291](http://code.google.com/p/v8/issues/detail?id=2291) [[#605](https://github.com/documentcloud/underscore/issues/605), [test](https://github.com/bestiejs/lodash/blob/v0.9.2/test/test.js#L828-840)]
* `_.keys` should work with `arguments` objects cross-browser [[#396](https://github.com/documentcloud/underscore/issues/396), [test](https://github.com/bestiejs/lodash/blob/v0.9.2/test/test.js#L921-923)]
* `_.range` should coerce arguments to numbers [[#634](https://github.com/documentcloud/underscore/issues/634), [#683](https://github.com/documentcloud/underscore/issues/683), [test](https://github.com/bestiejs/lodash/blob/v0.9.2/test/test.js#L1337-1340)]
## Release Notes ## Release Notes
### <sup>v0.9.2</sup> ### <sup>v1.1.1</sup>
* Added `fromIndex` argument to `_.contains` * Ensured the `underscore` build version of `_.forEach` accepts a `thisArg` argument
* Added `moduleId` build option * Updated vendor/tar to work with Node v0.10.x
* Added Closure Compiler *“simple”* optimizations to the build process
* Added support for strings in `_.max` and `_.min` ### <sup>v1.1.0</sup>
* Added support for ES6 template delimiters to `_.template`
* Ensured re-minification of Lo-Dash by third parties avoids Closure Compiler bugs * Added `rhino -require` support
* Optimized `_.every`, `_.find`, `_.some`, and `_.uniq` * Added `_.createCallback`, `_findIndex`, `_.findKey`, `_.parseInt`, `_.runInContext`, and `_.support`
* Added support for `callback` and `thisArg` arguments to `_.flatten`
* Added CommonJS/Node support to precompiled templates
* Ensured the `exports` object is not a DOM element
* Ensured `_.isPlainObject` returns `false` for objects without a `[[Class]]` of “Object”
* Made `_.cloneDeep`s `callback` support more closely follow its documentation
* Made the template precompiler create nonexistent directories of `--output` paths
* Made `_.object` an alias of `_.zipObject`
* Optimized method chaining, object iteration, `_.find`, and `_.pluck` (an average of 18% overall better performance)
* Updated `backbone` build Lo-Dash method dependencies
The full changelog is available [here](https://github.com/bestiejs/lodash/wiki/Changelog). The full changelog is available [here](https://github.com/bestiejs/lodash/wiki/Changelog).
## BestieJS ## BestieJS
Lo-Dash is part of the BestieJS *“Best in Class”* module collection. This means we promote solid browser/environment support, ES5 precedents, unit testing, and plenty of documentation. Lo-Dash is part of the BestieJS *“Best in Class”* module collection. This means we promote solid browser/environment support, ES5+ precedents, unit testing, and plenty of documentation.
## Author ## Author

2532
build.js

File diff suppressed because it is too large Load Diff

View File

@@ -2,35 +2,73 @@
;(function() { ;(function() {
'use strict'; 'use strict';
/** The Node filesystem, path, `zlib`, and child process modules */ /** Load Node.js modules */
var fs = require('fs'), var fs = require('fs'),
gzip = require('zlib').gzip, https = require('https'),
path = require('path'), path = require('path'),
spawn = require('child_process').spawn; spawn = require('child_process').spawn,
zlib = require('zlib');
/** Load other modules */
var _ = require('../lodash.js'),
mkdirpSync = require('./mkdirp-sync.js'),
preprocess = require('./pre-compile.js'),
postprocess = require('./post-compile.js'),
tar = require('../vendor/tar/tar.js');
/** Add `fs.existsSync` for older versions of Node.js */
fs.existsSync || (fs.existsSync = path.existsSync);
/** Add `path.sep` for older versions of Node.js */
path.sep || (path.sep = process.platform == 'win32' ? '\\' : '/');
/** The Git object ID of `closure-compiler.tar.gz` */
var closureId = 'a95a8007892aa824ce90c6aa3d3abb0489bf0fff';
/** The Git object ID of `uglifyjs.tar.gz` */
var uglifyId = '41308bd569db41a32d4f08af115875d0342e8bfb';
/** The path of the directory that is the base of the repository */ /** The path of the directory that is the base of the repository */
var basePath = fs.realpathSync(path.join(__dirname, '..')); var basePath = fs.realpathSync(path.join(__dirname, '..'));
/** The path of the directory where the Closure Compiler is located */ /** The path of the `vendor` directory */
var closurePath = path.join(basePath, 'vendor', 'closure-compiler', 'compiler.jar'); var vendorPath = path.join(basePath, 'vendor');
/** Load other modules */ /** The path to the Closure Compiler `.jar` */
var preprocess = require('./pre-compile.js'), var closurePath = path.join(vendorPath, 'closure-compiler', 'compiler.jar');
postprocess = require('./post-compile.js'),
uglifyJS = require('../vendor/uglifyjs/uglify-js.js'); /** The path to the UglifyJS module */
var uglifyPath = path.join(vendorPath, 'uglifyjs', 'tools', 'node.js');
/** The Closure Compiler command-line options */ /** The Closure Compiler command-line options */
var closureOptions = ['--warning_level=QUIET']; var closureOptions = ['--warning_level=QUIET'];
/** The media type for raw blob data */
var mediaType = 'application/vnd.github.v3.raw';
/** Used to detect the Node.js executable in command-line arguments */
var reNode = RegExp('(?:^|' + path.sep + ')node(?:\\.exe)?$');
/** Used to reference parts of the blob href */
var location = (function() {
var host = 'api.github.com',
origin = 'https://api.github.com',
pathname = '/repos/bestiejs/lodash/git/blobs';
return {
'host': host,
'href': origin + pathname,
'origin': origin,
'pathname': pathname
};
}());
/** The Closure Compiler optimization modes */ /** The Closure Compiler optimization modes */
var optimizationModes = { var optimizationModes = {
'simple': 'SIMPLE_OPTIMIZATIONS', 'simple': 'SIMPLE_OPTIMIZATIONS',
'advanced': 'ADVANCED_OPTIMIZATIONS' 'advanced': 'ADVANCED_OPTIMIZATIONS'
}; };
/** Reassign `existsSync` for older versions of Node */
fs.existsSync || (fs.existsSync = path.existsSync);
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
/** /**
@@ -50,6 +88,12 @@
* onComplete - The function called once minification has finished. * onComplete - The function called once minification has finished.
*/ */
function minify(source, options) { function minify(source, options) {
// used to specify the source map URL
var sourceMapURL;
// used to specify the default minifer modes
var modes = ['simple', 'advanced', 'hybrid'];
source || (source = ''); source || (source = '');
options || (options = {}); options || (options = {});
@@ -58,28 +102,106 @@
// convert commands to an options object // convert commands to an options object
options = source; options = source;
// used to report invalid command-line arguments
var invalidArgs = _.reject(options.slice(reNode.test(options[0]) ? 2 : 0), function(value, index, options) {
if (/^(?:-o|--output)$/.test(options[index - 1]) ||
/^modes=.*$/.test(value)) {
return true;
}
var result = [
'-o', '--output',
'-p', '--source-map',
'-s', '--silent',
'-t', '--template'
].indexOf(value) > -1;
if (!result && /^(?:-p|--source-map)$/.test(options[index - 1])) {
result = true;
sourceMapURL = value;
}
return result;
});
// report invalid arguments
if (invalidArgs.length) {
console.log(
'\n' +
'Invalid argument' + (invalidArgs.length > 1 ? 's' : '') +
' passed: ' + invalidArgs.join(', ')
);
return;
}
var filePath = options[options.length - 1], var filePath = options[options.length - 1],
isSilent = options.indexOf('-s') > -1 || options.indexOf('--silent') > -1, isMapped = _.contains(options, '-p') || _.contains(options, '--source-map'),
isTemplate = options.indexOf('-t') > -1 || options.indexOf('--template') > -1, isSilent = _.contains(options, '-s') || _.contains(options, '--silent'),
isTemplate = _.contains(options, '-t') || _.contains(options, '--template'),
outputPath = path.join(path.dirname(filePath), path.basename(filePath, '.js') + '.min.js'); outputPath = path.join(path.dirname(filePath), path.basename(filePath, '.js') + '.min.js');
modes = options.reduce(function(result, value) {
var match = value.match(/modes=(.*)$/);
return match ? match[1].split(/, */) : result;
}, modes);
outputPath = options.reduce(function(result, value, index) { outputPath = options.reduce(function(result, value, index) {
if (/-o|--output/.test(value)) { if (/-o|--output/.test(value)) {
result = options[index + 1]; result = options[index + 1];
result = path.join(fs.realpathSync(path.dirname(result)), path.basename(result)); var dirname = path.dirname(result);
mkdirpSync(dirname);
result = path.join(fs.realpathSync(dirname), path.basename(result));
} }
return result; return result;
}, outputPath); }, outputPath);
options = { options = {
'filePath': filePath,
'isMapped': isMapped,
'isSilent': isSilent, 'isSilent': isSilent,
'isTemplate': isTemplate, 'isTemplate': isTemplate,
'outputPath': outputPath 'modes': modes,
'outputPath': outputPath,
'sourceMapURL': sourceMapURL
}; };
source = fs.readFileSync(filePath, 'utf8'); source = fs.readFileSync(filePath, 'utf8');
} }
new Minify(source, options);
modes = options.modes || modes;
if (options.isMapped) {
modes = modes.filter(function(mode) {
return mode != 'hybrid';
});
}
if (options.isTemplate) {
modes = modes.filter(function(mode) {
return mode != 'advanced';
});
}
options.modes = modes;
// fetch the Closure Compiler
getDependency({
'id': 'closure-compiler',
'hashId': closureId,
'path': vendorPath,
'title': 'the Closure Compiler',
'onComplete': function(exception) {
var error = exception;
// fetch UglifyJS
getDependency({
'id': 'uglifyjs',
'hashId': uglifyId,
'title': 'UglifyJS',
'path': vendorPath,
'onComplete': function(exception) {
error || (error = exception);
if (!error) {
new Minify(source, options);
}
}
});
}
});
} }
/** /**
@@ -104,19 +226,114 @@
this.hybrid = { 'simple': {}, 'advanced': {} }; this.hybrid = { 'simple': {}, 'advanced': {} };
this.uglified = {}; this.uglified = {};
this.filePath = options.filePath;
this.isMapped = !!options.isMapped;
this.isSilent = !!options.isSilent; this.isSilent = !!options.isSilent;
this.isTemplate = !!options.isTemplate; this.isTemplate = !!options.isTemplate;
this.outputPath = options.outputPath; this.outputPath = options.outputPath;
this.sourceMapURL = options.sourceMapURL;
source = preprocess(source, options); var modes = this.modes = options.modes;
this.source = source; source = this.source = preprocess(source, options);
this.onComplete = options.onComplete || function(source) { this.onComplete = options.onComplete || function(data) {
fs.writeFileSync(this.outputPath, source, 'utf8'); var outputPath = this.outputPath,
sourceMap = data.sourceMap;
fs.writeFileSync(outputPath, data.source, 'utf8');
if (sourceMap) {
fs.writeFileSync(getMapPath(outputPath), sourceMap, 'utf8');
}
}; };
// begin the minification process // begin the minification process
closureCompile.call(this, source, 'simple', onClosureSimpleCompile.bind(this)); if (_.contains(modes, 'simple')) {
closureCompile.call(this, source, 'simple', onClosureSimpleCompile.bind(this));
} else if (_.contains(modes, 'advanced')) {
onClosureSimpleGzip.call(this);
} else {
onClosureAdvancedGzip.call(this);
}
}
/*--------------------------------------------------------------------------*/
/**
* Fetches a required `.tar.gz` dependency with the given Git object ID from
* the Lo-Dash repo on GitHub. The object ID may be obtained by running
* `git hash-object path/to/dependency.tar.gz`.
*
* @private
* @param {Object} options The options object.
* id - The Git object ID of the `.tar.gz` file.
* onComplete - The function called once the extraction has finished.
* path - The path of the extraction directory.
* title - The dependency's title used in status updates logged to the console.
*/
function getDependency(options) {
options || (options = {});
var ran,
destPath = options.path,
hashId = options.hashId,
id = options.id,
onComplete = options.onComplete,
title = options.title;
// exit early if dependency exists
if (fs.existsSync(path.join(destPath, id))) {
onComplete();
return;
}
var callback = function(exception) {
if (ran) {
return;
}
if (exception) {
console.error([
'There was a problem installing ' + title + '.',
'Try running the command as root, via `sudo`, or manually install by running:',
'',
"curl -H 'Accept: " + mediaType + "' " + location.href + '/' + hashId + " | tar xvz -C '" + destPath + "'",
''
].join('\n'));
}
ran = true;
process.removeListener('uncaughtException', callback);
onComplete(exception);
};
console.log('Downloading ' + title + '...');
process.on('uncaughtException', callback);
https.get({
'host': location.host,
'path': location.pathname + '/' + hashId,
'headers': {
// By default, all GitHub blob API endpoints return a JSON document
// containing Base64-encoded blob data. Overriding the `Accept` header
// with the GitHub raw media type returns the blob data directly.
// See http://developer.github.com/v3/media/.
'Accept': mediaType
}
}, function(response) {
var decompressor = zlib.createUnzip(),
parser = new tar.Extract({ 'path': destPath });
parser.on('end', callback);
response.pipe(decompressor).pipe(parser);
});
}
/**
* Resolves the source map path from the given output path.
*
* @private
* @param {String} outputPath The output path.
* @returns {String} Returns the source map path.
*/
function getMapPath(outputPath) {
return path.join(path.dirname(outputPath), path.basename(outputPath, '.js') + '.map');
} }
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
@@ -131,36 +348,82 @@
* @param {Function} callback The function called once the process has completed. * @param {Function} callback The function called once the process has completed.
*/ */
function closureCompile(source, mode, callback) { function closureCompile(source, mode, callback) {
// use simple optimizations when minifying template files var filePath = this.filePath,
var options = closureOptions.slice(); isAdvanced = mode == 'advanced',
options.push('--compilation_level=' + optimizationModes[this.isTemplate ? 'simple' : mode]); isMapped = this.isMapped,
options = closureOptions.slice(),
outputPath = this.outputPath,
mapPath = getMapPath(outputPath),
sourceMapURL = this.sourceMapURL || path.basename(mapPath);
// the standard error stream, standard output stream, and the Closure Compiler process // remove copyright header to make other modifications easier
var error = '', var license = (/^(?:\s*\/\/.*\s*|\s*\/\*[^*]*\*+(?:[^\/][^*]*\*+)*\/\s*)*/.exec(source) || [''])[0];
output = '', if (license) {
compiler = spawn('java', ['-jar', closurePath].concat(options)); source = source.replace(license, '');
if (!this.isSilent) {
console.log('Compressing ' + path.basename(this.outputPath, '.js') + ' using the Closure Compiler (' + mode + ')...');
} }
compiler.stdout.on('data', function(data) {
// append the data to the output stream var hasIIFE = /^;?\(function[^{]+{/.test(source),
output += data; isStrict = hasIIFE && /^;?\(function[^{]+{\s*["']use strict["']/.test(source);
// to avoid stripping the IIFE, convert it to a function call
if (hasIIFE && isAdvanced) {
source = source
.replace(/\(function/, '__iife__$&')
.replace(/\(this\)\)([\s;]*(\n\/\/.+)?)$/, ', this)$1');
}
options.push('--compilation_level=' + optimizationModes[mode]);
if (isMapped) {
options.push('--create_source_map=' + mapPath, '--source_map_format=V3');
}
var compiler = spawn('java', ['-jar', closurePath].concat(options));
if (!this.isSilent) {
console.log('Compressing ' + path.basename(outputPath, '.js') + ' using the Closure Compiler (' + mode + ')...');
}
var error = '';
compiler.stderr.on('data', function(data) {
error += data;
}); });
compiler.stderr.on('data', function(data) { var output = '';
// append the error message to the error stream compiler.stdout.on('data', function(data) {
error += data; output += data;
}); });
compiler.on('exit', function(status) { compiler.on('exit', function(status) {
// `status` contains the process exit code // `status` contains the process exit code
var exception = null;
if (status) { if (status) {
exception = new Error(error); var exception = new Error(error);
exception.status = status; exception.status = status;
} }
callback(exception, output); // restore IIFE and move exposed vars inside the IIFE
if (hasIIFE && isAdvanced) {
output = output
.replace(/__iife__\(/, '(')
.replace(/,\s*this\)([\s;]*(\n\/\/.+)?)$/, '(this))$1')
.replace(/^((?:var (?:\w+=(?:!0|!1|null)[,;])+)?)([\s\S]*?function[^{]+{)/, '$2$1');
}
// inject "use strict" directive
if (isStrict) {
output = output.replace(/^[\s\S]*?function[^{]+{/, '$&"use strict";');
}
// restore copyright header
if (license) {
output = license + output;
}
if (isMapped) {
var mapOutput = fs.readFileSync(mapPath, 'utf8');
fs.unlinkSync(mapPath);
output = output.replace(/[\s;]*$/, '\n/*\n//@ sourceMappingURL=' + sourceMapURL) + '\n*/';
mapOutput = JSON.parse(mapOutput);
mapOutput.file = path.basename(outputPath);
mapOutput.sources = [path.basename(filePath)];
mapOutput = JSON.stringify(mapOutput, null, 2);
}
callback(exception, output, mapOutput);
}); });
// proxy the standard input to the Closure Compiler // proxy the standard input to the Closure Compiler
@@ -178,31 +441,47 @@
* @param {Function} callback The function called once the process has completed. * @param {Function} callback The function called once the process has completed.
*/ */
function uglify(source, label, callback) { function uglify(source, label, callback) {
var exception,
result,
ugly = uglifyJS.uglify;
if (!this.isSilent) { if (!this.isSilent) {
console.log('Compressing ' + path.basename(this.outputPath, '.js') + ' using ' + label + '...'); console.log('Compressing ' + path.basename(this.outputPath, '.js') + ' using ' + label + '...');
} }
try { try {
result = ugly.gen_code( var uglifyJS = require(uglifyPath);
// enable unsafe transformations
ugly.ast_squeeze_more( // 1. parse
ugly.ast_squeeze( var toplevel = uglifyJS.parse(source);
// munge variable and function names, excluding the special `define`
// function exposed by AMD loaders // 2. compress
ugly.ast_mangle(uglifyJS.parser.parse(source), { // enable unsafe comparisons
'except': ['define'] toplevel.figure_out_scope();
} toplevel = toplevel.transform(uglifyJS.Compressor({
))), { 'comparisons': false,
'ascii_only': true 'unsafe': true,
'unsafe_comps': true,
'warnings': false
}));
// 3. mangle
// excluding the `define` function exposed by AMD loaders
toplevel.figure_out_scope();
toplevel.compute_char_frequency();
toplevel.mangle_names({
'except': ['define']
}); });
} catch(e) {
exception = e; // 4. output
// restrict lines to 500 characters for consistency with the Closure Compiler
var stream = uglifyJS.OutputStream({
'ascii_only': true,
'comments': /@cc_on|@license|@preserve/i,
'max_line_len': 500,
});
toplevel.print(stream);
} }
// lines are restricted to 500 characters for consistency with the Closure Compiler catch(e) {
callback(exception, result && ugly.split_lines(result, 500)); var exception = e;
}
callback(exception, stream && String(stream));
} }
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
@@ -213,14 +492,18 @@
* @private * @private
* @param {Object|Undefined} exception The error object. * @param {Object|Undefined} exception The error object.
* @param {String} result The resulting minified source. * @param {String} result The resulting minified source.
* @param {String} map The source map output.
*/ */
function onClosureSimpleCompile(exception, result) { function onClosureSimpleCompile(exception, result, map) {
if (exception) { if (exception) {
throw exception; throw exception;
} }
result = postprocess(result); result = postprocess(result);
this.compiled.simple.source = result;
gzip(result, onClosureSimpleGzip.bind(this)); var simple = this.compiled.simple;
simple.source = result;
simple.sourceMap = map;
zlib.gzip(result, onClosureSimpleGzip.bind(this));
} }
/** /**
@@ -234,13 +517,18 @@
if (exception) { if (exception) {
throw exception; throw exception;
} }
if (!this.isSilent) { if (result != null) {
console.log('Done. Size: %d bytes.', result.length); if (!this.isSilent) {
console.log('Done. Size: %d bytes.', result.length);
}
this.compiled.simple.gzip = result;
}
// compile the source using advanced optimizations
if (_.contains(this.modes, 'advanced')) {
closureCompile.call(this, this.source, 'advanced', onClosureAdvancedCompile.bind(this));
} else {
onClosureAdvancedGzip.call(this);
} }
this.compiled.simple.gzip = result;
// next, compile the source using advanced optimizations
closureCompile.call(this, this.source, 'advanced', onClosureAdvancedCompile.bind(this));
} }
/** /**
@@ -249,14 +537,18 @@
* @private * @private
* @param {Object|Undefined} exception The error object. * @param {Object|Undefined} exception The error object.
* @param {String} result The resulting minified source. * @param {String} result The resulting minified source.
* @param {String} map The source map output.
*/ */
function onClosureAdvancedCompile(exception, result) { function onClosureAdvancedCompile(exception, result, map) {
if (exception) { if (exception) {
throw exception; throw exception;
} }
result = postprocess(result); result = postprocess(result);
this.compiled.advanced.source = result;
gzip(result, onClosureAdvancedGzip.bind(this)); var advanced = this.compiled.advanced;
advanced.source = result;
advanced.sourceMap = map;
zlib.gzip(result, onClosureAdvancedGzip.bind(this));
} }
/** /**
@@ -270,13 +562,18 @@
if (exception) { if (exception) {
throw exception; throw exception;
} }
if (!this.isSilent) { if (result != null) {
console.log('Done. Size: %d bytes.', result.length); if (!this.isSilent) {
console.log('Done. Size: %d bytes.', result.length);
}
this.compiled.advanced.gzip = result;
}
// minify the source using UglifyJS
if (!this.isMapped) {
uglify.call(this, this.source, 'UglifyJS', onUglify.bind(this));
} else {
onComplete.call(this);
} }
this.compiled.advanced.gzip = result;
// next, minify the source using only UglifyJS
uglify.call(this, this.source, 'UglifyJS', onUglify.bind(this));
} }
/** /**
@@ -292,7 +589,7 @@
} }
result = postprocess(result); result = postprocess(result);
this.uglified.source = result; this.uglified.source = result;
gzip(result, onUglifyGzip.bind(this)); zlib.gzip(result, onUglifyGzip.bind(this));
} }
/** /**
@@ -306,13 +603,23 @@
if (exception) { if (exception) {
throw exception; throw exception;
} }
if (!this.isSilent) { if (result != null) {
console.log('Done. Size: %d bytes.', result.length); if (!this.isSilent) {
console.log('Done. Size: %d bytes.', result.length);
}
this.uglified.gzip = result;
}
// minify the already Closure Compiler simple optimized source using UglifyJS
var modes = this.modes;
if (_.contains(modes, 'hybrid')) {
if (_.contains(modes, 'simple')) {
uglify.call(this, this.compiled.simple.source, 'hybrid (simple)', onSimpleHybrid.bind(this));
} else if (_.contains(modes, 'advanced')) {
onSimpleHybridGzip.call(this);
}
} else {
onComplete.call(this);
} }
this.uglified.gzip = result;
// next, minify the already Closure Compiler simple optimized source using UglifyJS
uglify.call(this, this.compiled.simple.source, 'hybrid (simple)', onSimpleHybrid.bind(this));
} }
/** /**
@@ -328,7 +635,7 @@
} }
result = postprocess(result); result = postprocess(result);
this.hybrid.simple.source = result; this.hybrid.simple.source = result;
gzip(result, onSimpleHybridGzip.bind(this)); zlib.gzip(result, onSimpleHybridGzip.bind(this));
} }
/** /**
@@ -342,13 +649,18 @@
if (exception) { if (exception) {
throw exception; throw exception;
} }
if (!this.isSilent) { if (result != null) {
console.log('Done. Size: %d bytes.', result.length); if (!this.isSilent) {
console.log('Done. Size: %d bytes.', result.length);
}
this.hybrid.simple.gzip = result;
}
// minify the already Closure Compiler advance optimized source using UglifyJS
if (_.contains(this.modes, 'advanced')) {
uglify.call(this, this.compiled.advanced.source, 'hybrid (advanced)', onAdvancedHybrid.bind(this));
} else {
onComplete.call(this);
} }
this.hybrid.simple.gzip = result;
// next, minify the already Closure Compiler advance optimized source using UglifyJS
uglify.call(this, this.compiled.advanced.source, 'hybrid (advanced)', onAdvancedHybrid.bind(this));
} }
/** /**
@@ -364,7 +676,7 @@
} }
result = postprocess(result); result = postprocess(result);
this.hybrid.advanced.source = result; this.hybrid.advanced.source = result;
gzip(result, onAdvancedHybridGzip.bind(this)); zlib.gzip(result, onAdvancedHybridGzip.bind(this));
} }
/** /**
@@ -378,11 +690,12 @@
if (exception) { if (exception) {
throw exception; throw exception;
} }
if (!this.isSilent) { if (result != null) {
console.log('Done. Size: %d bytes.', result.length); if (!this.isSilent) {
console.log('Done. Size: %d bytes.', result.length);
}
this.hybrid.advanced.gzip = result;
} }
this.hybrid.advanced.gzip = result;
// finish by choosing the smallest compressed file // finish by choosing the smallest compressed file
onComplete.call(this); onComplete.call(this);
} }
@@ -399,20 +712,32 @@
hybridSimple = this.hybrid.simple, hybridSimple = this.hybrid.simple,
hybridAdvanced = this.hybrid.advanced; hybridAdvanced = this.hybrid.advanced;
var objects = [
compiledSimple,
compiledAdvanced,
uglified,
hybridSimple,
hybridAdvanced
];
var gzips = objects
.map(function(data) { return data.gzip; })
.filter(Boolean);
// select the smallest gzipped file and use its minified counterpart as the // select the smallest gzipped file and use its minified counterpart as the
// official minified release (ties go to the Closure Compiler) // official minified release (ties go to the Closure Compiler)
var min = Math.min( var min = gzips.reduce(function(min, gzip) {
compiledSimple.gzip.length, var length = gzip.length;
compiledAdvanced.gzip.length, return min > length ? length : min;
uglified.gzip.length, }, Infinity);
hybridSimple.gzip.length,
hybridAdvanced.gzip.length
);
// pass the minified source to the "onComplete" callback // pass the minified source to the "onComplete" callback
[compiledSimple, compiledAdvanced, uglified, hybridSimple, hybridAdvanced].some(function(data) { objects.some(function(data) {
if (data.gzip.length == min) { var gzip = data.gzip;
this.onComplete(data.source); if (gzip && gzip.length == min) {
data.outputPath = this.outputPath;
this.onComplete(data);
return true;
} }
}, this); }, this);
} }

43
build/mkdirp-sync.js Executable file
View File

@@ -0,0 +1,43 @@
#!/usr/bin/env node
;(function() {
'use strict';
/** Load Node.js modules */
var fs = require('fs'),
path = require('path');
/** Add `path.sep` for older versions of Node.js */
path.sep || (path.sep = process.platform == 'win32' ? '\\' : '/');
/*--------------------------------------------------------------------------*/
/**
* Makes the given `dirname` directory, without throwing errors for existing
* directories and making parent directories as needed.
*
* @param {String} dirname The path of the directory.
* @param {Number|String} [mode='0777'] The permission mode.
*/
function mkdirpSync(dirname, mode) {
var sep = path.sep;
// ensure relative paths are prefixed with `./`
if (!RegExp('^\\.?' + sep).test(dirname)) {
dirname = '.' + sep + dirname;
}
dirname.split(sep).reduce(function(currPath, segment) {
currPath += sep + segment;
try {
currPath = fs.realpathSync(currPath);
} catch(e) {
fs.mkdirSync(currPath, mode);
}
return currPath;
});
}
/*--------------------------------------------------------------------------*/
// expose
module.exports = mkdirpSync;
}());

View File

@@ -2,19 +2,17 @@
;(function() { ;(function() {
'use strict'; 'use strict';
/** The Node filesystem module */ /** The Node.js filesystem module */
var fs = require('fs'); var fs = require('fs');
/** The minimal license/copyright template */ /** The minimal license/copyright template */
var licenseTemplate = { var licenseTemplate = [
'lodash': '/**',
'/*!\n' + ' * @license',
' Lo-Dash @VERSION lodash.com/license\n' + ' * Lo-Dash <%= VERSION %> lodash.com/license',
' Underscore.js 1.4.2 underscorejs.org/LICENSE\n' + ' * Underscore.js 1.4.4 underscorejs.org/LICENSE',
'*/', ' */'
'underscore': ].join('\n');
'/*! Underscore.js @VERSION underscorejs.org/LICENSE */'
};
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
@@ -26,32 +24,39 @@
* @returns {String} Returns the processed source. * @returns {String} Returns the processed source.
*/ */
function postprocess(source) { function postprocess(source) {
// move vars exposed by the Closure Compiler into the IIFE // remove copyright header
source = source.replace(/^((?:(['"])use strict\2;)?(?:var (?:[a-z]+=(?:!0|!1|null)[,;])+)?)([\s\S]*?function[^)]+\){)/, '$3$1'); source = source.replace(/^\/\**[\s\S]+?\*\/\n/, '');
// correct overly aggressive Closure Compiler advanced optimizations // correct overly aggressive Closure Compiler advanced optimizations
source = source.replace(/prototype\s*=\s*{\s*valueOf\s*:\s*1\s*}/, 'prototype={valueOf:1,y:1}'); source = source
.replace(/prototype\s*=\s*{\s*valueOf\s*:\s*1\s*}/, 'prototype={valueOf:1,y:1}')
.replace(/(document[^&]+&&)\s*(?:\w+|!\d)/, '$1!({toString:0}+"")')
// unescape properties (i.e. foo["bar"] => foo.bar) source = source.replace(/(\w+\.prototype\s*=\s*)\w+(?=\.prototype;)/, function(match, left) {
source = source.replace(/(\w)\["([^."]+)"\]/g, function(match, left, right) { return left + /\w+(?=\.VERSION)/.exec(source);
return /\W/.test(right) ? match : (left + '.' + right);
}); });
// correct AMD module definition for AMD build optimizers // flip `typeof` expressions to help optimize Safari and
source = source.replace(/("function")\s*==\s*(typeof define)\s*&&\s*\(?\s*("object")\s*==\s*(typeof define\.amd)\s*&&\s*(define\.amd)\s*\)?/, '$2==$1&&$4==$3&&$5'); // correct the AMD module definition for AMD build optimizers
// (e.g. from `"number" == typeof x` to `typeof x == "number")
source = source.replace(/(\w)?("[^"]+")\s*([!=]=)\s*(typeof(?:\s*\([^)]+\)|\s+[.\w]+(?!\[)))/g, function(match, other, type, equality, expression) {
return (other ? other + ' ' : '') + expression + equality + type;
});
// add trailing semicolon // add trailing semicolon
if (source) { if (source) {
source = source.replace(/[\s;]*$/, ';'); source = source.replace(/[\s;]*?(\s*\/\/.*\s*|\s*\/\*[^*]*\*+(?:[^\/][^*]*\*+)*\/\s*)*$/, ';$1');
} }
// exit early if version snippet isn't found // exit early if version snippet isn't found
var snippet = /VERSION\s*[=:]\s*([\'"])(.*?)\1/.exec(source); var snippet = /VERSION\s*[=:]\s*([\'"])(.*?)\1/.exec(source);
if (!snippet) { if (!snippet) {
return source; return source;
} }
// add license // add new copyright header
return licenseTemplate[/call\(this\);?$/.test(source) ? 'underscore' : 'lodash'] var version = snippet[2];
.replace('@VERSION', snippet[2]) + '\n;' + source; source = licenseTemplate.replace('<%= VERSION %>', version) + '\n;' + source;
return source;
} }
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/

View File

@@ -1,106 +0,0 @@
#!/usr/bin/env node
;(function () {
'use strict';
/** Load Node modules */
var exec = require('child_process').exec,
fs = require('fs'),
https = require('https'),
path = require('path'),
tar = require('../vendor/tar/tar.js'),
zlib = require('zlib');
/** The path of the directory that is the base of the repository */
var basePath = fs.realpathSync(path.join(__dirname, '..'));
/** The path of the `vendor` directory */
var vendorPath = path.join(basePath, 'vendor');
/** The Git object ID of `closure-compiler.tar.gz` */
var closureId = 'aa29a2ecf6f51d4da5a2a418c0d4ea0e368ee80d';
/** The Git object ID of `uglifyjs.tar.gz` */
var uglifyId = '9869c4443fb22598235d1019fcc8245be41e8889';
/*--------------------------------------------------------------------------*/
/**
* Fetches a required `.tar.gz` dependency with the given Git object ID from
* the Lo-Dash repo on GitHub. The object ID may be obtained by running
* `git hash-object path/to/dependency.tar.gz`.
*
* @private
* @param {Object} options The options object.
*
* id - The Git object ID of the `.tar.gz` file.
* onComplete - The function, invoked with one argument (exception),
* called once the extraction has finished.
* path - The path of the extraction directory.
* title - The dependency's title used in status updates logged to the console.
*/
function getDependency(options) {
options || (options = {});
var onComplete = options.onComplete,
title = options.title;
function callback(exception) {
if (exception) {
console.error('There was a problem downloading ' + title + '.');
}
onComplete(exception);
}
console.log('Downloading ' + title + '...');
https.get({
'host': 'api.github.com',
'path': '/repos/bestiejs/lodash/git/blobs/' + options.id,
'headers': {
// By default, all GitHub blob API endpoints return a JSON document
// containing Base64-encoded blob data. Overriding the `Accept` header
// with the GitHub raw media type returns the blob data directly.
'Accept': 'application/vnd.github.v3.raw'
}
}, function(response) {
var parser = new tar.Extract({
'path': options.path
})
.on('end', callback)
.on('error', callback);
response.pipe(zlib.createUnzip()).pipe(parser);
})
.on('error', callback);
}
/*--------------------------------------------------------------------------*/
exec('npm -g root', function(exception, stdout) {
if (exception) {
console.error('There was a problem loading the npm registry.');
process.exit(1);
}
// exit early if not a global install
if (path.resolve(basePath, '..') != stdout.trim()) {
return;
}
// download the Closure Compiler
getDependency({
'title': 'the Closure Compiler',
'id': closureId,
'path': vendorPath,
'onComplete':function(exceptionA) {
// download UglifyJS
getDependency({
'title': 'UglifyJS',
'id': uglifyId,
'path': vendorPath,
'onComplete': function(exceptionB) {
process.exit(exceptionA || exceptionB ? 1 : 0);
}
});
}
});
});
}());

View File

@@ -2,50 +2,49 @@
;(function() { ;(function() {
'use strict'; 'use strict';
/** The Node filesystem module */ /** The Node.js filesystem module */
var fs = require('fs'); var fs = require('fs');
/** Used to minify variables embedded in compiled strings */ /** Used to minify variables embedded in compiled strings */
var compiledVars = [ var compiledVars = [
'args',
'argsIndex', 'argsIndex',
'argsLength', 'argsLength',
'callback', 'callback',
'collection', 'collection',
'createCallback',
'ctor', 'ctor',
'guard',
'hasOwnProperty', 'hasOwnProperty',
'index', 'index',
'isArguments', 'isArguments',
'isArray',
'isString', 'isString',
'iteratee', 'iterable',
'length', 'length',
'nativeKeys', 'keys',
'lodash',
'object', 'object',
'objectTypes', 'objectTypes',
'ownIndex', 'ownIndex',
'ownProps', 'ownProps',
'propertyIsEnumerable',
'result', 'result',
'skipProto', 'skipProto',
'thisArg', 'source',
'value' 'thisArg'
]; ];
/** Used to minify `compileIterator` option properties */ /** Used to minify `iteratorTemplate` data properties */
var iteratorOptions = [ var iteratorOptions = [
'args', 'args',
'arrayLoop', 'arrays',
'bottom', 'bottom',
'firstArg', 'firstArg',
'hasDontEnumBug', 'init',
'isKeysFast', 'loop',
'objectLoop', 'shadowedProps',
'noArgsEnum',
'noCharByIndex',
'shadowed',
'top', 'top',
'useHas', 'useHas',
'useStrict' 'useKeys'
]; ];
/** Used to minify variables and string values to a single character */ /** Used to minify variables and string values to a single character */
@@ -56,23 +55,40 @@
/** Used to protect the specified properties from getting minified */ /** Used to protect the specified properties from getting minified */
var propWhitelist = [ var propWhitelist = [
'Array',
'Boolean',
'Date',
'Function',
'Math',
'Number',
'Object',
'RegExp',
'String',
'TypeError',
'VERSION',
'_', '_',
'__chain__',
'__wrapped__', '__wrapped__',
'after', 'after',
'all', 'all',
'amd', 'amd',
'any', 'any',
'argsClass',
'argsObject',
'assign',
'at',
'attachEvent', 'attachEvent',
'bind', 'bind',
'bindAll', 'bindAll',
'chain', 'bindKey',
'clearTimeout',
'clone', 'clone',
'cloneDeep',
'collect', 'collect',
'compact', 'compact',
'compose', 'compose',
'contains', 'contains',
'countBy', 'countBy',
'createCallback',
'criteria', 'criteria',
'debounce', 'debounce',
'defaults', 'defaults',
@@ -82,14 +98,19 @@
'difference', 'difference',
'drop', 'drop',
'each', 'each',
'enumPrototypes',
'environment', 'environment',
'escape', 'escape',
'evaluate', 'evaluate',
'every', 'every',
'exports', 'exports',
'extend', 'extend',
'fastBind',
'fastKeys',
'filter', 'filter',
'find', 'find',
'findIndex',
'findKey',
'first', 'first',
'flatten', 'flatten',
'foldl', 'foldl',
@@ -103,6 +124,7 @@
'has', 'has',
'head', 'head',
'identity', 'identity',
'imports',
'include', 'include',
'index', 'index',
'indexOf', 'indexOf',
@@ -134,7 +156,6 @@
'keys', 'keys',
'last', 'last',
'lastIndexOf', 'lastIndexOf',
'lateBind',
'map', 'map',
'max', 'max',
'memoize', 'memoize',
@@ -143,12 +164,17 @@
'min', 'min',
'mixin', 'mixin',
'noConflict', 'noConflict',
'nodeClass',
'nonEnumArgs',
'nonEnumShadows',
'object', 'object',
'omit', 'omit',
'once', 'once',
'opera', 'ownLast',
'pairs', 'pairs',
'parseInt',
'partial', 'partial',
'partialRight',
'pick', 'pick',
'pluck', 'pluck',
'random', 'random',
@@ -158,13 +184,18 @@
'reject', 'reject',
'rest', 'rest',
'result', 'result',
'runInContext',
'select', 'select',
'setImmediate',
'setTimeout',
'shuffle', 'shuffle',
'size', 'size',
'some', 'some',
'sortBy', 'sortBy',
'sortedIndex', 'sortedIndex',
'source', 'source',
'spliceObjects',
'support',
'tail', 'tail',
'take', 'take',
'tap', 'tap',
@@ -174,6 +205,7 @@
'times', 'times',
'toArray', 'toArray',
'unescape', 'unescape',
'unindexedChars',
'union', 'union',
'uniq', 'uniq',
'unique', 'unique',
@@ -181,15 +213,16 @@
'value', 'value',
'values', 'values',
'variable', 'variable',
'VERSION',
'where', 'where',
'without', 'without',
'wrap', 'wrap',
'zip', 'zip',
'zipObject',
// properties used by underscore.js // properties used by the `backbone` and `underscore` builds
'_chain', '__chain__',
'_wrapped' 'chain',
'findWhere'
]; ];
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
@@ -211,20 +244,21 @@
if (options.isTemplate) { if (options.isTemplate) {
return source; return source;
} }
// remove copyright to add later in post-compile.js
source = source.replace(/\/\*![\s\S]+?\*\//, '');
// add brackets to whitelisted properties so the Closure Compiler won't mung them // add brackets to whitelisted properties so the Closure Compiler won't mung them
// http://code.google.com/closure/compiler/docs/api-tutorial3.html#export // http://code.google.com/closure/compiler/docs/api-tutorial3.html#export
source = source.replace(RegExp('\\.(' + propWhitelist.join('|') + ')\\b', 'g'), "['$1']"); source = source.replace(RegExp('\\.(' + propWhitelist.join('|') + ')\\b', 'g'), function(match, prop) {
return "['" + prop.replace(/['\n\r\t]/g, '\\$&') + "']";
});
// remove brackets from `_.escape()` in `_.template` // remove brackets from `lodash.createCallback` in `eachIteratorOptions`
source = source.replace('lodash[\'createCallback\'](callback, thisArg)"', 'lodash.createCallback(callback, thisArg)"');
// remove brackets from `lodash.createCallback` in `_.assign`
source = source.replace("' var callback = lodash['createCallback']", "'var callback=lodash.createCallback");
// remove brackets from `_.escape` in `_.template`
source = source.replace(/__e *= *_\['escape']/g, '__e=_.escape'); source = source.replace(/__e *= *_\['escape']/g, '__e=_.escape');
// remove brackets from `_.escape()` in underscore.js `_.template`
source = source.replace(/_\['escape'\]\(__t'/g, '_.escape(__t');
// remove brackets from `collection.indexOf` in `_.contains` // remove brackets from `collection.indexOf` in `_.contains`
source = source.replace("collection['indexOf'](target)", 'collection.indexOf(target)'); source = source.replace("collection['indexOf'](target)", 'collection.indexOf(target)');
@@ -232,31 +266,28 @@
source = source.replace("result[length]['value']", 'result[length].value'); source = source.replace("result[length]['value']", 'result[length].value');
// remove whitespace from string literals // remove whitespace from string literals
source = source.replace(/'(?:(?=(\\?))\1.)*?'/g, function(string) { source = source.replace(/^((?:[ "'\w]+:)? *)"[^"\\\n]*(?:\\.[^"\\\n]*)*"|'[^'\\\n]*(?:\\.[^'\\\n]*)*'/gm, function(string, left) {
// clip after an object literal property name or leading spaces
if (left) {
string = string.slice(left.length);
}
// avoids removing the '\n' of the `stringEscapes` object // avoids removing the '\n' of the `stringEscapes` object
return string.replace(/\[object |delete |else |function | in |return\s+[\w']|throw |typeof |use strict|var |@ |'\\n'|\\\\n|\\n|\s+/g, function(match) { string = string.replace(/\[object |delete |else (?!{)|function | in |return\s+[\w"']|throw |typeof |use strict|var |@ |(["'])\\n\1|\\\\n|\\n|\s+/g, function(match) {
return match == false || match == '\\n' ? '' : match; return match == false || match == '\\n' ? '' : match;
}); });
// unclip
return (left || '') + string;
}); });
// add newline to `+"__p+='"` in underscore.js `_.template`
source = source.replace(/\+"__p\+='"/g, '+"\\n__p+=\'"');
// remove whitespace from `_.template` related regexes // remove whitespace from `_.template` related regexes
source = source.replace(/(?:reEmptyString\w+|reInsertVariable) *=.+/g, function(match) { source = source.replace(/reEmptyString\w+ *=.+/g, function(match) {
return match.replace(/ |\\n/g, ''); return match.replace(/ |\\n/g, '');
}); });
// remove newline from double-quoted strings in `_.template` // remove newline from double-quoted strings in `_.template`
source = source source = source
.replace('"\';\\n__with ("', '"\';__with("') .replace('"__p += \'"', '"__p+=\'"')
.replace('"\\n}__\\n__p += \'"', '"}____p+=\'"') .replace('"\';\n"', '"\';"')
.replace('"__p = \'"', '"__p=\'"')
.replace('"\';\\n"', '"\';"')
.replace("') {\\n'", "'){'")
// remove `useSourceURL` variable
source = source.replace(/(?:\n +\/\*[^*]*\*+(?:[^\/][^*]*\*+)*\/)?\n *try *\{(?:\s*\/\/.*)*\n *var useSourceURL[\s\S]+?catch[^}]+}\n/, '');
// remove debug sourceURL use in `_.template` // remove debug sourceURL use in `_.template`
source = source.replace(/(?:\s*\/\/.*\n)* *var sourceURL[^;]+;|\+ *sourceURL/g, ''); source = source.replace(/(?:\s*\/\/.*\n)* *var sourceURL[^;]+;|\+ *sourceURL/g, '');
@@ -274,18 +305,21 @@
// minify properties // minify properties
properties.forEach(function(property, index) { properties.forEach(function(property, index) {
var reBracketProp = RegExp("\\['(" + property + ")'\\]", 'g'), var minName = minNames[index],
reBracketProp = RegExp("\\['(" + property + ")'\\]", 'g'),
reDotProp = RegExp('\\.' + property + '\\b', 'g'), reDotProp = RegExp('\\.' + property + '\\b', 'g'),
rePropColon = RegExp("([^?\\s])\\s*([\"'])?\\b" + property + "\\2 *:", 'g'); rePropColon = RegExp("([^?\\s])\\s*([\"'])?\\b" + property + "\\2 *:", 'g');
modified = modified modified = modified
.replace(reBracketProp, "['" + minNames[index] + "']") .replace(reBracketProp, "['" + minName + "']")
.replace(reDotProp, "['" + minNames[index] + "']") .replace(reDotProp, "['" + minName + "']")
.replace(rePropColon, "$1'" + minNames[index] + "':"); .replace(rePropColon, "$1'" + minName + "':");
}); });
// replace with modified snippet // replace with modified snippet
source = source.replace(snippet, modified); source = source.replace(snippet, function() {
return modified;
});
}); });
}()); }());
@@ -295,7 +329,7 @@
// match the `iteratorTemplate` // match the `iteratorTemplate`
'( +)var iteratorTemplate\\b[\\s\\S]+?\\n\\1}', '( +)var iteratorTemplate\\b[\\s\\S]+?\\n\\1}',
// match methods created by `createIterator` calls // match methods created by `createIterator` calls
'createIterator\\((?:{|[a-zA-Z]+)[\\s\\S]+?\\);\\n', 'createIterator\\((?:{|[a-zA-Z]+)[\\s\\S]*?\\);\\n',
// match variables storing `createIterator` options // match variables storing `createIterator` options
'( +)var [a-zA-Z]+IteratorOptions\\b[\\s\\S]+?\\n\\2}', '( +)var [a-zA-Z]+IteratorOptions\\b[\\s\\S]+?\\n\\2}',
// match the the `createIterator` function // match the the `createIterator` function
@@ -313,45 +347,43 @@
isIteratorTemplate = /var iteratorTemplate\b/.test(snippet), isIteratorTemplate = /var iteratorTemplate\b/.test(snippet),
modified = snippet; modified = snippet;
// add brackets to whitelisted properties so the Closure Compiler won't mung them // add brackets to iterator option properties so the Closure Compiler won't mung them
modified = modified.replace(RegExp('\\.(' + iteratorOptions.join('|') + ')\\b', 'g'), "['$1']"); modified = modified.replace(RegExp('\\.(' + iteratorOptions.join('|') + ')\\b', 'g'), function(match, prop) {
return "['" + prop.replace(/['\n\r\t]/g, '\\$&') + "']";
if (isCreateIterator) {
// replace with modified snippet early and clip snippet to the `factory`
// call so other arguments aren't minified
source = source.replace(snippet, modified);
snippet = modified = modified.replace(/factory\([\s\S]+$/, '');
}
// minify snippet variables / arguments
compiledVars.forEach(function(variable, index) {
// ensure properties in compiled strings aren't minified
modified = modified.replace(RegExp('([^.]\\b)' + variable + '\\b(?!\' *[\\]:])', 'g'), '$1' + minNames[index]);
// correct `typeof x == 'object'`
if (variable == 'object') {
modified = modified.replace(RegExp("(typeof [^']+')" + minNames[index] + "'", 'g'), "$1object'");
}
}); });
// minify `createIterator` option property names // minify `createIterator` option property names
iteratorOptions.forEach(function(property, index) { iteratorOptions.forEach(function(property, index) {
if (isIteratorTemplate) { var minName = minNames[index];
// minify property names as interpolated template variables
modified = modified.replace(RegExp('\\b' + property + '\\b', 'g'), minNames[index]); // minify variables in `iteratorTemplate` or property names in everything else
modified = isIteratorTemplate
? modified.replace(RegExp('\\b' + property + '\\b', 'g'), minName)
: modified.replace(RegExp("'" + property + "'", 'g'), "'" + minName + "'");
});
// minify snippet variables / arguments
compiledVars.forEach(function(varName, index) {
var minName = minNames[index];
// minify variable names present in strings
if (isCreateIterator) {
modified = modified.replace(RegExp('(([\'"])[^\\n\\2]*?)\\b' + varName + '\\b(?=[^\\n\\2]*\\2[ ,+]+$)', 'gm'), '$1' + minName);
} }
// ensure properties in compiled strings aren't minified
else { else {
// minify property name strings modified = modified.replace(RegExp('([^.])\\b' + varName + '\\b(?!\' *[\\]:])', 'g'), '$1' + minName);
modified = modified.replace(RegExp("'" + property + "'", 'g'), "'" + minNames[index] + "'"); }
// minify property names in accessors // correct `typeof` values
if (isCreateIterator) { if (/^(?:boolean|function|object|number|string|undefined)$/.test(varName)) {
modified = modified.replace(RegExp('\\.' + property + '\\b' , 'g'), '.' + minNames[index]); modified = modified.replace(RegExp("(typeof [^']+')" + minName + "'", 'g'), '$1' + varName + "'");
}
} }
}); });
// replace with modified snippet // replace with modified snippet
source = source.replace(snippet, modified); source = source.replace(snippet, function() {
return modified;
});
}); });
return source; return source;

5438
dist/lodash.compat.js vendored Normal file

File diff suppressed because it is too large Load Diff

46
dist/lodash.compat.min.js vendored Normal file
View File

@@ -0,0 +1,46 @@
/**
* @license
* Lo-Dash 1.1.1 (Custom Build) lodash.com/license
* Build: `lodash -o ./dist/lodash.compat.js`
* Underscore.js 1.4.4 underscorejs.org/LICENSE
*/
;(function(n){function t(r){function a(n){return n&&typeof n=="object"&&!fe(n)&&Vt.call(n,"__wrapped__")?n:new K(n)}function q(n,t,e){var r=n.length,u=r-t>=e;if(u){var a={};for(e=t-1;++e<r;){var o=qt(n[e]);(Vt.call(a,o)?a[o]:a[o]=[]).push(n[e])}}return function(e){if(u){var r=qt(e);return Vt.call(a,r)&&-1<yt(a[r],e)}return-1<yt(n,e,t)}}function B(n){return n.charCodeAt(0)}function F(n,t){var e=n.b,r=t.b;if(n=n.a,t=t.a,n!==t){if(n>t||typeof n=="undefined")return 1;if(n<t||typeof t=="undefined")return-1
}return e<r?-1:1}function R(n,t,e,r){function u(){var r=arguments,c=o?this:t;return a||(n=t[i]),e.length&&(r=r.length?(r=V(r),f?r.concat(e):e.concat(r)):e),this instanceof u?(M.prototype=n.prototype,c=new M,M.prototype=null,r=n.apply(c,r),Z(r)?r:c):n.apply(c,r)}var a=Y(n),o=!e,i=t;if(o){var f=r;e=t}else if(!a){if(!r)throw new Bt;t=n}return u}function T(){for(var n,t={g:_,b:"k(m)",c:"",e:"m",f:"",h:"",i:!0,j:!!le},e=0;n=arguments[e];e++)for(var r in n)t[r]=n[r];if(n=t.a,t.d=/^[^,]+/.exec(n)[0],e=At,r="var i,m="+t.d+",u="+t.e+";if(!m)return u;"+t.h+";",t.b?(r+="var n=m.length;i=-1;if("+t.b+"){",ie.unindexedChars&&(r+="if(l(m)){m=m.split('')}"),r+="while(++i<n){"+t.f+"}}else{"):ie.nonEnumArgs&&(r+="var n=m.length;i=-1;if(n&&j(m)){while(++i<n){i+='';"+t.f+"}}else{"),ie.enumPrototypes&&(r+="var v=typeof m=='function';"),t.i&&t.j)r+="var s=-1,t=r[typeof m]?o(m):[],n=t.length;while(++s<n){i=t[s];",ie.enumPrototypes&&(r+="if(!(v&&i=='prototype')){"),r+=t.f,ie.enumPrototypes&&(r+="}"),r+="}";
else if(r+="for(i in m){",(ie.enumPrototypes||t.i)&&(r+="if(",ie.enumPrototypes&&(r+="!(v&&i=='prototype')"),ie.enumPrototypes&&t.i&&(r+="&&"),t.i&&(r+="h.call(m,i)"),r+="){"),r+=t.f+";",(ie.enumPrototypes||t.i)&&(r+="}"),r+="}",ie.nonEnumShadows){r+="var f=m.constructor;";for(var u=0;7>u;u++)r+="i='"+t.g[u]+"';if(","constructor"==t.g[u]&&(r+="!(f&&f.prototype===m)&&"),r+="h.call(m,i)){"+t.f+"}"}return(t.b||ie.nonEnumArgs)&&(r+="}"),r+=t.c+";return u",e("h,j,k,l,o,p,r","return function("+n+"){"+r+"}")(Vt,H,fe,tt,le,a,P)
}function D(n){return"\\"+N[n]}function z(n){return se[n]}function L(n){return typeof n.toString!="function"&&typeof(n+"")=="string"}function K(n){this.__wrapped__=n}function M(){}function U(n){var t=!1;if(!n||Qt.call(n)!=E||!ie.argsClass&&H(n))return t;var e=n.constructor;return(Y(e)?e instanceof e:ie.nodeClass||!L(n))?ie.ownLast?(ye(n,function(n,e,r){return t=Vt.call(r,e),!1}),!0===t):(ye(n,function(n,e){t=e}),!1===t||Vt.call(n,t)):t}function V(n,t,e){t||(t=0),typeof e=="undefined"&&(e=n?n.length:0);
var r=-1;e=e-t||0;for(var u=Ot(0>e?0:e);++r<e;)u[r]=n[t+r];return u}function G(n){return ve[n]}function H(n){return Qt.call(n)==C}function J(n,t,r,u,o,i){var f=n;if(typeof t=="function"&&(u=r,r=t,t=!1),typeof r=="function"){if(r=typeof u=="undefined"?r:a.createCallback(r,u,1),f=r(f),typeof f!="undefined")return f;f=n}if(u=Z(f)){var c=Qt.call(f);if(!I[c]||!ie.nodeClass&&L(f))return f;var l=fe(f)}if(!u||!t)return u?l?V(f):ge({},f):f;switch(u=oe[c],c){case j:case k:return new u(+f);case O:case A:return new u(f);
case S:return u(f.source,v.exec(f))}for(o||(o=[]),i||(i=[]),c=o.length;c--;)if(o[c]==n)return i[c];return f=l?u(f.length):{},l&&(Vt.call(n,"index")&&(f.index=n.index),Vt.call(n,"input")&&(f.input=n.input)),o.push(n),i.push(f),(l?ft:me)(n,function(n,u){f[u]=J(n,t,r,e,o,i)}),f}function Q(n){var t=[];return ye(n,function(n,e){Y(n)&&t.push(e)}),t.sort()}function W(n){for(var t=-1,e=le(n),r=e.length,u={};++t<r;){var a=e[t];u[n[a]]=a}return u}function X(n,t,e,r,u,o){var f=e===i;if(e&&!f){e=typeof r=="undefined"?e:a.createCallback(e,r,2);
var c=e(n,t);if(typeof c!="undefined")return!!c}if(n===t)return 0!==n||1/n==1/t;var l=typeof n,p=typeof t;if(n===n&&(!n||"function"!=l&&"object"!=l)&&(!t||"function"!=p&&"object"!=p))return!1;if(null==n||null==t)return n===t;if(p=Qt.call(n),l=Qt.call(t),p==C&&(p=E),l==C&&(l=E),p!=l)return!1;switch(p){case j:case k:return+n==+t;case O:return n!=+n?t!=+t:0==n?1/n==1/t:n==+t;case S:case A:return n==qt(t)}if(l=p==w,!l){if(Vt.call(n,"__wrapped__")||Vt.call(t,"__wrapped__"))return X(n.__wrapped__||n,t.__wrapped__||t,e,r,u,o);
if(p!=E||!ie.nodeClass&&(L(n)||L(t)))return!1;var p=!ie.argsObject&&H(n)?Nt:n.constructor,s=!ie.argsObject&&H(t)?Nt:t.constructor;if(p!=s&&(!Y(p)||!(p instanceof p&&Y(s)&&s instanceof s)))return!1}for(u||(u=[]),o||(o=[]),p=u.length;p--;)if(u[p]==n)return o[p]==t;var v=0,c=!0;if(u.push(n),o.push(t),l){if(p=n.length,v=t.length,c=v==n.length,!c&&!f)return c;for(;v--;)if(l=p,s=t[v],f)for(;l--&&!(c=X(n[l],s,e,r,u,o)););else if(!(c=X(n[v],s,e,r,u,o)))break;return c}return ye(t,function(t,a,i){return Vt.call(i,a)?(v++,c=Vt.call(n,a)&&X(n[a],t,e,r,u,o)):void 0
}),c&&!f&&ye(n,function(n,t,e){return Vt.call(e,t)?c=-1<--v:void 0}),c}function Y(n){return typeof n=="function"}function Z(n){return n?P[typeof n]:!1}function nt(n){return typeof n=="number"||Qt.call(n)==O}function tt(n){return typeof n=="string"||Qt.call(n)==A}function et(n,t,e){var r=arguments,u=0,o=2;if(!Z(n))return n;if(e===i)var f=r[3],c=r[4],l=r[5];else c=[],l=[],typeof e!="number"&&(o=r.length),3<o&&"function"==typeof r[o-2]?f=a.createCallback(r[--o-1],r[o--],2):2<o&&"function"==typeof r[o-1]&&(f=r[--o]);
for(;++u<o;)(fe(r[u])?ft:me)(r[u],function(t,e){var r,u,a=t,o=n[e];if(t&&((u=fe(t))||de(t))){for(a=c.length;a--;)if(r=c[a]==t){o=l[a];break}r||(o=u?fe(o)?o:[]:de(o)?o:{},f&&(a=f(o,t),typeof a!="undefined"&&(o=a)),c.push(t),l.push(o),f||(o=et(o,t,i,f,c,l)))}else f&&(a=f(o,t),typeof a=="undefined"&&(a=t)),typeof a!="undefined"&&(o=a);n[e]=o});return n}function rt(n){for(var t=-1,e=le(n),r=e.length,u=Ot(r);++t<r;)u[t]=n[e[t]];return u}function ut(n,t,e){var r=-1,u=n?n.length:0,a=!1;return e=(0>e?te(0,u+e):e)||0,typeof u=="number"?a=-1<(tt(n)?n.indexOf(t,e):yt(n,t,e)):pe(n,function(n){return++r<e?void 0:!(a=n===t)
}),a}function at(n,t,e){var r=!0;if(t=a.createCallback(t,e),fe(n)){e=-1;for(var u=n.length;++e<u&&(r=!!t(n[e],e,n)););}else pe(n,function(n,e,u){return r=!!t(n,e,u)});return r}function ot(n,t,e){var r=[];if(t=a.createCallback(t,e),fe(n)){e=-1;for(var u=n.length;++e<u;){var o=n[e];t(o,e,n)&&r.push(o)}}else pe(n,function(n,e,u){t(n,e,u)&&r.push(n)});return r}function it(n,t,e){if(t=a.createCallback(t,e),!fe(n)){var r;return pe(n,function(n,e,u){return t(n,e,u)?(r=n,!1):void 0}),r}e=-1;for(var u=n.length;++e<u;){var o=n[e];
if(t(o,e,n))return o}}function ft(n,t,e){if(t&&typeof e=="undefined"&&fe(n)){e=-1;for(var r=n.length;++e<r&&!1!==t(n[e],e,n););}else pe(n,t,e);return n}function ct(n,t,e){var r=-1,u=n?n.length:0,o=Ot(typeof u=="number"?u:0);if(t=a.createCallback(t,e),fe(n))for(;++r<u;)o[r]=t(n[r],r,n);else pe(n,function(n,e,u){o[++r]=t(n,e,u)});return o}function lt(n,t,e){var r=-1/0,u=r;if(!t&&fe(n)){e=-1;for(var o=n.length;++e<o;){var i=n[e];i>u&&(u=i)}}else t=!t&&tt(n)?B:a.createCallback(t,e),pe(n,function(n,e,a){e=t(n,e,a),e>r&&(r=e,u=n)
});return u}function pt(n,t,e,r){var u=3>arguments.length;if(t=a.createCallback(t,r,4),fe(n)){var o=-1,i=n.length;for(u&&(e=n[++o]);++o<i;)e=t(e,n[o],o,n)}else pe(n,function(n,r,a){e=u?(u=!1,n):t(e,n,r,a)});return e}function st(n,t,e,r){var u=n,o=n?n.length:0,i=3>arguments.length;if(typeof o!="number")var f=le(n),o=f.length;else ie.unindexedChars&&tt(n)&&(u=n.split(""));return t=a.createCallback(t,r,4),ft(n,function(n,r,a){r=f?f[--o]:--o,e=i?(i=!1,u[r]):t(e,u[r],r,a)}),e}function vt(n,t,e){var r;
if(t=a.createCallback(t,e),fe(n)){e=-1;for(var u=n.length;++e<u&&!(r=t(n[e],e,n)););}else pe(n,function(n,e,u){return!(r=t(n,e,u))});return!!r}function gt(n,t,e){if(n){var r=0,u=n.length;if(typeof t!="number"&&null!=t){var o=-1;for(t=a.createCallback(t,e);++o<u&&t(n[o],o,n);)r++}else if(r=t,null==r||e)return n[0];return V(n,0,ee(te(0,r),u))}}function ht(n,t,e,r){var u=-1,o=n?n.length:0,i=[];for(typeof t!="boolean"&&null!=t&&(r=e,e=t,t=!1),null!=e&&(e=a.createCallback(e,r));++u<o;)r=n[u],e&&(r=e(r,u,n)),fe(r)?Gt.apply(i,t?r:ht(r)):i.push(r);
return i}function yt(n,t,e){var r=-1,u=n?n.length:0;if(typeof e=="number")r=(0>e?te(0,u+e):e||0)-1;else if(e)return r=dt(n,t),n[r]===t?r:-1;for(;++r<u;)if(n[r]===t)return r;return-1}function mt(n,t,e){if(typeof t!="number"&&null!=t){var r=0,u=-1,o=n?n.length:0;for(t=a.createCallback(t,e);++u<o&&t(n[u],u,n);)r++}else r=null==t||e?1:te(0,t);return V(n,r)}function dt(n,t,e,r){var u=0,o=n?n.length:u;for(e=e?a.createCallback(e,r,1):jt,t=e(t);u<o;)r=u+o>>>1,e(n[r])<t?u=r+1:o=r;return u}function bt(n,t,e,r){var u=-1,o=n?n.length:0,i=[],f=i;
typeof t!="boolean"&&null!=t&&(r=e,e=t,t=!1);var c=!t&&75<=o;if(c)var l={};for(null!=e&&(f=[],e=a.createCallback(e,r));++u<o;){r=n[u];var p=e?e(r,u,n):r;if(c)var s=qt(p),s=Vt.call(l,s)?!(f=l[s]):f=l[s]=[];(t?!u||f[f.length-1]!==p:s||0>yt(f,p))&&((e||c)&&f.push(p),i.push(r))}return i}function _t(n,t){for(var e=-1,r=n?n.length:0,u={};++e<r;){var a=n[e];t?u[a]=t[e]:u[a[0]]=a[1]}return u}function Ct(n,t){return ie.fastBind||Wt&&2<arguments.length?Wt.call.apply(Wt,arguments):R(n,t,V(arguments,2))}function wt(n){var t=V(arguments,1);
return Jt(function(){n.apply(e,t)},1)}function jt(n){return n}function kt(n){ft(Q(n),function(t){var e=a[t]=n[t];a.prototype[t]=function(){var n=this.__wrapped__,t=[n];return Gt.apply(t,arguments),t=e.apply(a,t),n&&typeof n=="object"&&n==t?this:new K(t)}})}function xt(){return this.__wrapped__}r=r?$.defaults(n.Object(),r,$.pick(n,b)):n;var Ot=r.Array,Et=r.Boolean,St=r.Date,At=r.Function,It=r.Math,Pt=r.Number,Nt=r.Object,$t=r.RegExp,qt=r.String,Bt=r.TypeError,Ft=Ot(),Rt=Nt(),Tt=r._,Dt=$t("^"+qt(Rt.valueOf).replace(/[.*+?^${}()|[\]\\]/g,"\\$&").replace(/valueOf|for [^\]]+/g,".+?")+"$"),zt=It.ceil,Lt=r.clearTimeout,Kt=Ft.concat,Mt=It.floor,Ut=Dt.test(Ut=Nt.getPrototypeOf)&&Ut,Vt=Rt.hasOwnProperty,Gt=Ft.push,Ht=r.setImmediate,Jt=r.setTimeout,Qt=Rt.toString,Wt=Dt.test(Wt=V.bind)&&Wt,Xt=Dt.test(Xt=Ot.isArray)&&Xt,Yt=r.isFinite,Zt=r.isNaN,ne=Dt.test(ne=Nt.keys)&&ne,te=It.max,ee=It.min,re=r.parseInt,ue=It.random,It=Dt.test(r.attachEvent),ae=Wt&&!/\n|true/.test(Wt+It),oe={};
oe[w]=Ot,oe[j]=Et,oe[k]=St,oe[E]=Nt,oe[O]=Pt,oe[S]=$t,oe[A]=qt;var ie=a.support={};(function(){var n=function(){this.x=1},t={0:1,length:1},e=[];n.prototype={valueOf:1,y:1};for(var r in new n)e.push(r);for(r in arguments);ie.argsObject=arguments.constructor==Nt,ie.argsClass=H(arguments),ie.enumPrototypes=n.propertyIsEnumerable("prototype"),ie.fastBind=Wt&&!ae,ie.ownLast="x"!=e[0],ie.nonEnumArgs=0!=r,ie.nonEnumShadows=!/valueOf/.test(e),ie.spliceObjects=(Ft.splice.call(t,0,1),!t[0]),ie.unindexedChars="xx"!="x"[0]+Nt("x")[0];
try{ie.nodeClass=!(Qt.call(document)==E&&!({toString:0}+""))}catch(u){ie.nodeClass=!0}})(1),a.templateSettings={escape:/<%-([\s\S]+?)%>/g,evaluate:/<%([\s\S]+?)%>/g,interpolate:g,variable:"",imports:{_:a}},Et={a:"q,w,g",h:"var a=arguments,b=0,c=typeof g=='number'?2:a.length;while(++b<c){m=a[b];if(m&&r[typeof m]){",f:"if(typeof u[i]=='undefined')u[i]=m[i]",c:"}}"},Pt={a:"e,d,x",h:"d=d&&typeof x=='undefined'?d:p.createCallback(d,x)",b:"typeof n=='number'",f:"if(d(m[i],i,e)===false)return u"},It={h:"if(!r[typeof m])return u;"+Pt.h,b:!1},K.prototype=a.prototype,ie.argsClass||(H=function(n){return n?Vt.call(n,"callee"):!1
});var fe=Xt||function(n){return ie.argsObject&&n instanceof Ot||Qt.call(n)==w},ce=T({a:"q",e:"[]",h:"if(!(r[typeof q]))return u",f:"u.push(i)",b:!1}),le=ne?function(n){return Z(n)?ie.enumPrototypes&&typeof n=="function"||ie.nonEnumArgs&&n.length&&H(n)?ce(n):ne(n):[]}:ce,pe=T(Pt),se={"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;"},ve=W(se),ge=T(Et,{h:Et.h.replace(";",";if(c>3&&typeof a[c-2]=='function'){var d=p.createCallback(a[--c-1],a[c--],2);}else if(c>2&&typeof a[c-1]=='function'){d=a[--c];}"),f:"u[i]=d?d(u[i],m[i]):m[i]"}),he=T(Et),ye=T(Pt,It,{i:!1}),me=T(Pt,It);
Y(/x/)&&(Y=function(n){return n instanceof At||Qt.call(n)==x});var de=Ut?function(n){if(!n||Qt.call(n)!=E||!ie.argsClass&&H(n))return!1;var t=n.valueOf,e=typeof t=="function"&&(e=Ut(t))&&Ut(e);return e?n==e||Ut(n)==e:U(n)}:U;return ae&&u&&typeof Ht=="function"&&(wt=Ct(Ht,r)),Ht=8==re("08")?re:function(n,t){return re(tt(n)?n.replace(h,""):n,t||0)},a.after=function(n,t){return 1>n?t():function(){return 1>--n?t.apply(this,arguments):void 0}},a.assign=ge,a.at=function(n){var t=-1,e=Kt.apply(Ft,V(arguments,1)),r=e.length,u=Ot(r);
for(ie.unindexedChars&&tt(n)&&(n=n.split(""));++t<r;)u[t]=n[e[t]];return u},a.bind=Ct,a.bindAll=function(n){for(var t=Kt.apply(Ft,arguments),e=1<t.length?0:(t=Q(n),-1),r=t.length;++e<r;){var u=t[e];n[u]=Ct(n[u],n)}return n},a.bindKey=function(n,t){return R(n,t,V(arguments,2),i)},a.compact=function(n){for(var t=-1,e=n?n.length:0,r=[];++t<e;){var u=n[t];u&&r.push(u)}return r},a.compose=function(){var n=arguments;return function(){for(var t=arguments,e=n.length;e--;)t=[n[e].apply(this,t)];return t[0]
}},a.countBy=function(n,t,e){var r={};return t=a.createCallback(t,e),ft(n,function(n,e,u){e=qt(t(n,e,u)),Vt.call(r,e)?r[e]++:r[e]=1}),r},a.createCallback=function(n,t,e){if(null==n)return jt;var r=typeof n;if("function"!=r){if("object"!=r)return function(t){return t[n]};var u=le(n);return function(t){for(var e=u.length,r=!1;e--&&(r=X(t[u[e]],n[u[e]],i)););return r}}return typeof t!="undefined"?1===e?function(e){return n.call(t,e)}:2===e?function(e,r){return n.call(t,e,r)}:4===e?function(e,r,u,a){return n.call(t,e,r,u,a)
}:function(e,r,u){return n.call(t,e,r,u)}:n},a.debounce=function(n,t,e){function r(){i=null,e||(a=n.apply(o,u))}var u,a,o,i;return function(){var f=e&&!i;return u=arguments,o=this,Lt(i),i=Jt(r,t),f&&(a=n.apply(o,u)),a}},a.defaults=he,a.defer=wt,a.delay=function(n,t){var r=V(arguments,2);return Jt(function(){n.apply(e,r)},t)},a.difference=function(n){for(var t=-1,e=n?n.length:0,r=Kt.apply(Ft,arguments),r=q(r,e,100),u=[];++t<e;){var a=n[t];r(a)||u.push(a)}return u},a.filter=ot,a.flatten=ht,a.forEach=ft,a.forIn=ye,a.forOwn=me,a.functions=Q,a.groupBy=function(n,t,e){var r={};
return t=a.createCallback(t,e),ft(n,function(n,e,u){e=qt(t(n,e,u)),(Vt.call(r,e)?r[e]:r[e]=[]).push(n)}),r},a.initial=function(n,t,e){if(!n)return[];var r=0,u=n.length;if(typeof t!="number"&&null!=t){var o=u;for(t=a.createCallback(t,e);o--&&t(n[o],o,n);)r++}else r=null==t||e?1:t||r;return V(n,0,ee(te(0,u-r),u))},a.intersection=function(n){var t=arguments,e=t.length,r={0:{}},u=-1,a=n?n.length:0,o=100<=a,i=[],f=i;n:for(;++u<a;){var c=n[u];if(o)var l=qt(c),l=Vt.call(r[0],l)?!(f=r[0][l]):f=r[0][l]=[];
if(l||0>yt(f,c)){o&&f.push(c);for(var p=e;--p;)if(!(r[p]||(r[p]=q(t[p],0,100)))(c))continue n;i.push(c)}}return i},a.invert=W,a.invoke=function(n,t){var e=V(arguments,2),r=-1,u=typeof t=="function",a=n?n.length:0,o=Ot(typeof a=="number"?a:0);return ft(n,function(n){o[++r]=(u?t:n[t]).apply(n,e)}),o},a.keys=le,a.map=ct,a.max=lt,a.memoize=function(n,t){var e={};return function(){var r=qt(t?t.apply(this,arguments):arguments[0]);return Vt.call(e,r)?e[r]:e[r]=n.apply(this,arguments)}},a.merge=et,a.min=function(n,t,e){var r=1/0,u=r;
if(!t&&fe(n)){e=-1;for(var o=n.length;++e<o;){var i=n[e];i<u&&(u=i)}}else t=!t&&tt(n)?B:a.createCallback(t,e),pe(n,function(n,e,a){e=t(n,e,a),e<r&&(r=e,u=n)});return u},a.omit=function(n,t,e){var r=typeof t=="function",u={};if(r)t=a.createCallback(t,e);else var o=Kt.apply(Ft,arguments);return ye(n,function(n,e,a){(r?!t(n,e,a):0>yt(o,e,1))&&(u[e]=n)}),u},a.once=function(n){var t,e;return function(){return t?e:(t=!0,e=n.apply(this,arguments),n=null,e)}},a.pairs=function(n){for(var t=-1,e=le(n),r=e.length,u=Ot(r);++t<r;){var a=e[t];
u[t]=[a,n[a]]}return u},a.partial=function(n){return R(n,V(arguments,1))},a.partialRight=function(n){return R(n,V(arguments,1),null,i)},a.pick=function(n,t,e){var r={};if(typeof t!="function")for(var u=0,o=Kt.apply(Ft,arguments),i=Z(n)?o.length:0;++u<i;){var f=o[u];f in n&&(r[f]=n[f])}else t=a.createCallback(t,e),ye(n,function(n,e,u){t(n,e,u)&&(r[e]=n)});return r},a.pluck=ct,a.range=function(n,t,e){n=+n||0,e=+e||1,null==t&&(t=n,n=0);var r=-1;t=te(0,zt((t-n)/e));for(var u=Ot(t);++r<t;)u[r]=n,n+=e;
return u},a.reject=function(n,t,e){return t=a.createCallback(t,e),ot(n,function(n,e,r){return!t(n,e,r)})},a.rest=mt,a.shuffle=function(n){var t=-1,e=n?n.length:0,r=Ot(typeof e=="number"?e:0);return ft(n,function(n){var e=Mt(ue()*(++t+1));r[t]=r[e],r[e]=n}),r},a.sortBy=function(n,t,e){var r=-1,u=n?n.length:0,o=Ot(typeof u=="number"?u:0);for(t=a.createCallback(t,e),ft(n,function(n,e,u){o[++r]={a:t(n,e,u),b:r,c:n}}),u=o.length,o.sort(F);u--;)o[u]=o[u].c;return o},a.tap=function(n,t){return t(n),n},a.throttle=function(n,t){function e(){i=new St,o=null,u=n.apply(a,r)
}var r,u,a,o,i=0;return function(){var f=new St,c=t-(f-i);return r=arguments,a=this,0<c?o||(o=Jt(e,c)):(Lt(o),o=null,i=f,u=n.apply(a,r)),u}},a.times=function(n,t,e){n=-1<(n=+n)?n:0;var r=-1,u=Ot(n);for(t=a.createCallback(t,e,1);++r<n;)u[r]=t(r);return u},a.toArray=function(n){return n&&typeof n.length=="number"?ie.unindexedChars&&tt(n)?n.split(""):V(n):rt(n)},a.union=function(){return bt(Kt.apply(Ft,arguments))},a.uniq=bt,a.values=rt,a.where=ot,a.without=function(n){for(var t=-1,e=n?n.length:0,r=q(arguments,1,30),u=[];++t<e;){var a=n[t];
r(a)||u.push(a)}return u},a.wrap=function(n,t){return function(){var e=[n];return Gt.apply(e,arguments),t.apply(this,e)}},a.zip=function(n){for(var t=-1,e=n?lt(ct(arguments,"length")):0,r=Ot(e);++t<e;)r[t]=ct(arguments,t);return r},a.zipObject=_t,a.collect=ct,a.drop=mt,a.each=ft,a.extend=ge,a.methods=Q,a.object=_t,a.select=ot,a.tail=mt,a.unique=bt,kt(a),a.clone=J,a.cloneDeep=function(n,t,e){return J(n,!0,t,e)},a.contains=ut,a.escape=function(n){return null==n?"":qt(n).replace(m,z)},a.every=at,a.find=it,a.findIndex=function(n,t,e){var r=-1,u=n?n.length:0;
for(t=a.createCallback(t,e);++r<u;)if(t(n[r],r,n))return r;return-1},a.findKey=function(n,t,e){var r;return t=a.createCallback(t,e),me(n,function(n,e,u){return t(n,e,u)?(r=e,!1):void 0}),r},a.has=function(n,t){return n?Vt.call(n,t):!1},a.identity=jt,a.indexOf=yt,a.isArguments=H,a.isArray=fe,a.isBoolean=function(n){return!0===n||!1===n||Qt.call(n)==j},a.isDate=function(n){return n instanceof St||Qt.call(n)==k},a.isElement=function(n){return n?1===n.nodeType:!1},a.isEmpty=function(n){var t=!0;if(!n)return t;
var e=Qt.call(n),r=n.length;return e==w||e==A||(ie.argsClass?e==C:H(n))||e==E&&typeof r=="number"&&Y(n.splice)?!r:(me(n,function(){return t=!1}),t)},a.isEqual=X,a.isFinite=function(n){return Yt(n)&&!Zt(parseFloat(n))},a.isFunction=Y,a.isNaN=function(n){return nt(n)&&n!=+n},a.isNull=function(n){return null===n},a.isNumber=nt,a.isObject=Z,a.isPlainObject=de,a.isRegExp=function(n){return n instanceof $t||Qt.call(n)==S},a.isString=tt,a.isUndefined=function(n){return typeof n=="undefined"},a.lastIndexOf=function(n,t,e){var r=n?n.length:0;
for(typeof e=="number"&&(r=(0>e?te(0,r+e):ee(e,r-1))+1);r--;)if(n[r]===t)return r;return-1},a.mixin=kt,a.noConflict=function(){return r._=Tt,this},a.parseInt=Ht,a.random=function(n,t){return null==n&&null==t&&(t=1),n=+n||0,null==t&&(t=n,n=0),n+Mt(ue()*((+t||0)-n+1))},a.reduce=pt,a.reduceRight=st,a.result=function(n,t){var r=n?n[t]:e;return Y(r)?n[t]():r},a.runInContext=t,a.size=function(n){var t=n?n.length:0;return typeof t=="number"?t:le(n).length},a.some=vt,a.sortedIndex=dt,a.template=function(n,t,r){var u=a.templateSettings;
n||(n=""),r=he({},r,u);var o,i=he({},r.imports,u.imports),u=le(i),i=rt(i),p=0,v=r.interpolate||y,h="__p+='",v=$t((r.escape||y).source+"|"+v.source+"|"+(v===g?s:y).source+"|"+(r.evaluate||y).source+"|$","g");n.replace(v,function(t,e,r,u,a,i){return r||(r=u),h+=n.slice(p,i).replace(d,D),e&&(h+="'+__e("+e+")+'"),a&&(o=!0,h+="';"+a+";__p+='"),r&&(h+="'+((__t=("+r+"))==null?'':__t)+'"),p=i+t.length,t}),h+="';\n",v=r=r.variable,v||(r="obj",h="with("+r+"){"+h+"}"),h=(o?h.replace(f,""):h).replace(c,"$1").replace(l,"$1;"),h="function("+r+"){"+(v?"":r+"||("+r+"={});")+"var __t,__p='',__e=_.escape"+(o?",__j=Array.prototype.join;function print(){__p+=__j.call(arguments,'')}":";")+h+"return __p}";
try{var m=At(u,"return "+h).apply(e,i)}catch(b){throw b.source=h,b}return t?m(t):(m.source=h,m)},a.unescape=function(n){return null==n?"":qt(n).replace(p,G)},a.uniqueId=function(n){var t=++o;return qt(null==n?"":n)+t},a.all=at,a.any=vt,a.detect=it,a.foldl=pt,a.foldr=st,a.include=ut,a.inject=pt,me(a,function(n,t){a.prototype[t]||(a.prototype[t]=function(){var t=[this.__wrapped__];return Gt.apply(t,arguments),n.apply(a,t)})}),a.first=gt,a.last=function(n,t,e){if(n){var r=0,u=n.length;if(typeof t!="number"&&null!=t){var o=u;
for(t=a.createCallback(t,e);o--&&t(n[o],o,n);)r++}else if(r=t,null==r||e)return n[u-1];return V(n,te(0,u-r))}},a.take=gt,a.head=gt,me(a,function(n,t){a.prototype[t]||(a.prototype[t]=function(t,e){var r=n(this.__wrapped__,t,e);return null==t||e&&typeof t!="function"?r:new K(r)})}),a.VERSION="1.1.1",a.prototype.toString=function(){return qt(this.__wrapped__)},a.prototype.value=xt,a.prototype.valueOf=xt,pe(["join","pop","shift"],function(n){var t=Ft[n];a.prototype[n]=function(){return t.apply(this.__wrapped__,arguments)
}}),pe(["push","reverse","sort","unshift"],function(n){var t=Ft[n];a.prototype[n]=function(){return t.apply(this.__wrapped__,arguments),this}}),pe(["concat","slice","splice"],function(n){var t=Ft[n];a.prototype[n]=function(){return new K(t.apply(this.__wrapped__,arguments))}}),ie.spliceObjects||pe(["pop","shift","splice"],function(n){var t=Ft[n],e="splice"==n;a.prototype[n]=function(){var n=this.__wrapped__,r=t.apply(n,arguments);return 0===n.length&&delete n[0],e?new K(r):r}}),a}var e,r=typeof exports=="object"&&exports,u=typeof module=="object"&&module&&module.exports==r&&module,a=typeof global=="object"&&global;
a.global===a&&(n=a);var o=0,i={},f=/\b__p\+='';/g,c=/\b(__p\+=)''\+/g,l=/(__e\(.*?\)|\b__t\))\+'';/g,p=/&(?:amp|lt|gt|quot|#39);/g,s=/\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g,v=/\w*$/,g=/<%=([\s\S]+?)%>/g,h=/^0+(?=.$)/,y=/($^)/,m=/[&<>"']/g,d=/['\n\r\t\u2028\u2029\\]/g,b="Array Boolean Date Function Math Number Object RegExp String _ attachEvent clearTimeout isFinite isNaN parseInt setImmediate setTimeout".split(" "),_="constructor hasOwnProperty isPrototypeOf propertyIsEnumerable toLocaleString toString valueOf".split(" "),C="[object Arguments]",w="[object Array]",j="[object Boolean]",k="[object Date]",x="[object Function]",O="[object Number]",E="[object Object]",S="[object RegExp]",A="[object String]",I={};
I[x]=!1,I[C]=I[w]=I[j]=I[k]=I[O]=I[E]=I[S]=I[A]=!0;var P={"boolean":!1,"function":!0,object:!0,number:!1,string:!1,undefined:!1},N={"\\":"\\","'":"'","\n":"n","\r":"r"," ":"t","\u2028":"u2028","\u2029":"u2029"},$=t();typeof define=="function"&&typeof define.amd=="object"&&define.amd?(n._=$,define(function(){return $})):r&&!r.nodeType?u?(u.exports=$)._=$:r._=$:n._=$})(this);

5217
dist/lodash.js vendored Normal file

File diff suppressed because it is too large Load Diff

42
dist/lodash.min.js vendored Normal file
View File

@@ -0,0 +1,42 @@
/**
* @license
* Lo-Dash 1.1.1 (Custom Build) lodash.com/license
* Build: `lodash modern -o ./dist/lodash.js`
* Underscore.js 1.4.4 underscorejs.org/LICENSE
*/
;(function(n){function t(r){function a(n){return n&&typeof n=="object"&&!ae(n)&&Ut.call(n,"__wrapped__")?n:new z(n)}function $(n,t,e){var r=n.length,u=r-t>=e;if(u){var a={};for(e=t-1;++e<r;){var o=$t(n[e]);(Ut.call(a,o)?a[o]:a[o]=[]).push(n[e])}}return function(e){if(u){var r=$t(e);return Ut.call(a,r)&&-1<gt(a[r],e)}return-1<gt(n,e,t)}}function q(n){return n.charCodeAt(0)}function B(n,t){var e=n.b,r=t.b;if(n=n.a,t=t.a,n!==t){if(n>t||typeof n=="undefined")return 1;if(n<t||typeof t=="undefined")return-1
}return e<r?-1:1}function F(n,t,e,r){function u(){var r=arguments,c=o?this:t;return a||(n=t[i]),e.length&&(r=r.length?(r=M(r),f?r.concat(e):e.concat(r)):e),this instanceof u?(P.prototype=n.prototype,c=new P,P.prototype=null,r=n.apply(c,r),W(r)?r:c):n.apply(c,r)}var a=Q(n),o=!e,i=t;if(o){var f=r;e=t}else if(!a){if(!r)throw new qt;t=n}return u}function R(){for(var n,t={b:"k(m)",c:"",e:"m",f:"",h:"",i:!0,j:!!oe},e=0;n=arguments[e];e++)for(var r in n)t[r]=n[r];return n=t.a,t.d=/^[^,]+/.exec(n)[0],e=Nt,r="var i,m="+t.d+",u="+t.e+";if(!m)return u;"+t.h+";",t.b&&(r+="var n=m.length;i=-1;if("+t.b+"){while(++i<n){"+t.f+"}}else{"),t.i&&t.j?r+="var s=-1,t=r[typeof m]?o(m):[],n=t.length;while(++s<n){i=t[s];"+t.f+"}":(r+="for(i in m){",t.i&&(r+="if(",t.i&&(r+="h.call(m,i)"),r+="){"),r+=t.f+";",t.i&&(r+="}"),r+="}"),t.b&&(r+="}"),r+=t.c+";return u",e("h,j,k,l,o,p,r","return function("+n+"){"+r+"}")(Ut,V,ae,Y,oe,a,I)
}function T(n){return"\\"+S[n]}function D(n){return ie[n]}function z(n){this.__wrapped__=n}function P(){}function K(n){var t=!1;if(!n||Jt.call(n)!=x)return t;var e=n.constructor;return(Q(e)?e instanceof e:ue.nodeClass||!isNode(n))?(pe(n,function(n,e){t=e}),!1===t||Ut.call(n,t)):t}function M(n,t,e){t||(t=0),typeof e=="undefined"&&(e=n?n.length:0);var r=-1;e=e-t||0;for(var u=Ct(0>e?0:e);++r<e;)u[r]=n[t+r];return u}function U(n){return fe[n]}function V(n){return Jt.call(n)==_}function G(n,t,r,u,o,i){var f=n;
if(typeof t=="function"&&(u=r,r=t,t=!1),typeof r=="function"){if(r=typeof u=="undefined"?r:a.createCallback(r,u,1),f=r(f),typeof f!="undefined")return f;f=n}if(u=W(f)){var c=Jt.call(f);if(!E[c])return f;var l=ae(f)}if(!u||!t)return u?l?M(f):ce({},f):f;switch(u=re[c],c){case w:case j:return new u(+f);case C:case N:return new u(f);case O:return u(f.source,v.exec(f))}for(o||(o=[]),i||(i=[]),c=o.length;c--;)if(o[c]==n)return i[c];return f=l?u(f.length):{},l&&(Ut.call(n,"index")&&(f.index=n.index),Ut.call(n,"input")&&(f.input=n.input)),o.push(n),i.push(f),(l?at:se)(n,function(n,u){f[u]=G(n,t,r,e,o,i)
}),f}function H(n){var t=[];return pe(n,function(n,e){Q(n)&&t.push(e)}),t.sort()}function J(n){for(var t=-1,e=oe(n),r=e.length,u={};++t<r;){var a=e[t];u[n[a]]=a}return u}function L(n,t,e,r,u,o){var f=e===i;if(e&&!f){e=typeof r=="undefined"?e:a.createCallback(e,r,2);var c=e(n,t);if(typeof c!="undefined")return!!c}if(n===t)return 0!==n||1/n==1/t;var l=typeof n,p=typeof t;if(n===n&&(!n||"function"!=l&&"object"!=l)&&(!t||"function"!=p&&"object"!=p))return!1;if(null==n||null==t)return n===t;if(p=Jt.call(n),l=Jt.call(t),p==_&&(p=x),l==_&&(l=x),p!=l)return!1;
switch(p){case w:case j:return+n==+t;case C:return n!=+n?t!=+t:0==n?1/n==1/t:n==+t;case O:case N:return n==$t(t)}if(l=p==k,!l){if(Ut.call(n,"__wrapped__")||Ut.call(t,"__wrapped__"))return L(n.__wrapped__||n,t.__wrapped__||t,e,r,u,o);if(p!=x)return!1;var p=n.constructor,s=t.constructor;if(p!=s&&(!Q(p)||!(p instanceof p&&Q(s)&&s instanceof s)))return!1}for(u||(u=[]),o||(o=[]),p=u.length;p--;)if(u[p]==n)return o[p]==t;var v=0,c=!0;if(u.push(n),o.push(t),l){if(p=n.length,v=t.length,c=v==n.length,!c&&!f)return c;
for(;v--;)if(l=p,s=t[v],f)for(;l--&&!(c=L(n[l],s,e,r,u,o)););else if(!(c=L(n[v],s,e,r,u,o)))break;return c}return pe(t,function(t,a,i){return Ut.call(i,a)?(v++,c=Ut.call(n,a)&&L(n[a],t,e,r,u,o)):void 0}),c&&!f&&pe(n,function(n,t,e){return Ut.call(e,t)?c=-1<--v:void 0}),c}function Q(n){return typeof n=="function"}function W(n){return n?I[typeof n]:!1}function X(n){return typeof n=="number"||Jt.call(n)==C}function Y(n){return typeof n=="string"||Jt.call(n)==N}function Z(n,t,e){var r=arguments,u=0,o=2;
if(!W(n))return n;if(e===i)var f=r[3],c=r[4],l=r[5];else c=[],l=[],typeof e!="number"&&(o=r.length),3<o&&"function"==typeof r[o-2]?f=a.createCallback(r[--o-1],r[o--],2):2<o&&"function"==typeof r[o-1]&&(f=r[--o]);for(;++u<o;)(ae(r[u])?at:se)(r[u],function(t,e){var r,u,a=t,o=n[e];if(t&&((u=ae(t))||ve(t))){for(a=c.length;a--;)if(r=c[a]==t){o=l[a];break}r||(o=u?ae(o)?o:[]:ve(o)?o:{},f&&(a=f(o,t),typeof a!="undefined"&&(o=a)),c.push(t),l.push(o),f||(o=Z(o,t,i,f,c,l)))}else f&&(a=f(o,t),typeof a=="undefined"&&(a=t)),typeof a!="undefined"&&(o=a);
n[e]=o});return n}function nt(n){for(var t=-1,e=oe(n),r=e.length,u=Ct(r);++t<r;)u[t]=n[e[t]];return u}function tt(n,t,e){var r=-1,u=n?n.length:0,a=!1;return e=(0>e?Zt(0,u+e):e)||0,typeof u=="number"?a=-1<(Y(n)?n.indexOf(t,e):gt(n,t,e)):se(n,function(n){return++r<e?void 0:!(a=n===t)}),a}function et(n,t,e){var r=!0;t=a.createCallback(t,e),e=-1;var u=n?n.length:0;if(typeof u=="number")for(;++e<u&&(r=!!t(n[e],e,n)););else se(n,function(n,e,u){return r=!!t(n,e,u)});return r}function rt(n,t,e){var r=[];
t=a.createCallback(t,e),e=-1;var u=n?n.length:0;if(typeof u=="number")for(;++e<u;){var o=n[e];t(o,e,n)&&r.push(o)}else se(n,function(n,e,u){t(n,e,u)&&r.push(n)});return r}function ut(n,t,e){t=a.createCallback(t,e),e=-1;var r=n?n.length:0;if(typeof r!="number"){var u;return se(n,function(n,e,r){return t(n,e,r)?(u=n,!1):void 0}),u}for(;++e<r;){var o=n[e];if(t(o,e,n))return o}}function at(n,t,e){var r=-1,u=n?n.length:0;if(t=t&&typeof e=="undefined"?t:a.createCallback(t,e),typeof u=="number")for(;++r<u&&!1!==t(n[r],r,n););else se(n,t);
return n}function ot(n,t,e){var r=-1,u=n?n.length:0;if(t=a.createCallback(t,e),typeof u=="number")for(var o=Ct(u);++r<u;)o[r]=t(n[r],r,n);else o=[],se(n,function(n,e,u){o[++r]=t(n,e,u)});return o}function it(n,t,e){var r=-1/0,u=r;if(!t&&ae(n)){e=-1;for(var o=n.length;++e<o;){var i=n[e];i>u&&(u=i)}}else t=!t&&Y(n)?q:a.createCallback(t,e),at(n,function(n,e,a){e=t(n,e,a),e>r&&(r=e,u=n)});return u}function ft(n,t){var e=-1,r=n?n.length:0;if(typeof r=="number")for(var u=Ct(r);++e<r;)u[e]=n[e][t];return u||ot(n,t)
}function ct(n,t,e,r){if(!n)return e;var u=3>arguments.length;t=a.createCallback(t,r,4);var o=-1,i=n.length;if(typeof i=="number")for(u&&(e=n[++o]);++o<i;)e=t(e,n[o],o,n);else se(n,function(n,r,a){e=u?(u=!1,n):t(e,n,r,a)});return e}function lt(n,t,e,r){var u=n?n.length:0,o=3>arguments.length;if(typeof u!="number")var i=oe(n),u=i.length;return t=a.createCallback(t,r,4),at(n,function(r,a,f){a=i?i[--u]:--u,e=o?(o=!1,n[a]):t(e,n[a],a,f)}),e}function pt(n,t,e){var r;t=a.createCallback(t,e),e=-1;var u=n?n.length:0;
if(typeof u=="number")for(;++e<u&&!(r=t(n[e],e,n)););else se(n,function(n,e,u){return!(r=t(n,e,u))});return!!r}function st(n,t,e){if(n){var r=0,u=n.length;if(typeof t!="number"&&null!=t){var o=-1;for(t=a.createCallback(t,e);++o<u&&t(n[o],o,n);)r++}else if(r=t,null==r||e)return n[0];return M(n,0,ne(Zt(0,r),u))}}function vt(n,t,e,r){var u=-1,o=n?n.length:0,i=[];for(typeof t!="boolean"&&null!=t&&(r=e,e=t,t=!1),null!=e&&(e=a.createCallback(e,r));++u<o;)r=n[u],e&&(r=e(r,u,n)),ae(r)?Vt.apply(i,t?r:vt(r)):i.push(r);
return i}function gt(n,t,e){var r=-1,u=n?n.length:0;if(typeof e=="number")r=(0>e?Zt(0,u+e):e||0)-1;else if(e)return r=yt(n,t),n[r]===t?r:-1;for(;++r<u;)if(n[r]===t)return r;return-1}function ht(n,t,e){if(typeof t!="number"&&null!=t){var r=0,u=-1,o=n?n.length:0;for(t=a.createCallback(t,e);++u<o&&t(n[u],u,n);)r++}else r=null==t||e?1:Zt(0,t);return M(n,r)}function yt(n,t,e,r){var u=0,o=n?n.length:u;for(e=e?a.createCallback(e,r,1):kt,t=e(t);u<o;)r=u+o>>>1,e(n[r])<t?u=r+1:o=r;return u}function mt(n,t,e,r){var u=-1,o=n?n.length:0,i=[],f=i;
typeof t!="boolean"&&null!=t&&(r=e,e=t,t=!1);var c=!t&&75<=o;if(c)var l={};for(null!=e&&(f=[],e=a.createCallback(e,r));++u<o;){r=n[u];var p=e?e(r,u,n):r;if(c)var s=$t(p),s=Ut.call(l,s)?!(f=l[s]):f=l[s]=[];(t?!u||f[f.length-1]!==p:s||0>gt(f,p))&&((e||c)&&f.push(p),i.push(r))}return i}function bt(n,t){for(var e=-1,r=n?n.length:0,u={};++e<r;){var a=n[e];t?u[a]=t[e]:u[a[0]]=a[1]}return u}function dt(n,t){return ue.fastBind||Lt&&2<arguments.length?Lt.call.apply(Lt,arguments):F(n,t,M(arguments,2))}function _t(n){var t=M(arguments,1);
return Ht(function(){n.apply(e,t)},1)}function kt(n){return n}function wt(n){at(H(n),function(t){var e=a[t]=n[t];a.prototype[t]=function(){var n=this.__wrapped__,t=[n];return Vt.apply(t,arguments),t=e.apply(a,t),n&&typeof n=="object"&&n==t?this:new z(t)}})}function jt(){return this.__wrapped__}r=r?A.defaults(n.Object(),r,A.pick(n,d)):n;var Ct=r.Array,xt=r.Boolean,Ot=r.Date,Nt=r.Function,Et=r.Math,It=r.Number,St=r.Object,At=r.RegExp,$t=r.String,qt=r.TypeError,Bt=Ct(),Ft=St(),Rt=r._,Tt=At("^"+$t(Ft.valueOf).replace(/[.*+?^${}()|[\]\\]/g,"\\$&").replace(/valueOf|for [^\]]+/g,".+?")+"$"),Dt=Et.ceil,zt=r.clearTimeout,Pt=Bt.concat,Kt=Et.floor,Mt=Tt.test(Mt=St.getPrototypeOf)&&Mt,Ut=Ft.hasOwnProperty,Vt=Bt.push,Gt=r.setImmediate,Ht=r.setTimeout,Jt=Ft.toString,Lt=Tt.test(Lt=M.bind)&&Lt,Qt=Tt.test(Qt=Ct.isArray)&&Qt,Wt=r.isFinite,Xt=r.isNaN,Yt=Tt.test(Yt=St.keys)&&Yt,Zt=Et.max,ne=Et.min,te=r.parseInt,ee=Et.random,Et=Tt.test(r.attachEvent),Et=Lt&&!/\n|true/.test(Lt+Et),re={};
re[k]=Ct,re[w]=xt,re[j]=Ot,re[x]=St,re[C]=It,re[O]=At,re[N]=$t;var ue=a.support={};ue.fastBind=Lt&&!Et,a.templateSettings={escape:/<%-([\s\S]+?)%>/g,evaluate:/<%([\s\S]+?)%>/g,interpolate:g,variable:"",imports:{_:a}},xt={a:"q,w,g",h:"var a=arguments,b=0,c=typeof g=='number'?2:a.length;while(++b<c){m=a[b];if(m&&r[typeof m]){",f:"if(typeof u[i]=='undefined')u[i]=m[i]",c:"}}"},It={a:"e,d,x",h:"d=d&&typeof x=='undefined'?d:p.createCallback(d,x)",b:!1,f:"if(d(m[i],i,e)===false)return u"},St={h:"if(!r[typeof m])return u;"+It.h,b:!1},z.prototype=a.prototype;
var ae=Qt||function(n){return n instanceof Ct||Jt.call(n)==k},Qt=R({a:"q",e:"[]",h:"if(!(r[typeof q]))return u",f:"u.push(i)",b:!1}),oe=Yt?function(n){return W(n)?Yt(n):[]}:Qt,ie={"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;"},fe=J(ie),ce=R(xt,{h:xt.h.replace(";",";if(c>3&&typeof a[c-2]=='function'){var d=p.createCallback(a[--c-1],a[c--],2);}else if(c>2&&typeof a[c-1]=='function'){d=a[--c];}"),f:"u[i]=d?d(u[i],m[i]):m[i]"}),le=R(xt),pe=R(It,St,{i:!1}),se=R(It,St),ve=function(n){if(!n||Jt.call(n)!=x)return!1;
var t=n.valueOf,e=typeof t=="function"&&(e=Mt(t))&&Mt(e);return e?n==e||Mt(n)==e:K(n)};return Et&&u&&typeof Gt=="function"&&(_t=dt(Gt,r)),Gt=8==te("08")?te:function(n,t){return te(Y(n)?n.replace(h,""):n,t||0)},a.after=function(n,t){return 1>n?t():function(){return 1>--n?t.apply(this,arguments):void 0}},a.assign=ce,a.at=function(n){for(var t=-1,e=Pt.apply(Bt,M(arguments,1)),r=e.length,u=Ct(r);++t<r;)u[t]=n[e[t]];return u},a.bind=dt,a.bindAll=function(n){for(var t=Pt.apply(Bt,arguments),e=1<t.length?0:(t=H(n),-1),r=t.length;++e<r;){var u=t[e];
n[u]=dt(n[u],n)}return n},a.bindKey=function(n,t){return F(n,t,M(arguments,2),i)},a.compact=function(n){for(var t=-1,e=n?n.length:0,r=[];++t<e;){var u=n[t];u&&r.push(u)}return r},a.compose=function(){var n=arguments;return function(){for(var t=arguments,e=n.length;e--;)t=[n[e].apply(this,t)];return t[0]}},a.countBy=function(n,t,e){var r={};return t=a.createCallback(t,e),at(n,function(n,e,u){e=$t(t(n,e,u)),Ut.call(r,e)?r[e]++:r[e]=1}),r},a.createCallback=function(n,t,e){if(null==n)return kt;var r=typeof n;
if("function"!=r){if("object"!=r)return function(t){return t[n]};var u=oe(n);return function(t){for(var e=u.length,r=!1;e--&&(r=L(t[u[e]],n[u[e]],i)););return r}}return typeof t!="undefined"?1===e?function(e){return n.call(t,e)}:2===e?function(e,r){return n.call(t,e,r)}:4===e?function(e,r,u,a){return n.call(t,e,r,u,a)}:function(e,r,u){return n.call(t,e,r,u)}:n},a.debounce=function(n,t,e){function r(){i=null,e||(a=n.apply(o,u))}var u,a,o,i;return function(){var f=e&&!i;return u=arguments,o=this,zt(i),i=Ht(r,t),f&&(a=n.apply(o,u)),a
}},a.defaults=le,a.defer=_t,a.delay=function(n,t){var r=M(arguments,2);return Ht(function(){n.apply(e,r)},t)},a.difference=function(n){for(var t=-1,e=n?n.length:0,r=Pt.apply(Bt,arguments),r=$(r,e,100),u=[];++t<e;){var a=n[t];r(a)||u.push(a)}return u},a.filter=rt,a.flatten=vt,a.forEach=at,a.forIn=pe,a.forOwn=se,a.functions=H,a.groupBy=function(n,t,e){var r={};return t=a.createCallback(t,e),at(n,function(n,e,u){e=$t(t(n,e,u)),(Ut.call(r,e)?r[e]:r[e]=[]).push(n)}),r},a.initial=function(n,t,e){if(!n)return[];
var r=0,u=n.length;if(typeof t!="number"&&null!=t){var o=u;for(t=a.createCallback(t,e);o--&&t(n[o],o,n);)r++}else r=null==t||e?1:t||r;return M(n,0,ne(Zt(0,u-r),u))},a.intersection=function(n){var t=arguments,e=t.length,r={0:{}},u=-1,a=n?n.length:0,o=100<=a,i=[],f=i;n:for(;++u<a;){var c=n[u];if(o)var l=$t(c),l=Ut.call(r[0],l)?!(f=r[0][l]):f=r[0][l]=[];if(l||0>gt(f,c)){o&&f.push(c);for(var p=e;--p;)if(!(r[p]||(r[p]=$(t[p],0,100)))(c))continue n;i.push(c)}}return i},a.invert=J,a.invoke=function(n,t){var e=M(arguments,2),r=-1,u=typeof t=="function",a=n?n.length:0,o=Ct(typeof a=="number"?a:0);
return at(n,function(n){o[++r]=(u?t:n[t]).apply(n,e)}),o},a.keys=oe,a.map=ot,a.max=it,a.memoize=function(n,t){var e={};return function(){var r=$t(t?t.apply(this,arguments):arguments[0]);return Ut.call(e,r)?e[r]:e[r]=n.apply(this,arguments)}},a.merge=Z,a.min=function(n,t,e){var r=1/0,u=r;if(!t&&ae(n)){e=-1;for(var o=n.length;++e<o;){var i=n[e];i<u&&(u=i)}}else t=!t&&Y(n)?q:a.createCallback(t,e),at(n,function(n,e,a){e=t(n,e,a),e<r&&(r=e,u=n)});return u},a.omit=function(n,t,e){var r=typeof t=="function",u={};
if(r)t=a.createCallback(t,e);else var o=Pt.apply(Bt,arguments);return pe(n,function(n,e,a){(r?!t(n,e,a):0>gt(o,e,1))&&(u[e]=n)}),u},a.once=function(n){var t,e;return function(){return t?e:(t=!0,e=n.apply(this,arguments),n=null,e)}},a.pairs=function(n){for(var t=-1,e=oe(n),r=e.length,u=Ct(r);++t<r;){var a=e[t];u[t]=[a,n[a]]}return u},a.partial=function(n){return F(n,M(arguments,1))},a.partialRight=function(n){return F(n,M(arguments,1),null,i)},a.pick=function(n,t,e){var r={};if(typeof t!="function")for(var u=0,o=Pt.apply(Bt,arguments),i=W(n)?o.length:0;++u<i;){var f=o[u];
f in n&&(r[f]=n[f])}else t=a.createCallback(t,e),pe(n,function(n,e,u){t(n,e,u)&&(r[e]=n)});return r},a.pluck=ft,a.range=function(n,t,e){n=+n||0,e=+e||1,null==t&&(t=n,n=0);var r=-1;t=Zt(0,Dt((t-n)/e));for(var u=Ct(t);++r<t;)u[r]=n,n+=e;return u},a.reject=function(n,t,e){return t=a.createCallback(t,e),rt(n,function(n,e,r){return!t(n,e,r)})},a.rest=ht,a.shuffle=function(n){var t=-1,e=n?n.length:0,r=Ct(typeof e=="number"?e:0);return at(n,function(n){var e=Kt(ee()*(++t+1));r[t]=r[e],r[e]=n}),r},a.sortBy=function(n,t,e){var r=-1,u=n?n.length:0,o=Ct(typeof u=="number"?u:0);
for(t=a.createCallback(t,e),at(n,function(n,e,u){o[++r]={a:t(n,e,u),b:r,c:n}}),u=o.length,o.sort(B);u--;)o[u]=o[u].c;return o},a.tap=function(n,t){return t(n),n},a.throttle=function(n,t){function e(){i=new Ot,o=null,u=n.apply(a,r)}var r,u,a,o,i=0;return function(){var f=new Ot,c=t-(f-i);return r=arguments,a=this,0<c?o||(o=Ht(e,c)):(zt(o),o=null,i=f,u=n.apply(a,r)),u}},a.times=function(n,t,e){n=-1<(n=+n)?n:0;var r=-1,u=Ct(n);for(t=a.createCallback(t,e,1);++r<n;)u[r]=t(r);return u},a.toArray=function(n){return n&&typeof n.length=="number"?M(n):nt(n)
},a.union=function(){return mt(Pt.apply(Bt,arguments))},a.uniq=mt,a.values=nt,a.where=rt,a.without=function(n){for(var t=-1,e=n?n.length:0,r=$(arguments,1,30),u=[];++t<e;){var a=n[t];r(a)||u.push(a)}return u},a.wrap=function(n,t){return function(){var e=[n];return Vt.apply(e,arguments),t.apply(this,e)}},a.zip=function(n){for(var t=-1,e=n?it(ft(arguments,"length")):0,r=Ct(e);++t<e;)r[t]=ft(arguments,t);return r},a.zipObject=bt,a.collect=ot,a.drop=ht,a.each=at,a.extend=ce,a.methods=H,a.object=bt,a.select=rt,a.tail=ht,a.unique=mt,wt(a),a.clone=G,a.cloneDeep=function(n,t,e){return G(n,!0,t,e)
},a.contains=tt,a.escape=function(n){return null==n?"":$t(n).replace(m,D)},a.every=et,a.find=ut,a.findIndex=function(n,t,e){var r=-1,u=n?n.length:0;for(t=a.createCallback(t,e);++r<u;)if(t(n[r],r,n))return r;return-1},a.findKey=function(n,t,e){var r;return t=a.createCallback(t,e),se(n,function(n,e,u){return t(n,e,u)?(r=e,!1):void 0}),r},a.has=function(n,t){return n?Ut.call(n,t):!1},a.identity=kt,a.indexOf=gt,a.isArguments=V,a.isArray=ae,a.isBoolean=function(n){return!0===n||!1===n||Jt.call(n)==w},a.isDate=function(n){return n instanceof Ot||Jt.call(n)==j
},a.isElement=function(n){return n?1===n.nodeType:!1},a.isEmpty=function(n){var t=!0;if(!n)return t;var e=Jt.call(n),r=n.length;return e==k||e==N||e==_||e==x&&typeof r=="number"&&Q(n.splice)?!r:(se(n,function(){return t=!1}),t)},a.isEqual=L,a.isFinite=function(n){return Wt(n)&&!Xt(parseFloat(n))},a.isFunction=Q,a.isNaN=function(n){return X(n)&&n!=+n},a.isNull=function(n){return null===n},a.isNumber=X,a.isObject=W,a.isPlainObject=ve,a.isRegExp=function(n){return n instanceof At||Jt.call(n)==O},a.isString=Y,a.isUndefined=function(n){return typeof n=="undefined"
},a.lastIndexOf=function(n,t,e){var r=n?n.length:0;for(typeof e=="number"&&(r=(0>e?Zt(0,r+e):ne(e,r-1))+1);r--;)if(n[r]===t)return r;return-1},a.mixin=wt,a.noConflict=function(){return r._=Rt,this},a.parseInt=Gt,a.random=function(n,t){return null==n&&null==t&&(t=1),n=+n||0,null==t&&(t=n,n=0),n+Kt(ee()*((+t||0)-n+1))},a.reduce=ct,a.reduceRight=lt,a.result=function(n,t){var r=n?n[t]:e;return Q(r)?n[t]():r},a.runInContext=t,a.size=function(n){var t=n?n.length:0;return typeof t=="number"?t:oe(n).length
},a.some=pt,a.sortedIndex=yt,a.template=function(n,t,r){var u=a.templateSettings;n||(n=""),r=le({},r,u);var o,i=le({},r.imports,u.imports),u=oe(i),i=nt(i),p=0,v=r.interpolate||y,h="__p+='",v=At((r.escape||y).source+"|"+v.source+"|"+(v===g?s:y).source+"|"+(r.evaluate||y).source+"|$","g");n.replace(v,function(t,e,r,u,a,i){return r||(r=u),h+=n.slice(p,i).replace(b,T),e&&(h+="'+__e("+e+")+'"),a&&(o=!0,h+="';"+a+";__p+='"),r&&(h+="'+((__t=("+r+"))==null?'':__t)+'"),p=i+t.length,t}),h+="';\n",v=r=r.variable,v||(r="obj",h="with("+r+"){"+h+"}"),h=(o?h.replace(f,""):h).replace(c,"$1").replace(l,"$1;"),h="function("+r+"){"+(v?"":r+"||("+r+"={});")+"var __t,__p='',__e=_.escape"+(o?",__j=Array.prototype.join;function print(){__p+=__j.call(arguments,'')}":";")+h+"return __p}";
try{var m=Nt(u,"return "+h).apply(e,i)}catch(d){throw d.source=h,d}return t?m(t):(m.source=h,m)},a.unescape=function(n){return null==n?"":$t(n).replace(p,U)},a.uniqueId=function(n){var t=++o;return $t(null==n?"":n)+t},a.all=et,a.any=pt,a.detect=ut,a.foldl=ct,a.foldr=lt,a.include=tt,a.inject=ct,se(a,function(n,t){a.prototype[t]||(a.prototype[t]=function(){var t=[this.__wrapped__];return Vt.apply(t,arguments),n.apply(a,t)})}),a.first=st,a.last=function(n,t,e){if(n){var r=0,u=n.length;if(typeof t!="number"&&null!=t){var o=u;
for(t=a.createCallback(t,e);o--&&t(n[o],o,n);)r++}else if(r=t,null==r||e)return n[u-1];return M(n,Zt(0,u-r))}},a.take=st,a.head=st,se(a,function(n,t){a.prototype[t]||(a.prototype[t]=function(t,e){var r=n(this.__wrapped__,t,e);return null==t||e&&typeof t!="function"?r:new z(r)})}),a.VERSION="1.1.1",a.prototype.toString=function(){return $t(this.__wrapped__)},a.prototype.value=jt,a.prototype.valueOf=jt,at(["join","pop","shift"],function(n){var t=Bt[n];a.prototype[n]=function(){return t.apply(this.__wrapped__,arguments)
}}),at(["push","reverse","sort","unshift"],function(n){var t=Bt[n];a.prototype[n]=function(){return t.apply(this.__wrapped__,arguments),this}}),at(["concat","slice","splice"],function(n){var t=Bt[n];a.prototype[n]=function(){return new z(t.apply(this.__wrapped__,arguments))}}),a}var e,r=typeof exports=="object"&&exports,u=typeof module=="object"&&module&&module.exports==r&&module,a=typeof global=="object"&&global;a.global===a&&(n=a);var o=0,i={},f=/\b__p\+='';/g,c=/\b(__p\+=)''\+/g,l=/(__e\(.*?\)|\b__t\))\+'';/g,p=/&(?:amp|lt|gt|quot|#39);/g,s=/\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g,v=/\w*$/,g=/<%=([\s\S]+?)%>/g,h=/^0+(?=.$)/,y=/($^)/,m=/[&<>"']/g,b=/['\n\r\t\u2028\u2029\\]/g,d="Array Boolean Date Function Math Number Object RegExp String _ attachEvent clearTimeout isFinite isNaN parseInt setImmediate setTimeout".split(" "),_="[object Arguments]",k="[object Array]",w="[object Boolean]",j="[object Date]",C="[object Number]",x="[object Object]",O="[object RegExp]",N="[object String]",E={"[object Function]":!1};
E[_]=E[k]=E[w]=E[j]=E[C]=E[x]=E[O]=E[N]=!0;var I={"boolean":!1,"function":!0,object:!0,number:!1,string:!1,undefined:!1},S={"\\":"\\","'":"'","\n":"n","\r":"r"," ":"t","\u2028":"u2028","\u2029":"u2029"},A=t();typeof define=="function"&&typeof define.amd=="object"&&define.amd?(n._=A,define(function(){return A})):r&&!r.nodeType?u?(u.exports=A)._=A:r._=A:n._=A})(this);

4355
dist/lodash.underscore.js vendored Normal file

File diff suppressed because it is too large Load Diff

34
dist/lodash.underscore.min.js vendored Normal file
View File

@@ -0,0 +1,34 @@
/**
* @license
* Lo-Dash 1.1.1 (Custom Build) lodash.com/license
* Build: `lodash underscore exports="amd,commonjs,global,node" -o ./dist/lodash.underscore.js`
* Underscore.js 1.4.4 underscorejs.org/LICENSE
*/
;(function(n){function t(n,t){var r;if(n&&st[typeof n])for(r in n)if(jt.call(n,r)&&t(n[r],r,n)===Z)break}function r(n,t){var r;if(n&&st[typeof n])for(r in n)if(t(n[r],r,n)===Z)break}function e(n){var t,r=[];if(!n||!st[typeof n])return r;for(t in n)jt.call(n,t)&&r.push(t);return r}function u(n){return n instanceof u?n:new c(n)}function o(n,t){var r=n.b,e=t.b;if(n=n.a,t=t.a,n!==t){if(n>t||typeof n=="undefined")return 1;if(n<t||typeof t=="undefined")return-1}return r<e?-1:1}function i(n,t,r){function e(){var f=arguments,c=o?this:t;
return u||(n=t[i]),r.length&&(f=f.length?(f=xt.call(f),a?f.concat(r):r.concat(f)):r),this instanceof e?(l.prototype=n.prototype,c=new l,l.prototype=J,f=n.apply(c,f),d(f)?f:c):n.apply(c,f)}var u=b(n),o=!r,i=t;if(o){var a=void 0;r=t}else if(!u)throw new TypeError;return e}function a(n){return"\\"+vt[n]}function f(n){return It[n]}function c(n){this.__wrapped__=n}function l(){}function p(n){return zt[n]}function s(n){return Ot.call(n)==ut}function v(n){if(!n)return n;for(var t=1,r=arguments.length;t<r;t++){var e=arguments[t];
if(e)for(var u in e)n[u]=e[u]}return n}function g(n){if(!n)return n;for(var t=1,r=arguments.length;t<r;t++){var e=arguments[t];if(e)for(var u in e)n[u]==J&&(n[u]=e[u])}return n}function h(n){var t=[];return r(n,function(n,r){b(n)&&t.push(r)}),t.sort()}function y(n){for(var t=-1,r=$t(n),e=r.length,u={};++t<e;){var o=r[t];u[n[o]]=o}return u}function m(n){if(!n)return H;if(Tt(n)||w(n))return!n.length;for(var t in n)if(jt.call(n,t))return K;return H}function _(n,t,e,o){if(n===t)return 0!==n||1/n==1/t;
var i=typeof n,a=typeof t;if(n===n&&(!n||"function"!=i&&"object"!=i)&&(!t||"function"!=a&&"object"!=a))return K;if(n==J||t==J)return n===t;if(a=Ot.call(n),i=Ot.call(t),a!=i)return K;switch(a){case it:case at:return+n==+t;case ft:return n!=+n?t!=+t:0==n?1/n==1/t:n==+t;case lt:case pt:return n==t+""}if(i=a==ot,!i){if(n instanceof u||t instanceof u)return _(n.__wrapped__||n,t.__wrapped__||t,e,o);if(a!=ct)return K;var a=n.constructor,f=t.constructor;if(a!=f&&(!b(a)||!(a instanceof a&&b(f)&&f instanceof f)))return K
}for(e||(e=[]),o||(o=[]),a=e.length;a--;)if(e[a]==n)return o[a]==t;var c=H,l=0;if(e.push(n),o.push(t),i){if(l=t.length,c=l==n.length)for(;l--&&(c=_(n[l],t[l],e,o)););return c}return r(t,function(t,r,u){return jt.call(u,r)?(l++,!(c=jt.call(n,r)&&_(n[r],t,e,o))&&Z):void 0}),c&&r(n,function(n,t,r){return jt.call(r,t)?!(c=-1<--l)&&Z:void 0}),c}function b(n){return typeof n=="function"}function d(n){return n?st[typeof n]:K}function j(n){return typeof n=="number"||Ot.call(n)==ft}function w(n){return typeof n=="string"||Ot.call(n)==pt
}function A(n){for(var t=-1,r=$t(n),e=r.length,u=Array(e);++t<e;)u[t]=n[r[t]];return u}function x(n,r){var e=K;return typeof(n?n.length:0)=="number"?e=-1<I(n,r):t(n,function(n){return(e=n===r)&&Z}),e}function O(n,r,e){var u=H;r=V(r,e),e=-1;var o=n?n.length:0;if(typeof o=="number")for(;++e<o&&(u=!!r(n[e],e,n)););else t(n,function(n,t,e){return!(u=!!r(n,t,e))&&Z});return u}function E(n,r,e){var u=[];r=V(r,e),e=-1;var o=n?n.length:0;if(typeof o=="number")for(;++e<o;){var i=n[e];r(i,e,n)&&u.push(i)}else t(n,function(n,t,e){r(n,t,e)&&u.push(n)
});return u}function S(n,r,e){r=V(r,e),e=-1;var u=n?n.length:0;if(typeof u!="number"){var o;return t(n,function(n,t,e){return r(n,t,e)?(o=n,Z):void 0}),o}for(;++e<u;){var i=n[e];if(r(i,e,n))return i}}function N(n,r,e){var u=-1,o=n?n.length:0;if(r=r&&typeof e=="undefined"?r:V(r,e),typeof o=="number")for(;++u<o&&r(n[u],u,n)!==Z;);else t(n,r)}function k(n,r,e){var u=-1,o=n?n.length:0;if(r=V(r,e),typeof o=="number")for(var i=Array(o);++u<o;)i[u]=r(n[u],u,n);else i=[],t(n,function(n,t,e){i[++u]=r(n,t,e)
});return i}function B(n,t,r){var e=-1/0,u=e,o=-1,i=n?n.length:0;if(t||typeof i!="number")t=V(t,r),N(n,function(n,r,o){r=t(n,r,o),r>e&&(e=r,u=n)});else for(;++o<i;)r=n[o],r>u&&(u=r);return u}function F(n,t){var r=-1,e=n?n.length:0;if(typeof e=="number")for(var u=Array(e);++r<e;)u[r]=n[r][t];return u||k(n,t)}function R(n,r,e,u){if(!n)return e;var o=3>arguments.length;r=V(r,u,4);var i=-1,a=n.length;if(typeof a=="number")for(o&&(e=n[++i]);++i<a;)e=r(e,n[i],i,n);else t(n,function(n,t,u){e=o?(o=K,n):r(e,n,t,u)
});return e}function q(n,t,r,e){var u=n?n.length:0,o=3>arguments.length;if(typeof u!="number")var i=$t(n),u=i.length;return t=V(t,e,4),N(n,function(e,a,f){a=i?i[--u]:--u,r=o?(o=K,n[a]):t(r,n[a],a,f)}),r}function D(n,r,e){var u;r=V(r,e),e=-1;var o=n?n.length:0;if(typeof o=="number")for(;++e<o&&!(u=r(n[e],e,n)););else t(n,function(n,t,e){return(u=r(n,t,e))&&Z});return!!u}function M(n,t,r){return r&&m(t)?J:(r?S:E)(n,t)}function T(n,t,r){if(n){var e=0,u=n.length;if(typeof t!="number"&&t!=J){var o=-1;
for(t=V(t,r);++o<u&&t(n[o],o,n);)e++}else if(e=t,e==J||r)return n[0];return xt.call(n,0,Rt(Ft(0,e),u))}}function $(n,t){for(var r=-1,e=n?n.length:0,u=[];++r<e;){var o=n[r];Tt(o)?wt.apply(u,t?o:$(o)):u.push(o)}return u}function I(n,t,r){var e=-1,u=n?n.length:0;if(typeof r=="number")e=(0>r?Ft(0,u+r):r||0)-1;else if(r)return e=C(n,t),n[e]===t?e:-1;for(;++e<u;)if(n[e]===t)return e;return-1}function z(n,t,r){if(typeof t!="number"&&t!=J){var e=0,u=-1,o=n?n.length:0;for(t=V(t,r);++u<o&&t(n[u],u,n);)e++}else e=t==J||r?1:Ft(0,t);
return xt.call(n,e)}function C(n,t,r,e){var u=0,o=n?n.length:u;for(r=r?V(r,e,1):W,t=r(t);u<o;)e=u+o>>>1,r(n[e])<t?u=e+1:o=e;return u}function P(n,t,r,e){var u=-1,o=n?n.length:0,i=[],a=i;for(typeof t!="boolean"&&t!=J&&(e=r,r=t,t=K),r!=J&&(a=[],r=V(r,e));++u<o;){e=n[u];var f=r?r(e,u,n):e;(t?!u||a[a.length-1]!==f:0>I(a,f))&&(r&&a.push(f),i.push(e))}return i}function U(n,t){return Mt.fastBind||Et&&2<arguments.length?Et.call.apply(Et,arguments):i(n,t,xt.call(arguments,2))}function V(n,t,r){if(n==J)return W;
var e=typeof n;if("function"!=e){if("object"!=e)return function(t){return t[n]};var u=$t(n);return function(t){for(var r=u.length,e=K;r--&&(e=t[u[r]]===n[u[r]]););return e}}return typeof t!="undefined"?1===r?function(r){return n.call(t,r)}:2===r?function(r,e){return n.call(t,r,e)}:4===r?function(r,e,u,o){return n.call(t,r,e,u,o)}:function(r,e,u){return n.call(t,r,e,u)}:n}function W(n){return n}function G(n){N(h(n),function(t){var r=u[t]=n[t];u.prototype[t]=function(){var n=[this.__wrapped__];return wt.apply(n,arguments),n=r.apply(u,n),this.__chain__&&(n=new c(n),n.__chain__=H),n
}})}var H=!0,J=null,K=!1,L=typeof exports=="object"&&exports,Q=typeof module=="object"&&module&&module.exports==L&&module,X=typeof global=="object"&&global;X.global===X&&(n=X);var Y=0,Z={},nt=/&(?:amp|lt|gt|quot|#39);/g,tt=/($^)/,rt=/[&<>"']/g,et=/['\n\r\t\u2028\u2029\\]/g,ut="[object Arguments]",ot="[object Array]",it="[object Boolean]",at="[object Date]",ft="[object Number]",ct="[object Object]",lt="[object RegExp]",pt="[object String]",st={"boolean":K,"function":H,object:H,number:K,string:K,undefined:K},vt={"\\":"\\","'":"'","\n":"n","\r":"r"," ":"t","\u2028":"u2028","\u2029":"u2029"},gt=[],X={},ht=n._,yt=RegExp("^"+(X.valueOf+"").replace(/[.*+?^${}()|[\]\\]/g,"\\$&").replace(/valueOf|for [^\]]+/g,".+?")+"$"),mt=Math.ceil,_t=n.clearTimeout,bt=gt.concat,dt=Math.floor,jt=X.hasOwnProperty,wt=gt.push,At=n.setTimeout,xt=gt.slice,Ot=X.toString,Et=yt.test(Et=xt.bind)&&Et,St=yt.test(St=Array.isArray)&&St,Nt=n.isFinite,kt=n.isNaN,Bt=yt.test(Bt=Object.keys)&&Bt,Ft=Math.max,Rt=Math.min,qt=Math.random,X=yt.test(n.attachEvent),Dt=Et&&!/\n|true/.test(Et+X),Mt={};
(function(){var n={0:1,length:1};Mt.argsObject=arguments.constructor==Object,Mt.fastBind=Et&&!Dt,Mt.spliceObjects=(gt.splice.call(n,0,1),!n[0])})(1),u.templateSettings={escape:/<%-([\s\S]+?)%>/g,evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,variable:""},c.prototype=u.prototype,s(arguments)||(s=function(n){return n?jt.call(n,"callee"):K});var Tt=St||function(n){return Mt.argsObject&&n instanceof Array||Ot.call(n)==ot},$t=Bt?function(n){return d(n)?Bt(n):[]}:e,It={"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;"},zt=y(It);
b(/x/)&&(b=function(n){return n instanceof Function||"[object Function]"==Ot.call(n)}),u.after=function(n,t){return 1>n?t():function(){return 1>--n?t.apply(this,arguments):void 0}},u.bind=U,u.bindAll=function(n){for(var t=bt.apply(gt,arguments),r=1<t.length?0:(t=h(n),-1),e=t.length;++r<e;){var u=t[r];n[u]=U(n[u],n)}return n},u.compact=function(n){for(var t=-1,r=n?n.length:0,e=[];++t<r;){var u=n[t];u&&e.push(u)}return e},u.compose=function(){var n=arguments;return function(){for(var t=arguments,r=n.length;r--;)t=[n[r].apply(this,t)];
return t[0]}},u.countBy=function(n,t,r){var e={};return t=V(t,r),N(n,function(n,r,u){r=t(n,r,u)+"",jt.call(e,r)?e[r]++:e[r]=1}),e},u.debounce=function(n,t,r){function e(){a=J,r||(o=n.apply(i,u))}var u,o,i,a;return function(){var f=r&&!a;return u=arguments,i=this,_t(a),a=At(e,t),f&&(o=n.apply(i,u)),o}},u.defaults=g,u.defer=function(n){var t=xt.call(arguments,1);return At(function(){n.apply(void 0,t)},1)},u.delay=function(n,t){var r=xt.call(arguments,2);return At(function(){n.apply(void 0,r)},t)},u.difference=function(n){for(var t=-1,r=n.length,e=bt.apply(gt,arguments),u=[];++t<r;){var o=n[t];
0>I(e,o,r)&&u.push(o)}return u},u.filter=E,u.flatten=$,u.forEach=N,u.functions=h,u.groupBy=function(n,t,r){var e={};return t=V(t,r),N(n,function(n,r,u){r=t(n,r,u)+"",(jt.call(e,r)?e[r]:e[r]=[]).push(n)}),e},u.initial=function(n,t,r){if(!n)return[];var e=0,u=n.length;if(typeof t!="number"&&t!=J){var o=u;for(t=V(t,r);o--&&t(n[o],o,n);)e++}else e=t==J||r?1:t||e;return xt.call(n,0,Rt(Ft(0,u-e),u))},u.intersection=function(n){var t=arguments,r=t.length,e=-1,u=n?n.length:0,o=[];n:for(;++e<u;){var i=n[e];
if(0>I(o,i)){for(var a=r;--a;)if(0>I(t[a],i))continue n;o.push(i)}}return o},u.invert=y,u.invoke=function(n,t){var r=xt.call(arguments,2),e=-1,u=typeof t=="function",o=n?n.length:0,i=Array(typeof o=="number"?o:0);return N(n,function(n){i[++e]=(u?t:n[t]).apply(n,r)}),i},u.keys=$t,u.map=k,u.max=B,u.memoize=function(n,t){var r={};return function(){var e=(t?t.apply(this,arguments):arguments[0])+"";return jt.call(r,e)?r[e]:r[e]=n.apply(this,arguments)}},u.min=function(n,t,r){var e=1/0,u=e,o=-1,i=n?n.length:0;
if(t||typeof i!="number")t=V(t,r),N(n,function(n,r,o){r=t(n,r,o),r<e&&(e=r,u=n)});else for(;++o<i;)r=n[o],r<u&&(u=r);return u},u.omit=function(n){var t=bt.apply(gt,arguments),e={};return r(n,function(n,r){0>I(t,r,1)&&(e[r]=n)}),e},u.once=function(n){var t,r;return function(){return t?r:(t=H,r=n.apply(this,arguments),n=J,r)}},u.pairs=function(n){for(var t=-1,r=$t(n),e=r.length,u=Array(e);++t<e;){var o=r[t];u[t]=[o,n[o]]}return u},u.partial=function(n){return i(n,xt.call(arguments,1))},u.pick=function(n){for(var t=0,r=bt.apply(gt,arguments),e=r.length,u={};++t<e;){var o=r[t];
o in n&&(u[o]=n[o])}return u},u.pluck=F,u.range=function(n,t,r){n=+n||0,r=+r||1,t==J&&(t=n,n=0);var e=-1;t=Ft(0,mt((t-n)/r));for(var u=Array(t);++e<t;)u[e]=n,n+=r;return u},u.reject=function(n,t,r){return t=V(t,r),E(n,function(n,r,e){return!t(n,r,e)})},u.rest=z,u.shuffle=function(n){var t=-1,r=n?n.length:0,e=Array(typeof r=="number"?r:0);return N(n,function(n){var r=dt(qt()*(++t+1));e[t]=e[r],e[r]=n}),e},u.sortBy=function(n,t,r){var e=-1,u=n?n.length:0,i=Array(typeof u=="number"?u:0);for(t=V(t,r),N(n,function(n,r,u){i[++e]={a:t(n,r,u),b:e,c:n}
}),u=i.length,i.sort(o);u--;)i[u]=i[u].c;return i},u.tap=function(n,t){return t(n),n},u.throttle=function(n,t){function r(){a=new Date,i=J,u=n.apply(o,e)}var e,u,o,i,a=0;return function(){var f=new Date,c=t-(f-a);return e=arguments,o=this,0<c?i||(i=At(r,c)):(_t(i),i=J,a=f,u=n.apply(o,e)),u}},u.times=function(n,t,r){for(var e=-1,u=Array(-1<n?n:0);++e<n;)u[e]=t.call(r,e);return u},u.toArray=function(n){return Tt(n)?xt.call(n):n&&typeof n.length=="number"?k(n):A(n)},u.union=function(){return P(bt.apply(gt,arguments))
},u.uniq=P,u.values=A,u.where=M,u.without=function(n){for(var t=-1,r=n.length,e=[];++t<r;){var u=n[t];0>I(arguments,u,1)&&e.push(u)}return e},u.wrap=function(n,t){return function(){var r=[n];return wt.apply(r,arguments),t.apply(this,r)}},u.zip=function(n){for(var t=-1,r=n?B(F(arguments,"length")):0,e=Array(r);++t<r;)e[t]=F(arguments,t);return e},u.collect=k,u.drop=z,u.each=N,u.extend=v,u.methods=h,u.object=function(n,t){for(var r=-1,e=n?n.length:0,u={};++r<e;){var o=n[r];t?u[o]=t[r]:u[o[0]]=o[1]}return u
},u.select=E,u.tail=z,u.unique=P,u.clone=function(n){return d(n)?Tt(n)?xt.call(n):v({},n):n},u.contains=x,u.escape=function(n){return n==J?"":(n+"").replace(rt,f)},u.every=O,u.find=S,u.findWhere=function(n,t){return M(n,t,H)},u.has=function(n,t){return n?jt.call(n,t):K},u.identity=W,u.indexOf=I,u.isArguments=s,u.isArray=Tt,u.isBoolean=function(n){return n===H||n===K||Ot.call(n)==it},u.isDate=function(n){return n instanceof Date||Ot.call(n)==at},u.isElement=function(n){return n?1===n.nodeType:K},u.isEmpty=m,u.isEqual=_,u.isFinite=function(n){return Nt(n)&&!kt(parseFloat(n))
},u.isFunction=b,u.isNaN=function(n){return j(n)&&n!=+n},u.isNull=function(n){return n===J},u.isNumber=j,u.isObject=d,u.isRegExp=function(n){return n instanceof RegExp||Ot.call(n)==lt},u.isString=w,u.isUndefined=function(n){return typeof n=="undefined"},u.lastIndexOf=function(n,t,r){var e=n?n.length:0;for(typeof r=="number"&&(e=(0>r?Ft(0,e+r):Rt(r,e-1))+1);e--;)if(n[e]===t)return e;return-1},u.mixin=G,u.noConflict=function(){return n._=ht,this},u.random=function(n,t){return n==J&&t==J&&(t=1),n=+n||0,t==J&&(t=n,n=0),n+dt(qt()*((+t||0)-n+1))
},u.reduce=R,u.reduceRight=q,u.result=function(n,t){var r=n?n[t]:J;return b(r)?n[t]():r},u.size=function(n){var t=n?n.length:0;return typeof t=="number"?t:$t(n).length},u.some=D,u.sortedIndex=C,u.template=function(n,t,r){n||(n=""),r=g({},r,u.templateSettings);var e=0,o="__p+='",i=r.variable;n.replace(RegExp((r.escape||tt).source+"|"+(r.interpolate||tt).source+"|"+(r.evaluate||tt).source+"|$","g"),function(t,r,u,i,f){return o+=n.slice(e,f).replace(et,a),r&&(o+="'+_['escape']("+r+")+'"),i&&(o+="';"+i+";__p+='"),u&&(o+="'+((__t=("+u+"))==null?'':__t)+'"),e=f+t.length,t
}),o+="';\n",i||(i="obj",o="with("+i+"||{}){"+o+"}"),o="function("+i+"){var __t,__p='',__j=Array.prototype.join;function print(){__p+=__j.call(arguments,'')}"+o+"return __p}";try{var f=Function("_","return "+o)(u)}catch(c){throw c.source=o,c}return t?f(t):(f.source=o,f)},u.unescape=function(n){return n==J?"":(n+"").replace(nt,p)},u.uniqueId=function(n){var t=++Y+"";return n?n+t:t},u.all=O,u.any=D,u.detect=S,u.foldl=R,u.foldr=q,u.include=x,u.inject=R,u.first=T,u.last=function(n,t,r){if(n){var e=0,u=n.length;
if(typeof t!="number"&&t!=J){var o=u;for(t=V(t,r);o--&&t(n[o],o,n);)e++}else if(e=t,e==J||r)return n[u-1];return xt.call(n,Ft(0,u-e))}},u.take=T,u.head=T,u.chain=function(n){return n=new c(n),n.__chain__=H,n},u.VERSION="1.1.1",G(u),u.prototype.chain=function(){return this.__chain__=H,this},u.prototype.value=function(){return this.__wrapped__},N("pop push reverse shift sort splice unshift".split(" "),function(n){var t=gt[n];u.prototype[n]=function(){var n=this.__wrapped__;return t.apply(n,arguments),!Mt.spliceObjects&&0===n.length&&delete n[0],this
}}),N(["concat","join","slice"],function(n){var t=gt[n];u.prototype[n]=function(){var n=t.apply(this.__wrapped__,arguments);return this.__chain__&&(n=new c(n),n.__chain__=H),n}}),typeof define=="function"&&typeof define.amd=="object"&&define.amd?(n._=u,define(function(){return u})):L&&!L.nodeType?Q?(Q.exports=u)._=u:L._=u:n._=u})(this);

File diff suppressed because it is too large Load Diff

View File

@@ -21,9 +21,9 @@
// generate Markdown // generate Markdown
$markdown = docdown(array( $markdown = docdown(array(
'path' => '../' . $file, 'path' => '../' . $file,
'title' => 'Lo-Dash <sup>v0.9.2</sup>', 'title' => 'Lo-Dash <sup>v1.1.1</sup>',
'toc' => 'categories', 'toc' => 'categories',
'url' => 'https://github.com/bestiejs/lodash/blob/master/lodash.js' 'url' => 'https://github.com/lodash/lodash/blob/1.1.1/lodash.js'
)); ));
// save to a .md file // save to a .md file

9195
lodash.js

File diff suppressed because it is too large Load Diff

40
lodash.min.js vendored
View File

@@ -1,40 +0,0 @@
/*!
Lo-Dash 0.9.2 lodash.com/license
Underscore.js 1.4.2 underscorejs.org/LICENSE
*/
;(function(e,t){function s(e){if(e&&e.__wrapped__)return e;if(!(this instanceof s))return new s(e);this.__wrapped__=e}function o(e,t,n){t||(t=0);var r=e.length,i=r-t>=(n||Y);if(i)for(var s={},n=t-1;++n<r;){var o=e[n]+"";(yt.call(s,o)?s[o]:s[o]=[]).push(e[n])}return function(n){if(i){var r=n+"";return yt.call(s,r)&&-1<q(s[r],n)}return-1<q(e,n,t)}}function u(e){return e.charCodeAt(0)}function a(e,n){var r=e.b,i=n.b,e=e.a,n=n.a;if(e!==n){if(e>n||e===t)return 1;if(e<n||n===t)return-1}return r<i?-1:1}function f
(e,t,n){function r(){var u=arguments,a=s?this:t;return i||(e=t[o]),n.length&&(u=u.length?n.concat(Et.call(u)):n),this instanceof r?(d.prototype=e.prototype,a=new d,u=e.apply(a,u),T(u)?u:a):e.apply(a,u)}var i=x(e),s=!n,o=e;return s&&(n=t),r}function l(e,n){return e?"function"!=typeof e?function(t){return t[e]}:n!==t?function(t,r,i){return e.call(n,t,r,i)}:e:X}function c(){for(var e={b:"",c:"",e:It,f:Kt,g:"",h:Ut,i:Xt,j:pt,k:"",l:n},t,r=0;t=arguments[r];r++)for(var i in t)e[i]=t[i];t=e.a,e.d=/^[^,]+/
.exec(t)[0],r="var h,v,k="+e.d+",s="+e.d+";if(!"+e.d+")return s;"+e.k+";",e.b?(r+="var l=k.length;h=-1;if(typeof l=='number'){",e.i&&(r+="if(j(k)){k=k.split('')}"),r+="while(++h<l){v=k[h];"+e.b+"}}else {"):e.h&&(r+="var l=k.length;h=-1;if(l&&i(k)){while(++h<l){v=k[h+=''];"+e.g+"}}else {"),e.e||(r+="var t=typeof k=='function'&&r.call(k,'prototype');");if(e.f&&e.l)r+="var p=-1,q=o[typeof k]?m(k):[],l=q.length;while(++p<l){h=q[p];",e.e||(r+="if(!(t&&h=='prototype')){"),r+="v=k[h];"+e.g+"",e.e||(r+="}"
);else{r+="for(h in k){";if(!e.e||e.l)r+="if(",e.e||(r+="!(t&&h=='prototype')"),!e.e&&e.l&&(r+="&&"),e.l&&(r+="g.call(k,h)"),r+="){";r+="v=k[h];"+e.g+";";if(!e.e||e.l)r+="}"}r+="}";if(e.e){r+="var f=k.constructor;";for(i=0;7>i;i++)r+="h='"+e.j[i]+"';if(","constructor"==e.j[i]&&(r+="!(f&&f.prototype===k)&&"),r+="g.call(k,h)){v=k[h];"+e.g+"}"}if(e.b||e.h)r+="}";return r+=e.c+";return s",Function("e,g,i,j,o,m,r","return function("+t+"){"+r+"}")(l,yt,m,N,Gt,kt,wt)}function h(e){return"\\"+Yt[e]}function p
(e){return sn[e]}function d(){}function v(e){return on[e]}function m(e){return St.call(e)==Mt}function g(e){var t=i;if(!e||"object"!=typeof e||m(e))return t;var n=e.constructor;return(!Vt||"function"==typeof e.toString||"string"!=typeof (e+""))&&(!x(n)||n instanceof n)?qt?(nn(e,function(e,n,r){return t=!yt.call(r,n),i}),t===i):(nn(e,function(e,n){t=n}),t===i||yt.call(e,t)):t}function y(e){var t=[];return rn(e,function(e,n){t.push(n)}),t}function b(e,t,n,s,o){if(e==r)return e;n&&(t=i);if(n=T(e)){var u=
St.call(e);if(!Qt[u]||zt&&m(e))return e;var a=u==_t,n=a||(u==Bt?ln(e):n)}if(!n||!t)return n?a?Et.call(e):an({},e):e;n=e.constructor;switch(u){case Dt:case Pt:return new n(+e);case Ht:case Ft:return new n(e);case jt:return n(e.source,st.exec(e))}s||(s=[]),o||(o=[]);for(u=s.length;u--;)if(s[u]==e)return o[u];var f=a?n(e.length):{};return s.push(e),o.push(f),(a?hn:rn)(e,function(e,n){f[n]=b(e,t,r,s,o)}),f}function w(e){var t=[];return nn(e,function(e,n){x(e)&&t.push(n)}),t.sort()}function E(e){var t=
{};return rn(e,function(e,n){t[e]=n}),t}function S(e,t,s,o){if(e===t)return 0!==e||1/e==1/t;if(e==r||t==r)return e===t;var u=St.call(e);if(u!=St.call(t))return i;switch(u){case Dt:case Pt:return+e==+t;case Ht:return e!=+e?t!=+t:0==e?1/e==1/t:e==+t;case jt:case Ft:return e==t+""}var a=u==_t||u==Mt;if(zt&&!a&&(a=m(e))&&!m(t))return i;if(!a){if(e.__wrapped__||t.__wrapped__)return S(e.__wrapped__||e,t.__wrapped__||t);if(u!=Bt||Vt&&("function"!=typeof e.toString&&"string"==typeof (e+"")||"function"!=typeof
t.toString&&"string"==typeof (t+"")))return i;var u=e.constructor,f=t.constructor;if(u!=f&&(!x(u)||!(u instanceof u&&x(f)&&f instanceof f)))return i}s||(s=[]),o||(o=[]);for(u=s.length;u--;)if(s[u]==e)return o[u]==t;var u=-1,f=n,l=0;s.push(e),o.push(t);if(a){l=e.length;if(f=l==t.length)for(;l--&&(f=S(e[l],t[l],s,o)););return f}for(var c in e)if(yt.call(e,c)&&(l++,!yt.call(t,c)||!S(e[c],t[c],s,o)))return i;for(c in t)if(yt.call(t,c)&&!(l--))return i;if(It)for(;7>++u;)if(c=pt[u],yt.call(e,c)&&(!yt.call
(t,c)||!S(e[c],t[c],s,o)))return i;return n}function x(e){return"function"==typeof e}function T(e){return e?Gt[typeof e]:i}function N(e){return St.call(e)==Ft}function C(e,t,n){var i=arguments,s=0,o=2,u=i[3],a=i[4];n!==Q&&(u=[],a=[],o=i.length);for(;++s<o;)rn(i[s],function(t,n){var i,s,o;if(t&&((s=fn(t))||ln(t))){for(var f=u.length;f--;)if(i=u[f]==t)break;i?e[n]=a[f]:(u.push(t),a.push(o=(o=e[n],s)?fn(o)?o:[]:ln(o)?o:{}),e[n]=C(o,t,Q,u,a))}else t!=r&&(e[n]=t)});return e}function k(e){var t=[];return rn
(e,function(e){t.push(e)}),t}function L(e,t,n){var r=-1,i=e?e.length:0,n=(0>n?Lt(0,i+n):n)||0;return"number"==typeof i?-1<(N(e)?e.indexOf(t,n):q(e,t,n)):j(e,function(e){return++r>=n&&e===t})}function A(e,t,r){var i=n,t=l(t,r);if(fn(e))for(var r=-1,s=e.length;++r<s&&(i=!!t(e[r],r,e)););else hn(e,function(e,n,r){return i=!!t(e,n,r)});return i}function O(e,t,n){var r=[],t=l(t,n);return hn(e,function(e,n,i){t(e,n,i)&&r.push(e)}),r}function M(e,t,n){var r,t=l(t,n);return hn(e,function(e,n,s){if(t(e,n,
s))return r=e,i}),r}function _(e,t,n){var r=-1,i=e?e.length:0,s=Array("number"==typeof i?i:0),t=l(t,n);if(fn(e))for(;++r<i;)s[r]=t(e[r],r,e);else hn(e,function(e,n,i){s[++r]=t(e,n,i)});return s}function D(e,t,n){var r=-Infinity,i=-1,s=e?e.length:0,o=r;if(t||!fn(e))t=!t&&N(e)?u:l(t,n),hn(e,function(e,n,i){n=t(e,n,i),n>r&&(r=n,o=e)});else for(;++i<s;)e[i]>o&&(o=e[i]);return o}function P(e,t){var n=[];return hn(e,function(e){n.push(e[t])}),n}function H(e,t,n,r){var s=3>arguments.length,t=l(t,r);return hn
(e,function(e,r,o){n=s?(s=i,e):t(n,e,r,o)}),n}function B(e,t,n,r){var s=e,o=e?e.length:0,u=3>arguments.length;if("number"!=typeof o)var a=cn(e),o=a.length;else Xt&&N(e)&&(s=e.split(""));return hn(e,function(e,f,l){f=a?a[--o]:--o,n=u?(u=i,s[f]):t.call(r,n,s[f],f,l)}),n}function j(e,t,n){var r,t=l(t,n);if(fn(e))for(var n=-1,i=e.length;++n<i&&!(r=t(e[n],n,e)););else hn(e,function(e,n,i){return!(r=t(e,n,i))});return!!r}function F(e,t,n){if(e)return t==r||n?e[0]:Et.call(e,0,t)}function I(e,t){for(var n=-1
,r=e?e.length:0,i=[];++n<r;){var s=e[n];fn(s)?bt.apply(i,t?s:I(s)):i.push(s)}return i}function q(e,t,n){var r=-1,i=e?e.length:0;if("number"==typeof n)r=(0>n?Lt(0,i+n):n||0)-1;else if(n)return r=U(e,t),e[r]===t?r:-1;for(;++r<i;)if(e[r]===t)return r;return-1}function R(e,t,n){return e?Et.call(e,t==r||n?1:t):[]}function U(e,t,n,r){for(var i=0,s=e?e.length:i,n=n?l(n,r):X,t=n(t);i<s;)r=i+s>>>1,n(e[r])<t?i=r+1:s=r;return i}function z(e,t,n,r){var s=-1,o=e?e.length:0,u=[],a=u;"function"==typeof t&&(r=n,
n=t,t=i);var f=!t&&74<o;if(f)var c={};n&&(a=[],n=l(n,r));for(;++s<o;){var r=e[s],h=n?n(r,s,e):r;f&&(a=yt.call(c,h+"")?c[h]:c[h]=[]);if(t?!s||a[a.length-1]!==h:0>q(a,h))(n||f)&&a.push(h),u.push(r)}return u}function W(e,t){return Jt||xt&&2<arguments.length?xt.call.apply(xt,arguments):f(e,t,Et.call(arguments,2))}function X(e){return e}function V(e){hn(w(e),function(t){var r=s[t]=e[t];s.prototype[t]=function(){var e=[this.__wrapped__];return bt.apply(e,arguments),e=r.apply(s,e),this.__chain__&&(e=new
s(e),e.__chain__=n),e}})}var n=!0,r=null,i=!1,$="object"==typeof exports&&exports,J="object"==typeof global&&global;J.global===J&&(e=J);var K=[],Q=new function(){},G=0,Y=30,Z=e._,et=/[-?+=!~*%&^<>|{(\/]|\[\D|\b(?:delete|in|instanceof|new|typeof|void)\b/,tt=/&(?:amp|lt|gt|quot|#x27);/g,nt=/\b__p\+='';/g,rt=/\b(__p\+=)''\+/g,it=/(__e\(.*?\)|\b__t\))\+'';/g,st=/\w*$/,ot=/(?:__e|__t=)\(\s*(?![\d\s"']|this\.)/g,ut=RegExp("^"+(Q.valueOf+"").replace(/[.*+?^=!:${}()|[\]\/\\]/g,"\\$&").replace(/valueOf|for [^\]]+/g
,".+?")+"$"),at=/\$\{((?:(?=\\?)\\?[\s\S])*?)}/g,ft=/<%=([\s\S]+?)%>/g,lt=/($^)/,ct=/[&<>"']/g,ht=/['\n\r\t\u2028\u2029\\]/g,pt="constructor hasOwnProperty isPrototypeOf propertyIsEnumerable toLocaleString toString valueOf".split(" "),dt=Math.ceil,vt=K.concat,mt=Math.floor,gt=ut.test(gt=Object.getPrototypeOf)&&gt,yt=Q.hasOwnProperty,bt=K.push,wt=Q.propertyIsEnumerable,Et=K.slice,St=Q.toString,xt=ut.test(xt=Et.bind)&&xt,Tt=ut.test(Tt=Array.isArray)&&Tt,Nt=e.isFinite,Ct=e.isNaN,kt=ut.test(kt=Object
.keys)&&kt,Lt=Math.max,At=Math.min,Ot=Math.random,Mt="[object Arguments]",_t="[object Array]",Dt="[object Boolean]",Pt="[object Date]",Ht="[object Number]",Bt="[object Object]",jt="[object RegExp]",Ft="[object String]",It,qt,Rt=(Rt={0:1,length:1},K.splice.call(Rt,0,1),Rt[0]),Ut=n;(function(){function e(){this.x=1}var t=[];e.prototype={valueOf:1,y:1};for(var n in new e)t.push(n);for(n in arguments)Ut=!n;It=!/valueOf/.test(t),qt="x"!=t[0]})(1);var zt=!m(arguments),Wt="x"!=Et.call("x")[0],Xt="xx"!="x"
[0]+Object("x")[0];try{var Vt=("[object Object]",St.call(e.document||0)==Bt)}catch($t){}var Jt=xt&&/\n|Opera/.test(xt+St.call(e.opera)),Kt=kt&&/^.+$|true/.test(kt+!!e.attachEvent),Qt={};Qt[Mt]=Qt["[object Function]"]=i,Qt[_t]=Qt[Dt]=Qt[Pt]=Qt[Ht]=Qt[Bt]=Qt[jt]=Qt[Ft]=n;var Gt={"boolean":i,"function":n,object:n,number:i,string:i,"undefined":i},Yt={"\\":"\\","'":"'","\n":"n","\r":"r"," ":"t","\u2028":"u2028","\u2029":"u2029"};s.templateSettings={escape:/<%-([\s\S]+?)%>/g,evaluate:/<%([\s\S]+?)%>/g,
interpolate:ft,variable:""};var Zt={a:"d,c,u",k:"c=e(c,u)",b:"if(c(v,h,d)===false)return s",g:"if(c(v,h,d)===false)return s"},en={l:i,a:"n",k:"for(var a=1,b=arguments.length;a<b;a++){if(k=arguments[a]){",g:"s[h]=v",c:"}}"},tn={b:r};zt&&(m=function(e){return e?yt.call(e,"callee"):i});var nn=c(Zt,tn,{l:i}),rn=c(Zt,tn),sn={"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#x27;"},on=E(sn),un=c(en,{g:"if(s[h]==null)"+en.g}),an=c(en),fn=Tt||function(e){return St.call(e)==_t};x(/x/)&&(x=function(e){
return"[object Function]"==St.call(e)});var ln=gt?function(e){if(!e||"object"!=typeof e)return i;var t=e.valueOf,n="function"==typeof t&&(n=gt(t))&&gt(n);return n?e==n||gt(e)==n&&!m(e):g(e)}:g,cn=kt?function(e){return"function"==typeof e&&wt.call(e,"prototype")?y(e):T(e)?kt(e):[]}:y,hn=c(Zt);s.VERSION="0.9.2",s.after=function(e,t){return 1>e?t():function(){if(1>--e)return t.apply(this,arguments)}},s.bind=W,s.bindAll=function(e){for(var t=arguments,n=1<t.length?0:(t=w(e),-1),r=t.length;++n<r;){var i=
t[n];e[i]=W(e[i],e)}return e},s.chain=function(e){return e=new s(e),e.__chain__=n,e},s.clone=b,s.compact=function(e){for(var t=-1,n=e?e.length:0,r=[];++t<n;){var i=e[t];i&&r.push(i)}return r},s.compose=function(){var e=arguments;return function(){for(var t=arguments,n=e.length;n--;)t=[e[n].apply(this,t)];return t[0]}},s.contains=L,s.countBy=function(e,t,n){var r={},t=l(t,n);return hn(e,function(e,n,i){n=t(e,n,i),yt.call(r,n)?r[n]++:r[n]=1}),r},s.debounce=function(e,t,n){function i(){a=r,n||(o=e.apply
(u,s))}var s,o,u,a;return function(){var r=n&&!a;return s=arguments,u=this,clearTimeout(a),a=setTimeout(i,t),r&&(o=e.apply(u,s)),o}},s.defaults=un,s.defer=function(e){var n=Et.call(arguments,1);return setTimeout(function(){e.apply(t,n)},1)},s.delay=function(e,n){var r=Et.call(arguments,2);return setTimeout(function(){e.apply(t,r)},n)},s.difference=function(e){for(var t=-1,n=e?e.length:0,r=vt.apply(K,arguments),r=o(r,n),i=[];++t<n;){var s=e[t];r(s)||i.push(s)}return i},s.escape=function(e){return e==
r?"":(e+"").replace(ct,p)},s.every=A,s.extend=an,s.filter=O,s.find=M,s.first=F,s.flatten=I,s.forEach=hn,s.forIn=nn,s.forOwn=rn,s.functions=w,s.groupBy=function(e,t,n){var r={},t=l(t,n);return hn(e,function(e,n,i){n=t(e,n,i),(yt.call(r,n)?r[n]:r[n]=[]).push(e)}),r},s.has=function(e,t){return e?yt.call(e,t):i},s.identity=X,s.indexOf=q,s.initial=function(e,t,n){return e?Et.call(e,0,-(t==r||n?1:t)):[]},s.intersection=function(e){var t=arguments,n=t.length,r={},i=[];return hn(e,function(e){if(0>q(i,e)
){for(var s=n;--s;)if(!(r[s]||(r[s]=o(t[s])))(e))return;i.push(e)}}),i},s.invert=E,s.invoke=function(e,t){var n=Et.call(arguments,2),r="function"==typeof t,i=[];return hn(e,function(e){i.push((r?t:e[t]).apply(e,n))}),i},s.isArguments=m,s.isArray=fn,s.isBoolean=function(e){return e===n||e===i||St.call(e)==Dt},s.isDate=function(e){return St.call(e)==Pt},s.isElement=function(e){return e?1===e.nodeType:i},s.isEmpty=function(e){var t=n;if(!e)return t;var r=St.call(e),s=e.length;return r==_t||r==Ft||r==
Mt||zt&&m(e)||r==Bt&&"number"==typeof s&&x(e.splice)?!s:(rn(e,function(){return t=i}),t)},s.isEqual=S,s.isFinite=function(e){return Nt(e)&&!Ct(parseFloat(e))},s.isFunction=x,s.isNaN=function(e){return St.call(e)==Ht&&e!=+e},s.isNull=function(e){return e===r},s.isNumber=function(e){return St.call(e)==Ht},s.isObject=T,s.isPlainObject=ln,s.isRegExp=function(e){return St.call(e)==jt},s.isString=N,s.isUndefined=function(e){return e===t},s.keys=cn,s.last=function(e,t,n){if(e){var i=e.length;return t==r||
n?e[i-1]:Et.call(e,-t||i)}},s.lastIndexOf=function(e,t,n){var r=e?e.length:0;for("number"==typeof n&&(r=(0>n?Lt(0,r+n):At(n,r-1))+1);r--;)if(e[r]===t)return r;return-1},s.lateBind=function(e,t){return f(t,e,Et.call(arguments,2))},s.map=_,s.max=D,s.memoize=function(e,t){var n={};return function(){var r=t?t.apply(this,arguments):arguments[0];return yt.call(n,r)?n[r]:n[r]=e.apply(this,arguments)}},s.merge=C,s.min=function(e,t,n){var r=Infinity,i=-1,s=e?e.length:0,o=r;if(t||!fn(e))t=!t&&N(e)?u:l(t,n)
,hn(e,function(e,n,i){n=t(e,n,i),n<r&&(r=n,o=e)});else for(;++i<s;)e[i]<o&&(o=e[i]);return o},s.mixin=V,s.noConflict=function(){return e._=Z,this},s.object=function(e,t){for(var n=-1,r=e?e.length:0,i={};++n<r;){var s=e[n];t?i[s]=t[n]:i[s[0]]=s[1]}return i},s.omit=function(e,t,n){var r="function"==typeof t,i={};if(r)t=l(t,n);else var s=vt.apply(K,arguments);return nn(e,function(e,n,o){if(r?!t(e,n,o):0>q(s,n,1))i[n]=e}),i},s.once=function(e){var t,s=i;return function(){return s?t:(s=n,t=e.apply(this
,arguments),e=r,t)}},s.pairs=function(e){var t=[];return rn(e,function(e,n){t.push([n,e])}),t},s.partial=function(e){return f(e,Et.call(arguments,1))},s.pick=function(e,t,n){var r={};if("function"!=typeof t)for(var i=0,s=vt.apply(K,arguments),o=s.length;++i<o;){var u=s[i];u in e&&(r[u]=e[u])}else t=l(t,n),nn(e,function(e,n,i){t(e,n,i)&&(r[n]=e)});return r},s.pluck=P,s.random=function(e,t){return e==r&&t==r&&(t=1),e=+e||0,t==r&&(t=e,e=0),e+mt(Ot()*((+t||0)-e+1))},s.range=function(e,t,n){e=+e||0,n=+
n||1,t==r&&(t=e,e=0);for(var i=-1,t=Lt(0,dt((t-e)/n)),s=Array(t);++i<t;)s[i]=e,e+=n;return s},s.reduce=H,s.reduceRight=B,s.reject=function(e,t,n){return t=l(t,n),O(e,function(e,n,r){return!t(e,n,r)})},s.rest=R,s.result=function(e,t){var n=e?e[t]:r;return x(n)?e[t]():n},s.shuffle=function(e){var t=-1,n=Array(e?e.length:0);return hn(e,function(e){var r=mt(Ot()*(++t+1));n[t]=n[r],n[r]=e}),n},s.size=function(e){var t=e?e.length:0;return"number"==typeof t?t:cn(e).length},s.some=j,s.sortBy=function(e,t
,n){var r=[],t=l(t,n);hn(e,function(e,n,i){r.push({a:t(e,n,i),b:n,c:e})}),e=r.length;for(r.sort(a);e--;)r[e]=r[e].c;return r},s.sortedIndex=U,s.tap=function(e,t){return t(e),e},s.template=function(e,t,n){e||(e=""),n||(n={});var r,i,o=s.templateSettings,u=0,a=n.interpolate||o.interpolate||lt,f="__p += '",l=n.variable||o.variable,c=l;e.replace(RegExp((n.escape||o.escape||lt).source+"|"+a.source+"|"+(a===ft?at:lt).source+"|"+(n.evaluate||o.evaluate||lt).source+"|$","g"),function(t,n,i,s,o,a){i||(i=s
),f+=e.slice(u,a).replace(ht,h),f+=n?"'+__e("+n+")+'":o?"';"+o+";__p+='":i?"'+((__t=("+i+"))==null?'':__t)+'":"",r||(r=o||et.test(n||i)),u=a+t.length}),f+="';",c||(l="obj",r?f="with("+l+"){"+f+"}":(n=RegExp("(\\(\\s*)"+l+"\\."+l+"\\b","g"),f=f.replace(ot,"$&"+l+".").replace(n,"$1__d"))),f=(r?f.replace(nt,""):f).replace(rt,"$1").replace(it,"$1;"),f="function("+l+"){"+(c?"":l+"||("+l+"={});")+"var __t,__p='',__e=_.escape"+(r?",__j=Array.prototype.join;function print(){__p+=__j.call(arguments,'')}":
(c?"":",__d="+l+"."+l+"||"+l)+";")+f+"return __p}";try{i=Function("_","return "+f)(s)}catch(p){throw p.source=f,p}return t?i(t):(i.source=f,i)},s.throttle=function(e,t){function n(){a=new Date,u=r,s=e.apply(o,i)}var i,s,o,u,a=0;return function(){var r=new Date,f=t-(r-a);return i=arguments,o=this,0>=f?(clearTimeout(u),a=r,s=e.apply(o,i)):u||(u=setTimeout(n,f)),s}},s.times=function(e,t,n){for(var e=+e||0,r=-1,i=Array(e);++r<e;)i[r]=t.call(n,r);return i},s.toArray=function(e){return e&&"number"==typeof
e.length?(Wt?N(e):"string"==typeof e)?e.split(""):Et.call(e):k(e)},s.unescape=function(e){return e==r?"":(e+"").replace(tt,v)},s.union=function(){return z(vt.apply(K,arguments))},s.uniq=z,s.uniqueId=function(e){var t=G++;return e?e+t:t},s.values=k,s.where=function(e,t){var n=[];return nn(t,function(e,t){n.push(t)}),O(e,function(e){for(var r=n.length;r--;){var i=e[n[r]]===t[n[r]];if(!i)break}return!!i})},s.without=function(e){for(var t=-1,n=e?e.length:0,r=o(arguments,1,20),i=[];++t<n;){var s=e[t];
r(s)||i.push(s)}return i},s.wrap=function(e,t){return function(){var n=[e];return bt.apply(n,arguments),t.apply(this,n)}},s.zip=function(e){for(var t=-1,n=e?D(P(arguments,"length")):0,r=Array(n);++t<n;)r[t]=P(arguments,t);return r},s.all=A,s.any=j,s.collect=_,s.detect=M,s.drop=R,s.each=hn,s.foldl=H,s.foldr=B,s.head=F,s.include=L,s.inject=H,s.methods=w,s.select=O,s.tail=R,s.take=F,s.unique=z,V(s),s.prototype.chain=function(){return this.__chain__=n,this},s.prototype.value=function(){return this.__wrapped__
},hn("pop push reverse shift sort splice unshift".split(" "),function(e){var t=K[e];s.prototype[e]=function(){var e=this.__wrapped__;return t.apply(e,arguments),Rt&&e.length===0&&delete e[0],this.__chain__&&(e=new s(e),e.__chain__=n),e}}),hn(["concat","join","slice"],function(e){var t=K[e];s.prototype[e]=function(){var e=t.apply(this.__wrapped__,arguments);return this.__chain__&&(e=new s(e),e.__chain__=n),e}}),typeof define=="function"&&typeof define.amd=="object"&&define.amd?(e._=s,define(function(
){return s})):$?"object"==typeof module&&module&&module.exports==$?(module.exports=s)._=s:$._=s:e._=s})(this);

View File

@@ -1,31 +0,0 @@
/*!
Lo-Dash 0.9.2 lodash.com/license
Underscore.js 1.4.2 underscorejs.org/LICENSE
*/
;(function(e,t){function n(e){if(e&&e.__wrapped__)return e;if(!(this instanceof n))return new n(e);this.__wrapped__=e}function r(e,n){var r=e.b,i=n.b,e=e.a,n=n.a;if(e!==n){if(e>n||e===t)return 1;if(e<n||n===t)return-1}return r<i?-1:1}function i(e,t,n){function r(){var i=arguments,s=t;return n.length&&(i=i.length?n.concat(Z.call(i)):n),this instanceof r?(a.prototype=e.prototype,s=new a,i=e.apply(s,i),v(i)?i:s):e.apply(s,i)}return r}function s(e,n){return e?"function"!=typeof e?function(t){return t[
e]}:n!==t?function(t,r,i){return e.call(n,t,r,i)}:e:H}function o(e){return"\\"+yt[e]}function u(e){return Et[e]}function a(){}function f(e){return St[e]}function l(e){var t=[];return wt(e,function(e,n){t.push(n)}),t}function c(e){var t=[];return bt(e,function(e,n){d(e)&&t.push(n)}),t.sort()}function h(e){var t={};return wt(e,function(e,n){t[e]=n}),t}function p(e,t,n,r){if(e===t)return 0!==e||1/e==1/t;if(null==e||null==t)return e===t;var i=et.call(e);if(i!=et.call(t))return!1;switch(i){case ft:case lt
:return+e==+t;case ct:return e!=+e?t!=+t:0==e?1/e==1/t:e==+t;case pt:case dt:return e==t+""}var s=i==at;if(!s){if(e.__wrapped__||t.__wrapped__)return p(e.__wrapped__||e,t.__wrapped__||t);if(i!=ht)return!1;var i=e.constructor,o=t.constructor;if(i!=o&&(!d(i)||!(i instanceof i&&d(o)&&o instanceof o)))return!1}n||(n=[]),r||(r=[]);for(i=n.length;i--;)if(n[i]==e)return r[i]==t;i=!0,o=0,n.push(e),r.push(t);if(s){o=e.length;if(i=o==t.length)for(;o--&&(i=p(e[o],t[o],n,r)););return i}for(var u in e)if(G.call
(e,u)&&(o++,!G.call(t,u)||!p(e[u],t[u],n,r)))return!1;for(u in t)if(G.call(t,u)&&!(o--))return!1;return!0}function d(e){return"function"==typeof e}function v(e){return e?gt[typeof e]:!1}function m(e){return et.call(e)==dt}function g(e){var t=[];return wt(e,function(e){t.push(e)}),t}function y(e,t){return"number"==typeof (e?e.length:0)?-1<O(e,t):k(e,function(e){return e===t})}function b(e,t,n){var r=!0,t=s(t,n);if(Nt(e))for(var n=-1,i=e.length;++n<i&&(r=!!t(e[n],n,e)););else kt(e,function(e,n,i){return!
(r=!!t(e,n,i))&&R});return r}function w(e,t,n){var r=[],t=s(t,n);return kt(e,function(e,n,i){t(e,n,i)&&r.push(e)}),r}function E(e,t,n){var r,t=s(t,n);return kt(e,function(e,n,i){if(t(e,n,i))return r=e,!1}),r}function S(e,t,n){var r=-1,i=e?e.length:0,o=Array("number"==typeof i?i:0),t=s(t,n);if(Nt(e))for(;++r<i;)o[r]=t(e[r],r,e);else kt(e,function(e,n,i){o[++r]=t(e,n,i)});return o}function x(e,t,n){var r=-Infinity,i=-1,o=e?e.length:0,u=r;if(t||!Nt(e))t=s(t,n),kt(e,function(e,n,i){n=t(e,n,i),n>r&&(r=
n,u=e)});else for(;++i<o;)e[i]>u&&(u=e[i]);return u}function T(e,t){var n=[];return kt(e,function(e){n.push(e[t])}),n}function N(e,t,n,r){var i=3>arguments.length,t=s(t,r);return kt(e,function(e,r,s){n=i?(i=!1,e):t(n,e,r,s)}),n}function C(e,t,n,r){var i=e?e.length:0,s=3>arguments.length;if("number"!=typeof i)var o=Ct(e),i=o.length;return kt(e,function(u,a,f){a=o?o[--i]:--i,n=s?(s=!1,e[a]):t.call(r,n,e[a],a,f)}),n}function k(e,t,n){var r,t=s(t,n);if(Nt(e))for(var n=-1,i=e.length;++n<i&&!(r=t(e[n],
n,e)););else kt(e,function(e,n,i){return(r=t(e,n,i))&&R});return!!r}function L(e,t,n){if(e)return null==t||n?e[0]:Z.call(e,0,t)}function A(e,t){for(var n=-1,r=e?e.length:0,i=[];++n<r;){var s=e[n];Nt(s)?Y.apply(i,t?s:A(s)):i.push(s)}return i}function O(e,t,n){var r=-1,i=e?e.length:0;if("number"==typeof n)r=(0>n?st(0,i+n):n||0)-1;else if(n)return r=_(e,t),e[r]===t?r:-1;for(;++r<i;)if(e[r]===t)return r;return-1}function M(e,t,n){return e?Z.call(e,null==t||n?1:t):[]}function _(e,t,n,r){for(var i=0,o=
e?e.length:i,n=n?s(n,r):H,t=n(t);i<o;)r=i+o>>>1,n(e[r])<t?i=r+1:o=r;return i}function D(e,t,n,r){var i=-1,o=e?e.length:0,u=[],a=u;n&&(a=[],n=s(n,r));for(;++i<o;){var r=e[i],f=n?n(r,i,e):r;if(t?!i||a[a.length-1]!==f:0>O(a,f))n&&a.push(f),u.push(r)}return u}function P(e,t){return mt||tt&&2<arguments.length?tt.call.apply(tt,arguments):i(e,t,Z.call(arguments,2))}function H(e){return e}function B(e){kt(c(e),function(t){var r=n[t]=e[t];n.prototype[t]=function(){var e=[this.__wrapped__];return Y.apply(e
,arguments),e=r.apply(n,e),this.__chain__&&(e=new n(e),e.__chain__=!0),e}})}var j="object"==typeof exports&&exports,F="object"==typeof global&&global;F.global===F&&(e=F);var I=[],F=new function(){},q=0,R=F,U=e._,z=/&(?:amp|lt|gt|quot|#x27);/g,W=RegExp("^"+(F.valueOf+"").replace(/[.*+?^=!:${}()|[\]\/\\]/g,"\\$&").replace(/valueOf|for [^\]]+/g,".+?")+"$"),X=/($^)/,V=/[&<>"']/g,$=/['\n\r\t\u2028\u2029\\]/g,J=Math.ceil,K=I.concat,Q=Math.floor,G=F.hasOwnProperty,Y=I.push,Z=I.slice,et=F.toString,tt=W.test
(tt=Z.bind)&&tt,nt=W.test(nt=Array.isArray)&&nt,rt=e.isFinite,it=W.test(it=Object.keys)&&it,st=Math.max,ot=Math.min,ut=Math.random,at="[object Array]",ft="[object Boolean]",lt="[object Date]",ct="[object Number]",ht="[object Object]",pt="[object RegExp]",dt="[object String]",vt=(vt={0:1,length:1},I.splice.call(vt,0,1),vt[0]),mt=tt&&/\n|Opera/.test(tt+et.call(e.opera)),gt={"boolean":!1,"function":!0,object:!0,number:!1,string:!1,"undefined":!1},yt={"\\":"\\","'":"'","\n":"n","\r":"r"," ":"t","\u2028"
:"u2028","\u2029":"u2029"};n.templateSettings={escape:/<%-([\s\S]+?)%>/g,evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,variable:""},n.isArguments=function(e){return"[object Arguments]"==et.call(e)},n.isArguments(arguments)||(n.isArguments=function(e){return e?G.call(e,"callee"):!1});var bt=function(e,t){var n,r;if(!e)return e;t=s(t);for(n in e)if(r=e[n],t(r,n,e)===R)break;return e},wt=function(e,t){var n,r;if(!e)return e;t=s(t);for(n in e)if(G.call(e,n)&&(r=e[n],t(r,n,e)===R))break;return e
},Et={"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#x27;"},St=h(Et),xt=function(e){var t,n,r=e;if(!e)return e;for(var i=1,s=arguments.length;i<s;i++)if(r=arguments[i])for(t in r)n=r[t],null==e[t]&&(e[t]=n);return e},Tt=function(e){var t,n,r=e;if(!e)return e;for(var i=1,s=arguments.length;i<s;i++)if(r=arguments[i])for(t in r)n=r[t],e[t]=n;return e},Nt=nt||function(e){return et.call(e)==at};d(/x/)&&(d=function(e){return"[object Function]"==et.call(e)});var Ct=it?function(e){return v(e)?it(e
):[]}:l,kt=function(e,t,n){var r;if(!e)return e;var t=s(t,n),i=e.length,n=-1;if("number"==typeof i){for(;++n<i;)if(r=e[n],t(r,n,e)===R)return e}else for(n in e)if(G.call(e,n)&&(r=e[n],t(r,n,e)===R))return e};n.VERSION="0.9.2",n.after=function(e,t){return 1>e?t():function(){if(1>--e)return t.apply(this,arguments)}},n.bind=P,n.bindAll=function(e){for(var t=arguments,n=1<t.length?0:(t=c(e),-1),r=t.length;++n<r;){var i=t[n];e[i]=P(e[i],e)}return e},n.chain=function(e){return e=new n(e),e.__chain__=!0
,e},n.clone=function(e){return e&&gt[typeof e]?Nt(e)?Z.call(e):Tt({},e):e},n.compact=function(e){for(var t=-1,n=e?e.length:0,r=[];++t<n;){var i=e[t];i&&r.push(i)}return r},n.compose=function(){var e=arguments;return function(){for(var t=arguments,n=e.length;n--;)t=[e[n].apply(this,t)];return t[0]}},n.contains=y,n.countBy=function(e,t,n){var r={},t=s(t,n);return kt(e,function(e,n,i){n=t(e,n,i),G.call(r,n)?r[n]++:r[n]=1}),r},n.debounce=function(e,t,n){function r(){u=null,n||(s=e.apply(o,i))}var i,s
,o,u;return function(){var a=n&&!u;return i=arguments,o=this,clearTimeout(u),u=setTimeout(r,t),a&&(s=e.apply(o,i)),s}},n.defaults=xt,n.defer=function(e){var n=Z.call(arguments,1);return setTimeout(function(){e.apply(t,n)},1)},n.delay=function(e,n){var r=Z.call(arguments,2);return setTimeout(function(){e.apply(t,r)},n)},n.difference=function(e){for(var t=-1,n=e.length,r=K.apply(I,arguments),i=[];++t<n;){var s=e[t];0>O(r,s,n)&&i.push(s)}return i},n.escape=function(e){return null==e?"":(e+"").replace
(V,u)},n.every=b,n.extend=Tt,n.filter=w,n.find=E,n.first=L,n.flatten=A,n.forEach=kt,n.functions=c,n.groupBy=function(e,t,n){var r={},t=s(t,n);return kt(e,function(e,n,i){n=t(e,n,i),(G.call(r,n)?r[n]:r[n]=[]).push(e)}),r},n.has=function(e,t){return e?G.call(e,t):!1},n.identity=H,n.indexOf=O,n.initial=function(e,t,n){return e?Z.call(e,0,-(null==t||n?1:t)):[]},n.intersection=function(e){var t=arguments,n=t.length,r=[];return kt(e,function(e){if(0>O(r,e)){for(var i=n;--i;)if(0>O(t[i],e))return;r.push
(e)}}),r},n.invert=h,n.invoke=function(e,t){var n=Z.call(arguments,2),r="function"==typeof t,i=[];return kt(e,function(e){i.push((r?t:e[t]).apply(e,n))}),i},n.isArray=Nt,n.isBoolean=function(e){return!0===e||!1===e||et.call(e)==ft},n.isDate=function(e){return et.call(e)==lt},n.isElement=function(e){return e?1===e.nodeType:!1},n.isEmpty=function(e){if(!e)return!0;if(Nt(e)||m(e))return!e.length;for(var t in e)if(G.call(e,t))return!1;return!0},n.isEqual=p,n.isFinite=function(e){return rt(e)&&et.call
(e)==ct},n.isFunction=d,n.isNaN=function(e){return et.call(e)==ct&&e!=+e},n.isNull=function(e){return null===e},n.isNumber=function(e){return et.call(e)==ct},n.isObject=v,n.isRegExp=function(e){return et.call(e)==pt},n.isString=m,n.isUndefined=function(e){return e===t},n.keys=Ct,n.last=function(e,t,n){if(e){var r=e.length;return null==t||n?e[r-1]:Z.call(e,-t||r)}},n.lastIndexOf=function(e,t,n){var r=e?e.length:0;for("number"==typeof n&&(r=(0>n?st(0,r+n):ot(n,r-1))+1);r--;)if(e[r]===t)return r;return-1
},n.map=S,n.max=x,n.memoize=function(e,t){var n={};return function(){var r=t?t.apply(this,arguments):arguments[0];return G.call(n,r)?n[r]:n[r]=e.apply(this,arguments)}},n.min=function(e,t,n){var r=Infinity,i=-1,o=e?e.length:0,u=r;if(t||!Nt(e))t=s(t,n),kt(e,function(e,n,i){n=t(e,n,i),n<r&&(r=n,u=e)});else for(;++i<o;)e[i]<u&&(u=e[i]);return u},n.mixin=B,n.noConflict=function(){return e._=U,this},n.object=function(e,t){for(var n=-1,r=e?e.length:0,i={};++n<r;){var s=e[n];t?i[s]=t[n]:i[s[0]]=s[1]}return i
},n.omit=function(e){var t=K.apply(I,arguments),n={};return bt(e,function(e,r){0>O(t,r,1)&&(n[r]=e)}),n},n.once=function(e){var t,n=!1;return function(){return n?t:(n=!0,t=e.apply(this,arguments),e=null,t)}},n.pairs=function(e){var t=[];return wt(e,function(e,n){t.push([n,e])}),t},n.pick=function(e){for(var t=0,n=K.apply(I,arguments),r=n.length,i={};++t<r;){var s=n[t];s in e&&(i[s]=e[s])}return i},n.pluck=T,n.random=function(e,t){return null==e&&null==t&&(t=1),e=+e||0,null==t&&(t=e,e=0),e+Q(ut()*
((+t||0)-e+1))},n.range=function(e,t,n){e=+e||0,n=+n||1,null==t&&(t=e,e=0);for(var r=-1,t=st(0,J((t-e)/n)),i=Array(t);++r<t;)i[r]=e,e+=n;return i},n.reduce=N,n.reduceRight=C,n.reject=function(e,t,n){return t=s(t,n),w(e,function(e,n,r){return!t(e,n,r)})},n.rest=M,n.result=function(e,t){var n=e?e[t]:null;return d(n)?e[t]():n},n.shuffle=function(e){var t=-1,n=Array(e?e.length:0);return kt(e,function(e){var r=Q(ut()*(++t+1));n[t]=n[r],n[r]=e}),n},n.size=function(e){var t=e?e.length:0;return"number"==typeof
t?t:Ct(e).length},n.some=k,n.sortBy=function(e,t,n){var i=[],t=s(t,n);kt(e,function(e,n,r){i.push({a:t(e,n,r),b:n,c:e})}),e=i.length;for(i.sort(r);e--;)i[e]=i[e].c;return i},n.sortedIndex=_,n.tap=function(e,t){return t(e),e},n.template=function(e,t,r){e||(e="");var r=xt({},r,n.templateSettings),i=0,s="__p += '",u=r.variable;e.replace(RegExp((r.escape||X).source+"|"+(r.interpolate||X).source+"|"+(r.evaluate||X).source+"|$","g"),function(t,n,r,u,a){s+=e.slice(i,a).replace($,o),s+=n?"'+_['escape']("+
n+")+'":u?"';"+u+";__p+='":r?"'+((__t=("+r+"))==null?'':__t)+'":"",i=a+t.length}),s+="';",u||(u="obj",s="with("+u+"||{}){"+s+"}"),s="function("+u+"){var __t,__p='',__j=Array.prototype.join;function print(){__p+=__j.call(arguments,'')}"+s+"return __p}";try{var a=Function("_","return "+s)(n)}catch(f){throw f.source=s,f}return t?a(t):(a.source=s,a)},n.throttle=function(e,t){function n(){u=new Date,o=null,i=e.apply(s,r)}var r,i,s,o,u=0;return function(){var a=new Date,f=t-(a-u);return r=arguments,s=this
,0>=f?(clearTimeout(o),u=a,i=e.apply(s,r)):o||(o=setTimeout(n,f)),i}},n.times=function(e,t,n){for(var e=+e||0,r=-1,i=Array(e);++r<e;)i[r]=t.call(n,r);return i},n.toArray=function(e){return e&&"number"==typeof e.length?"string"==typeof e?e.split(""):Z.call(e):g(e)},n.unescape=function(e){return null==e?"":(e+"").replace(z,f)},n.union=function(){return D(K.apply(I,arguments))},n.uniq=D,n.uniqueId=function(e){var t=q++;return e?e+t:t},n.values=g,n.where=function(e,t){var n=[];return bt(t,function(e,
t){n.push(t)}),w(e,function(e){for(var r=n.length;r--;){var i=e[n[r]]===t[n[r]];if(!i)break}return!!i})},n.without=function(e){for(var t=-1,n=e.length,r=[];++t<n;){var i=e[t];0>O(arguments,i,1)&&r.push(i)}return r},n.wrap=function(e,t){return function(){var n=[e];return Y.apply(n,arguments),t.apply(this,n)}},n.zip=function(e){for(var t=-1,n=e?x(T(arguments,"length")):0,r=Array(n);++t<n;)r[t]=T(arguments,t);return r},n.all=b,n.any=k,n.collect=S,n.detect=E,n.drop=M,n.each=kt,n.foldl=N,n.foldr=C,n.head=
L,n.include=y,n.inject=N,n.methods=c,n.select=w,n.tail=M,n.take=L,n.unique=D,B(n),n.prototype.chain=function(){return this.__chain__=!0,this},n.prototype.value=function(){return this.__wrapped__},kt("pop push reverse shift sort splice unshift".split(" "),function(e){var t=I[e];n.prototype[e]=function(){var e=this.__wrapped__;return t.apply(e,arguments),vt&&e.length===0&&delete e[0],this.__chain__&&(e=new n(e),e.__chain__=!0),e}}),kt(["concat","join","slice"],function(e){var t=I[e];n.prototype[e]=
function(){var e=t.apply(this.__wrapped__,arguments);return this.__chain__&&(e=new n(e),e.__chain__=!0),e}}),j?"object"==typeof module&&module&&module.exports==j?(module.exports=n)._=n:j._=n:e._=n})(this);

View File

@@ -1,9 +1,9 @@
{ {
"name": "lodash", "name": "lodash",
"version": "0.9.2", "version": "1.1.1",
"description": "A drop-in replacement for Underscore.js delivering performance, bug fixes, and additional features.", "description": "A low-level utility library delivering consistency, customization, performance, and extra features.",
"homepage": "http://lodash.com", "homepage": "http://lodash.com",
"main": "./lodash", "main": "./dist/lodash",
"keywords": [ "keywords": [
"browser", "browser",
"client", "client",
@@ -46,8 +46,7 @@
"main": "./lodash.js" "main": "./lodash.js"
}, },
"scripts": { "scripts": {
"build": "node build", "build": "node ./build.js",
"test": "node test/test && node test/test-build", "test": "node ./test/test.js ./dist/lodash.js && node ./test/test.js ./dist/lodash.min.js && node ./test/test-build.js"
"install": "node build/post-install"
} }
} }

View File

@@ -29,6 +29,7 @@
<body> <body>
<div id="perf-toolbar"></div> <div id="perf-toolbar"></div>
<script src="../vendor/platform.js/platform.js"></script> <script src="../vendor/platform.js/platform.js"></script>
<script src="../lodash.js"></script>
<script src="../vendor/benchmark.js/benchmark.js"></script> <script src="../vendor/benchmark.js/benchmark.js"></script>
<script src="../vendor/firebug-lite/src/firebug-lite-debug.js"></script> <script src="../vendor/firebug-lite/src/firebug-lite-debug.js"></script>
<script src="perf-ui.js"></script> <script src="perf-ui.js"></script>

View File

@@ -34,19 +34,21 @@
// expose Lo-Dash build file path // expose Lo-Dash build file path
ui.buildPath = (function() { ui.buildPath = (function() {
switch (build) { switch (build) {
case 'lodash-dev': return 'lodash.js'; case 'lodash-dev': return 'dist/lodash.compat.js';
case 'lodash-underscore': return 'lodash.underscore.min.js'; case 'lodash-modern': return 'dist/lodash.min.js';
case 'lodash-underscore': return 'dist/lodash.underscore.min.js';
case 'lodash-custom': return 'lodash.custom.min.js'; case 'lodash-custom': return 'lodash.custom.min.js';
} }
return 'lodash.min.js'; return 'dist/lodash.compat.min.js';
}()); }());
// expose other library file path // expose other library file path
ui.otherPath = (function() { ui.otherPath = (function() {
switch (other) { switch (other) {
case 'lodash-dev': return 'lodash.js'; case 'lodash-dev': return 'dist/lodash.compat.js';
case 'lodash-prod': return 'lodash.min.js'; case 'lodash-prod': return 'dist/lodash.compat.min.js';
case 'lodash-underscore': return 'lodash.underscore.min.js'; case 'lodash-modern': return 'dist/lodash.min.js';
case 'lodash-underscore': return 'dist/lodash.underscore.min.js';
case 'lodash-custom': return 'lodash.custom.min.js'; case 'lodash-custom': return 'lodash.custom.min.js';
case 'underscore-dev': return 'vendor/underscore/underscore.js'; case 'underscore-dev': return 'vendor/underscore/underscore.js';
} }
@@ -76,6 +78,7 @@
'<select id="perf-build">' + '<select id="perf-build">' +
'<option value="lodash-dev">Lo-Dash</option>' + '<option value="lodash-dev">Lo-Dash</option>' +
'<option value="lodash-prod">Lo-Dash (minified)</option>' + '<option value="lodash-prod">Lo-Dash (minified)</option>' +
'<option value="lodash-modern">Lo-Dash (modern)</option>' +
'<option value="lodash-underscore">Lo-Dash (underscore)</option>' + '<option value="lodash-underscore">Lo-Dash (underscore)</option>' +
'<option value="lodash-custom">Lo-Dash (custom)</option>' + '<option value="lodash-custom">Lo-Dash (custom)</option>' +
'</select>'; '</select>';
@@ -89,6 +92,7 @@
'<option value="underscore-prod">Underscore (minified)</option>' + '<option value="underscore-prod">Underscore (minified)</option>' +
'<option value="lodash-dev">Lo-Dash</option>' + '<option value="lodash-dev">Lo-Dash</option>' +
'<option value="lodash-prod">Lo-Dash (minified)</option>' + '<option value="lodash-prod">Lo-Dash (minified)</option>' +
'<option value="lodash-modern">Lo-Dash (modern)</option>' +
'<option value="lodash-underscore">Lo-Dash (underscore)</option>' + '<option value="lodash-underscore">Lo-Dash (underscore)</option>' +
'<option value="lodash-custom">Lo-Dash (custom)</option>' + '<option value="lodash-custom">Lo-Dash (custom)</option>' +
'</select>'; '</select>';
@@ -102,20 +106,22 @@
buildList.selectedIndex = (function() { buildList.selectedIndex = (function() {
switch (build) { switch (build) {
case 'lodash-dev': return 0; case 'lodash-dev': return 0;
case 'lodash-underscore': return 2; case 'lodash-modern': return 2;
case 'lodash-custom': return 3; case 'lodash-underscore': return 3;
case 'lodash-custom': return 4;
} }
return 1; return 1;
}()); }());
otherList.selectedIndex = (function() { otherList.selectedIndex = (function() {
switch (other) { switch (other) {
case 'underscore-dev': return 0; case 'underscore-dev': return 0;
case 'lodash-dev': return 2; case 'lodash-dev': return 2;
case 'lodash-prod': return 3; case 'lodash-prod': return 3;
case 'lodash-underscore': return 4; case 'lodash-modern': return 4;
case 'lodash-custom': return 5; case 'lodash-underscore': return 5;
case 'lodash-custom': return 6;
} }
return 1; return 1;
}()); }());

View File

@@ -1,55 +1,91 @@
(function(window) { (function(window) {
/** Use a single load function */ /** Use a single "load" function */
var load = typeof require == 'function' ? require : window.load; var load = typeof require == 'function' ? require : window.load;
/** Load Benchmark.js */ /** The file path of the Lo-Dash file to test */
var Benchmark = var filePath = (function() {
window.Benchmark || ( var min = 0;
Benchmark = load('../vendor/benchmark.js/benchmark.js') || window.Benchmark, var result = window.phantom
Benchmark.Benchmark || Benchmark ? phantom.args
); : (window.system
? (min = 1, system.args)
: (window.process ? (min = 2, process.argv) : (window.arguments || []))
);
var last = result[result.length - 1];
result = (result.length > min && !/perf(?:\.js)?$/.test(last))
? last
: '../lodash.js';
try {
result = require('fs').realpathSync(result);
} catch(e) { }
return result;
}());
/** Load Lo-Dash */ /** Load Lo-Dash */
var lodash = var lodash = window.lodash || (window.lodash = (
window.lodash || ( lodash = load(filePath) || window._,
lodash = load('../lodash.js') || window._, lodash = lodash._ || lodash,
lodash = lodash._ || lodash, lodash.noConflict()
lodash.noConflict() ));
);
/** Load Benchmark.js */
var Benchmark = window.Benchmark || (window.Benchmark = (
Benchmark = load('../vendor/benchmark.js/benchmark.js') || window.Benchmark,
Benchmark = Benchmark.Benchmark || Benchmark,
Benchmark.runInContext(lodash.extend({}, window, { '_': lodash }))
));
/** Load Underscore */ /** Load Underscore */
var _ = var _ = window._ || (window._ = (
window._ || ( _ = load('../vendor/underscore/underscore.js') || window._,
_ = load('../vendor/underscore/underscore.js') || window._, _._ || _
_._ || _ ));
);
/** Used to access the Firebug Lite panel (set by `run`) */ /** Used to access the Firebug Lite panel (set by `run`) */
var fbPanel; var fbPanel;
/** Used to match path separators */
var rePathSeparator = /[\/\\]/;
/** Used to detect primitive types */
var rePrimitive = /^(?:boolean|number|string|undefined)$/;
/** Used to match RegExp special characters */
var reSpecialChars = /[.*+?^=!:${}()|[\]\/\\]/g;
/** Used to score performance */ /** Used to score performance */
var score = { 'a': 0, 'b': 0 }; var score = { 'a': 0, 'b': 0 };
/** Used to queue benchmark suites */ /** Used to queue benchmark suites */
var suites = []; var suites = [];
/** Used to resolve a value's internal [[Class]] */
var toString = Object.prototype.toString;
/** The `ui` object */ /** The `ui` object */
var ui = window.ui || {}; var ui = window.ui || ({
'buildPath': basename(filePath, '.js'),
'otherPath': 'underscore'
});
/** The Lo-Dash build basename */ /** The Lo-Dash build basename */
var buildName = basename(ui.buildPath || 'lodash', '.js'); var buildName = basename(ui.buildPath, '.js');
/** The other library basename */ /** The other library basename */
var otherName = basename(ui.otherPath || 'underscore', '.js'); var otherName = basename(ui.otherPath, '.js');
/** Add `console.log()` support for Narwhal and RingoJS */ /** Detect if in a browser environment */
window.console || (window.console = { 'log': window.print }); var isBrowser = isHostType(window, 'document') && isHostType(window, 'navigator');
/** Expose functions to the global object */ /** Detect Java environment */
window._ = _; var isJava = !isBrowser && /Java/.test(toString.call(window.java));
window.Benchmark = Benchmark;
window.lodash = lodash; /** Add `console.log()` support for Narwhal, Rhino, and RingoJS */
var console = window.console || (window.console = { 'log': window.print });
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
@@ -63,10 +99,10 @@
* @returns {String} Returns the basename. * @returns {String} Returns the basename.
*/ */
function basename(filePath, extension) { function basename(filePath, extension) {
var result = (filePath || '').split(/[\\/]/).pop(); var result = (filePath || '').split(rePathSeparator).pop();
return arguments.length < 2 return (arguments.length < 2)
? result ? result
: result.replace(RegExp(extension.replace(/[.*+?^=!:${}()|[\]\/\\]/g, '\\$&') + '$'), ''); : result.replace(RegExp(extension.replace(reSpecialChars, '\\$&') + '$'), '');
} }
/** /**
@@ -78,7 +114,26 @@
* @returns {Number} Returns the adjusted Hz. * @returns {Number} Returns the adjusted Hz.
*/ */
function getHz(bench) { function getHz(bench) {
return 1 / (bench.stats.mean + bench.stats.moe); var result = 1 / (bench.stats.mean + bench.stats.moe);
return isFinite(result) ? result : 0;
}
/**
* Host objects can return type values that are different from their actual
* data type. The objects we are concerned with usually return non-primitive
* types of "object", "function", or "unknown".
*
* @private
* @param {Mixed} object The owner of the property.
* @param {String} property The property to check.
* @returns {Boolean} Returns `true` if the property value is a non-primitive, else `false`.
*/
function isHostType(object, property) {
if (object == null) {
return false;
}
var type = typeof object[property];
return !rePrimitive.test(type) && (type != 'object' || !!object[property]);
} }
/** /**
@@ -106,7 +161,7 @@
fbPanel.getElementById('fbPanel1'); fbPanel.getElementById('fbPanel1');
log('\nSit back and relax, this may take a while.'); log('\nSit back and relax, this may take a while.');
suites[0].run(); suites[0].run({ 'async': !isJava });
} }
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
@@ -149,7 +204,7 @@
if (suites.length) { if (suites.length) {
// run next suite // run next suite
suites[0].run(); suites[0].run({ 'async': !isJava });
} }
else { else {
var fastestTotalHz = Math.max(score.a, score.b), var fastestTotalHz = Math.max(score.a, score.b),
@@ -173,8 +228,7 @@
lodash.extend(Benchmark.options, { lodash.extend(Benchmark.options, {
'async': true, 'async': true,
'setup': '\ 'setup': '\
var window = Function("return this || global")(),\ var _ = window._,\
_ = window._,\
lodash = window.lodash,\ lodash = window.lodash,\
belt = this.name == "Lo-Dash" ? lodash : _;\ belt = this.name == "Lo-Dash" ? lodash : _;\
\ \
@@ -187,7 +241,7 @@
numbers = Array(limit),\ numbers = Array(limit),\
fourNumbers = [5, 25, 10, 30],\ fourNumbers = [5, 25, 10, 30],\
nestedNumbers = [1, [2], [3, [[4]]]],\ nestedNumbers = [1, [2], [3, [[4]]]],\
twoNumbers = [12, 21];\ twoNumbers = [12, 23];\
\ \
for (index = 0; index < limit; index++) {\ for (index = 0; index < limit; index++) {\
numbers[index] = index;\ numbers[index] = index;\
@@ -196,20 +250,18 @@
}\ }\
\ \
if (typeof bind != "undefined") {\ if (typeof bind != "undefined") {\
var contextObject = { "name": "moe" },\ var thisArg = { "name": "moe" },\
ctor = function() {};\ ctor = function() {};\
\ \
var func = function(greeting, punctuation) {\ var func = function(greeting, punctuation) {\
return greeting + ", " + this.name + (punctuation || ".");\ return greeting + ", " + this.name + (punctuation || ".");\
};\ };\
\ \
var lodashBoundNormal = lodash.bind(func, contextObject),\ var _boundNormal = _.bind(func, thisArg),\
lodashBoundCtor = lodash.bind(ctor, contextObject),\ _boundPartial = _.bind(func, thisArg, "hi");\
lodashBoundPartial = lodash.bind(func, contextObject, "hi");\
\ \
var _boundNormal = _.bind(func, contextObject),\ var lodashBoundNormal = lodash.bind(func, thisArg),\
_boundCtor = _.bind(ctor, contextObject),\ lodashBoundPartial = lodash.bind(func, thisArg, "hi");\
_boundPartial = _.bind(func, contextObject, "hi");\
}\ }\
\ \
if (typeof bindAll != "undefined") {\ if (typeof bindAll != "undefined") {\
@@ -224,6 +276,10 @@
}, {});\ }, {});\
}\ }\
}\ }\
if (typeof chaining != "undefined") {\
var _chaining = _.chain ? _(numbers).chain() : _(numbers),\
lodashChaining = lodash(numbers);\
}\
if (typeof compact != "undefined") {\ if (typeof compact != "undefined") {\
var uncompacted = numbers.slice();\ var uncompacted = numbers.slice();\
uncompacted[2] = false;\ uncompacted[2] = false;\
@@ -294,44 +350,86 @@
var object2 = {},\ var object2 = {},\
objects2 = Array(limit),\ objects2 = Array(limit),\
numbers2 = Array(limit),\ numbers2 = Array(limit),\
nestedNumbers2 = [1, [2], [3, [[4]]]];\ nestedNumbers2 = [1, [2], [3, [[4]]]],\
nestedNumbers3 = [1, [2], [5, [[6]]]],\
simpleObject = { "a": 1 },\
simpleObject2 = { "a": 2 },\
simpleObjects = [simpleObject],\
simpleObjects2 = [simpleObject2],\
twoNumbers2 = [18, 27];\
\ \
for (index = 0; index < limit; index++) {\ for (index = 0; index < limit; index++) {\
numbers2[index] = index;\
object2["key" + index] = index;\ object2["key" + index] = index;\
objects2[index] = { "num": index };\ objects2[index] = { "num": index };\
numbers2[index] = index;\
}\ }\
}\ }\
\ \
if (typeof multiArrays != "undefined") {\ if (typeof multiArrays != "undefined") {\
var twentyFiveValues = Array(25),\ var twentyValues = Array(20),\
twentyValues2 = Array(20),\
twentyFiveValues = Array(25),\
twentyFiveValues2 = Array(25),\ twentyFiveValues2 = Array(25),\
thirtyValues = Array(30),\
thirtyValues2 = Array(30),\
fortyValues = Array(40),\
fortyValues2 = Array(40),\
fiftyValues = Array(50),\ fiftyValues = Array(50),\
fiftyValues2 = Array(50),\
seventyFiveValues = Array(75),\ seventyFiveValues = Array(75),\
seventyFiveValues2 = Array(75),\ seventyFiveValues2 = Array(75),\
hundredValues = Array(100),\
hundredValues2 = Array(100),\
lowerChars = "abcdefghijklmnopqrstuvwxyz".split(""),\ lowerChars = "abcdefghijklmnopqrstuvwxyz".split(""),\
upperChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".split("");\ upperChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".split("");\
\ \
for (index = 0; index < 75; index++) {\ for (index = 0; index < 100; index++) {\
if (index < 26) {\ if (index < 15) {\
if (index < 20) {\ twentyValues[index] = lowerChars[index];\
twentyFiveValues[index] = lowerChars[index];\ twentyValues2[index] = upperChars[index];\
twentyFiveValues2[index] = upperChars[index];\ }\
}\ if (index < 20) {\
else if (index < 25) {\ twentyValues[index] =\
twentyFiveValues[index] =\ twentyValues2[index] = index;\
twentyFiveValues2[index] = index;\ \
}\ twentyFiveValues[index] = lowerChars[index];\
twentyFiveValues2[index] = upperChars[index];\
}\
if (index < 25) {\
twentyFiveValues[index] =\
twentyFiveValues2[index] = index;\
\
thirtyValues[index] =\
fortyValues[index] =\
fiftyValues[index] =\ fiftyValues[index] =\
seventyFiveValues[index] = lowerChars[index];\ seventyFiveValues[index] =\
seventyFiveValues2[index] = upperChars[index];\ hundredValues[index] = lowerChars[index];\
\
thirtyValues2[index] =\
fortyValues2[index] =\
fiftyValues2[index] =\
seventyFiveValues2[index] =\
hundredValues2[index] = upperChars[index];\
}\ }\
else {\ else {\
if (index < 50) {\ if (index < 30) {\
fiftyValues[index] = index;\ thirtyValues[index] =\
thirtyValues2[index] = index;\
}\ }\
seventyFiveValues[index] = index;\ if (index < 40) {\
seventyFiveValues2[index] = index + (index < 60 ? 75 : 0);\ fortyValues[index] =\
fortyValues2[index] = index;\
}\
if (index < 50) {\
fiftyValues[index] =\
fiftyValues2[index] = index;\
}\
if (index < 75) {\
seventyFiveValues[index] =\
seventyFiveValues2[index] = index;\
}\
hundredValues[index] =\
hundredValues2[index] = index;\
}\ }\
}\ }\
}\ }\
@@ -347,33 +445,14 @@
"list": ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"]\ "list": ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"]\
};\ };\
\ \
var tplBase =\ var tpl =\
"<div>" +\ "<div>" +\
"<h1 class=\'header1\'><%= header1 %></h1>" +\ "<h1 class=\'header1\'><%= header1 %></h1>" +\
"<h2 class=\'header2\'><%= header2 %></h2>" +\ "<h2 class=\'header2\'><%= header2 %></h2>" +\
"<h3 class=\'header3\'><%= header3 %></h3>" +\ "<h3 class=\'header3\'><%= header3 %></h3>" +\
"<h4 class=\'header4\'><%= header4 %></h4>" +\ "<h4 class=\'header4\'><%= header4 %></h4>" +\
"<h5 class=\'header5\'><%= header5 %></h5>" +\ "<h5 class=\'header5\'><%= header5 %></h5>" +\
"<h6 class=\'header6\'><%= header6 %></h6>";\ "<h6 class=\'header6\'><%= header6 %></h6>" +\
\
var tpl =\
tplBase +\
"<ul class=\'list\'>" +\
"<li class=\'item\'><%= list[0] %></li>" +\
"<li class=\'item\'><%= list[1] %></li>" +\
"<li class=\'item\'><%= list[2] %></li>" +\
"<li class=\'item\'><%= list[3] %></li>" +\
"<li class=\'item\'><%= list[4] %></li>" +\
"<li class=\'item\'><%= list[5] %></li>" +\
"<li class=\'item\'><%= list[6] %></li>" +\
"<li class=\'item\'><%= list[7] %></li>" +\
"<li class=\'item\'><%= list[8] %></li>" +\
"<li class=\'item\'><%= list[9] %></li>" +\
"</ul>" +\
"</div>";\
\
var tplWithEvaluate =\
tplBase +\
"<ul class=\'list\'>" +\ "<ul class=\'list\'>" +\
"<% for (var index = 0, length = list.length; index < length; index++) { %>" +\ "<% for (var index = 0, length = list.length; index < length; index++) { %>" +\
"<li class=\'item\'><%= list[index] %></li>" +\ "<li class=\'item\'><%= list[index] %></li>" +\
@@ -381,33 +460,14 @@
"</ul>" +\ "</ul>" +\
"</div>";\ "</div>";\
\ \
var tplBaseVerbose =\ var tplVerbose =\
"<div>" +\ "<div>" +\
"<h1 class=\'header1\'><%= data.header1 %></h1>" +\ "<h1 class=\'header1\'><%= data.header1 %></h1>" +\
"<h2 class=\'header2\'><%= data.header2 %></h2>" +\ "<h2 class=\'header2\'><%= data.header2 %></h2>" +\
"<h3 class=\'header3\'><%= data.header3 %></h3>" +\ "<h3 class=\'header3\'><%= data.header3 %></h3>" +\
"<h4 class=\'header4\'><%= data.header4 %></h4>" +\ "<h4 class=\'header4\'><%= data.header4 %></h4>" +\
"<h5 class=\'header5\'><%= data.header5 %></h5>" +\ "<h5 class=\'header5\'><%= data.header5 %></h5>" +\
"<h6 class=\'header6\'><%= data.header6 %></h6>";\ "<h6 class=\'header6\'><%= data.header6 %></h6>" +\
\
var tplVerbose =\
tplBaseVerbose +\
"<ul class=\'list\'>" +\
"<li class=\'item\'><%= data.list[0] %></li>" +\
"<li class=\'item\'><%= data.list[1] %></li>" +\
"<li class=\'item\'><%= data.list[2] %></li>" +\
"<li class=\'item\'><%= data.list[3] %></li>" +\
"<li class=\'item\'><%= data.list[4] %></li>" +\
"<li class=\'item\'><%= data.list[5] %></li>" +\
"<li class=\'item\'><%= data.list[6] %></li>" +\
"<li class=\'item\'><%= data.list[7] %></li>" +\
"<li class=\'item\'><%= data.list[8] %></li>" +\
"<li class=\'item\'><%= data.list[9] %></li>" +\
"</ul>" +\
"</div>";\
\
var tplVerboseWithEvaluate =\
tplBaseVerbose +\
"<ul class=\'list\'>" +\ "<ul class=\'list\'>" +\
"<% for (var index = 0, length = data.list.length; index < length; index++) { %>" +\ "<% for (var index = 0, length = data.list.length; index < length; index++) { %>" +\
"<li class=\'item\'><%= data.list[index] %></li>" +\ "<li class=\'item\'><%= data.list[index] %></li>" +\
@@ -417,20 +477,68 @@
\ \
var settingsObject = { "variable": "data" };\ var settingsObject = { "variable": "data" };\
\ \
var lodashTpl = lodash.template(tpl),\
lodashTplWithEvaluate = lodash.template(tplWithEvaluate),\
lodashTplVerbose = lodash.template(tplVerbose, null, settingsObject),\
lodashTplVerboseWithEvaluate = lodash.template(tplVerboseWithEvaluate, null, settingsObject);\
\
var _tpl = _.template(tpl),\ var _tpl = _.template(tpl),\
_tplWithEvaluate = _.template(tplWithEvaluate),\ _tplVerbose = _.template(tplVerbose, null, settingsObject);\
_tplVerbose = _.template(tplVerbose, null, settingsObject),\ \
_tplVerboseWithEvaluate = _.template(tplVerboseWithEvaluate, null, settingsObject);\ var lodashTpl = lodash.template(tpl),\
lodashTplVerbose = lodash.template(tplVerbose, null, settingsObject);\
}\
if (typeof where != "undefined") {\
var _findWhere = _.findWhere || _.find,\
lodashFindWhere = lodash.findWhere || lodash.find,\
whereObject = { "num": 9 };\
}' }'
}); });
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
suites.push(
Benchmark.Suite('`_(...)` with a number')
.add(buildName, '\
lodash(2)'
)
.add(otherName, '\
_(2)'
)
);
suites.push(
Benchmark.Suite('`_(...)` with an array')
.add(buildName, '\
lodash(numbers)'
)
.add(otherName, '\
_(numbers)'
)
);
suites.push(
Benchmark.Suite('`_(...)` with an object')
.add(buildName, '\
lodash(object)'
)
.add(otherName, '\
_(object)'
)
);
// avoid Underscore induced `OutOfMemoryError` in Rhino, Narwhal, and Ringo
if (!isJava) {
suites.push(
Benchmark.Suite('`_(...).tap(...)`')
.add(buildName, {
'fn': 'lodashChaining.tap(lodash.identity)',
'teardown': 'function chaining(){}'
})
.add(otherName, {
'fn': '_chaining.tap(_.identity)',
'teardown': 'function chaining(){}'
})
);
}
/*--------------------------------------------------------------------------*/
suites.push( suites.push(
Benchmark.Suite('`_.bind` (uses native `Function#bind` if available and inferred fast)') Benchmark.Suite('`_.bind` (uses native `Function#bind` if available and inferred fast)')
.add(buildName, { .add(buildName, {
@@ -491,18 +599,6 @@
}) })
); );
suites.push(
Benchmark.Suite('bound and called in a `new` expression, i.e. `new bound` (edge case)')
.add(buildName, {
'fn': 'new lodashBoundCtor()',
'teardown': 'function bind(){}'
})
.add(otherName, {
'fn': 'new _boundCtor()',
'teardown': 'function bind(){}'
})
);
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
suites.push( suites.push(
@@ -630,45 +726,33 @@
suites.push( suites.push(
Benchmark.Suite('`_.difference`') Benchmark.Suite('`_.difference`')
.add(buildName, '\ .add(buildName, '\
lodash.difference(numbers, fourNumbers, twoNumbers)' lodash.difference(numbers, twoNumbers, fourNumbers)'
) )
.add(otherName, '\ .add(otherName, '\
_.difference(numbers, fourNumbers, twoNumbers)' _.difference(numbers, twoNumbers, fourNumbers)'
) )
); );
suites.push( suites.push(
Benchmark.Suite('`_.difference` iterating 25 elements') Benchmark.Suite('`_.difference` iterating 100 elements')
.add(buildName, { .add(buildName, {
'fn': 'lodash.difference(twentyFiveValues, twentyFiveValues2)', 'fn': 'lodash.difference(hundredValues, hundredValues2)',
'teardown': 'function multiArrays(){}' 'teardown': 'function multiArrays(){}'
}) })
.add(otherName, { .add(otherName, {
'fn': '_.difference(twentyFiveValues, twentyFiveValues2)', 'fn': '_.difference(hundredValues, hundredValues2)',
'teardown': 'function multiArrays(){}' 'teardown': 'function multiArrays(){}'
}) })
); );
suites.push( suites.push(
Benchmark.Suite('`_.difference` iterating 50 and 75 elements') Benchmark.Suite('`_.difference` iterating 20 and 40 elements')
.add(buildName, { .add(buildName, {
'fn': 'lodash.difference(fiftyValues, seventyFiveValues2)', 'fn': 'lodash.difference(twentyValues, fortyValues2)',
'teardown': 'function multiArrays(){}' 'teardown': 'function multiArrays(){}'
}) })
.add(otherName, { .add(otherName, {
'fn': '_.difference(fiftyValues, seventyFiveValues2)', 'fn': '_.difference(twentyValues, fortyValues2)',
'teardown': 'function multiArrays(){}'
})
);
suites.push(
Benchmark.Suite('`_.difference` iterating 75 elements')
.add(buildName, {
'fn': 'lodash.difference(seventyFiveValues, seventyFiveValues2)',
'teardown': 'function multiArrays(){}'
})
.add(otherName, {
'fn': '_.difference(seventyFiveValues, seventyFiveValues2)',
'teardown': 'function multiArrays(){}' 'teardown': 'function multiArrays(){}'
}) })
); );
@@ -839,6 +923,21 @@
) )
); );
// avoid Underscore induced `OutOfMemoryError` in Rhino, Narwhal, and Ringo
if (!isJava) {
suites.push(
Benchmark.Suite('`_.find` with `properties`')
.add(buildName, {
'fn': 'lodashFindWhere(objects, whereObject)',
'teardown': 'function where(){}'
})
.add(otherName, {
'fn': '_findWhere(objects, whereObject)',
'teardown': 'function where(){}'
})
);
}
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
suites.push( suites.push(
@@ -936,45 +1035,21 @@
suites.push( suites.push(
Benchmark.Suite('`_.intersection`') Benchmark.Suite('`_.intersection`')
.add(buildName, '\ .add(buildName, '\
lodash.intersection(numbers, fourNumbers, twoNumbers)' lodash.intersection(numbers, twoNumbers, fourNumbers)'
) )
.add(otherName, '\ .add(otherName, '\
_.intersection(numbers, fourNumbers, twoNumbers)' _.intersection(numbers, twoNumbers, fourNumbers)'
) )
); );
suites.push( suites.push(
Benchmark.Suite('`_.intersection` iterating 25 elements') Benchmark.Suite('`_.intersection` iterating 100 elements')
.add(buildName, { .add(buildName, {
'fn': 'lodash.intersection(twentyFiveValues, twentyFiveValues2)', 'fn': 'lodash.intersection(hundredValues, hundredValues2)',
'teardown': 'function multiArrays(){}' 'teardown': 'function multiArrays(){}'
}) })
.add(otherName, { .add(otherName, {
'fn': '_.intersection(twentyFiveValues, twentyFiveValues2)', 'fn': '_.intersection(hundredValues, hundredValues2)',
'teardown': 'function multiArrays(){}'
})
);
suites.push(
Benchmark.Suite('`_.intersection` iterating 50 and 75 elements')
.add(buildName, {
'fn': 'lodash.intersection(fiftyValues, seventyFiveValues2)',
'teardown': 'function multiArrays(){}'
})
.add(otherName, {
'fn': '_.intersection(fiftyValues, seventyFiveValues2)',
'teardown': 'function multiArrays(){}'
})
);
suites.push(
Benchmark.Suite('`_.intersection` iterating 75 elements')
.add(buildName, {
'fn': 'lodash.intersection(seventyFiveValues, seventyFiveValues2)',
'teardown': 'function multiArrays(){}'
})
.add(otherName, {
'fn': '_.intersection(seventyFiveValues, seventyFiveValues2)',
'teardown': 'function multiArrays(){}' 'teardown': 'function multiArrays(){}'
}) })
); );
@@ -1040,11 +1115,15 @@
suites.push( suites.push(
Benchmark.Suite('`_.isEqual` comparing arrays') Benchmark.Suite('`_.isEqual` comparing arrays')
.add(buildName, { .add(buildName, {
'fn': 'lodash.isEqual(numbers, numbers2)', 'fn': '\
lodash.isEqual(numbers, numbers2);\
lodash.isEqual(twoNumbers, twoNumbers2);',
'teardown': 'function isEqual(){}' 'teardown': 'function isEqual(){}'
}) })
.add(otherName, { .add(otherName, {
'fn': '_.isEqual(numbers, numbers2)', 'fn': '\
_.isEqual(numbers, numbers2);\
_.isEqual(twoNumbers, twoNumbers2);',
'teardown': 'function isEqual(){}' 'teardown': 'function isEqual(){}'
}) })
); );
@@ -1052,11 +1131,15 @@
suites.push( suites.push(
Benchmark.Suite('`_.isEqual` comparing nested arrays') Benchmark.Suite('`_.isEqual` comparing nested arrays')
.add(buildName, { .add(buildName, {
'fn': 'lodash.isEqual(nestedNumbers, nestedNumbers2)', 'fn': '\
lodash.isEqual(nestedNumbers, nestedNumbers2);\
lodash.isEqual(nestedNumbers2, nestedNumbers3);',
'teardown': 'function isEqual(){}' 'teardown': 'function isEqual(){}'
}) })
.add(otherName, { .add(otherName, {
'fn': '_.isEqual(nestedNumbers, nestedNumbers2)', 'fn': '\
_.isEqual(nestedNumbers, nestedNumbers2);\
_.isEqual(nestedNumbers2, nestedNumbers3);',
'teardown': 'function isEqual(){}' 'teardown': 'function isEqual(){}'
}) })
); );
@@ -1064,11 +1147,15 @@
suites.push( suites.push(
Benchmark.Suite('`_.isEqual` comparing arrays of objects') Benchmark.Suite('`_.isEqual` comparing arrays of objects')
.add(buildName, { .add(buildName, {
'fn': 'lodash.isEqual(objects, objects2)', 'fn': '\
lodash.isEqual(objects, objects2);\
lodash.isEqual(simpleObjects, simpleObjects2);',
'teardown': 'function isEqual(){}' 'teardown': 'function isEqual(){}'
}) })
.add(otherName, { .add(otherName, {
'fn': '_.isEqual(objects, objects2)', 'fn': '\
_.isEqual(objects, objects2);\
_.isEqual(simpleObjects, simpleObjects2);',
'teardown': 'function isEqual(){}' 'teardown': 'function isEqual(){}'
}) })
); );
@@ -1076,11 +1163,15 @@
suites.push( suites.push(
Benchmark.Suite('`_.isEqual` comparing objects') Benchmark.Suite('`_.isEqual` comparing objects')
.add(buildName, { .add(buildName, {
'fn': 'lodash.isEqual(object, object2)', 'fn': '\
lodash.isEqual(object, object2);\
lodash.isEqual(simpleObject, simpleObject2);',
'teardown': 'function isEqual(){}' 'teardown': 'function isEqual(){}'
}) })
.add(otherName, { .add(otherName, {
'fn': '_.isEqual(object, object2)', 'fn': '\
_.isEqual(object, object2);\
_.isEqual(simpleObject, simpleObject2);',
'teardown': 'function isEqual(){}' 'teardown': 'function isEqual(){}'
}) })
); );
@@ -1226,7 +1317,7 @@
'teardown': 'function omit(){}' 'teardown': 'function omit(){}'
}) })
.add(otherName, { .add(otherName, {
'fn': 'result = _.omit(wordToNumber, words)', 'fn': '_.omit(wordToNumber, words)',
'teardown': 'function omit(){}' 'teardown': 'function omit(){}'
}) })
); );
@@ -1289,13 +1380,13 @@
Benchmark.Suite('`_.reduce` iterating an object') Benchmark.Suite('`_.reduce` iterating an object')
.add(buildName, '\ .add(buildName, '\
lodash.reduce(object, function(result, value, key) {\ lodash.reduce(object, function(result, value, key) {\
result.push([key, value]);\ result.push(key, value);\
return result;\ return result;\
}, []);' }, []);'
) )
.add(otherName, '\ .add(otherName, '\
_.reduce(object, function(result, value, key) {\ _.reduce(object, function(result, value, key) {\
result.push([key, value]);\ result.push(key, value);\
return result;\ return result;\
}, []);' }, []);'
) )
@@ -1323,13 +1414,13 @@
Benchmark.Suite('`_.reduceRight` iterating an object') Benchmark.Suite('`_.reduceRight` iterating an object')
.add(buildName, '\ .add(buildName, '\
lodash.reduceRight(object, function(result, value, key) {\ lodash.reduceRight(object, function(result, value, key) {\
result.push([key, value]);\ result.push(key, value);\
return result;\ return result;\
}, []);' }, []);'
) )
.add(otherName, '\ .add(otherName, '\
_.reduceRight(object, function(result, value, key) {\ _.reduceRight(object, function(result, value, key) {\
result.push([key, value]);\ result.push(key, value);\
return result;\ return result;\
}, []);' }, []);'
) )
@@ -1419,6 +1510,20 @@
) )
); );
suites.push(
Benchmark.Suite('`_.some` with `thisArg` iterating an array (slow path)')
.add(buildName, '\
lodash.some(objects, function(value, index) {\
return this["key" + index] == 19;\
}, object)'
)
.add(otherName, '\
_.some(objects, function(value, index) {\
return this["key" + index] == 19;\
}, object)'
)
);
suites.push( suites.push(
Benchmark.Suite('`_.some` iterating an object') Benchmark.Suite('`_.some` iterating an object')
.add(buildName, '\ .add(buildName, '\
@@ -1500,7 +1605,7 @@
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
suites.push( suites.push(
Benchmark.Suite('`_.template` without "evaluate" delimiters (slow path)') Benchmark.Suite('`_.template` (slow path)')
.add(buildName, { .add(buildName, {
'fn': 'lodash.template(tpl, tplData)', 'fn': 'lodash.template(tpl, tplData)',
'teardown': 'function template(){}' 'teardown': 'function template(){}'
@@ -1512,19 +1617,7 @@
); );
suites.push( suites.push(
Benchmark.Suite('`_.template` with "evaluate" delimiters (slow path)') Benchmark.Suite('compiled template')
.add(buildName, {
'fn': 'lodash.template(tplWithEvaluate, tplData)',
'teardown': 'function template(){}'
})
.add(otherName, {
'fn': '_.template(tplWithEvaluate, tplData)',
'teardown': 'function template(){}'
})
);
suites.push(
Benchmark.Suite('compiled template without "evaluate" delimiters')
.add(buildName, { .add(buildName, {
'fn': 'lodashTpl(tplData)', 'fn': 'lodashTpl(tplData)',
'teardown': 'function template(){}' 'teardown': 'function template(){}'
@@ -1536,19 +1629,7 @@
); );
suites.push( suites.push(
Benchmark.Suite('compiled template with "evaluate" delimiters') Benchmark.Suite('compiled template without a with-statement')
.add(buildName, {
'fn': 'lodashTplWithEvaluate(tplData)',
'teardown': 'function template(){}'
})
.add(otherName, {
'fn': '_tplWithEvaluate(tplData)',
'teardown': 'function template(){}'
})
);
suites.push(
Benchmark.Suite('compiled template without a with-statement or "evaluate" delimiters')
.add(buildName, { .add(buildName, {
'fn': 'lodashTplVerbose(tplData)', 'fn': 'lodashTplVerbose(tplData)',
'teardown': 'function template(){}' 'teardown': 'function template(){}'
@@ -1559,18 +1640,6 @@
}) })
); );
suites.push(
Benchmark.Suite('compiled template without a with-statement using "evaluate" delimiters')
.add(buildName, {
'fn': 'lodashTplVerboseWithEvaluate(tplData)',
'teardown': 'function template(){}'
})
.add(otherName, {
'fn': '_tplVerboseWithEvaluate(tplData)',
'teardown': 'function template(){}'
})
);
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
suites.push( suites.push(
@@ -1600,7 +1669,7 @@
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
suites.push( suites.push(
Benchmark.Suite('`_.toArray` with an array') Benchmark.Suite('`_.toArray` with an array (edge case)')
.add(buildName, '\ .add(buildName, '\
lodash.toArray(numbers)' lodash.toArray(numbers)'
) )
@@ -1624,51 +1693,51 @@
suites.push( suites.push(
Benchmark.Suite('`_.union`') Benchmark.Suite('`_.union`')
.add(buildName, '\ .add(buildName, '\
lodash.union(numbers, fourNumbers, twoNumbers)' lodash.union(numbers, twoNumbers, fourNumbers)'
) )
.add(otherName, '\ .add(otherName, '\
_.union(numbers, fourNumbers, twoNumbers)' _.union(numbers, twoNumbers, fourNumbers)'
) )
); );
suites.push(
Benchmark.Suite('`_.union` iterating an array of 75 elements')
.add(buildName, {
'fn': 'lodash.union(fiftyValues, twentyFiveValues2);',
'teardown': 'function multiArrays(){}'
})
.add(otherName, {
'fn': '_.union(fiftyValues, twentyFiveValues2);',
'teardown': 'function multiArrays(){}'
})
);
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
suites.push( suites.push(
Benchmark.Suite('`_.uniq`') Benchmark.Suite('`_.uniq`')
.add(buildName, '\ .add(buildName, '\
lodash.uniq(numbers.concat(fourNumbers, twoNumbers))' lodash.uniq(numbers.concat(twoNumbers, fourNumbers))'
) )
.add(otherName, '\ .add(otherName, '\
_.uniq(numbers.concat(fourNumbers, twoNumbers))' _.uniq(numbers.concat(twoNumbers, fourNumbers))'
) )
); );
suites.push( suites.push(
Benchmark.Suite('`_.uniq` with `callback`') Benchmark.Suite('`_.uniq` with `callback`')
.add(buildName, '\ .add(buildName, '\
lodash.uniq(numbers.concat(fourNumbers, twoNumbers), function(num) {\ lodash.uniq(numbers.concat(twoNumbers, fourNumbers), function(num) {\
return num % 2;\ return num % 2;\
});' });'
) )
.add(otherName, '\ .add(otherName, '\
_.uniq(numbers.concat(fourNumbers, twoNumbers), function(num) {\ _.uniq(numbers.concat(twoNumbers, fourNumbers), function(num) {\
return num % 2;\ return num % 2;\
})' })'
) )
); );
suites.push(
Benchmark.Suite('`_.uniq` iterating an array of 50 elements')
.add(buildName, {
'fn': 'lodash.uniq(twentyFiveValues.concat(twentyFiveValues2));',
'teardown': 'function multiArrays(){}'
})
.add(otherName, {
'fn': '_.uniq(twentyFiveValues.concat(twentyFiveValues2));',
'teardown': 'function multiArrays(){}'
})
);
suites.push( suites.push(
Benchmark.Suite('`_.uniq` iterating an array of 75 elements') Benchmark.Suite('`_.uniq` iterating an array of 75 elements')
.add(buildName, { .add(buildName, {
@@ -1681,18 +1750,6 @@
}) })
); );
suites.push(
Benchmark.Suite('`_.uniq` iterating an array of 100 elements')
.add(buildName, {
'fn': 'lodash.uniq(seventyFiveValues.concat(twentyFiveValues2));',
'teardown': 'function multiArrays(){}'
})
.add(otherName, {
'fn': '_.uniq(seventyFiveValues.concat(twentyFiveValues2));',
'teardown': 'function multiArrays(){}'
})
);
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
suites.push( suites.push(
@@ -1709,12 +1766,14 @@
suites.push( suites.push(
Benchmark.Suite('`_.where`') Benchmark.Suite('`_.where`')
.add(buildName, '\ .add(buildName, {
lodash.where(objects, { "num": 9 });' 'fn': 'lodash.where(objects, whereObject);',
) 'teardown': 'function where(){}'
.add(otherName, '\ })
_.where(objects, { "num": 9 });' .add(otherName, {
) 'fn': '_.where(objects, whereObject);',
'teardown': 'function where(){}'
})
); );
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
@@ -1730,37 +1789,13 @@
); );
suites.push( suites.push(
Benchmark.Suite('`_.without` iterating an array of 25 elements') Benchmark.Suite('`_.without` iterating an array of 30 elements')
.add(buildName, { .add(buildName, {
'fn': 'lodash.without.apply(lodash, [twentyFiveValues].concat(twentyFiveValues2));', 'fn': 'lodash.without.apply(lodash, [thirtyValues].concat(thirtyValues2));',
'teardown': 'function multiArrays(){}' 'teardown': 'function multiArrays(){}'
}) })
.add(otherName, { .add(otherName, {
'fn': '_.without.apply(_, [twentyFiveValues].concat(twentyFiveValues2));', 'fn': '_.without.apply(_, [thirtyValues].concat(thirtyValues2));',
'teardown': 'function multiArrays(){}'
})
);
suites.push(
Benchmark.Suite('`_.without` iterating an array of 75 and 50 elements')
.add(buildName, {
'fn': 'lodash.without.apply(lodash, [seventyFiveValues2].concat(fiftyValues));',
'teardown': 'function multiArrays(){}'
})
.add(otherName, {
'fn': '_.without.apply(_, [seventyFiveValues2].concat(fiftyValues));',
'teardown': 'function multiArrays(){}'
})
);
suites.push(
Benchmark.Suite('`_.without` iterating an array of 75 elements')
.add(buildName, {
'fn': 'lodash.without.apply(lodash, [seventyFiveValues].concat(seventyFiveValues2));',
'teardown': 'function multiArrays(){}'
})
.add(otherName, {
'fn': '_.without.apply(_, [seventyFiveValues].concat(seventyFiveValues2));',
'teardown': 'function multiArrays(){}' 'teardown': 'function multiArrays(){}'
}) })
); );
@@ -1770,9 +1805,8 @@
if (Benchmark.platform + '') { if (Benchmark.platform + '') {
log(Benchmark.platform); log(Benchmark.platform);
} }
// in the browser, expose `run` to be called later // in the browser, expose `run` to be called later
if (window.document) { if (window.document && !window.phantom) {
window.run = run; window.run = run;
} else { } else {
run(); run();

View File

@@ -1,9 +1,14 @@
cd "$(dirname "$0")" cd "$(dirname "$0")"
for cmd in node narwhal ringo rhino; do
echo "" echo "Running performance suite in node..."
echo "Running performance suite in $cmd..." node perf.js ../dist/lodash.js && node perf.js ../dist/lodash.min.js
$cmd perf.js
for cmd in rhino "rhino -require" narwhal ringo phantomjs; do
echo ""
echo "Running performance suite in $cmd..."
$cmd perf.js ../dist/lodash.compat.js && $cmd perf.js ../dist/lodash.compat.min.js
done done
echo "" echo ""
echo "Running performance suite in a browser..." echo "Running performance suite in a browser..."
open index.html open index.html

View File

@@ -12,7 +12,7 @@
</head> </head>
<body> <body>
<div id="qunit"></div> <div id="qunit"></div>
<h1 id="qunit-header"><a href="#">Backbone Speed Suite</a></h1> <h1 id="qunit-header"></h1>
<div id="qunit-fixture"> <div id="qunit-fixture">
<div id='testElement'> <div id='testElement'>
<h1>Test</h1> <h1>Test</h1>
@@ -21,17 +21,26 @@
<script src="../vendor/json3/lib/json3.js"></script> <script src="../vendor/json3/lib/json3.js"></script>
<script src="../vendor/jquery/jquery.js"></script> <script src="../vendor/jquery/jquery.js"></script>
<script src="../vendor/platform.js/platform.js"></script> <script src="../vendor/platform.js/platform.js"></script>
<script> <script src="../vendor/qunit/qunit/qunit.js"></script>
// avoid syntax errors for `QUnit.throws` in older Firefoxes
document.write(platform.name == 'Firefox' && /^1\b/.test(platform.version)
? '<script src="../vendor/qunit/qunit/qunit-1.8.0.js"><\/script>'
: '<script src="../vendor/qunit/qunit/qunit.js"><\/script>'
);
</script>
<script src="test-ui.js"></script> <script src="test-ui.js"></script>
<script src="../lodash.js"></script>
<script> <script>
var lodash = _.noConflict();
document.write('<script src="../' + ui.buildPath + '"><\/script>'); document.write('<script src="../' + ui.buildPath + '"><\/script>');
</script> </script>
<script>
_.mixin({
'debounce': lodash.debounce,
'defer': lodash.defer
});
if (!_.chain) {
_.mixin({
'chain': function(value) {
return new _(value);
}
});
}
</script>
<script src="../vendor/backbone/backbone.js"></script> <script src="../vendor/backbone/backbone.js"></script>
<script src="../vendor/backbone/test/environment.js"></script> <script src="../vendor/backbone/test/environment.js"></script>
<script src="../vendor/backbone/test/noconflict.js"></script> <script src="../vendor/backbone/test/noconflict.js"></script>

View File

@@ -4,18 +4,18 @@
<meta charset="utf-8"> <meta charset="utf-8">
<title>Lo-Dash Test Suite</title> <title>Lo-Dash Test Suite</title>
<link rel="stylesheet" href="../vendor/qunit/qunit/qunit.css"> <link rel="stylesheet" href="../vendor/qunit/qunit/qunit.css">
<style>
#exports {
display: none;
}
</style>
</head> </head>
<body> <body>
<div id="qunit"></div> <script src="../vendor/qunit/qunit/qunit.js"></script>
<script src="../vendor/platform.js/platform.js"></script> <script src="../vendor/platform.js/platform.js"></script>
<script>
// avoid syntax errors for `QUnit.throws` in older Firefoxes
document.write(platform.name == 'Firefox' && /^1\b/.test(platform.version)
? '<script src="../vendor/qunit/qunit/qunit-1.8.0.js"><\/script>'
: '<script src="../vendor/qunit/qunit/qunit.js"><\/script>'
);
</script>
<script src="test-ui.js"></script> <script src="test-ui.js"></script>
<div id="qunit"></div>
<div id="exports"></div>
<script> <script>
// set a bad shim // set a bad shim
Object._keys = Object.keys; Object._keys = Object.keys;

View File

@@ -1,10 +1,14 @@
cd "$(dirname "$0")" cd "$(dirname "$0")"
for cmd in rhino ringo narwhal node; do
echo "" for cmd in rhino "rhino -require" narwhal ringo phantomjs; do
echo "Testing in $cmd..." echo "Testing in $cmd..."
$cmd test.js $cmd test.js ../dist/lodash.compat.js && $cmd test.js ../dist/lodash.compat.min.js
echo ""
done done
echo "Testing in node..."
node test.js ../dist/lodash.js && node test.js ../dist/lodash.min.js
echo "" echo ""
echo "Testing build..." echo "Testing build..."
node test-build.js node test-build.js

View File

@@ -1,3 +1,3 @@
<ul> <ul>
<% _.forEach(people, function(name) { %><li><%= name %></li><% }); %> <% _.forEach(people, function(name) { %><li><%- name %></li><% }); %>
</ul> </ul>

1
test/template/c.jst Normal file
View File

@@ -0,0 +1 @@
Hello ${ name }!

File diff suppressed because it is too large Load Diff

View File

@@ -18,8 +18,10 @@
// expose Lo-Dash build file path // expose Lo-Dash build file path
ui.buildPath = (function() { ui.buildPath = (function() {
switch (build) { switch (build) {
case 'lodash-prod': return 'lodash.min.js'; case 'lodash-prod': return 'dist/lodash.compat.min.js';
case 'lodash-underscore': return 'lodash.underscore.min.js'; case 'lodash-underscore': return 'dist/lodash.underscore.min.js';
case 'lodash-modern': return 'dist/lodash.min.js';
case 'lodash-modern-debug': return 'dist/lodash.js';
case 'lodash-custom': return 'lodash.custom.min.js'; case 'lodash-custom': return 'lodash.custom.min.js';
case 'lodash-custom-debug': return 'lodash.custom.js'; case 'lodash-custom-debug': return 'lodash.custom.js';
} }
@@ -58,8 +60,10 @@
switch (build) { switch (build) {
case 'lodash-prod': return 1; case 'lodash-prod': return 1;
case 'lodash-underscore': return 2; case 'lodash-underscore': return 2;
case 'lodash-custom': return 3; case 'lodash-modern': return 3;
case 'lodash-custom-debug': return 4; case 'lodash-modern-debug': return 4;
case 'lodash-custom': return 5;
case 'lodash-custom-debug': return 6;
} }
return 0; return 0;
}()); }());
@@ -86,6 +90,8 @@
'<option value="lodash-dev">Developement</option>' + '<option value="lodash-dev">Developement</option>' +
'<option value="lodash-prod">Production</option>' + '<option value="lodash-prod">Production</option>' +
'<option value="lodash-underscore">Underscore</option>' + '<option value="lodash-underscore">Underscore</option>' +
'<option value="lodash-modern">Modern</option>' +
'<option value="lodash-modern-debug">Modern (debug)</option>' +
'<option value="lodash-custom">Custom</option>' + '<option value="lodash-custom">Custom</option>' +
'<option value="lodash-custom-debug">Custom (debug)</option>' + '<option value="lodash-custom-debug">Custom (debug)</option>' +
'</select>'; '</select>';

File diff suppressed because it is too large Load Diff

View File

@@ -5,7 +5,7 @@
<title>Underscore Test Suite</title> <title>Underscore Test Suite</title>
<link rel="stylesheet" href="../vendor/qunit/qunit/qunit.css"> <link rel="stylesheet" href="../vendor/qunit/qunit/qunit.css">
<style> <style>
iframe, img { iframe {
display: none; display: none;
} }
</style> </style>
@@ -19,20 +19,73 @@
</div> </div>
<img id="chart_image" src="data:image/gif;base64,R0lGODlhAQABAIAAAP///////yH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=="> <img id="chart_image" src="data:image/gif;base64,R0lGODlhAQABAIAAAP///////yH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==">
</div> </div>
<script src="../vendor/json3/lib/json3.js"></script>
<script src="../vendor/jquery/jquery.js"></script> <script src="../vendor/jquery/jquery.js"></script>
<script src="../vendor/platform.js/platform.js"></script> <script src="../vendor/platform.js/platform.js"></script>
<script> <script src="../vendor/qunit/qunit/qunit.js"></script>
// avoid syntax errors for `QUnit.throws` in older Firefoxes
document.write(platform.name == 'Firefox' && /^1\b/.test(platform.version)
? '<script src="../vendor/qunit/qunit/qunit-1.8.0.js"><\/script>'
: '<script src="../vendor/qunit/qunit/qunit.js"><\/script>'
);
</script>
<script src="test-ui.js"></script> <script src="test-ui.js"></script>
<script> <script>
document.write('<script src="../' + ui.buildPath + '"><\/script>'); document.write('<script src="../' + ui.buildPath + '"><\/script>');
</script> </script>
<script>
(function() {
var arrayProto = Array.prototype,
concat = arrayProto.concat,
pop = arrayProto.pop,
push = arrayProto.push,
slice = arrayProto.slice;
if (_.chain) {
return;
}
_.mixin = function(object) {
_.forEach(_.functions(object), function(methodName) {
var func = _[methodName] = object[methodName];
_.prototype[methodName] = function() {
var args = [this.__wrapped__];
push.apply(args, arguments);
var result = func.apply(_, args);
if (this.__chain__) {
result = new _(result);
result.__chain__ = true;
}
return result;
};
});
};
_.mixin(_);
_.mixin({
'findWhere': _.find
});
_.chain = function(value) {
value = new _(value);
value.__chain__ = true;
return value;
};
_.prototype.chain = function() {
this.__chain__ = true;
return this;
};
_.prototype.concat = function() {
var result = concat.apply(this.__wrapped__, arguments);
if (this.__chain__) {
result = new _(result);
result.__chain__ = true;
}
return result;
};
_.prototype.pop = function() {
pop.apply(this.__wrapped__, arguments);
return this;
};
}());
</script>
<script src="../vendor/underscore/test/collections.js"></script> <script src="../vendor/underscore/test/collections.js"></script>
<script src="../vendor/underscore/test/arrays.js"></script> <script src="../vendor/underscore/test/arrays.js"></script>
<script src="../vendor/underscore/test/functions.js"></script> <script src="../vendor/underscore/test/functions.js"></script>

View File

@@ -1,4 +1,4 @@
Copyright (c) 2010-2012 Jeremy Ashkenas, DocumentCloud Copyright (c) 2010-2013 Jeremy Ashkenas, DocumentCloud
Permission is hereby granted, free of charge, to any person Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation obtaining a copy of this software and associated documentation

File diff suppressed because it is too large Load Diff

View File

@@ -18,17 +18,21 @@ $(document).ready(function() {
})); }));
test("new and sort", 7, function() { test("new and sort", 9, function() {
var counter = 0;
col.on('sort', function(){ counter++; });
equal(col.first(), a, "a should be first"); equal(col.first(), a, "a should be first");
equal(col.last(), d, "d should be last"); equal(col.last(), d, "d should be last");
col.comparator = function(a, b) { col.comparator = function(a, b) {
return a.id > b.id ? -1 : 1; return a.id > b.id ? -1 : 1;
}; };
col.sort(); col.sort();
equal(counter, 1);
equal(col.first(), a, "a should be first"); equal(col.first(), a, "a should be first");
equal(col.last(), d, "d should be last"); equal(col.last(), d, "d should be last");
col.comparator = function(model) { return model.id; }; col.comparator = function(model) { return model.id; };
col.sort(); col.sort();
equal(counter, 2);
equal(col.first(), d, "d should be first"); equal(col.first(), d, "d should be first");
equal(col.last(), a, "a should be last"); equal(col.last(), a, "a should be last");
equal(col.length, 4); equal(col.length, 4);
@@ -58,22 +62,29 @@ $(document).ready(function() {
strictEqual(collection.last().get('a'), 4); strictEqual(collection.last().get('a'), 4);
}); });
test("get, getByCid", 3, function() { test("get", 6, function() {
equal(col.get(0), d); equal(col.get(0), d);
equal(col.get(d.clone()), d);
equal(col.get(2), b); equal(col.get(2), b);
equal(col.getByCid(col.first().cid), col.first()); equal(col.get({id: 1}), c);
equal(col.get(c.clone()), c);
equal(col.get(col.first().cid), col.first());
}); });
test("get with non-default ids", 2, function() { test("get with non-default ids", 5, function() {
var col = new Backbone.Collection(); var col = new Backbone.Collection();
var MongoModel = Backbone.Model.extend({ var MongoModel = Backbone.Model.extend({idAttribute: '_id'});
idAttribute: '_id'
});
var model = new MongoModel({_id: 100}); var model = new MongoModel({_id: 100});
col.push(model); col.add(model);
equal(col.get(100), model); equal(col.get(100), model);
model.set({_id: 101}); equal(col.get(model.cid), model);
equal(col.get(101), model); equal(col.get(model), model);
equal(col.get(101), void 0);
var col2 = new Backbone.Collection();
col2.model = MongoModel;
col2.add(model.attributes);
equal(col2.get(model.clone()), col2.first());
}); });
test("update index when id changes", 3, function() { test("update index when id changes", 3, function() {
@@ -214,6 +225,19 @@ $(document).ready(function() {
equal(col.at(0).get('value'), 2); equal(col.at(0).get('value'), 2);
}); });
test("add with parse and merge", function() {
var Model = Backbone.Model.extend({
parse: function (data) {
return data.model;
}
});
var collection = new Backbone.Collection();
collection.model = Model;
collection.add({id: 1});
collection.add({model: {id: 1, name: 'Alf'}}, {parse: true, merge: true});
equal(collection.first().get('name'), 'Alf');
});
test("add model to collection with sort()-style comparator", 3, function() { test("add model to collection with sort()-style comparator", 3, function() {
var col = new Backbone.Collection; var col = new Backbone.Collection;
col.comparator = function(a, b) { col.comparator = function(a, b) {
@@ -304,13 +328,13 @@ $(document).ready(function() {
var colE = new Backbone.Collection([e]); var colE = new Backbone.Collection([e]);
var colF = new Backbone.Collection([f]); var colF = new Backbone.Collection([f]);
ok(e != f); ok(e != f);
ok(colE.length == 1); ok(colE.length === 1);
ok(colF.length == 1); ok(colF.length === 1);
colE.remove(e); colE.remove(e);
equal(passed, false); equal(passed, false);
ok(colE.length == 0); ok(colE.length === 0);
colF.remove(e); colF.remove(e);
ok(colF.length == 0); ok(colF.length === 0);
equal(passed, true); equal(passed, true);
}); });
@@ -338,24 +362,24 @@ $(document).ready(function() {
}); });
equal(colE, e.collection); equal(colE, e.collection);
colF.remove(e); colF.remove(e);
ok(colF.length == 0); ok(colF.length === 0);
ok(colE.length == 1); ok(colE.length === 1);
equal(counter, 1); equal(counter, 1);
equal(colE, e.collection); equal(colE, e.collection);
colE.remove(e); colE.remove(e);
equal(null, e.collection); equal(null, e.collection);
ok(colE.length == 0); ok(colE.length === 0);
equal(counter, 2); equal(counter, 2);
}); });
test("model destroy removes from all collections", 3, function() { test("model destroy removes from all collections", 3, function() {
var e = new Backbone.Model({id: 5, title: 'Othello'}); var e = new Backbone.Model({id: 5, title: 'Othello'});
e.sync = function(method, model, options) { options.success({}); }; e.sync = function(method, model, options) { options.success(); };
var colE = new Backbone.Collection([e]); var colE = new Backbone.Collection([e]);
var colF = new Backbone.Collection([e]); var colF = new Backbone.Collection([e]);
e.destroy(); e.destroy();
ok(colE.length == 0); ok(colE.length === 0);
ok(colF.length == 0); ok(colF.length === 0);
equal(undefined, e.collection); equal(undefined, e.collection);
}); });
@@ -365,8 +389,8 @@ $(document).ready(function() {
var colE = new Backbone.Collection([e]); var colE = new Backbone.Collection([e]);
var colF = new Backbone.Collection([e]); var colF = new Backbone.Collection([e]);
e.destroy(); e.destroy();
ok(colE.length == 0); ok(colE.length === 0);
ok(colF.length == 0); ok(colF.length === 0);
equal(undefined, e.collection); equal(undefined, e.collection);
}); });
@@ -382,6 +406,28 @@ $(document).ready(function() {
equal(this.syncArgs.options.parse, false); equal(this.syncArgs.options.parse, false);
}); });
test("fetch with an error response triggers an error event", 1, function () {
var collection = new Backbone.Collection();
collection.on('error', function () {
ok(true);
});
collection.sync = function (method, model, options) { options.error(); };
collection.fetch();
});
test("ensure fetch only parses once", 1, function() {
var collection = new Backbone.Collection;
var counter = 0;
collection.parse = function(models) {
counter++;
return models;
};
collection.url = '/test';
collection.fetch();
this.syncArgs.options.success();
equal(counter, 1);
});
test("create", 4, function() { test("create", 4, function() {
var collection = new Backbone.Collection; var collection = new Backbone.Collection;
collection.url = '/test'; collection.url = '/test';
@@ -392,7 +438,7 @@ $(document).ready(function() {
equal(model.collection, collection); equal(model.collection, collection);
}); });
test("create enforces validation", 1, function() { test("create with validate:true enforces validation", 2, function() {
var ValidatingModel = Backbone.Model.extend({ var ValidatingModel = Backbone.Model.extend({
validate: function(attrs) { validate: function(attrs) {
return "fail"; return "fail";
@@ -402,10 +448,13 @@ $(document).ready(function() {
model: ValidatingModel model: ValidatingModel
}); });
var col = new ValidatingCollection(); var col = new ValidatingCollection();
equal(col.create({"foo":"bar"}), false); col.on('invalid', function (collection, attrs, options) {
equal(options.validationError, 'fail');
});
equal(col.create({"foo":"bar"}, {validate:true}), false);
}); });
test("a failing create runs the error callback", 1, function() { test("a failing create returns model with errors", function() {
var ValidatingModel = Backbone.Model.extend({ var ValidatingModel = Backbone.Model.extend({
validate: function(attrs) { validate: function(attrs) {
return "fail"; return "fail";
@@ -414,11 +463,10 @@ $(document).ready(function() {
var ValidatingCollection = Backbone.Collection.extend({ var ValidatingCollection = Backbone.Collection.extend({
model: ValidatingModel model: ValidatingModel
}); });
var flag = false;
var callback = function(model, error) { flag = true; };
var col = new ValidatingCollection(); var col = new ValidatingCollection();
col.create({"foo":"bar"}, { error: callback }); var m = col.create({"foo":"bar"});
equal(flag, true); equal(m.validationError, 'fail');
equal(col.length, 1);
}); });
test("initialize", 1, function() { test("initialize", 1, function() {
@@ -435,9 +483,10 @@ $(document).ready(function() {
equal(JSON.stringify(col), '[{"id":3,"label":"a"},{"id":2,"label":"b"},{"id":1,"label":"c"},{"id":0,"label":"d"}]'); equal(JSON.stringify(col), '[{"id":3,"label":"a"},{"id":2,"label":"b"},{"id":1,"label":"c"},{"id":0,"label":"d"}]');
}); });
test("where", 6, function() { test("where and findWhere", 8, function() {
var model = new Backbone.Model({a: 1});
var coll = new Backbone.Collection([ var coll = new Backbone.Collection([
{a: 1}, model,
{a: 1}, {a: 1},
{a: 1, b: 2}, {a: 1, b: 2},
{a: 2, b: 2}, {a: 2, b: 2},
@@ -449,6 +498,8 @@ $(document).ready(function() {
equal(coll.where({b: 1}).length, 0); equal(coll.where({b: 1}).length, 0);
equal(coll.where({b: 2}).length, 2); equal(coll.where({b: 2}).length, 2);
equal(coll.where({a: 1, b: 2}).length, 1); equal(coll.where({a: 1, b: 2}).length, 1);
equal(coll.findWhere({a: 1}), model);
equal(coll.findWhere({a: 4}), void 0);
}); });
test("Underscore methods", 13, function() { test("Underscore methods", 13, function() {
@@ -458,10 +509,10 @@ $(document).ready(function() {
equal(col.indexOf(b), 1); equal(col.indexOf(b), 1);
equal(col.size(), 4); equal(col.size(), 4);
equal(col.rest().length, 3); equal(col.rest().length, 3);
ok(!_.include(col.rest()), a); ok(!_.include(col.rest(), a));
ok(!_.include(col.rest()), d); ok(_.include(col.rest(), d));
ok(!col.isEmpty()); ok(!col.isEmpty());
ok(!_.include(col.without(d)), d); ok(!_.include(col.without(d), d));
equal(col.max(function(model){ return model.id; }).id, 3); equal(col.max(function(model){ return model.id; }).id, 3);
equal(col.min(function(model){ return model.id; }).id, 0); equal(col.min(function(model){ return model.id; }).id, 0);
deepEqual(col.chain() deepEqual(col.chain()
@@ -471,7 +522,19 @@ $(document).ready(function() {
[4, 0]); [4, 0]);
}); });
test("reset", 10, function() { test("sortedIndex", function () {
var model = new Backbone.Model({key: 2});
var collection = new (Backbone.Collection.extend({
comparator: 'key'
}))([model, {key: 1}]);
equal(collection.sortedIndex(model), 1);
equal(collection.sortedIndex(model, 'key'), 1);
equal(collection.sortedIndex(model, function (model) {
return model.get('key');
}), 1);
});
test("reset", 12, function() {
var resetCount = 0; var resetCount = 0;
var models = col.models; var models = col.models;
col.on('reset', function() { resetCount += 1; }); col.on('reset', function() { resetCount += 1; });
@@ -488,6 +551,22 @@ $(document).ready(function() {
equal(col.length, 4); equal(col.length, 4);
ok(col.last() !== d); ok(col.last() !== d);
ok(_.isEqual(col.last().attributes, d.attributes)); ok(_.isEqual(col.last().attributes, d.attributes));
col.reset();
equal(col.length, 0);
equal(resetCount, 4);
});
test ("reset with different values", function(){
var col = new Backbone.Collection({id: 1});
col.reset({id: 1, a: 1});
equal(col.get(1).get('a'), 1);
});
test("same references in reset", function() {
var model = new Backbone.Model({id: 1});
var collection = new Backbone.Collection({id: 1});
collection.reset(model);
equal(collection.get(1), model);
}); });
test("reset passes caller options", 3, function() { test("reset passes caller options", 3, function() {
@@ -542,8 +621,7 @@ $(document).ready(function() {
equal(col.length, 0); equal(col.length, 0);
}); });
test("#861, adding models to a collection which do not pass validation", 1, function() { test("#861, adding models to a collection which do not pass validation, with validate:true", function() {
raises(function() {
var Model = Backbone.Model.extend({ var Model = Backbone.Model.extend({
validate: function(attrs) { validate: function(attrs) {
if (attrs.id == 3) return "id can't be 3"; if (attrs.id == 3) return "id can't be 3";
@@ -554,26 +632,26 @@ $(document).ready(function() {
model: Model model: Model
}); });
var col = new Collection; var collection = new Collection;
collection.on("error", function() { ok(true); });
col.add([{id: 1}, {id: 2}, {id: 3}, {id: 4}, {id: 5}, {id: 6}]); collection.add([{id: 1}, {id: 2}, {id: 3}, {id: 4}, {id: 5}, {id: 6}], {validate:true});
}, function(e) { deepEqual(collection.pluck('id'), [1, 2, 4, 5, 6]);
return e.message === "Can't add an invalid model to a collection";
});
}); });
test("throwing during add leaves consistent state", 4, function() { test("Invalid models are discarded with validate:true.", 5, function() {
var col = new Backbone.Collection(); var collection = new Backbone.Collection;
col.on('test', function() { ok(false); }); collection.on('test', function() { ok(true); });
col.model = Backbone.Model.extend({ collection.model = Backbone.Model.extend({
validate: function(attrs){ if (!attrs.valid) return 'invalid'; } validate: function(attrs){ if (!attrs.valid) return 'invalid'; }
}); });
var model = new col.model({id: 1, valid: true}); var model = new collection.model({id: 1, valid: true});
raises(function() { col.add([model, {id: 2}]); }); collection.add([model, {id: 2}], {validate:true});
model.trigger('test'); model.trigger('test');
ok(!col.getByCid(model.cid)); ok(collection.get(model.cid));
ok(!col.get(1)); ok(collection.get(1));
equal(col.length, 0); ok(!collection.get(2));
equal(collection.length, 1);
}); });
test("multiple copies of the same model", 3, function() { test("multiple copies of the same model", 3, function() {
@@ -632,19 +710,34 @@ $(document).ready(function() {
} }
}; };
col.sync = m.sync = function( method, collection, options ){ col.sync = m.sync = function( method, collection, options ){
options.success(); options.success(collection, [], options);
}; };
col.fetch(opts); col.fetch(opts);
col.create(m, opts); col.create(m, opts);
}); });
test("#1412 - Trigger 'sync' event.", 2, function() { test("#1412 - Trigger 'request' and 'sync' events.", 4, function() {
var collection = new Backbone.Collection; var collection = new Backbone.Collection;
collection.url = '/test'; collection.url = '/test';
collection.on('sync', function() { ok(true); });
Backbone.ajax = function(settings){ settings.success(); }; Backbone.ajax = function(settings){ settings.success(); };
collection.on('request', function(obj, xhr, options) {
ok(obj === collection, "collection has correct 'request' event after fetching");
});
collection.on('sync', function(obj, response, options) {
ok(obj === collection, "collection has correct 'sync' event after fetching");
});
collection.fetch(); collection.fetch();
collection.off();
collection.on('request', function(obj, xhr, options) {
ok(obj === collection.get(1), "collection has correct 'request' event after one of its models save");
});
collection.on('sync', function(obj, response, options) {
ok(obj === collection.get(1), "collection has correct 'sync' event after one of its models save");
});
collection.create({id: 1}); collection.create({id: 1});
collection.off();
}); });
test("#1447 - create with wait adds model.", 1, function() { test("#1447 - create with wait adds model.", 1, function() {
@@ -716,4 +809,292 @@ $(document).ready(function() {
this.ajaxSettings.success([model]); this.ajaxSettings.success([model]);
}); });
test("`sort` shouldn't always fire on `add`", 1, function() {
var c = new Backbone.Collection([{id: 1}, {id: 2}, {id: 3}], {
comparator: 'id'
});
c.sort = function(){ ok(true); };
c.add([]);
c.add({id: 1});
c.add([{id: 2}, {id: 3}]);
c.add({id: 4});
});
test("#1407 parse option on constructor parses collection and models", 2, function() {
var model = {
namespace : [{id: 1}, {id:2}]
};
var Collection = Backbone.Collection.extend({
model: Backbone.Model.extend({
parse: function(model) {
model.name = 'test';
return model;
}
}),
parse: function(model) {
return model.namespace;
}
});
var c = new Collection(model, {parse:true});
equal(c.length, 2);
equal(c.at(0).get('name'), 'test');
});
test("#1407 parse option on reset parses collection and models", 2, function() {
var model = {
namespace : [{id: 1}, {id:2}]
};
var Collection = Backbone.Collection.extend({
model: Backbone.Model.extend({
parse: function(model) {
model.name = 'test';
return model;
}
}),
parse: function(model) {
return model.namespace;
}
});
var c = new Collection();
c.reset(model, {parse:true});
equal(c.length, 2);
equal(c.at(0).get('name'), 'test');
});
test("Reset includes previous models in triggered event.", 1, function() {
var model = new Backbone.Model();
var collection = new Backbone.Collection([model])
.on('reset', function(collection, options) {
deepEqual(options.previousModels, [model]);
});
collection.reset([]);
});
test("set", function() {
var m1 = new Backbone.Model();
var m2 = new Backbone.Model({id: 2});
var m3 = new Backbone.Model();
var c = new Backbone.Collection([m1, m2]);
// Test add/change/remove events
c.on('add', function(model) {
strictEqual(model, m3);
});
c.on('change', function(model) {
strictEqual(model, m2);
});
c.on('remove', function(model) {
strictEqual(model, m1);
});
// remove: false doesn't remove any models
c.set([], {remove: false});
strictEqual(c.length, 2);
// add: false doesn't add any models
c.set([m1, m2, m3], {add: false});
strictEqual(c.length, 2);
// merge: false doesn't change any models
c.set([m1, {id: 2, a: 1}], {merge: false});
strictEqual(m2.get('a'), void 0);
// add: false, remove: false only merges existing models
c.set([m1, {id: 2, a: 0}, m3, {id: 4}], {add: false, remove: false});
strictEqual(c.length, 2);
strictEqual(m2.get('a'), 0);
// default options add/remove/merge as appropriate
c.set([{id: 2, a: 1}, m3]);
strictEqual(c.length, 2);
strictEqual(m2.get('a'), 1);
// Test removing models not passing an argument
c.off('remove').on('remove', function(model) {
ok(model === m2 || model === m3);
});
c.set([]);
strictEqual(c.length, 0);
});
test("set with only cids", 3, function() {
var m1 = new Backbone.Model;
var m2 = new Backbone.Model;
var c = new Backbone.Collection;
c.set([m1, m2]);
equal(c.length, 2);
c.set([m1]);
equal(c.length, 1);
c.set([m1, m1, m1, m2, m2], {remove: false});
equal(c.length, 2);
});
test("set with only idAttribute", 3, function() {
var m1 = { _id: 1 };
var m2 = { _id: 2 };
var col = Backbone.Collection.extend({
model: Backbone.Model.extend({
idAttribute: '_id'
})
});
var c = new col;
c.set([m1, m2]);
equal(c.length, 2);
c.set([m1]);
equal(c.length, 1);
c.set([m1, m1, m1, m2, m2], {remove: false});
equal(c.length, 2);
});
test("set + merge with default values defined", function() {
var Model = Backbone.Model.extend({
defaults: {
key: 'value'
}
});
var m = new Model({id: 1});
var col = new Backbone.Collection([m], {model: Model});
equal(col.first().get('key'), 'value');
col.set({id: 1, key: 'other'});
equal(col.first().get('key'), 'other');
col.set({id: 1, other: 'value'});
equal(col.first().get('key'), 'value');
equal(col.length, 1);
});
test("`set` and model level `parse`", function() {
var Model = Backbone.Model.extend({
parse: function (res) { return res.model; }
});
var Collection = Backbone.Collection.extend({
model: Model,
parse: function (res) { return res.models; }
});
var model = new Model({id: 1});
var collection = new Collection(model);
collection.set({models: [
{model: {id: 1}},
{model: {id: 2}}
]}, {parse: true});
equal(collection.first(), model);
});
test("`set` data is only parsed once", function() {
var collection = new Backbone.Collection();
collection.model = Backbone.Model.extend({
parse: function (data) {
equal(data.parsed, void 0);
data.parsed = true;
return data;
}
});
collection.set({}, {parse: true});
});
test("#1894 - Push should not trigger a sort", 0, function() {
var Collection = Backbone.Collection.extend({
comparator: 'id',
sort: function() {
ok(false);
}
});
new Collection().push({id: 1});
});
test("`set` with non-normal id", function() {
var Collection = Backbone.Collection.extend({
model: Backbone.Model.extend({idAttribute: '_id'})
});
var collection = new Collection({_id: 1});
collection.set([{_id: 1, a: 1}], {add: false});
equal(collection.first().get('a'), 1);
});
test("#1894 - `sort` can optionally be turned off", 0, function() {
var Collection = Backbone.Collection.extend({
comparator: 'id',
sort: function() { ok(true); }
});
new Collection().add({id: 1}, {sort: false});
});
test("#1915 - `parse` data in the right order in `set`", function() {
var collection = new (Backbone.Collection.extend({
parse: function (data) {
strictEqual(data.status, 'ok');
return data.data;
}
}));
var res = {status: 'ok', data:[{id: 1}]};
collection.set(res, {parse: true});
});
asyncTest("#1939 - `parse` is passed `options`", 1, function () {
var collection = new (Backbone.Collection.extend({
url: '/',
parse: function (data, options) {
strictEqual(options.xhr.someHeader, 'headerValue');
return data;
}
}));
var ajax = Backbone.ajax;
Backbone.ajax = function (params) {
_.defer(params.success);
return {someHeader: 'headerValue'};
};
collection.fetch({
success: function () { start(); }
});
Backbone.ajax = ajax;
});
test("`add` only `sort`s when necessary", 2, function () {
var collection = new (Backbone.Collection.extend({
comparator: 'a'
}))([{id: 1}, {id: 2}, {id: 3}]);
collection.on('sort', function () { ok(true); });
collection.add({id: 4}); // do sort, new model
collection.add({id: 1, a: 1}, {merge: true}); // do sort, comparator change
collection.add({id: 1, b: 1}, {merge: true}); // don't sort, no comparator change
collection.add({id: 1, a: 1}, {merge: true}); // don't sort, no comparator change
collection.add(collection.models); // don't sort, nothing new
collection.add(collection.models, {merge: true}); // don't sort
});
test("`add` only `sort`s when necessary with comparator function", 3, function () {
var collection = new (Backbone.Collection.extend({
comparator: function(a, b) {
return a.get('a') > b.get('a') ? 1 : (a.get('a') < b.get('a') ? -1 : 0);
}
}))([{id: 1}, {id: 2}, {id: 3}]);
collection.on('sort', function () { ok(true); });
collection.add({id: 4}); // do sort, new model
collection.add({id: 1, a: 1}, {merge: true}); // do sort, model change
collection.add({id: 1, b: 1}, {merge: true}); // do sort, model change
collection.add({id: 1, a: 1}, {merge: true}); // don't sort, no model change
collection.add(collection.models); // don't sort, nothing new
collection.add(collection.models, {merge: true}); // don't sort
});
test("Attach options to collection.", 3, function() {
var url = '/somewhere';
var model = new Backbone.Model;
var comparator = function(){};
var collection = new Backbone.Collection([], {
url: url,
model: model,
comparator: comparator
});
strictEqual(collection.url, url);
ok(collection.model === model);
ok(collection.comparator === comparator);
});
}); });

View File

@@ -17,7 +17,7 @@ $(document).ready(function() {
test("binding and triggering multiple events", 4, function() { test("binding and triggering multiple events", 4, function() {
var obj = { counter: 0 }; var obj = { counter: 0 };
_.extend(obj,Backbone.Events); _.extend(obj, Backbone.Events);
obj.on('a b c', function() { obj.counter += 1; }); obj.on('a b c', function() { obj.counter += 1; });
@@ -35,6 +35,130 @@ $(document).ready(function() {
equal(obj.counter, 5); equal(obj.counter, 5);
}); });
test("binding and triggering with event maps", function() {
var obj = { counter: 0 };
_.extend(obj, Backbone.Events);
var increment = function() {
this.counter += 1;
};
obj.on({
a: increment,
b: increment,
c: increment
}, obj);
obj.trigger('a');
equal(obj.counter, 1);
obj.trigger('a b');
equal(obj.counter, 3);
obj.trigger('c');
equal(obj.counter, 4);
obj.off({
a: increment,
c: increment
}, obj);
obj.trigger('a b c');
equal(obj.counter, 5);
});
test("listenTo and stopListening", 1, function() {
var a = _.extend({}, Backbone.Events);
var b = _.extend({}, Backbone.Events);
a.listenTo(b, 'all', function(){ ok(true); });
b.trigger('anything');
a.listenTo(b, 'all', function(){ ok(false); });
a.stopListening();
b.trigger('anything');
});
test("listenTo and stopListening with event maps", 4, function() {
var a = _.extend({}, Backbone.Events);
var b = _.extend({}, Backbone.Events);
var cb = function(){ ok(true); };
a.listenTo(b, {event: cb});
b.trigger('event');
a.listenTo(b, {event2: cb});
b.on('event2', cb);
a.stopListening(b, {event2: cb});
b.trigger('event event2');
a.stopListening();
b.trigger('event event2');
});
test("stopListening with omitted args", 2, function () {
var a = _.extend({}, Backbone.Events);
var b = _.extend({}, Backbone.Events);
var cb = function () { ok(true); };
a.listenTo(b, 'event', cb);
b.on('event', cb);
a.listenTo(b, 'event2', cb);
a.stopListening(null, {event: cb});
b.trigger('event event2');
b.off();
a.listenTo(b, 'event event2', cb);
a.stopListening(null, 'event');
a.stopListening();
b.trigger('event2');
});
test("listenToOnce and stopListening", 1, function() {
var a = _.extend({}, Backbone.Events);
var b = _.extend({}, Backbone.Events);
a.listenToOnce(b, 'all', function() { ok(true); });
b.trigger('anything');
b.trigger('anything');
a.listenToOnce(b, 'all', function() { ok(false); });
a.stopListening();
b.trigger('anything');
});
test("listenTo, listenToOnce and stopListening", 1, function() {
var a = _.extend({}, Backbone.Events);
var b = _.extend({}, Backbone.Events);
a.listenToOnce(b, 'all', function() { ok(true); });
b.trigger('anything');
b.trigger('anything');
a.listenTo(b, 'all', function() { ok(false); });
a.stopListening();
b.trigger('anything');
});
test("listenTo and stopListening with event maps", 1, function() {
var a = _.extend({}, Backbone.Events);
var b = _.extend({}, Backbone.Events);
a.listenTo(b, {change: function(){ ok(true); }});
b.trigger('change');
a.listenTo(b, {change: function(){ ok(false); }});
a.stopListening();
b.trigger('change');
});
test("listenTo yourself", 1, function(){
var e = _.extend({}, Backbone.Events);
e.listenTo(e, "foo", function(){ ok(true); });
e.trigger("foo");
});
test("listenTo yourself cleans yourself up with stopListening", 1, function(){
var e = _.extend({}, Backbone.Events);
e.listenTo(e, "foo", function(){ ok(true); });
e.trigger("foo");
e.stopListening();
e.trigger("foo");
});
test("listenTo with empty callback doesn't throw an error", 1, function(){
var e = _.extend({}, Backbone.Events);
e.listenTo(e, "foo", null);
e.trigger("foo");
ok(true);
});
test("trigger all for each event", 3, function() { test("trigger all for each event", 3, function() {
var a, b, obj = { counter: 0 }; var a, b, obj = { counter: 0 };
_.extend(obj, Backbone.Events); _.extend(obj, Backbone.Events);
@@ -154,6 +278,13 @@ $(document).ready(function() {
_.extend({}, Backbone.Events).on('test').trigger('test'); _.extend({}, Backbone.Events).on('test').trigger('test');
}); });
test("if callback is truthy but not a function, `on` should throw an error just like jQuery", 1, function() {
var view = _.extend({}, Backbone.Events).on('test', 'noop');
throws(function() {
view.trigger('test');
});
});
test("remove all events for a specific context", 4, function() { test("remove all events for a specific context", 4, function() {
var obj = _.extend({}, Backbone.Events); var obj = _.extend({}, Backbone.Events);
obj.on('x y all', function() { ok(true); }); obj.on('x y all', function() { ok(true); });
@@ -172,18 +303,6 @@ $(document).ready(function() {
obj.trigger('x y'); obj.trigger('x y');
}); });
test("off is chainable", 3, function() {
var obj = _.extend({}, Backbone.Events);
// With no events
ok(obj.off() === obj);
// When removing all events
obj.on('event', function(){}, obj);
ok(obj.off() === obj);
// When removing some events
obj.on('event', function(){}, obj);
ok(obj.off('event') === obj);
});
test("#1310 - off does not skip consecutive events", 0, function() { test("#1310 - off does not skip consecutive events", 0, function() {
var obj = _.extend({}, Backbone.Events); var obj = _.extend({}, Backbone.Events);
obj.on('event', function() { ok(false); }, obj); obj.on('event', function() { ok(false); }, obj);
@@ -192,4 +311,142 @@ $(document).ready(function() {
obj.trigger('event'); obj.trigger('event');
}); });
test("once", 2, function() {
// Same as the previous test, but we use once rather than having to explicitly unbind
var obj = { counterA: 0, counterB: 0 };
_.extend(obj, Backbone.Events);
var incrA = function(){ obj.counterA += 1; obj.trigger('event'); };
var incrB = function(){ obj.counterB += 1; };
obj.once('event', incrA);
obj.once('event', incrB);
obj.trigger('event');
equal(obj.counterA, 1, 'counterA should have only been incremented once.');
equal(obj.counterB, 1, 'counterB should have only been incremented once.');
});
test("once variant one", 3, function() {
var f = function(){ ok(true); };
var a = _.extend({}, Backbone.Events).once('event', f);
var b = _.extend({}, Backbone.Events).on('event', f);
a.trigger('event');
b.trigger('event');
b.trigger('event');
});
test("once variant two", 3, function() {
var f = function(){ ok(true); };
var obj = _.extend({}, Backbone.Events);
obj
.once('event', f)
.on('event', f)
.trigger('event')
.trigger('event');
});
test("once with off", 0, function() {
var f = function(){ ok(true); };
var obj = _.extend({}, Backbone.Events);
obj.once('event', f);
obj.off('event', f);
obj.trigger('event');
});
test("once with event maps", function() {
var obj = { counter: 0 };
_.extend(obj, Backbone.Events);
var increment = function() {
this.counter += 1;
};
obj.once({
a: increment,
b: increment,
c: increment
}, obj);
obj.trigger('a');
equal(obj.counter, 1);
obj.trigger('a b');
equal(obj.counter, 2);
obj.trigger('c');
equal(obj.counter, 3);
obj.trigger('a b c');
equal(obj.counter, 3);
});
test("once with off only by context", 0, function() {
var context = {};
var obj = _.extend({}, Backbone.Events);
obj.once('event', function(){ ok(false); }, context);
obj.off(null, null, context);
obj.trigger('event');
});
test("Backbone object inherits Events", function() {
ok(Backbone.on === Backbone.Events.on);
});
asyncTest("once with asynchronous events", 1, function() {
var func = _.debounce(function() { ok(true); start(); }, 50);
var obj = _.extend({}, Backbone.Events).once('async', func);
obj.trigger('async');
obj.trigger('async');
});
test("once with multiple events.", 2, function() {
var obj = _.extend({}, Backbone.Events);
obj.once('x y', function() { ok(true); });
obj.trigger('x y');
});
test("Off during iteration with once.", 2, function() {
var obj = _.extend({}, Backbone.Events);
var f = function(){ this.off('event', f); };
obj.on('event', f);
obj.once('event', function(){});
obj.on('event', function(){ ok(true); });
obj.trigger('event');
obj.trigger('event');
});
test("`once` on `all` should work as expected", 1, function() {
Backbone.once('all', function() {
ok(true);
Backbone.trigger('all');
});
Backbone.trigger('all');
});
test("once without a callback is a noop", 0, function() {
_.extend({}, Backbone.Events).once('event').trigger('event');
});
test("event functions are chainable", function() {
var obj = _.extend({}, Backbone.Events);
var obj2 = _.extend({}, Backbone.Events);
var fn = function() {};
equal(obj, obj.trigger('noeventssetyet'));
equal(obj, obj.off('noeventssetyet'));
equal(obj, obj.stopListening('noeventssetyet'));
equal(obj, obj.on('a', fn));
equal(obj, obj.once('c', fn));
equal(obj, obj.trigger('a'));
equal(obj, obj.listenTo(obj2, 'a', fn));
equal(obj, obj.listenToOnce(obj2, 'b', fn));
equal(obj, obj.off('a c'));
equal(obj, obj.stopListening(obj2, 'a'));
equal(obj, obj.stopListening());
});
}); });

View File

@@ -46,19 +46,31 @@ $(document).ready(function() {
test("initialize with parsed attributes", 1, function() { test("initialize with parsed attributes", 1, function() {
var Model = Backbone.Model.extend({ var Model = Backbone.Model.extend({
parse: function(obj) { parse: function(attrs) {
obj.value += 1; attrs.value += 1;
return obj; return attrs;
} }
}); });
var model = new Model({value: 1}, {parse: true}); var model = new Model({value: 1}, {parse: true});
equal(model.get('value'), 2); equal(model.get('value'), 2);
}); });
test("initialize with defaults", 2, function() {
var Model = Backbone.Model.extend({
defaults: {
first_name: 'Unknown',
last_name: 'Unknown'
}
});
var model = new Model({'first_name': 'John'});
equal(model.get('first_name'), 'John');
equal(model.get('last_name'), 'Unknown');
});
test("parse can return null", 1, function() { test("parse can return null", 1, function() {
var Model = Backbone.Model.extend({ var Model = Backbone.Model.extend({
parse: function(obj) { parse: function(attrs) {
obj.value += 1; attrs.value += 1;
return null; return null;
} }
}); });
@@ -99,7 +111,24 @@ $(document).ready(function() {
equal(model.url(), '/nested/1/collection/2'); equal(model.url(), '/nested/1/collection/2');
}); });
test("clone", 8, function() { test('url and urlRoot are directly attached if passed in the options', 2, function () {
var model = new Backbone.Model({a: 1}, {url: '/test'});
var model2 = new Backbone.Model({a: 2}, {urlRoot: '/test2'});
equal(model.url, '/test');
equal(model2.urlRoot, '/test2');
});
test("underscore methods", 5, function() {
var model = new Backbone.Model({ 'foo': 'a', 'bar': 'b', 'baz': 'c' });
var model2 = model.clone();
deepEqual(model.keys(), ['foo', 'bar', 'baz']);
deepEqual(model.values(), ['a', 'b', 'c']);
deepEqual(model.invert(), { 'a': 'foo', 'b': 'bar', 'c': 'baz' });
deepEqual(model.pick('foo', 'baz'), {'foo': 'a', 'baz': 'c'});
deepEqual(model.omit('foo', 'bar'), {'baz': 'c'});
});
test("clone", 10, function() {
var a = new Backbone.Model({ 'foo': 1, 'bar': 2, 'baz': 3}); var a = new Backbone.Model({ 'foo': 1, 'bar': 2, 'baz': 3});
var b = a.clone(); var b = a.clone();
equal(a.get('foo'), 1); equal(a.get('foo'), 1);
@@ -111,6 +140,12 @@ $(document).ready(function() {
a.set({foo : 100}); a.set({foo : 100});
equal(a.get('foo'), 100); equal(a.get('foo'), 100);
equal(b.get('foo'), 1, "Changing a parent attribute does not change the clone."); equal(b.get('foo'), 1, "Changing a parent attribute does not change the clone.");
var foo = new Backbone.Model({p: 1});
var bar = new Backbone.Model({p: 2});
bar.set(foo.clone().attributes, {unset: true});
equal(foo.get('p'), 1);
equal(bar.get('p'), undefined);
}); });
test("isNew", 6, function() { test("isNew", 6, function() {
@@ -184,9 +219,9 @@ $(document).ready(function() {
ok(changeCount == 1, "Change count should NOT have incremented."); ok(changeCount == 1, "Change count should NOT have incremented.");
a.validate = function(attrs) { a.validate = function(attrs) {
equal(attrs.foo, void 0, "don't ignore values when unsetting"); equal(attrs.foo, void 0, "validate:true passed while unsetting");
}; };
a.unset('foo'); a.unset('foo', {validate: true});
equal(a.get('foo'), void 0, "Foo should have changed"); equal(a.get('foo'), void 0, "Foo should have changed");
delete a.validate; delete a.validate;
ok(changeCount == 2, "Change count should have incremented for unset."); ok(changeCount == 2, "Change count should have incremented for unset.");
@@ -195,6 +230,46 @@ $(document).ready(function() {
equal(a.id, undefined, "Unsetting the id should remove the id property."); equal(a.id, undefined, "Unsetting the id should remove the id property.");
}); });
test("#2030 - set with failed validate, followed by another set triggers change", function () {
var attr = 0, main = 0, error = 0;
var Model = Backbone.Model.extend({
validate: function (attr) {
if (attr.x > 1) {
error++;
return "this is an error";
}
}
});
var model = new Model({x:0});
model.on('change:x', function () { attr++; });
model.on('change', function () { main++; });
model.set({x:2}, {validate:true});
model.set({x:1}, {validate:true});
deepEqual([attr, main, error], [1, 1, 1]);
});
test("set triggers changes in the correct order", function() {
var value = null;
var model = new Backbone.Model;
model.on('last', function(){ value = 'last'; });
model.on('first', function(){ value = 'first'; });
model.trigger('first');
model.trigger('last');
equal(value, 'last');
});
test("set falsy values in the correct order", 2, function() {
var model = new Backbone.Model({result: 'result'});
model.on('change', function() {
equal(model.changed.result, void 0);
equal(model.previous('result'), false);
});
model.set({result: void 0}, {silent: true});
model.set({result: null}, {silent: true});
model.set({result: false}, {silent: true});
model.set({result: void 0});
});
test("multiple unsets", 1, function() { test("multiple unsets", 1, function() {
var i = 0; var i = 0;
var counter = function(){ i++; }; var counter = function(){ i++; };
@@ -206,14 +281,12 @@ $(document).ready(function() {
equal(i, 2, 'Unset does not fire an event for missing attributes.'); equal(i, 2, 'Unset does not fire an event for missing attributes.');
}); });
test("unset and changedAttributes", 2, function() { test("unset and changedAttributes", 1, function() {
var model = new Backbone.Model({a: 1}); var model = new Backbone.Model({a: 1});
model.unset('a', {silent: true}); model.on('change', function() {
var changedAttributes = model.changedAttributes(); ok('a' in model.changedAttributes(), 'changedAttributes should contain unset properties');
ok('a' in changedAttributes, 'changedAttributes should contain unset properties'); });
model.unset('a');
changedAttributes = model.changedAttributes();
ok('a' in changedAttributes, 'changedAttributes should contain unset properties when running changedAttributes again after an unset.');
}); });
test("using a non-default id attribute.", 5, function() { test("using a non-default id attribute.", 5, function() {
@@ -233,6 +306,21 @@ $(document).ready(function() {
equal(model.get('name'), ''); equal(model.get('name'), '');
}); });
test("setting an object", 1, function() {
var model = new Backbone.Model({
custom: { foo: 1 }
});
model.on('change', function() {
ok(1);
});
model.set({
custom: { foo: 1 } // no change should be fired
});
model.set({
custom: { foo: 2 } // change event should be fired
});
});
test("clear", 3, function() { test("clear", 3, function() {
var changed; var changed;
var model = new Backbone.Model({id: 1, name : "Model"}); var model = new Backbone.Model({id: 1, name : "Model"});
@@ -253,9 +341,9 @@ $(document).ready(function() {
"two": 2 "two": 2
} }
}); });
var model = new Defaulted({two: null}); var model = new Defaulted({two: undefined});
equal(model.get('one'), 1); equal(model.get('one'), 1);
equal(model.get('two'), null); equal(model.get('two'), 2);
Defaulted = Backbone.Model.extend({ Defaulted = Backbone.Model.extend({
defaults: function() { defaults: function() {
return { return {
@@ -264,14 +352,14 @@ $(document).ready(function() {
}; };
} }
}); });
var model = new Defaulted({two: null}); model = new Defaulted({two: undefined});
equal(model.get('one'), 3); equal(model.get('one'), 3);
equal(model.get('two'), null); equal(model.get('two'), 4);
}); });
test("change, hasChanged, changedAttributes, previous, previousAttributes", 12, function() { test("change, hasChanged, changedAttributes, previous, previousAttributes", 9, function() {
var model = new Backbone.Model({name : "Tim", age : 10}); var model = new Backbone.Model({name: "Tim", age: 10});
equal(model.changedAttributes(), false); deepEqual(model.changedAttributes(), false);
model.on('change', function() { model.on('change', function() {
ok(model.hasChanged('name'), 'name changed'); ok(model.hasChanged('name'), 'name changed');
ok(!model.hasChanged('age'), 'age did not'); ok(!model.hasChanged('age'), 'age did not');
@@ -281,18 +369,13 @@ $(document).ready(function() {
}); });
equal(model.hasChanged(), false); equal(model.hasChanged(), false);
equal(model.hasChanged(undefined), false); equal(model.hasChanged(undefined), false);
model.set({name : 'Rob'}, {silent : true}); model.set({name : 'Rob'});
equal(model.hasChanged(), true);
equal(model.hasChanged(undefined), true);
equal(model.hasChanged('name'), true);
model.change();
equal(model.get('name'), 'Rob'); equal(model.get('name'), 'Rob');
}); });
test("changedAttributes", 3, function() { test("changedAttributes", 3, function() {
var model = new Backbone.Model({a: 'a', b: 'b'}); var model = new Backbone.Model({a: 'a', b: 'b'});
equal(model.changedAttributes(), false); deepEqual(model.changedAttributes(), false);
equal(model.changedAttributes({a: 'a'}), false); equal(model.changedAttributes({a: 'a'}), false);
equal(model.changedAttributes({a: 'b'}).a, 'b'); equal(model.changedAttributes({a: 'b'}).a, 'b');
}); });
@@ -303,8 +386,7 @@ $(document).ready(function() {
model.on('change', function(model, options) { model.on('change', function(model, options) {
value = options.prefix + model.get('name'); value = options.prefix + model.get('name');
}); });
model.set({name: 'Bob'}, {silent: true}); model.set({name: 'Bob'}, {prefix: 'Mr. '});
model.change({prefix: 'Mr. '});
equal(value, 'Mr. Bob'); equal(value, 'Mr. Bob');
model.set({name: 'Sue'}, {prefix: 'Ms. '}); model.set({name: 'Sue'}, {prefix: 'Ms. '});
equal(value, 'Ms. Sue'); equal(value, 'Ms. Sue');
@@ -330,7 +412,7 @@ $(document).ready(function() {
model.set({lastName: 'Hicks'}); model.set({lastName: 'Hicks'});
}); });
test("validate after save", 1, function() { test("validate after save", 2, function() {
var lastError, model = new Backbone.Model(); var lastError, model = new Backbone.Model();
model.validate = function(attrs) { model.validate = function(attrs) {
if (attrs.admin) return "Can't change admin status."; if (attrs.admin) return "Can't change admin status.";
@@ -338,23 +420,13 @@ $(document).ready(function() {
model.sync = function(method, model, options) { model.sync = function(method, model, options) {
options.success.call(this, {admin: true}); options.success.call(this, {admin: true});
}; };
model.save(null, {error: function(model, error) { model.on('invalid', function(model, error) {
lastError = error; lastError = error;
}}); });
model.save(null);
equal(lastError, "Can't change admin status."); equal(lastError, "Can't change admin status.");
}); equal(model.validationError, "Can't change admin status.");
test("isValid", 5, function() {
var model = new Backbone.Model({valid: true});
model.validate = function(attrs) {
if (!attrs.valid) return "invalid";
};
equal(model.isValid(), true);
equal(model.set({valid: false}), false);
equal(model.isValid(), true);
ok(model.set('valid', false, {silent: true}));
equal(model.isValid(), false);
}); });
test("save", 2, function() { test("save", 2, function() {
@@ -363,6 +435,33 @@ $(document).ready(function() {
ok(_.isEqual(this.syncArgs.model, doc)); ok(_.isEqual(this.syncArgs.model, doc));
}); });
test("save, fetch, destroy triggers error event when an error occurs", 3, function () {
var model = new Backbone.Model();
model.on('error', function () {
ok(true);
});
model.sync = function (method, model, options) {
options.error();
};
model.save({data: 2, id: 1});
model.fetch();
model.destroy();
});
test("save with PATCH", function() {
doc.clear().set({id: 1, a: 1, b: 2, c: 3, d: 4});
doc.save();
equal(this.syncArgs.method, 'update');
equal(this.syncArgs.options.attrs, undefined);
doc.save({b: 2, d: 4}, {patch: true});
equal(this.syncArgs.method, 'patch');
equal(_.size(this.syncArgs.options.attrs), 2);
equal(this.syncArgs.options.attrs.d, 4);
equal(this.syncArgs.options.attrs.a, undefined);
equal(this.ajaxSettings.data, "{\"b\":2,\"d\":4}");
});
test("save in positional style", 1, function() { test("save in positional style", 1, function() {
var model = new Backbone.Model(); var model = new Backbone.Model();
model.sync = function(method, model, options) { model.sync = function(method, model, options) {
@@ -372,7 +471,18 @@ $(document).ready(function() {
equal(model.get('title'), 'Twelfth Night'); equal(model.get('title'), 'Twelfth Night');
}); });
test("save with non-object success response", 2, function () {
var model = new Backbone.Model();
model.sync = function(method, model, options) {
options.success('', options);
options.success(null, options);
};
model.save({testing:'empty'}, {
success: function (model) {
deepEqual(model.attributes, {testing:'empty'});
}
});
});
test("fetch", 2, function() { test("fetch", 2, function() {
doc.fetch(); doc.fetch();
@@ -396,22 +506,22 @@ $(document).ready(function() {
ok(true, "non-persisted model should not call sync"); ok(true, "non-persisted model should not call sync");
}); });
test("validate", 7, function() { test("validate", function() {
var lastError; var lastError;
var model = new Backbone.Model(); var model = new Backbone.Model();
model.validate = function(attrs) { model.validate = function(attrs) {
if (attrs.admin != this.get('admin')) return "Can't change admin status."; if (attrs.admin != this.get('admin')) return "Can't change admin status.";
}; };
model.on('error', function(model, error) { model.on('invalid', function(model, error) {
lastError = error; lastError = error;
}); });
var result = model.set({a: 100}); var result = model.set({a: 100});
equal(result, model); equal(result, model);
equal(model.get('a'), 100); equal(model.get('a'), 100);
equal(lastError, undefined); equal(lastError, undefined);
result = model.set({admin: true}, {silent: true}); result = model.set({admin: true});
equal(model.get('admin'), true); equal(model.get('admin'), true);
result = model.set({a: 200, admin: false}); result = model.set({a: 200, admin: false}, {validate:true});
equal(lastError, "Can't change admin status."); equal(lastError, "Can't change admin status.");
equal(result, false); equal(result, false);
equal(model.get('a'), 100); equal(model.get('a'), 100);
@@ -429,10 +539,10 @@ $(document).ready(function() {
model.set({name: "Two"}); model.set({name: "Two"});
equal(model.get('name'), 'Two'); equal(model.get('name'), 'Two');
equal(error, undefined); equal(error, undefined);
model.unset('name'); model.unset('name', {validate: true});
equal(error, true); equal(error, true);
equal(model.get('name'), 'Two'); equal(model.get('name'), 'Two');
model.clear(); model.clear({validate:true});
equal(model.get('name'), 'Two'); equal(model.get('name'), 'Two');
delete model.validate; delete model.validate;
model.clear(); model.clear();
@@ -445,21 +555,18 @@ $(document).ready(function() {
model.validate = function(attrs) { model.validate = function(attrs) {
if (attrs.admin) return "Can't change admin status."; if (attrs.admin) return "Can't change admin status.";
}; };
var callback = function(model, error) { model.on('invalid', function(model, error) {
lastError = error;
};
model.on('error', function(model, error) {
boundError = true; boundError = true;
}); });
var result = model.set({a: 100}, {error: callback}); var result = model.set({a: 100}, {validate:true});
equal(result, model); equal(result, model);
equal(model.get('a'), 100); equal(model.get('a'), 100);
equal(lastError, undefined); equal(model.validationError, null);
equal(boundError, undefined); equal(boundError, undefined);
result = model.set({a: 200, admin: true}, {error: callback}); result = model.set({a: 200, admin: true}, {validate:true});
equal(result, false); equal(result, false);
equal(model.get('a'), 100); equal(model.get('a'), 100);
equal(lastError, "Can't change admin status."); equal(model.validationError, "Can't change admin status.");
equal(boundError, true); equal(boundError, true);
}); });
@@ -554,9 +661,16 @@ $(document).ready(function() {
ok(model.get('x') === a); ok(model.get('x') === a);
}); });
test("unset fires change for undefined attributes", 1, function() { test("set same value does not trigger change", 0, function() {
var model = new Backbone.Model({x: 1});
model.on('change change:x', function() { ok(false); });
model.set({x: 1});
model.set({x: 1});
});
test("unset does not fire a change for undefined attributes", 0, function() {
var model = new Backbone.Model({x: undefined}); var model = new Backbone.Model({x: undefined});
model.on('change:x', function(){ ok(true); }); model.on('change:x', function(){ ok(false); });
model.unset('x'); model.unset('x');
}); });
@@ -565,19 +679,29 @@ $(document).ready(function() {
ok('x' in model.attributes); ok('x' in model.attributes);
}); });
test("change fires change:attr", 1, function() { test("hasChanged works outside of change events, and true within", 6, function() {
var model = new Backbone.Model({x: 1}); var model = new Backbone.Model({x: 1});
model.set({x: 2}, {silent: true}); model.on('change:x', function() {
model.on('change:x', function(){ ok(true); }); ok(model.hasChanged('x'));
model.change(); equal(model.get('x'), 1);
}); });
test("hasChanged is false after original values are set", 2, function() {
var model = new Backbone.Model({x: 1});
model.on('change:x', function(){ ok(false); });
model.set({x: 2}, {silent: true}); model.set({x: 2}, {silent: true});
ok(model.hasChanged()); ok(model.hasChanged());
model.set({x: 1}, {silent: true}); equal(model.hasChanged('x'), true);
model.set({x: 1});
ok(model.hasChanged());
equal(model.hasChanged('x'), true);
});
test("hasChanged gets cleared on the following set", 4, function() {
var model = new Backbone.Model;
model.set({x: 1});
ok(model.hasChanged());
model.set({x: 1});
ok(!model.hasChanged());
model.set({x: 2});
ok(model.hasChanged());
model.set({});
ok(!model.hasChanged()); ok(!model.hasChanged());
}); });
@@ -633,13 +757,20 @@ $(document).ready(function() {
equal(model.get('x'), 3); equal(model.get('x'), 3);
}); });
test("save with wait validates attributes", 1, function() { test("save with wait validates attributes", function() {
var model = new Backbone.Model(); var model = new Backbone.Model();
model.url = '/test'; model.url = '/test';
model.validate = function() { ok(true); }; model.validate = function() { ok(true); };
model.save({x: 1}, {wait: true}); model.save({x: 1}, {wait: true});
}); });
test("save turns on parse flag", function () {
var Model = Backbone.Model.extend({
sync: function(method, model, options) { ok(options.parse); }
});
new Model().save();
});
test("nested `set` during `'change:attr'`", 2, function() { test("nested `set` during `'change:attr'`", 2, function() {
var events = []; var events = [];
var model = new Backbone.Model(); var model = new Backbone.Model();
@@ -653,25 +784,19 @@ $(document).ready(function() {
model.set({x: true}); model.set({x: true});
deepEqual(events, ['change:y', 'change:x', 'change']); deepEqual(events, ['change:y', 'change:x', 'change']);
events = []; events = [];
model.change(); model.set({z: true});
deepEqual(events, ['change:z', 'change']); deepEqual(events, []);
}); });
test("nested `change` only fires once", 1, function() { test("nested `change` only fires once", 1, function() {
var model = new Backbone.Model(); var model = new Backbone.Model();
model.on('change', function() { model.on('change', function() {
ok(true); ok(true);
model.change(); model.set({x: true});
}); });
model.set({x: true}); model.set({x: true});
}); });
test("no `'change'` event if no changes", 0, function() {
var model = new Backbone.Model();
model.on('change', function() { ok(false); });
model.change();
});
test("nested `set` during `'change'`", 6, function() { test("nested `set` during `'change'`", 6, function() {
var count = 0; var count = 0;
var model = new Backbone.Model(); var model = new Backbone.Model();
@@ -683,13 +808,13 @@ $(document).ready(function() {
model.set({y: true}); model.set({y: true});
break; break;
case 1: case 1:
deepEqual(this.changedAttributes(), {y: true}); deepEqual(this.changedAttributes(), {x: true, y: true});
equal(model.previous('x'), true); equal(model.previous('x'), undefined);
model.set({z: true}); model.set({z: true});
break; break;
case 2: case 2:
deepEqual(this.changedAttributes(), {z: true}); deepEqual(this.changedAttributes(), {x: true, y: true, z: true});
equal(model.previous('y'), true); equal(model.previous('y'), undefined);
break; break;
default: default:
ok(false); ok(false);
@@ -698,30 +823,34 @@ $(document).ready(function() {
model.set({x: true}); model.set({x: true});
}); });
test("nested `'change'` with silent", 3, function() { test("nested `change` with silent", 3, function() {
var count = 0; var count = 0;
var model = new Backbone.Model(); var model = new Backbone.Model();
model.on('change:y', function() { ok(true); }); model.on('change:y', function() { ok(false); });
model.on('change', function() { model.on('change', function() {
switch(count++) { switch(count++) {
case 0: case 0:
deepEqual(this.changedAttributes(), {x: true}); deepEqual(this.changedAttributes(), {x: true});
model.set({y: true}, {silent: true}); model.set({y: true}, {silent: true});
model.set({z: true});
break; break;
case 1: case 1:
deepEqual(this.changedAttributes(), {y: true, z: true}); deepEqual(this.changedAttributes(), {x: true, y: true, z: true});
break;
case 2:
deepEqual(this.changedAttributes(), {z: false});
break; break;
default: default:
ok(false); ok(false);
} }
}); });
model.set({x: true}); model.set({x: true});
model.set({z: true}); model.set({z: false});
}); });
test("nested `'change:attr'` with silent", 1, function() { test("nested `change:attr` with silent", 0, function() {
var model = new Backbone.Model(); var model = new Backbone.Model();
model.on('change:y', function(){ ok(true); }); model.on('change:y', function(){ ok(false); });
model.on('change', function() { model.on('change', function() {
model.set({y: true}, {silent: true}); model.set({y: true}, {silent: true});
model.set({z: true}); model.set({z: true});
@@ -739,21 +868,25 @@ $(document).ready(function() {
equal(val, 2); equal(val, 2);
}); });
model.set({x: true}); model.set({x: true});
model.change();
}); });
test("multiple nested changes with silent", 2, function() { test("multiple nested changes with silent", 1, function() {
var changes = []; var changes = [];
var model = new Backbone.Model(); var model = new Backbone.Model();
model.on('change:b', function(model, val) { changes.push(val); }); model.on('change:b', function(model, val) { changes.push(val); });
model.on('change', function() { model.on('change', function() {
model.set({b: 1}); model.set({b: 1});
model.set({b: 2}, {silent: true});
}); });
model.set({b: 0}); model.set({b: 0});
deepEqual(changes, [0, 1]); deepEqual(changes, [0, 1]);
model.change(); });
deepEqual(changes, [0, 1, 2, 1]);
test("basic silent change semantics", 1, function() {
var model = new Backbone.Model;
model.set({x: 1});
model.on('change', function(){ ok(true); });
model.set({x: 2}, {silent: true});
model.set({x: 1});
}); });
test("nested set multiple times", 1, function() { test("nested set multiple times", 1, function() {
@@ -768,12 +901,6 @@ $(document).ready(function() {
model.set({a: true}); model.set({a: true});
}); });
test("#1179 - isValid returns true in the absence of validate.", 1, function() {
var model = new Backbone.Model();
model.validate = null;
ok(model.isValid());
});
test("#1122 - clear does not alter options.", 1, function() { test("#1122 - clear does not alter options.", 1, function() {
var model = new Backbone.Model(); var model = new Backbone.Model();
var options = {}; var options = {};
@@ -805,9 +932,8 @@ $(document).ready(function() {
test("#1412 - Trigger 'sync' event.", 3, function() { test("#1412 - Trigger 'sync' event.", 3, function() {
var model = new Backbone.Model({id: 1}); var model = new Backbone.Model({id: 1});
model.url = '/test'; model.sync = function (method, model, options) { options.success(); };
model.on('sync', function(){ ok(true); }); model.on('sync', function(){ ok(true); });
Backbone.ajax = function(settings){ settings.success(); };
model.fetch(); model.fetch();
model.save(); model.save();
model.destroy(); model.destroy();
@@ -834,7 +960,7 @@ $(document).ready(function() {
validate: function(){ return 'invalid'; } validate: function(){ return 'invalid'; }
}); });
var model = new Model({id: 1}); var model = new Model({id: 1});
model.on('error', function(){ ok(true); }); model.on('invalid', function(){ ok(true); });
model.save(); model.save();
}); });
@@ -863,9 +989,9 @@ $(document).ready(function() {
.save(null, {wait: true}); .save(null, {wait: true});
}); });
test("#1664 - Changing from one value, silently to another, back to original does not trigger change.", 0, function() { test("#1664 - Changing from one value, silently to another, back to original triggers a change.", 1, function() {
var model = new Backbone.Model({x:1}); var model = new Backbone.Model({x:1});
model.on('change:x', function() { ok(false); }); model.on('change:x', function() { ok(true); });
model.set({x:2},{silent:true}); model.set({x:2},{silent:true});
model.set({x:3},{silent:true}); model.set({x:3},{silent:true});
model.set({x:1}); model.set({x:1});
@@ -878,15 +1004,11 @@ $(document).ready(function() {
model.set({a:'c'}, {silent:true}); model.set({a:'c'}, {silent:true});
model.set({b:2}, {silent:true}); model.set({b:2}, {silent:true});
model.unset('c', {silent:true}); model.unset('c', {silent:true});
model.set({a:'a'}, {silent:true});
model.set({b:1}, {silent:true});
model.set({c:'item'}, {silent:true});
}); });
model.on('change:a change:b change:c', function(model, val) { changes.push(val); }); model.on('change:a change:b change:c', function(model, val) { changes.push(val); });
model.set({a:'a', b:1, c:'item'}); model.set({a:'a', b:1, c:'item'});
deepEqual(changes, ['a',1,'item']); deepEqual(changes, ['a',1,'item']);
model.change(); deepEqual(model.attributes, {a: 'c', b: 2});
deepEqual(changes, ['a',1,'item']);
}); });
test("#1791 - `attributes` is available for `parse`", function() { test("#1791 - `attributes` is available for `parse`", function() {
@@ -897,4 +1019,84 @@ $(document).ready(function() {
expect(0); expect(0);
}); });
test("silent changes in last `change` event back to original triggers change", 2, function() {
var changes = [];
var model = new Backbone.Model();
model.on('change:a change:b change:c', function(model, val) { changes.push(val); });
model.on('change', function() {
model.set({a:'c'}, {silent:true});
});
model.set({a:'a'});
deepEqual(changes, ['a']);
model.set({a:'a'});
deepEqual(changes, ['a', 'a']);
});
test("#1943 change calculations should use _.isEqual", function() {
var model = new Backbone.Model({a: {key: 'value'}});
model.set('a', {key:'value'}, {silent:true});
equal(model.changedAttributes(), false);
});
test("#1964 - final `change` event is always fired, regardless of interim changes", 1, function () {
var model = new Backbone.Model();
model.on('change:property', function() {
model.set('property', 'bar');
});
model.on('change', function() {
ok(true);
});
model.set('property', 'foo');
});
test("isValid", function() {
var model = new Backbone.Model({valid: true});
model.validate = function(attrs) {
if (!attrs.valid) return "invalid";
};
equal(model.isValid(), true);
equal(model.set({valid: false}, {validate:true}), false);
equal(model.isValid(), true);
model.set({valid:false});
equal(model.isValid(), false);
ok(!model.set('valid', false, {validate: true}));
});
test("#1179 - isValid returns true in the absence of validate.", 1, function() {
var model = new Backbone.Model();
model.validate = null;
ok(model.isValid());
});
test("#1961 - Creating a model with {validate:true} will call validate and use the error callback", function () {
var Model = Backbone.Model.extend({
validate: function (attrs) {
if (attrs.id === 1) return "This shouldn't happen";
}
});
var model = new Model({id: 1}, {validate: true});
equal(model.validationError, "This shouldn't happen");
});
test("toJSON receives attrs during save(..., {wait: true})", 1, function() {
var Model = Backbone.Model.extend({
url: '/test',
toJSON: function() {
strictEqual(this.attributes.x, 1);
return _.clone(this.attributes);
}
});
var model = new Model;
model.save({x: 1}, {wait: true});
});
test("#2034 - nested set with silent only triggers one change", 1, function() {
var model = new Backbone.Model();
model.on('change', function() {
model.set({b: true}, {silent: true});
ok(true);
});
model.set({a: true});
});
}); });

View File

@@ -57,6 +57,15 @@ $(document).ready(function() {
}); });
var ExternalObject = {
value: 'unset',
routingFunction: function(value) {
this.value = value;
}
};
_.bindAll(ExternalObject);
var Router = Backbone.Router.extend({ var Router = Backbone.Router.extend({
count: 0, count: 0,
@@ -69,10 +78,15 @@ $(document).ready(function() {
"contacts": "contacts", "contacts": "contacts",
"contacts/new": "newContact", "contacts/new": "newContact",
"contacts/:id": "loadContact", "contacts/:id": "loadContact",
"route-event/:arg": "routeEvent",
"optional(/:item)": "optionalItem", "optional(/:item)": "optionalItem",
"named/optional/(y:z)": "namedOptional",
"splat/*args/end": "splat", "splat/*args/end": "splat",
"*first/complex-:part/*rest": "complex", ":repo/compare/*from...*to": "github",
"decode/:named/*splat": "decode",
"*first/complex-*part/*rest": "complex",
":entity?*args": "query", ":entity?*args": "query",
"function/:value": ExternalObject.routingFunction,
"*anything": "anything" "*anything": "anything"
}, },
@@ -107,26 +121,44 @@ $(document).ready(function() {
}, },
optionalItem: function(arg){ optionalItem: function(arg){
this.arg = arg !== undefined ? arg : null; this.arg = arg != void 0 ? arg : null;
}, },
splat : function(args) { splat: function(args) {
this.args = args; this.args = args;
}, },
complex : function(first, part, rest) { github: function(repo, from, to) {
this.repo = repo;
this.from = from;
this.to = to;
},
complex: function(first, part, rest) {
this.first = first; this.first = first;
this.part = part; this.part = part;
this.rest = rest; this.rest = rest;
}, },
query : function(entity, args) { query: function(entity, args) {
this.entity = entity; this.entity = entity;
this.queryArgs = args; this.queryArgs = args;
}, },
anything : function(whatever) { anything: function(whatever) {
this.anything = whatever; this.anything = whatever;
},
namedOptional: function(z) {
this.z = z;
},
decode: function(named, path) {
this.named = named;
this.path = path;
},
routeEvent: function(arg) {
} }
}); });
@@ -139,11 +171,20 @@ $(document).ready(function() {
location.replace('http://example.com#search/news'); location.replace('http://example.com#search/news');
Backbone.history.checkUrl(); Backbone.history.checkUrl();
equal(router.query, 'news'); equal(router.query, 'news');
equal(router.page, undefined); equal(router.page, void 0);
equal(lastRoute, 'search'); equal(lastRoute, 'search');
equal(lastArgs[0], 'news'); equal(lastArgs[0], 'news');
}); });
test("routes (simple, but unicode)", 4, function() {
location.replace('http://example.com#search/тест');
Backbone.history.checkUrl();
equal(router.query, "тест");
equal(router.page, void 0);
equal(lastRoute, 'search');
equal(lastArgs[0], "тест");
});
test("routes (two part)", 2, function() { test("routes (two part)", 2, function() {
location.replace('http://example.com#search/nyc/p10'); location.replace('http://example.com#search/nyc/p10');
Backbone.history.checkUrl(); Backbone.history.checkUrl();
@@ -204,10 +245,18 @@ $(document).ready(function() {
equal(router.args, 'long-list/of/splatted_99args'); equal(router.args, 'long-list/of/splatted_99args');
}); });
test("routes (github)", 3, function() {
location.replace('http://example.com#backbone/compare/1.0...braddunbar:with/slash');
Backbone.history.checkUrl();
equal(router.repo, 'backbone');
equal(router.from, '1.0');
equal(router.to, 'braddunbar:with/slash');
});
test("routes (optional)", 2, function() { test("routes (optional)", 2, function() {
location.replace('http://example.com#optional'); location.replace('http://example.com#optional');
Backbone.history.checkUrl(); Backbone.history.checkUrl();
equal(router.arg, null); ok(!router.arg);
location.replace('http://example.com#optional/thing'); location.replace('http://example.com#optional/thing');
Backbone.history.checkUrl(); Backbone.history.checkUrl();
equal(router.arg, 'thing'); equal(router.arg, 'thing');
@@ -237,6 +286,23 @@ $(document).ready(function() {
equal(router.anything, 'doesnt-match-a-route'); equal(router.anything, 'doesnt-match-a-route');
}); });
test("routes (function)", 3, function() {
router.on('route', function(name) {
ok(name === '');
});
equal(ExternalObject.value, 'unset');
location.replace('http://example.com#function/set');
Backbone.history.checkUrl();
equal(ExternalObject.value, 'set');
});
test("Decode named parameters, not splats.", 2, function() {
location.replace('http://example.com#decode/a%2Fb/c%2Fd/e');
Backbone.history.checkUrl();
strictEqual(router.named, 'a/b');
strictEqual(router.path, 'c/d/e');
});
test("fires event when router doesn't have callback on it", 1, function() { test("fires event when router doesn't have callback on it", 1, function() {
router.on("route:noCallback", function(){ ok(true); }); router.on("route:noCallback", function(){ ok(true); });
location.replace('http://example.com#noCallback'); location.replace('http://example.com#noCallback');
@@ -265,12 +331,12 @@ $(document).ready(function() {
if (!Backbone.history.iframe) ok(true); if (!Backbone.history.iframe) ok(true);
}); });
test("route callback gets passed decoded values", 3, function() { test("#967 - Route callback gets passed encoded values.", 3, function() {
var route = 'has%2Fslash/complex-has%23hash/has%20space'; var route = 'has%2Fslash/complex-has%23hash/has%20space';
Backbone.history.navigate(route, {trigger: true}); Backbone.history.navigate(route, {trigger: true});
equal(router.first, 'has/slash'); strictEqual(router.first, 'has/slash');
equal(router.part, 'has#hash'); strictEqual(router.part, 'has#hash');
equal(router.rest, 'has space'); strictEqual(router.rest, 'has space');
}); });
test("correctly handles URLs with % (#868)", 3, function() { test("correctly handles URLs with % (#868)", 3, function() {
@@ -279,7 +345,7 @@ $(document).ready(function() {
location.replace('http://example.com#search/fat'); location.replace('http://example.com#search/fat');
Backbone.history.checkUrl(); Backbone.history.checkUrl();
equal(router.query, 'fat'); equal(router.query, 'fat');
equal(router.page, undefined); equal(router.page, void 0);
equal(lastRoute, 'search'); equal(lastRoute, 'search');
}); });
@@ -497,4 +563,50 @@ $(document).ready(function() {
strictEqual(history.getFragment('fragment '), 'fragment'); strictEqual(history.getFragment('fragment '), 'fragment');
}); });
test("#1820 - Leading slash and trailing space.", 1, function() {
var history = new Backbone.History;
strictEqual(history.getFragment('/fragment '), 'fragment');
});
test("#1980 - Optional parameters.", 2, function() {
location.replace('http://example.com#named/optional/y');
Backbone.history.checkUrl();
strictEqual(router.z, undefined);
location.replace('http://example.com#named/optional/y123');
Backbone.history.checkUrl();
strictEqual(router.z, '123');
});
test("#2062 - Trigger 'route' event on router instance.", 2, function() {
router.on('route', function(name, args) {
strictEqual(name, 'routeEvent');
deepEqual(args, ['x']);
});
location.replace('http://example.com#route-event/x');
Backbone.history.checkUrl();
});
test("#2255 - Extend routes by making routes a function.", 1, function() {
var RouterBase = Backbone.Router.extend({
routes: function() {
return {
home: "root",
index: "index.html"
};
}
});
var RouterExtended = RouterBase.extend({
routes: function() {
var _super = RouterExtended.__super__.routes;
return _.extend(_super(),
{ show: "show",
search: "search" });
}
});
var router = new RouterExtended();
deepEqual({home: "root", index: "index.html", show: "show", search: "search"}, router.routes);
});
}); });

View File

@@ -29,22 +29,6 @@ $(document).ready(function() {
strictEqual(view.$('a b').html(), 'test'); strictEqual(view.$('a b').html(), 'test');
}); });
test("make", 3, function() {
var div = view.make('div', {id: 'test-div'}, "one two three");
equal(div.tagName.toLowerCase(), 'div');
equal(div.id, 'test-div');
equal($(div).text(), 'one two three');
});
test("make can take falsy values for content", 2, function() {
var div = view.make('div', {id: 'test-div'}, 0);
equal($(div).text(), '0');
var div = view.make('div', {id: 'test-div'}, '');
equal($(div).text(), '');
});
test("initialize", 1, function() { test("initialize", 1, function() {
var View = Backbone.View.extend({ var View = Backbone.View.extend({
initialize: function() { initialize: function() {
@@ -101,6 +85,13 @@ $(document).ready(function() {
equal(view.counter, 3); equal(view.counter, 3);
}); });
test("delegateEvents ignore undefined methods", 0, function() {
var view = new Backbone.View({el: '<p></p>'});
view.delegateEvents({'click': 'undefinedMethod'});
view.$el.trigger('click');
});
test("undelegateEvents", 6, function() { test("undelegateEvents", 6, function() {
var counter1 = 0, counter2 = 0; var counter1 = 0, counter2 = 0;
@@ -165,6 +156,30 @@ $(document).ready(function() {
strictEqual(new View().el.id, 'id'); strictEqual(new View().el.id, 'id');
}); });
test("with options function", 3, function() {
var View1 = Backbone.View.extend({
options: function() {
return {
title: 'title1',
acceptText: 'confirm'
};
}
});
var View2 = View1.extend({
options: function() {
return _.extend(View1.prototype.options.call(this), {
title: 'title2',
fixed: true
});
}
});
strictEqual(new View2().options.title, 'title2');
strictEqual(new View2().options.acceptText, 'confirm');
strictEqual(new View2().options.fixed, true);
});
test("with attributes", 2, function() { test("with attributes", 2, function() {
var View = Backbone.View.extend({ var View = Backbone.View.extend({
attributes: { attributes: {
@@ -286,14 +301,11 @@ $(document).ready(function() {
ok(new View().$el.is('p')); ok(new View().$el.is('p'));
}); });
test("dispose", 0, function() { test("views stopListening", 0, function() {
var View = Backbone.View.extend({ var View = Backbone.View.extend({
events: {
click: function() { ok(false); }
},
initialize: function() { initialize: function() {
this.model.on('all x', function(){ ok(false); }, this); this.listenTo(this.model, 'all x', function(){ ok(false); }, this);
this.collection.on('all x', function(){ ok(false); }, this); this.listenTo(this.collection, 'all x', function(){ ok(false); }, this);
} }
}); });
@@ -302,22 +314,9 @@ $(document).ready(function() {
collection: new Backbone.Collection collection: new Backbone.Collection
}); });
view.dispose(); view.stopListening();
view.model.trigger('x'); view.model.trigger('x');
view.collection.trigger('x'); view.collection.trigger('x');
view.$el.click();
});
test("dispose with non Backbone objects", 0, function() {
var view = new Backbone.View({model: {}, collection: {}});
view.dispose();
});
test("view#remove calls dispose.", 1, function() {
var view = new Backbone.View();
view.dispose = function() { ok(true); };
view.remove();
}); });
test("Provide function for el.", 1, function() { test("Provide function for el.", 1, function() {
@@ -331,4 +330,28 @@ $(document).ready(function() {
ok(view.$el.is('p:has(a)')); ok(view.$el.is('p:has(a)'));
}); });
test("events passed in options", 2, function() {
var counter = 0;
var View = Backbone.View.extend({
el: '<p><a id="test"></a></p>',
increment: function() {
counter++;
}
});
var view = new View({events:{'click #test':'increment'}});
var view2 = new View({events:function(){
return {'click #test':'increment'};
}});
view.$('#test').trigger('click');
view2.$('#test').trigger('click');
equal(counter, 2);
view.$('#test').trigger('click');
view2.$('#test').trigger('click');
equal(counter, 4);
});
}); });

View File

@@ -1,4 +1,4 @@
Copyright 2010-2012 Mathias Bynens <http://mathiasbynens.be/> Copyright 2010-2013 Mathias Bynens <http://mathiasbynens.be/>
Based on JSLitmus.js, copyright Robert Kieffer <http://broofa.com/> Based on JSLitmus.js, copyright Robert Kieffer <http://broofa.com/>
Modified by John-David Dalton <http://allyoucanleet.com/> Modified by John-David Dalton <http://allyoucanleet.com/>

View File

@@ -15,13 +15,16 @@ For a list of upcoming features, check out our [roadmap](https://github.com/best
## Support ## Support
Benchmark.js has been tested in at least Adobe AIR 3.1, Chrome 5-21, Firefox 1-15, IE 6-9, Opera 9.25-12, Safari 3-6, Node.js 0.8.8, Narwhal 0.3.2, RingoJS 0.8, and Rhino 1.7RC5. Benchmark.js has been tested in at least Chrome 5~25, Firefox 1~19, IE 6-10, Opera 9.25-12, Safari 3-6, Node.js 0.4.8-0.10.1, Narwhal 0.3.2, PhantomJS 1.8.1, RingoJS 0.9, and Rhino 1.7RC5.
## Installation and usage ## Installation and usage
In a browser or Adobe AIR: Benchmark.js only hard dependency is [Lo-Dash](http://lodash.com/).
In a browser:
```html ```html
<script src="lodash.js"></script>
<script src="benchmark.js"></script> <script src="benchmark.js"></script>
``` ```
@@ -68,25 +71,14 @@ load('benchmark.js');
In an AMD loader like [RequireJS](http://requirejs.org/): In an AMD loader like [RequireJS](http://requirejs.org/):
```js ```js
require({
'paths': {
'benchmark': 'path/to/benchmark'
}
},
['benchmark'], function(Benchmark) {
console.log(Benchmark.version);
});
// or with platform.js
// https://github.com/bestiejs/platform.js
require({ require({
'paths': { 'paths': {
'benchmark': 'path/to/benchmark', 'benchmark': 'path/to/benchmark',
'lodash': 'path/to/lodash',
'platform': 'path/to/platform' 'platform': 'path/to/platform'
} }
}, },
['benchmark', 'platform'], function(Benchmark, platform) { ['benchmark'], function(Benchmark) {
Benchmark.platform = platform;
console.log(Benchmark.platform.name); console.log(Benchmark.platform.name);
}); });
``` ```
@@ -108,7 +100,7 @@ suite.add('RegExp#test', function() {
console.log(String(event.target)); console.log(String(event.target));
}) })
.on('complete', function() { .on('complete', function() {
console.log('Fastest is ' + this.filter('fastest').pluck('name')); console.log('Fastest is ' + _.pluck(this.filter('fastest'), 'name'));
}) })
// run async // run async
.run({ 'async': true }); .run({ 'async': true });
@@ -121,7 +113,7 @@ suite.add('RegExp#test', function() {
## BestieJS ## BestieJS
Benchmark.js is part of the BestieJS *"Best in Class"* module collection. This means we promote solid browser/environment support, ES5 precedents, unit testing, and plenty of documentation. Benchmark.js is part of the BestieJS *"Best in Class"* module collection. This means we promote solid browser/environment support, ES5+ precedents, unit testing, and plenty of documentation.
## Authors ## Authors

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +1,4 @@
Copyright 2011-2012 John-David Dalton <http://allyoucanleet.com/> Copyright 2011-2013 John-David Dalton <http://allyoucanleet.com/>
Permission is hereby granted, free of charge, to any person obtaining Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the a copy of this software and associated documentation files (the

View File

@@ -1,7 +1,7 @@
<?php <?php
/*! /*!
* Docdown v1.0.0-pre * Docdown v1.0.0-pre
* Copyright 2011-2012 John-David Dalton <http://allyoucanleet.com/> * Copyright 2011-2013 John-David Dalton <http://allyoucanleet.com/>
* Available under MIT license <http://mths.be/mit> * Available under MIT license <http://mths.be/mit>
*/ */
require(dirname(__FILE__) . '/src/DocDown/Generator.php'); require(dirname(__FILE__) . '/src/DocDown/Generator.php');

View File

@@ -29,15 +29,16 @@ class Alias {
$this->_category = $owner->getCategory(); $this->_category = $owner->getCategory();
$this->_desc = $owner->getDesc(); $this->_desc = $owner->getDesc();
$this->_example = $owner->getExample(); $this->_example = $owner->getExample();
$this->_isCtor = $owner->isCtor();
$this->_isLicense = $owner->isLicense();
$this->_isPlugin = $owner->isPlugin();
$this->_isPrivate = $owner->isPrivate();
$this->_isStatic = $owner->isStatic();
$this->_lineNumber = $owner->getLineNumber(); $this->_lineNumber = $owner->getLineNumber();
$this->_members = $owner->getMembers(); $this->_members = $owner->getMembers();
$this->_params = $owner->getParams(); $this->_params = $owner->getParams();
$this->_returns = $owner->getReturns(); $this->_returns = $owner->getReturns();
$this->_type = $owner->getType(); $this->_type = $owner->getType();
$this->_isCtor = $owner->isCtor();
$this->_isPlugin = $owner->isPlugin();
$this->_isPrivate = $owner->isPrivate();
$this->_isStatic = $owner->isStatic();
} }
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
@@ -96,6 +97,66 @@ class Alias {
return $this->_example; return $this->_example;
} }
/**
* Checks if the entry is an alias.
*
* @memberOf Alias
* @returns {Boolean} Returns `true`.
*/
public function isAlias() {
return true;
}
/**
* Checks if the owner entry is a constructor.
*
* @memberOf Alias
* @returns {Boolean} Returns `true` if a constructor, else `false`.
*/
public function isCtor() {
return $this->_isCtor;
}
/**
* Checks if the owner entry is a license.
*
* @memberOf Alias
* @returns {Boolean} Returns `true` if a license, else `false`.
*/
public function isLicense() {
return $this->_isLicense;
}
/**
* Checks if the owner entry *is* assigned to a prototype.
*
* @memberOf Alias
* @returns {Boolean} Returns `true` if assigned to a prototype, else `false`.
*/
public function isPlugin() {
return $this->_isPlugin;
}
/**
* Checks if the owner entry is private.
*
* @memberOf Alias
* @returns {Boolean} Returns `true` if private, else `false`.
*/
public function isPrivate() {
return $this->_isPrivate;
}
/**
* Checks if the owner entry is *not* assigned to a prototype.
*
* @memberOf Alias
* @returns {Boolean} Returns `true` if not assigned to a prototype, else `false`.
*/
public function isStatic() {
return $this->_isStatic;
}
/** /**
* Resolves the owner entry's line number. * Resolves the owner entry's line number.
* *
@@ -161,55 +222,5 @@ class Alias {
public function getType() { public function getType() {
return $this->_type; return $this->_type;
} }
/**
* Checks if the entry is an alias.
*
* @memberOf Alias
* @returns {Boolean} Returns `true`.
*/
public function isAlias() {
return true;
}
/**
* Checks if the owner entry is a constructor.
*
* @memberOf Alias
* @returns {Boolean} Returns `true` if a constructor, else `false`.
*/
public function isCtor() {
return $this->_isCtor;
}
/**
* Checks if the owner entry *is* assigned to a prototype.
*
* @memberOf Alias
* @returns {Boolean} Returns `true` if assigned to a prototype, else `false`.
*/
public function isPlugin() {
return $this->_isPlugin;
}
/**
* Checks if the owner entry is private.
*
* @memberOf Alias
* @returns {Boolean} Returns `true` if private, else `false`.
*/
public function isPrivate() {
return $this->_isPrivate;
}
/**
* Checks if the owner entry is *not* assigned to a prototype.
*
* @memberOf Alias
* @returns {Boolean} Returns `true` if not assigned to a prototype, else `false`.
*/
public function isStatic() {
return $this->_isStatic;
}
} }
?> ?>

View File

@@ -187,7 +187,10 @@ class Entry {
preg_match('#/\*\*(?:\s*\*)?([\s\S]*?)(?=\*\s\@[a-z]|\*/)#', $this->entry, $result); preg_match('#/\*\*(?:\s*\*)?([\s\S]*?)(?=\*\s\@[a-z]|\*/)#', $this->entry, $result);
if (count($result)) { if (count($result)) {
$type = $this->getType(); $type = $this->getType();
$result = trim(preg_replace('/(?:^|\n)\s*\* ?/', ' ', $result[1])); $result = preg_replace('/:\n *\* */', ":<br>\n", $result[1]);
$result = preg_replace('/(?:^|\n) *\*\n *\* */', "\n\n", $result);
$result = preg_replace('/(?:^|\n) *\* ?/', ' ', $result);
$result = trim($result);
$result = ($type == 'Function' ? '' : '(' . str_replace('|', ', ', trim($type, '{}')) . '): ') . $result; $result = ($type == 'Function' ? '' : '(' . str_replace('|', ', ', trim($type, '{}')) . '): ') . $result;
} }
$this->_desc = $result; $this->_desc = $result;
@@ -214,6 +217,100 @@ class Entry {
return $result; return $result;
} }
/**
* Checks if the entry is an alias.
*
* @memberOf Entry
* @returns {Boolean} Returns `false`.
*/
public function isAlias() {
return false;
}
/**
* Checks if the entry is a constructor.
*
* @memberOf Entry
* @returns {Boolean} Returns `true` if a constructor, else `false`.
*/
public function isCtor() {
if (!isset($this->_isCtor)) {
$this->_isCtor = !!preg_match('/\* *@constructor\b/', $this->entry);
}
return $this->_isCtor;
}
/**
* Checks if the entry is a license.
*
* @memberOf Entry
* @returns {Boolean} Returns `true` if a license, else `false`.
*/
public function isLicense() {
if (!isset($this->_isLicense)) {
$this->_isLicense = !!preg_match('/\* *@license\b/', $this->entry);
}
return $this->_isLicense;
}
/**
* Checks if the entry *is* assigned to a prototype.
*
* @memberOf Entry
* @returns {Boolean} Returns `true` if assigned to a prototype, else `false`.
*/
public function isPlugin() {
if (!isset($this->_isPlugin)) {
$this->_isPlugin = !$this->isCtor() && !$this->isPrivate() && !$this->isStatic();
}
return $this->_isPlugin;
}
/**
* Checks if the entry is private.
*
* @memberOf Entry
* @returns {Boolean} Returns `true` if private, else `false`.
*/
public function isPrivate() {
if (!isset($this->_isPrivate)) {
$this->_isPrivate = $this->isLicense() || !!preg_match('/\* *@private\b/', $this->entry) || !preg_match('/\* *@[a-z]+\b/', $this->entry);
}
return $this->_isPrivate;
}
/**
* Checks if the entry is *not* assigned to a prototype.
*
* @memberOf Entry
* @returns {Boolean} Returns `true` if not assigned to a prototype, else `false`.
*/
public function isStatic() {
if (isset($this->_isStatic)) {
return $this->_isStatic;
}
$public = !$this->isPrivate();
$result = $public && !!preg_match('/\* *@static\b/', $this->entry);
// set in cases where it isn't explicitly stated
if ($public && !$result) {
if ($parent = array_pop(preg_split('/[#.]/', $this->getMembers(0)))) {
foreach (Entry::getEntries($this->source) as $entry) {
$entry = new Entry($entry, $this->source);
if ($entry->getName() == $parent) {
$result = !$entry->isCtor();
break;
}
}
} else {
$result = true;
}
}
$this->_isStatic = $result;
return $result;
}
/** /**
* Resolves the entry's line number. * Resolves the entry's line number.
* *
@@ -341,86 +438,5 @@ class Entry {
$this->_type = $result; $this->_type = $result;
return $result; return $result;
} }
/**
* Checks if the entry is an alias.
*
* @memberOf Entry
* @returns {Boolean} Returns `false`.
*/
public function isAlias() {
return false;
}
/**
* Checks if the entry is a constructor.
*
* @memberOf Entry
* @returns {Boolean} Returns `true` if a constructor, else `false`.
*/
public function isCtor() {
if (!isset($this->_isCtor)) {
$this->_isCtor = !!preg_match('/\* *@constructor\b/', $this->entry);
}
return $this->_isCtor;
}
/**
* Checks if the entry *is* assigned to a prototype.
*
* @memberOf Entry
* @returns {Boolean} Returns `true` if assigned to a prototype, else `false`.
*/
public function isPlugin() {
if (!isset($this->_isPlugin)) {
$this->_isPlugin = !$this->isCtor() && !$this->isPrivate() && !$this->isStatic();
}
return $this->_isPlugin;
}
/**
* Checks if the entry is private.
*
* @memberOf Entry
* @returns {Boolean} Returns `true` if private, else `false`.
*/
public function isPrivate() {
if (!isset($this->_isPrivate)) {
$this->_isPrivate = !!preg_match('/\* *@private\b/', $this->entry) || !preg_match('/\* *@[a-z]+\b/', $this->entry);
}
return $this->_isPrivate;
}
/**
* Checks if the entry is *not* assigned to a prototype.
*
* @memberOf Entry
* @returns {Boolean} Returns `true` if not assigned to a prototype, else `false`.
*/
public function isStatic() {
if (isset($this->_isStatic)) {
return $this->_isStatic;
}
$public = !$this->isPrivate();
$result = $public && !!preg_match('/\* *@static\b/', $this->entry);
// set in cases where it isn't explicitly stated
if ($public && !$result) {
if ($parent = array_pop(preg_split('/[#.]/', $this->getMembers(0)))) {
foreach (Entry::getEntries($this->source) as $entry) {
$entry = new Entry($entry, $this->source);
if ($entry->getName() == $parent) {
$result = !$entry->isCtor();
break;
}
}
} else {
$result = true;
}
}
$this->_isStatic = $result;
return $result;
}
} }
?> ?>

View File

@@ -1,4 +1,4 @@
Copyright 2011-2012 John-David Dalton <http://allyoucanleet.com/> Copyright 2011-2013 John-David Dalton <http://allyoucanleet.com/>
Permission is hereby granted, free of charge, to any person obtaining Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the a copy of this software and associated documentation files (the

View File

@@ -8,7 +8,7 @@ Platform.js is for informational purposes only and **not** intended as a substit
## BestieJS ## BestieJS
Platform.js is part of the BestieJS *"Best in Class"* module collection. This means we promote solid browser/environment support, ES5 precedents, unit testing, and plenty of documentation. Platform.js is part of the BestieJS *"Best in Class"* module collection. This means we promote solid browser/environment support, ES5+ precedents, unit testing, and plenty of documentation.
## Documentation ## Documentation
@@ -18,7 +18,7 @@ For a list of upcoming features, check out our [roadmap](https://github.com/best
## Support ## Support
Platform.js has been tested in at least Adobe AIR 3.1, Chrome 5-21, Firefox 1-14, IE 6-9, Opera 9.25-12, Safari 3-6, Node.js 0.8.6, Narwhal 0.3.2, RingoJS 0.8, and Rhino 1.7RC5. Platform.js has been tested in at least Chrome 5~25, Firefox 1~19, IE 6-10, Opera 9.25-12, Safari 3-6, Node.js 0.4.8-0.10.1, Narwhal 0.3.2, PhantomJS 1.8.1, RingoJS 0.9, and Rhino 1.7RC5.
## Installation and usage ## Installation and usage

View File

@@ -1,6 +1,6 @@
/*! /*!
* Platform.js v1.0.0 <http://mths.be/platform> * Platform.js v1.0.0 <http://mths.be/platform>
* Copyright 2010-2012 John-David Dalton <http://allyoucanleet.com/> * Copyright 2010-2013 John-David Dalton <http://allyoucanleet.com/>
* Available under MIT license <http://mths.be/mit> * Available under MIT license <http://mths.be/mit>
*/ */
;(function(window) { ;(function(window) {
@@ -20,11 +20,14 @@
var reOpera = /Opera/; var reOpera = /Opera/;
/** Used to resolve a value's internal [[Class]] */ /** Used to resolve a value's internal [[Class]] */
var toString = {}.toString; var toString = Object.prototype.toString;
/** Detect Java environment */ /** Detect Java environment */
var java = /Java/.test(getClassOf(window.java)) && window.java; var java = /Java/.test(getClassOf(window.java)) && window.java;
/** Detect Rhino */
var rhino = java && getClassOf(window.environment) == 'Environment';
/** A character to represent alpha */ /** A character to represent alpha */
var alpha = java ? 'a' : '\u03b1'; var alpha = java ? 'a' : '\u03b1';
@@ -581,10 +584,11 @@
// detect stubborn layout engines // detect stubborn layout engines
if (layout == 'iCab' && parseFloat(version) > 3) { if (layout == 'iCab' && parseFloat(version) > 3) {
layout = ['WebKit']; layout = ['WebKit'];
} else if (data = } else if ((data =
/Opera/.test(name) && 'Presto' || /Opera/.test(name) && 'Presto' ||
/\b(?:Midori|Nook|Safari)\b/i.test(ua) && 'WebKit' || /\b(?:Midori|Nook|Safari)\b/i.test(ua) && 'WebKit' ||
!layout && /\bMSIE\b/i.test(ua) && (/^Mac/.test(os) ? 'Tasman' : 'Trident')) { !layout && /\bMSIE\b/i.test(ua) && (/^Mac/.test(os) ? 'Tasman' : 'Trident')
)) {
layout = [data]; layout = [data];
} }
// leverage environment features // leverage environment features
@@ -597,7 +601,7 @@
arch = data.getProperty('os.arch'); arch = data.getProperty('os.arch');
os = os || data.getProperty('os.name') + ' ' + data.getProperty('os.version'); os = os || data.getProperty('os.name') + ' ' + data.getProperty('os.version');
} }
if (typeof exports == 'object' && exports) { if (freeExports) {
// if `thisBinding` is the [ModuleScope] // if `thisBinding` is the [ModuleScope]
if (thisBinding == oldWin && typeof system == 'object' && (data = [system])[0]) { if (thisBinding == oldWin && typeof system == 'object' && (data = [system])[0]) {
os || (os = data[0].os || null); os || (os = data[0].os || null);
@@ -610,23 +614,28 @@
name = 'Narwhal'; name = 'Narwhal';
} }
} }
} else if (typeof process == 'object' && (data = process)) { }
else if (typeof process == 'object' && (data = process)) {
name = 'Node.js'; name = 'Node.js';
arch = data.arch; arch = data.arch;
os = data.platform; os = data.platform;
version = /[\d.]+/.exec(data.version)[0]; version = /[\d.]+/.exec(data.version)[0];
} }
} else if (getClassOf(window.environment) == 'Environment') { else if (rhino) {
name = 'Rhino';
}
}
else if (rhino) {
name = 'Rhino'; name = 'Rhino';
} }
} }
// detect Adobe AIR // detect Adobe AIR
else if (getClassOf(data = window.runtime) == 'ScriptBridgingProxyObject') { else if (getClassOf((data = window.runtime)) == 'ScriptBridgingProxyObject') {
name = 'Adobe AIR'; name = 'Adobe AIR';
os = data.flash.system.Capabilities.os; os = data.flash.system.Capabilities.os;
} }
// detect PhantomJS // detect PhantomJS
else if (getClassOf(data = window.phantom) == 'RuntimeObject') { else if (getClassOf((data = window.phantom)) == 'RuntimeObject') {
name = 'PhantomJS'; name = 'PhantomJS';
version = (data = data.version || null) && (data.major + '.' + data.minor + '.' + data.patch); version = (data = data.version || null) && (data.major + '.' + data.minor + '.' + data.patch);
} }
@@ -646,9 +655,10 @@
} }
// detect prerelease phases // detect prerelease phases
if (version && (data = if (version && (data =
/(?:[ab]|dp|pre|[ab]\d+pre)(?:\d+\+?)?$/i.exec(version) || /(?:[ab]|dp|pre|[ab]\d+pre)(?:\d+\+?)?$/i.exec(version) ||
/(?:alpha|beta)(?: ?\d)?/i.exec(ua + ';' + (useFeatures && nav.appMinorVersion)) || /(?:alpha|beta)(?: ?\d)?/i.exec(ua + ';' + (useFeatures && nav.appMinorVersion)) ||
/\bMinefield\b/i.test(ua) && 'a')) { /\bMinefield\b/i.test(ua) && 'a'
)) {
prerelease = /b/i.test(data) ? 'beta' : 'alpha'; prerelease = /b/i.test(data) ? 'beta' : 'alpha';
version = version.replace(RegExp(data + '\\+?$'), '') + version = version.replace(RegExp(data + '\\+?$'), '') +
(prerelease == 'beta' ? beta : alpha) + (/\d+\+?/.exec(data) || ''); (prerelease == 'beta' ? beta : alpha) + (/\d+\+?/.exec(data) || '');
@@ -689,8 +699,9 @@
// detect BlackBerry OS version // detect BlackBerry OS version
// http://docs.blackberry.com/en/developers/deliverables/18169/HTTP_headers_sent_by_BB_Browser_1234911_11.jsp // http://docs.blackberry.com/en/developers/deliverables/18169/HTTP_headers_sent_by_BB_Browser_1234911_11.jsp
else if (/BlackBerry/.test(product) && (data = else if (/BlackBerry/.test(product) && (data =
(RegExp(product.replace(/ +/g, ' *') + '/([.\\d]+)', 'i').exec(ua) || 0)[1] || (RegExp(product.replace(/ +/g, ' *') + '/([.\\d]+)', 'i').exec(ua) || 0)[1] ||
version)) { version
)) {
os = 'Device Software ' + data; os = 'Device Software ' + data;
version = null; version = null;
} }
@@ -705,7 +716,7 @@
/Windows XP/.test(os) && version > 8 || /Windows XP/.test(os) && version > 8 ||
version == 8 && !/Trident/.test(ua) version == 8 && !/Trident/.test(ua)
)) ))
) && !reOpera.test(data = parse.call(forOwn, ua.replace(reOpera, '') + ';')) && data.name) { ) && !reOpera.test((data = parse.call(forOwn, ua.replace(reOpera, '') + ';'))) && data.name) {
// when "indentifying", the UA contains both Opera and the other browser's name // when "indentifying", the UA contains both Opera and the other browser's name
data = 'ing as ' + data.name + ((data = data.version) ? ' ' + data : ''); data = 'ing as ' + data.name + ((data = data.version) ? ' ' + data : '');
@@ -793,7 +804,7 @@
} }
} }
// strip incorrect OS versions // strip incorrect OS versions
if (version && version.indexOf(data = /[\d.]+$/.exec(os)) == 0 && if (version && version.indexOf((data = /[\d.]+$/.exec(os))) == 0 &&
ua.indexOf('/' + data + '-') > -1) { ua.indexOf('/' + data + '-') > -1) {
os = trim(os.replace(data, '')); os = trim(os.replace(data, ''));
} }
@@ -885,7 +896,7 @@
* The CPU architecture the OS is built for. * The CPU architecture the OS is built for.
* *
* @memberOf platform.os * @memberOf platform.os
* @type String|Null * @type Number|Null
*/ */
'architecture': null, 'architecture': null,
@@ -981,7 +992,7 @@
}); });
} }
// check for `exports` after `define` in case a build optimizer adds an `exports` object // check for `exports` after `define` in case a build optimizer adds an `exports` object
else if (freeExports) { else if (freeExports && !freeExports.nodeType) {
// in Narwhal, Node.js, or RingoJS // in Narwhal, Node.js, or RingoJS
forOwn(parse(), function(value, key) { forOwn(parse(), function(value, key) {
freeExports[key] = value; freeExports[key] = value;
@@ -989,8 +1000,6 @@
} }
// in a browser or Rhino // in a browser or Rhino
else { else {
// use square bracket notation so Closure Compiler won't munge `platform` window.platform = parse();
// http://code.google.com/closure/compiler/docs/api-tutorial3.html#export
window['platform'] = parse();
} }
}(this)); }(this));

View File

@@ -1,4 +1,4 @@
Copyright 2011-2012 John-David Dalton <http://allyoucanleet.com/> Copyright 2011-2013 John-David Dalton <http://allyoucanleet.com/>
Permission is hereby granted, free of charge, to any person obtaining Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the a copy of this software and associated documentation files (the

View File

@@ -1,7 +1,7 @@
# QUnit CLIB <sup>v1.0.0</sup> # QUnit CLIB <sup>v1.3.0</sup>
## command-line interface boilerplate ## command-line interface boilerplate
QUnit CLIB helps extend QUnit's CLI support to many common CLI environments. QUnit CLIB helps extend QUnits CLI support to many common CLI environments.
## Screenshot ## Screenshot
@@ -9,25 +9,29 @@ QUnit CLIB helps extend QUnit's CLI support to many common CLI environments.
## Support ## Support
QUnit CLIB has been tested in at least Node.js 0.4.8-0.8.6, Narwhal v0.3.2, RingoJS v0.8.0, and Rhino v1.7RC3-RC5. QUnit CLIB has been tested in at least Node.js 0.4.8-0.10.1, Narwhal 0.3.2, PhantomJS 1.8.1, RingoJS 0.9, and Rhino 1.7RC5.
## Usage ## Usage
```js ```js
(function(window) { ;(function(window) {
'use strict';
// use a single load function // use a single "load" function
var load = typeof require == 'function' ? require : window.load; var load = typeof require == 'function' ? require : window.load;
// load QUnit and CLIB if needed // load QUnit and CLIB if needed
var QUnit = var QUnit = (function() {
window.QUnit || ( var noop = Function.prototype;
window.setTimeout || (window.addEventListener = window.setTimeout = / /), return window.QUnit || (
window.QUnit = load('path/to/qunit.js') || window.QUnit, window.addEventListener || (window.addEventListener = noop),
load('path/to/qunit-clib.js'), window.setTimeout || (window.setTimeout = noop),
(window.addEventListener || 0).test && delete window.addEventListener, window.QUnit = load('../vendor/qunit/qunit/qunit.js') || window.QUnit,
(load('../vendor/qunit-clib/qunit-clib.js') || { 'runInContext': noop }).runInContext(window),
addEventListener === noop && delete window.addEventListener,
window.QUnit window.QUnit
); );
}());
// explicitly call `QUnit.module()` instead of `module()` // explicitly call `QUnit.module()` instead of `module()`
// in case we are in a CLI environment // in case we are in a CLI environment
@@ -37,9 +41,8 @@ QUnit CLIB has been tested in at least Node.js 0.4.8-0.8.6, Narwhal v0.3.2, Ring
// ... // ...
}); });
// must call `QUnit.start()` if using QUnit < 1.3.0 with Node.js or any // call `QUnit.start()` for Narwhal, Node.js, PhantomJS, Rhino, and RingoJS
// version of QUnit with Narwhal, Rhino, or RingoJS if (!window.document || window.phantom) {
if (!window.document) {
QUnit.start(); QUnit.start();
} }
}(typeof global == 'object' && global || this)); }(typeof global == 'object' && global || this));
@@ -48,7 +51,6 @@ QUnit CLIB has been tested in at least Node.js 0.4.8-0.8.6, Narwhal v0.3.2, Ring
## Footnotes ## Footnotes
1. QUnit v1.3.0 does not work with Narwhal or Ringo < v0.8.0 1. QUnit v1.3.0 does not work with Narwhal or Ringo < v0.8.0
2. Rhino v1.7RC4 does not support timeout fallbacks `clearTimeout` and `setTimeout` 2. Rhino v1.7RC4 does not support timeout fallbacks `clearTimeout` and `setTimeout`
## Author ## Author

View File

@@ -1,324 +1,292 @@
/*! /*!
* QUnit CLI Boilerplate v1.0.0 * QUnit CLI Boilerplate v1.3.0
* Copyright 2011-2012 John-David Dalton <http://allyoucanleet.com/> * Copyright 2011-2012 John-David Dalton <http://allyoucanleet.com/>
* Based on a gist by Jörn Zaefferer <https://gist.github.com/722381> * Based on a gist by Jörn Zaefferer <https://gist.github.com/722381>
* Available under MIT license <http://mths.be/mit> * Available under MIT license <http://mths.be/mit>
*/ */
;(function(global) { ;(function(window) {
'use strict'; 'use strict';
/** Add `console.log()` support for Narwhal, Rhino, and RingoJS */ /** Detect free variable `exports` */
global.console || (global.console = { 'log': global.print }); var freeExports = typeof exports == 'object' && exports;
/** Reduce global.QUnit.QUnit -> global.QUnit */ /** Detect free variable `global` and use it as `window` */
global.QUnit && (QUnit = QUnit.QUnit || QUnit); var freeGlobal = typeof global == 'object' && global;
if (freeGlobal.global === freeGlobal) {
/*--------------------------------------------------------------------------*/ window = freeGlobal;
/** Used as a horizontal rule in console output */
var hr = '----------------------------------------';
/** Shortcut used to convert array-like objects to arrays */
var slice = [].slice;
/** Used to resolve a value's internal [[Class]] */
var toString = {}.toString;
/** Used by timer methods */
var doneCalled,
timer,
counter = 0,
ids = {};
/*--------------------------------------------------------------------------*/
/**
* An iteration utility for arrays.
*
* @private
* @param {Array} array The array to iterate over.
* @param {Function} callback The function called per iteration.
*/
function each(array, callback) {
var index = -1,
length = array.length;
while (++index < length) {
callback(array[index], index, array);
}
}
/**
* Checks if the specified `value` is a function.
*
* @private
* @param {Mixed} value The value to check.
* @returns {Boolean} Returns `true` if `value` is a function, else `false`.
*/
function isFunction(value) {
return toString.call(value) == '[object Function]';
} }
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
/** /**
* Timeout fallbacks based on the work of Andrea Giammarchi and Weston C. * Installs the CLI boilerplate additions on the given `context` object.
* https://github.com/WebReflection/wru/blob/master/src/rhinoTimers.js
* http://stackoverflow.com/questions/2261705/how-to-run-a-javascript-function-asynchronously-without-using-settimeout
*/
/**
* Clears the delay set by `setInterval` or `setTimeout`.
* *
* @memberOf global * @memberOf exports
* @param {Number} id The ID of the timeout to be cleared. * @param {Object} context The context object.
*/ */
function clearTimer(id) { function runInContext(context) {
if (ids[id]) { // exit early if no `context` is provided or if `QUnit` does not exist
ids[id].cancel(); if (!context || !context.QUnit) {
timer.purge();
delete ids[id];
}
}
/**
* Schedules timer-based callbacks.
*
* @private
* @param {Function} fn The function to call.
* @oaram {Number} delay The number of milliseconds to delay the `fn` call.
* @param [arg1, arg2, ...] Arguments to invoke `fn` with.
* @param {Boolean} repeated A flag to specify whether `fn` is called repeatedly.
* @returns {Number} The the ID of the timeout.
*/
function schedule(fn, delay, args, repeated) {
// Rhino 1.7RC4 will error assigning `task` below
// https://bugzilla.mozilla.org/show_bug.cgi?id=775566
var task = ids[++counter] = new JavaAdapter(java.util.TimerTask, {
'run': function() {
fn.apply(global, args);
}
});
// support non-functions
if (!isFunction(fn)) {
fn = (function(code) {
code = String(code);
return function() { eval(code); };
}(fn));
}
// used by setInterval
if (repeated) {
timer.schedule(task, delay, delay);
}
// used by setTimeout
else {
timer.schedule(task, delay);
}
return counter;
}
/**
* Executes a code snippet or function repeatedly, with a delay between each call.
*
* @memberOf global
* @param {Function|String} fn The function to call or string to evaluate.
* @oaram {Number} delay The number of milliseconds to delay each `fn` call.
* @param [arg1, arg2, ...] Arguments to invoke `fn` with.
* @returns {Number} The the ID of the timeout.
*/
function setInterval(fn, delay) {
return schedule(fn, delay, slice.call(arguments, 2), true);
}
/**
* Executes a code snippet or a function after specified delay.
*
* @memberOf global
* @param {Function|String} fn The function to call or string to evaluate.
* @oaram {Number} delay The number of milliseconds to delay the `fn` call.
* @param [arg1, arg2, ...] Arguments to invoke `fn` with.
* @returns {Number} The the ID of the timeout.
*/
function setTimeout(fn, delay) {
return schedule(fn, delay, slice.call(arguments, 2));
}
/*--------------------------------------------------------------------------*/
/**
* A logging callback triggered when all testing is completed.
*
* @memberOf QUnit
* @param {Object} details An object with properties `failed`, `passed`,
* `runtime`, and `total`.
*/
function done(details) {
// stop `asyncTest()` from erroneously calling `done()` twice in
// environments w/o timeouts
if (doneCalled) {
return; return;
} }
doneCalled = true;
console.log(hr);
console.log(' PASS: ' + details.passed + ' FAIL: ' + details.failed + ' TOTAL: ' + details.total);
console.log(' Finished in ' + details.runtime + ' milliseconds.');
console.log(hr);
// exit out of Rhino /**
try { * Schedules timer-based callbacks.
quit(); *
} catch(e) { } * @private
* @param {Function|String} fn The function to call.
// exit out of Node.js * @oaram {Number} delay The number of milliseconds to delay the `fn` call.
try { * @param [arg1, arg2, ...] Arguments to invoke `fn` with.
if (details.failed) { * @param {Boolean} repeated A flag to specify whether `fn` is called repeatedly.
console.error('Error: ' + details.failed + ' of ' + details.total + ' tests failed.'); * @returns {Number} The the ID of the timeout.
process.exit(1); */
} else { function schedule(fn, delay, args, repeated) {
process.exit(0); // Rhino 1.7RC4 will error assigning `task` below
} // https://bugzilla.mozilla.org/show_bug.cgi?id=775566
} catch(e) { } var task = ids[++counter] = new JavaAdapter(java.util.TimerTask, {
} 'run': function() {
fn.apply(context, args);
/** }
* A logging callback triggered after every assertion.
*
* @memberOf QUnit
* @param {Object} details An object with properties `actual`, `expected`,
* `message`, and `result`.
*/
function log(details) {
var expected = details.expected,
result = details.result,
type = typeof expected != 'undefined' ? 'EQ' : 'OK';
var assertion = [
result ? 'PASS' : 'FAIL',
type,
details.message || 'ok'
];
if (!result && type == 'EQ') {
assertion.push('Expected: ' + expected + ', Actual: ' + details.actual);
}
QUnit.config.testStats.assertions.push(assertion.join(' | '));
}
/**
* A logging callback triggered at the start of every test module.
*
* @memberOf QUnit
* @param {Object} details An object with property `name`.
*/
function moduleStart(details) {
console.log(hr);
console.log(details.name);
console.log(hr);
}
/**
* Converts an object into a string representation.
*
* @memberOf QUnit
* @type Function
* @param {Object} object The object to stringify.
* @returns {String} The result string.
*/
var parseObject = (function() {
var func = QUnit.jsDump.parsers.object;
return function(object) {
// fork to support Rhino's error objects
if (typeof object.rhinoException == 'object') {
return object.name +
' { message: "' + object.message +
'", fileName: "' + object.fileName +
'", lineNumber: ' + object.lineNumber + ' }';
}
return func(object);
};
}());
/**
* A logging callback triggered after a test is completed.
*
* @memberOf QUnit
* @param {Object} details An object with properties `failed`, `name`,
* `passed`, and `total`.
*/
function testDone(details) {
var assertions = QUnit.config.testStats.assertions,
testName = details.name;
if (details.failed > 0) {
console.log(' FAIL - '+ testName);
each(assertions, function(value) {
console.log(' ' + value);
}); });
// support non-functions
if (typeof fn != 'function') {
fn = (function(code) {
code = String(code);
return function() { eval(code); };
}(fn));
}
// used by setInterval
if (repeated) {
timer.schedule(task, delay, delay);
}
// used by setTimeout
else {
timer.schedule(task, delay);
}
return counter;
} }
else {
console.log(' PASS - ' + testName); /**
* Clears the delay set by `setInterval` or `setTimeout`.
*
* @memberOf context
* @param {Number} id The ID of the timeout to be cleared.
*/
function clearTimer(id) {
if (ids[id]) {
ids[id].cancel();
timer.purge();
delete ids[id];
}
} }
assertions.length = 0;
/**
* Executes a code snippet or function repeatedly, with a delay between each call.
*
* @memberOf context
* @param {Function|String} fn The function to call or string to evaluate.
* @oaram {Number} delay The number of milliseconds to delay each `fn` call.
* @param [arg1, arg2, ...] Arguments to invoke `fn` with.
* @returns {Number} The the ID of the timeout.
*/
function setInterval(fn, delay) {
return schedule(fn, delay, slice.call(arguments, 2), true);
}
/**
* Executes a code snippet or a function after specified delay.
*
* @memberOf context
* @param {Function|String} fn The function to call or string to evaluate.
* @oaram {Number} delay The number of milliseconds to delay the `fn` call.
* @param [arg1, arg2, ...] Arguments to invoke `fn` with.
* @returns {Number} The the ID of the timeout.
*/
function setTimeout(fn, delay) {
return schedule(fn, delay, slice.call(arguments, 2));
}
/*------------------------------------------------------------------------*/
/** Add `console.log()` support for Narwhal, Rhino, and RingoJS */
var console = context.console || (context.console = { 'log': context.print });
/** Shorten `context.QUnit.QUnit` to `context.QUnit` */
var QUnit = context.QUnit = context.QUnit.QUnit || context.QUnit;
/** Used as a horizontal rule in console output */
var hr = '----------------------------------------';
/**
* A logging callback triggered when all testing is completed.
*
* @memberOf QUnit
* @param {Object} details An object with properties `failed`, `passed`, `runtime`, and `total`.
*/
QUnit.done(function() {
var ran;
return function(details) {
// stop `asyncTest()` from erroneously calling `done()` twice in
// environments w/o timeouts
if (ran) {
return;
}
ran = true;
console.log(hr);
console.log(' PASS: ' + details.passed + ' FAIL: ' + details.failed + ' TOTAL: ' + details.total);
console.log(' Finished in ' + details.runtime + ' milliseconds.');
console.log(hr);
// exit out of Narhwal, Rhino, or Ringo
try {
quit();
} catch(e) { }
// exit out of Node.js or PhantomJS
try {
var process = context.process || context.phantom;
if (details.failed) {
console.error('Error: ' + details.failed + ' of ' + details.total + ' tests failed.');
process.exit(1);
} else {
process.exit(0);
}
} catch(e) { }
};
}());
/**
* A logging callback triggered after every assertion.
*
* @memberOf QUnit
* @param {Object} details An object with properties `actual`, `expected`, `message`, and `result`.
*/
QUnit.log(function(details) {
var expected = details.expected,
result = details.result,
type = typeof expected != 'undefined' ? 'EQ' : 'OK';
var assertion = [
result ? 'PASS' : 'FAIL',
type,
details.message || 'ok'
];
if (!result && type == 'EQ') {
assertion.push('Expected: ' + expected + ', Actual: ' + details.actual);
}
QUnit.config.testStats.assertions.push(assertion.join(' | '));
});
/**
* A logging callback triggered at the start of every test module.
*
* @memberOf QUnit
* @param {Object} details An object with property `name`.
*/
QUnit.moduleStart(function(details) {
console.log(hr);
console.log(details.name);
console.log(hr);
});
/**
* Converts an object into a string representation.
*
* @memberOf QUnit
* @type Function
* @param {Object} object The object to stringify.
* @returns {String} The result string.
*/
QUnit.jsDump.parsers.object = (function() {
var func = QUnit.jsDump.parsers.object;
return function(object) {
// fork to support Rhino's error objects
if (typeof object.rhinoException == 'object') {
return object.name +
' { message: "' + object.message +
'", fileName: "' + object.fileName +
'", lineNumber: ' + object.lineNumber + ' }';
}
return func(object);
};
}());
/**
* A logging callback triggered after a test is completed.
*
* @memberOf QUnit
* @param {Object} details An object with properties `failed`, `name`, `passed`, and `total`.
*/
QUnit.testDone(function(details) {
var assertions = QUnit.config.testStats.assertions,
testName = details.name;
if (details.failed > 0) {
console.log(' FAIL - '+ testName);
assertions.forEach(function(value) {
console.log(' ' + value);
});
}
else {
console.log(' PASS - ' + testName);
}
assertions.length = 0;
});
/**
* An object used to hold information about the current running test.
*
* @memberOf QUnit.config
* @type Object
*/
QUnit.config.testStats = {
/**
* An array of test summaries (pipe separated).
*
* @memberOf QUnit.config.testStats
* @type Array
*/
'assertions': []
};
/*------------------------------------------------------------------------*/
// Timeout fallbacks based on the work of Andrea Giammarchi and Weston C.
// https://github.com/WebReflection/wru/blob/master/src/rhinoTimers.js
// http://stackoverflow.com/questions/2261705/how-to-run-a-javascript-function-asynchronously-without-using-settimeout
try {
var counter = 0,
ids = {},
slice = Array.prototype.slice,
timer = new java.util.Timer;
context.clearInterval =
context.clearTimeout = clearTimer;
context.setInterval = setInterval;
context.setTimeout = setTimeout;
} catch(e) { }
// expose shortcuts
// exclude `module` because some environments have it as a built-in object
('asyncTest deepEqual equal equals expect notDeepEqual notEqual notStrictEqual ' +
'ok raises same start stop strictEqual test throws').replace(/\S+/g, function(methodName) {
context[methodName] = QUnit[methodName];
});
// must call `QUnit.start()` in the test file if using QUnit < 1.3.0 with
// Node.js or any version of QUnit with Narwhal, PhantomJS, Rhino, or RingoJS
QUnit.init();
} }
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
/** // expose QUnit CLIB
* An object used to hold information about the current running test. if (freeExports) {
* freeExports.runInContext = runInContext;
* @memberOf QUnit.config } else {
* @type Object runInContext(window);
*/ }
QUnit.config.testStats = { }(this));
/**
* An array of test summaries (pipe separated).
*
* @memberOf QUnit.config.testStats
* @type Array
*/
'assertions': []
};
// add shortcuts to the global
// exclude `module` because some environments have it as a built-in object
each(['asyncTest', 'deepEqual', 'equal', 'equals', 'expect', 'notDeepEqual',
'notEqual', 'notStrictEqual', 'ok', 'raises', 'same', 'start', 'stop',
'strictEqual', 'test', 'throws'], function(funcName) {
var func = QUnit[funcName];
if (func) {
global[funcName] = func;
}
});
// expose timer methods to global
try {
timer = new java.util.Timer;
if (!isFunction(global.clearInterval)) {
global.clearInterval = clearTimer;
}
if (!isFunction(global.clearTimeout)) {
global.clearTimeout = clearTimer;
}
if (!isFunction(global.setInterval)) {
global.setInterval = setInterval;
}
if (!isFunction(global.setTimeout)) {
global.setTimeout = setTimeout;
}
} catch(e) { }
// add callbacks
QUnit.done(done);
QUnit.log(log);
QUnit.moduleStart(moduleStart);
QUnit.testDone(testDone);
// add wrapped function
QUnit.jsDump.parsers.object = parseObject;
// must call `QUnit.start()` in the test file if using QUnit < 1.3.0 with
// Node.js or any version of QUnit with Narwhal, Rhino, or RingoJS
QUnit.init();
}(typeof global == 'object' && global || this));

View File

@@ -23,9 +23,6 @@ If you are interested in helping developing QUnit, you are in the right place.
For related discussions, visit the For related discussions, visit the
[QUnit and Testing forum](http://forum.jquery.com/qunit-and-testing). [QUnit and Testing forum](http://forum.jquery.com/qunit-and-testing).
Planning for a qunitjs.com site and other testing tools related work now happens
on the [jQuery Testing Team planning wiki](http://jquerytesting.pbworks.com/w/page/41556026/FrontPage).
Development Development
----------- -----------
@@ -49,11 +46,17 @@ tag, update them again to the next version, commit and push commits and tags
Put the 'v' in front of the tag, e.g. `v1.8.0`. Clean up the changelog, removing merge commits Put the 'v' in front of the tag, e.g. `v1.8.0`. Clean up the changelog, removing merge commits
or whitespace cleanups. or whitespace cleanups.
To upload to code.jquery.com (replace $version accordingly): To upload to code.jquery.com (replace $version accordingly), ssh to code.origin.jquery.com:
scp -q qunit/qunit.js jqadmin@code.origin.jquery.com:/var/www/html/code.jquery.com/qunit/qunit-$version.js cp qunit/qunit.js /var/www/html/code.jquery.com/qunit/qunit-$version.js
scp -q qunit/qunit.css jqadmin@code.origin.jquery.com:/var/www/html/code.jquery.com/qunit/qunit-$version.css cp qunit/qunit.css /var/www/html/code.jquery.com/qunit/qunit-$version.css
Then update /var/www/html/code.jquery.com/index.html and purge it with: Then update /var/www/html/code.jquery.com/index.html and purge it with:
curl -s http://code.origin.jquery.com/?reload curl -s http://code.origin.jquery.com/?reload
Update web-base-template to link to those files for qunitjs.com.
Publish to npm via
npm publish

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,5 @@
/** /**
* QUnit v1.10.0 - A JavaScript Unit Testing Framework * QUnit v1.11.0 - A JavaScript Unit Testing Framework
* *
* http://qunitjs.com * http://qunitjs.com
* *
@@ -20,7 +20,7 @@
/** Resets */ /** Resets */
#qunit-tests, #qunit-tests ol, #qunit-header, #qunit-banner, #qunit-userAgent, #qunit-testresult, #qunit-modulefilter { #qunit-tests, #qunit-header, #qunit-banner, #qunit-userAgent, #qunit-testresult, #qunit-modulefilter {
margin: 0; margin: 0;
padding: 0; padding: 0;
} }
@@ -111,7 +111,12 @@
color: #000; color: #000;
} }
#qunit-tests ol { #qunit-tests li .runtime {
float: right;
font-size: smaller;
}
.qunit-assert-list {
margin-top: 0.5em; margin-top: 0.5em;
padding: 0.5em; padding: 0.5em;
@@ -122,6 +127,10 @@
-webkit-border-radius: 5px; -webkit-border-radius: 5px;
} }
.qunit-collapsed {
display: none;
}
#qunit-tests table { #qunit-tests table {
border-collapse: collapse; border-collapse: collapse;
margin-top: .2em; margin-top: .2em;

View File

@@ -1,5 +1,5 @@
/** /**
* QUnit v1.10.0 - A JavaScript Unit Testing Framework * QUnit v1.11.0 - A JavaScript Unit Testing Framework
* *
* http://qunitjs.com * http://qunitjs.com
* *
@@ -11,6 +11,7 @@
(function( window ) { (function( window ) {
var QUnit, var QUnit,
assert,
config, config,
onErrorFnPrev, onErrorFnPrev,
testId = 0, testId = 0,
@@ -20,18 +21,67 @@ var QUnit,
// Keep a local reference to Date (GH-283) // Keep a local reference to Date (GH-283)
Date = window.Date, Date = window.Date,
defined = { defined = {
setTimeout: typeof window.setTimeout !== "undefined", setTimeout: typeof window.setTimeout !== "undefined",
sessionStorage: (function() { sessionStorage: (function() {
var x = "qunit-test-string"; var x = "qunit-test-string";
try { try {
sessionStorage.setItem( x, x ); sessionStorage.setItem( x, x );
sessionStorage.removeItem( x ); sessionStorage.removeItem( x );
return true; return true;
} catch( e ) { } catch( e ) {
return false; return false;
}
}())
},
/**
* Provides a normalized error string, correcting an issue
* with IE 7 (and prior) where Error.prototype.toString is
* not properly implemented
*
* Based on http://es5.github.com/#x15.11.4.4
*
* @param {String|Error} error
* @return {String} error message
*/
errorString = function( error ) {
var name, message,
errorString = error.toString();
if ( errorString.substring( 0, 7 ) === "[object" ) {
name = error.name ? error.name.toString() : "Error";
message = error.message ? error.message.toString() : "";
if ( name && message ) {
return name + ": " + message;
} else if ( name ) {
return name;
} else if ( message ) {
return message;
} else {
return "Error";
}
} else {
return errorString;
} }
}()) },
}; /**
* Makes a clone of an object using only Array or Object as base,
* and copies over the own enumerable properties.
*
* @param {Object} obj
* @return {Object} New object with only the own properties (recursively).
*/
objectValues = function( obj ) {
// Grunt 0.3.x uses an older version of jshint that still has jshint/jshint#392.
/*jshint newcap: false */
var key, val,
vals = QUnit.is( "array", obj ) ? [] : {};
for ( key in obj ) {
if ( hasOwn.call( obj, key ) ) {
val = obj[key];
vals[key] = val === Object(val) ? objectValues(val) : val;
}
}
return vals;
};
function Test( settings ) { function Test( settings ) {
extend( this, settings ); extend( this, settings );
@@ -44,11 +94,11 @@ Test.count = 0;
Test.prototype = { Test.prototype = {
init: function() { init: function() {
var a, b, li, var a, b, li,
tests = id( "qunit-tests" ); tests = id( "qunit-tests" );
if ( tests ) { if ( tests ) {
b = document.createElement( "strong" ); b = document.createElement( "strong" );
b.innerHTML = this.name; b.innerHTML = this.nameHtml;
// `a` initialized at top of scope // `a` initialized at top of scope
a = document.createElement( "a" ); a = document.createElement( "a" );
@@ -92,6 +142,7 @@ Test.prototype = {
teardown: function() {} teardown: function() {}
}, this.moduleTestEnvironment ); }, this.moduleTestEnvironment );
this.started = +new Date();
runLoggingCallbacks( "testStart", QUnit, { runLoggingCallbacks( "testStart", QUnit, {
name: this.testName, name: this.testName,
module: this.module module: this.module
@@ -111,7 +162,7 @@ Test.prototype = {
try { try {
this.testEnvironment.setup.call( this.testEnvironment ); this.testEnvironment.setup.call( this.testEnvironment );
} catch( e ) { } catch( e ) {
QUnit.pushFailure( "Setup failed on " + this.testName + ": " + e.message, extractStacktrace( e, 1 ) ); QUnit.pushFailure( "Setup failed on " + this.testName + ": " + ( e.message || e ), extractStacktrace( e, 1 ) );
} }
}, },
run: function() { run: function() {
@@ -120,22 +171,28 @@ Test.prototype = {
var running = id( "qunit-testresult" ); var running = id( "qunit-testresult" );
if ( running ) { if ( running ) {
running.innerHTML = "Running: <br/>" + this.name; running.innerHTML = "Running: <br/>" + this.nameHtml;
} }
if ( this.async ) { if ( this.async ) {
QUnit.stop(); QUnit.stop();
} }
this.callbackStarted = +new Date();
if ( config.notrycatch ) { if ( config.notrycatch ) {
this.callback.call( this.testEnvironment, QUnit.assert ); this.callback.call( this.testEnvironment, QUnit.assert );
this.callbackRuntime = +new Date() - this.callbackStarted;
return; return;
} }
try { try {
this.callback.call( this.testEnvironment, QUnit.assert ); this.callback.call( this.testEnvironment, QUnit.assert );
this.callbackRuntime = +new Date() - this.callbackStarted;
} catch( e ) { } catch( e ) {
QUnit.pushFailure( "Died on test #" + (this.assertions.length + 1) + " " + this.stack + ": " + e.message, extractStacktrace( e, 0 ) ); this.callbackRuntime = +new Date() - this.callbackStarted;
QUnit.pushFailure( "Died on test #" + (this.assertions.length + 1) + " " + this.stack + ": " + ( e.message || e ), extractStacktrace( e, 0 ) );
// else next test will carry the responsibility // else next test will carry the responsibility
saveGlobal(); saveGlobal();
@@ -148,38 +205,43 @@ Test.prototype = {
teardown: function() { teardown: function() {
config.current = this; config.current = this;
if ( config.notrycatch ) { if ( config.notrycatch ) {
if ( typeof this.callbackRuntime === "undefined" ) {
this.callbackRuntime = +new Date() - this.callbackStarted;
}
this.testEnvironment.teardown.call( this.testEnvironment ); this.testEnvironment.teardown.call( this.testEnvironment );
return; return;
} else { } else {
try { try {
this.testEnvironment.teardown.call( this.testEnvironment ); this.testEnvironment.teardown.call( this.testEnvironment );
} catch( e ) { } catch( e ) {
QUnit.pushFailure( "Teardown failed on " + this.testName + ": " + e.message, extractStacktrace( e, 1 ) ); QUnit.pushFailure( "Teardown failed on " + this.testName + ": " + ( e.message || e ), extractStacktrace( e, 1 ) );
} }
} }
checkPollution(); checkPollution();
}, },
finish: function() { finish: function() {
config.current = this; config.current = this;
if ( config.requireExpects && this.expected == null ) { if ( config.requireExpects && this.expected === null ) {
QUnit.pushFailure( "Expected number of assertions to be defined, but expect() was not called.", this.stack ); QUnit.pushFailure( "Expected number of assertions to be defined, but expect() was not called.", this.stack );
} else if ( this.expected != null && this.expected != this.assertions.length ) { } else if ( this.expected !== null && this.expected !== this.assertions.length ) {
QUnit.pushFailure( "Expected " + this.expected + " assertions, but " + this.assertions.length + " were run", this.stack ); QUnit.pushFailure( "Expected " + this.expected + " assertions, but " + this.assertions.length + " were run", this.stack );
} else if ( this.expected == null && !this.assertions.length ) { } else if ( this.expected === null && !this.assertions.length ) {
QUnit.pushFailure( "Expected at least one assertion, but none were run - call expect(0) to accept zero assertions.", this.stack ); QUnit.pushFailure( "Expected at least one assertion, but none were run - call expect(0) to accept zero assertions.", this.stack );
} }
var assertion, a, b, i, li, ol, var i, assertion, a, b, time, li, ol,
test = this, test = this,
good = 0, good = 0,
bad = 0, bad = 0,
tests = id( "qunit-tests" ); tests = id( "qunit-tests" );
this.runtime = +new Date() - this.started;
config.stats.all += this.assertions.length; config.stats.all += this.assertions.length;
config.moduleStats.all += this.assertions.length; config.moduleStats.all += this.assertions.length;
if ( tests ) { if ( tests ) {
ol = document.createElement( "ol" ); ol = document.createElement( "ol" );
ol.className = "qunit-assert-list";
for ( i = 0; i < this.assertions.length; i++ ) { for ( i = 0; i < this.assertions.length; i++ ) {
assertion = this.assertions[i]; assertion = this.assertions[i];
@@ -208,22 +270,22 @@ Test.prototype = {
} }
if ( bad === 0 ) { if ( bad === 0 ) {
ol.style.display = "none"; addClass( ol, "qunit-collapsed" );
} }
// `b` initialized at top of scope // `b` initialized at top of scope
b = document.createElement( "strong" ); b = document.createElement( "strong" );
b.innerHTML = this.name + " <b class='counts'>(<b class='failed'>" + bad + "</b>, <b class='passed'>" + good + "</b>, " + this.assertions.length + ")</b>"; b.innerHTML = this.nameHtml + " <b class='counts'>(<b class='failed'>" + bad + "</b>, <b class='passed'>" + good + "</b>, " + this.assertions.length + ")</b>";
addEvent(b, "click", function() { addEvent(b, "click", function() {
var next = b.nextSibling.nextSibling, var next = b.parentNode.lastChild,
display = next.style.display; collapsed = hasClass( next, "qunit-collapsed" );
next.style.display = display === "none" ? "block" : "none"; ( collapsed ? removeClass : addClass )( next, "qunit-collapsed" );
}); });
addEvent(b, "dblclick", function( e ) { addEvent(b, "dblclick", function( e ) {
var target = e && e.target ? e.target : window.event.srcElement; var target = e && e.target ? e.target : window.event.srcElement;
if ( target.nodeName.toLowerCase() == "span" || target.nodeName.toLowerCase() == "b" ) { if ( target.nodeName.toLowerCase() === "span" || target.nodeName.toLowerCase() === "b" ) {
target = target.parentNode; target = target.parentNode;
} }
if ( window.location && target.nodeName.toLowerCase() === "strong" ) { if ( window.location && target.nodeName.toLowerCase() === "strong" ) {
@@ -231,13 +293,19 @@ Test.prototype = {
} }
}); });
// `time` initialized at top of scope
time = document.createElement( "span" );
time.className = "runtime";
time.innerHTML = this.runtime + " ms";
// `li` initialized at top of scope // `li` initialized at top of scope
li = id( this.id ); li = id( this.id );
li.className = bad ? "fail" : "pass"; li.className = bad ? "fail" : "pass";
li.removeChild( li.firstChild ); li.removeChild( li.firstChild );
a = li.firstChild; a = li.firstChild;
li.appendChild( b ); li.appendChild( b );
li.appendChild ( a ); li.appendChild( a );
li.appendChild( time );
li.appendChild( ol ); li.appendChild( ol );
} else { } else {
@@ -255,7 +323,8 @@ Test.prototype = {
module: this.module, module: this.module,
failed: bad, failed: bad,
passed: this.assertions.length - bad, passed: this.assertions.length - bad,
total: this.assertions.length total: this.assertions.length,
duration: this.runtime
}); });
QUnit.reset(); QUnit.reset();
@@ -321,7 +390,7 @@ QUnit = {
test: function( testName, expected, callback, async ) { test: function( testName, expected, callback, async ) {
var test, var test,
name = "<span class='test-name'>" + escapeInnerText( testName ) + "</span>"; nameHtml = "<span class='test-name'>" + escapeText( testName ) + "</span>";
if ( arguments.length === 2 ) { if ( arguments.length === 2 ) {
callback = expected; callback = expected;
@@ -329,11 +398,11 @@ QUnit = {
} }
if ( config.currentModule ) { if ( config.currentModule ) {
name = "<span class='module-name'>" + config.currentModule + "</span>: " + name; nameHtml = "<span class='module-name'>" + escapeText( config.currentModule ) + "</span>: " + nameHtml;
} }
test = new Test({ test = new Test({
name: name, nameHtml: nameHtml,
testName: testName, testName: testName,
expected: expected, expected: expected,
async: async, async: async,
@@ -360,6 +429,18 @@ QUnit = {
}, },
start: function( count ) { start: function( count ) {
// QUnit hasn't been initialized yet.
// Note: RequireJS (et al) may delay onLoad
if ( config.semaphore === undefined ) {
QUnit.begin(function() {
// This is triggered at the top of QUnit.load, push start() to the event loop, to allow QUnit.load to finish first
setTimeout(function() {
QUnit.start( count );
});
});
return;
}
config.semaphore -= count || 1; config.semaphore -= count || 1;
// don't start until equal number of stop-calls // don't start until equal number of stop-calls
if ( config.semaphore > 0 ) { if ( config.semaphore > 0 ) {
@@ -368,6 +449,8 @@ QUnit = {
// ignore if start is called more often then stop // ignore if start is called more often then stop
if ( config.semaphore < 0 ) { if ( config.semaphore < 0 ) {
config.semaphore = 0; config.semaphore = 0;
QUnit.pushFailure( "Called start() while already started (QUnit.config.semaphore was 0 already)", null, sourceFromStacktrace(2) );
return;
} }
// A slight delay, to avoid any current callbacks // A slight delay, to avoid any current callbacks
if ( defined.setTimeout ) { if ( defined.setTimeout ) {
@@ -403,11 +486,14 @@ QUnit = {
} }
}; };
// `assert` initialized at top of scope
// Asssert helpers // Asssert helpers
// All of these must call either QUnit.push() or manually do: // All of these must either call QUnit.push() or manually do:
// - runLoggingCallbacks( "log", .. ); // - runLoggingCallbacks( "log", .. );
// - config.current.assertions.push({ .. }); // - config.current.assertions.push({ .. });
QUnit.assert = { // We attach it to the QUnit object *after* we expose the public API,
// otherwise `assert` will become a global variable in browsers (#341).
assert = {
/** /**
* Asserts rough true-ish result. * Asserts rough true-ish result.
* @name ok * @name ok
@@ -428,14 +514,14 @@ QUnit.assert = {
message: msg message: msg
}; };
msg = escapeInnerText( msg || (result ? "okay" : "failed" ) ); msg = escapeText( msg || (result ? "okay" : "failed" ) );
msg = "<span class='test-message'>" + msg + "</span>"; msg = "<span class='test-message'>" + msg + "</span>";
if ( !result ) { if ( !result ) {
source = sourceFromStacktrace( 2 ); source = sourceFromStacktrace( 2 );
if ( source ) { if ( source ) {
details.source = source; details.source = source;
msg += "<table><tr class='test-source'><th>Source: </th><td><pre>" + escapeInnerText( source ) + "</pre></td></tr></table>"; msg += "<table><tr class='test-source'><th>Source: </th><td><pre>" + escapeText( source ) + "</pre></td></tr></table>";
} }
} }
runLoggingCallbacks( "log", QUnit, details ); runLoggingCallbacks( "log", QUnit, details );
@@ -453,6 +539,7 @@ QUnit.assert = {
* @example equal( format( "Received {0} bytes.", 2), "Received 2 bytes.", "format() replaces {0} with next argument" ); * @example equal( format( "Received {0} bytes.", 2), "Received 2 bytes.", "format() replaces {0} with next argument" );
*/ */
equal: function( actual, expected, message ) { equal: function( actual, expected, message ) {
/*jshint eqeqeq:false */
QUnit.push( expected == actual, actual, expected, message ); QUnit.push( expected == actual, actual, expected, message );
}, },
@@ -461,9 +548,30 @@ QUnit.assert = {
* @function * @function
*/ */
notEqual: function( actual, expected, message ) { notEqual: function( actual, expected, message ) {
/*jshint eqeqeq:false */
QUnit.push( expected != actual, actual, expected, message ); QUnit.push( expected != actual, actual, expected, message );
}, },
/**
* @name propEqual
* @function
*/
propEqual: function( actual, expected, message ) {
actual = objectValues(actual);
expected = objectValues(expected);
QUnit.push( QUnit.equiv(actual, expected), actual, expected, message );
},
/**
* @name notPropEqual
* @function
*/
notPropEqual: function( actual, expected, message ) {
actual = objectValues(actual);
expected = objectValues(expected);
QUnit.push( !QUnit.equiv(actual, expected), actual, expected, message );
},
/** /**
* @name deepEqual * @name deepEqual
* @function * @function
@@ -496,8 +604,9 @@ QUnit.assert = {
QUnit.push( expected !== actual, actual, expected, message ); QUnit.push( expected !== actual, actual, expected, message );
}, },
throws: function( block, expected, message ) { "throws": function( block, expected, message ) {
var actual, var actual,
expectedOutput = expected,
ok = false; ok = false;
// 'expected' is optional // 'expected' is optional
@@ -518,18 +627,20 @@ QUnit.assert = {
// we don't want to validate thrown error // we don't want to validate thrown error
if ( !expected ) { if ( !expected ) {
ok = true; ok = true;
expectedOutput = null;
// expected is a regexp // expected is a regexp
} else if ( QUnit.objectType( expected ) === "regexp" ) { } else if ( QUnit.objectType( expected ) === "regexp" ) {
ok = expected.test( actual ); ok = expected.test( errorString( actual ) );
// expected is a constructor // expected is a constructor
} else if ( actual instanceof expected ) { } else if ( actual instanceof expected ) {
ok = true; ok = true;
// expected is a validation function which returns true is validation passed // expected is a validation function which returns true is validation passed
} else if ( expected.call( {}, actual ) === true ) { } else if ( expected.call( {}, actual ) === true ) {
expectedOutput = null;
ok = true; ok = true;
} }
QUnit.push( ok, actual, null, message ); QUnit.push( ok, actual, expectedOutput, message );
} else { } else {
QUnit.pushFailure( message, null, 'No exception was thrown.' ); QUnit.pushFailure( message, null, 'No exception was thrown.' );
} }
@@ -538,15 +649,16 @@ QUnit.assert = {
/** /**
* @deprecate since 1.8.0 * @deprecate since 1.8.0
* Kept assertion helpers in root for backwards compatibility * Kept assertion helpers in root for backwards compatibility.
*/ */
extend( QUnit, QUnit.assert ); extend( QUnit, assert );
/** /**
* @deprecated since 1.9.0 * @deprecated since 1.9.0
* Kept global "raises()" for backwards compatibility * Kept root "raises()" for backwards compatibility.
* (Note that we don't introduce assert.raises).
*/ */
QUnit.raises = QUnit.assert.throws; QUnit.raises = assert[ "throws" ];
/** /**
* @deprecated since 1.0.0, replaced with error pushes since 1.3.0 * @deprecated since 1.0.0, replaced with error pushes since 1.3.0
@@ -622,6 +734,15 @@ config = {
moduleDone: [] moduleDone: []
}; };
// Export global variables, unless an 'exports' object exists,
// in that case we assume we're in CommonJS (dealt with on the bottom of the script)
if ( typeof exports === "undefined" ) {
extend( window, QUnit );
// Expose QUnit object
window.QUnit = QUnit;
}
// Initialize more QUnit.config and QUnit.urlParams // Initialize more QUnit.config and QUnit.urlParams
(function() { (function() {
var i, var i,
@@ -655,18 +776,11 @@ config = {
QUnit.isLocal = location.protocol === "file:"; QUnit.isLocal = location.protocol === "file:";
}()); }());
// Export global variables, unless an 'exports' object exists,
// in that case we assume we're in CommonJS (dealt with on the bottom of the script)
if ( typeof exports === "undefined" ) {
extend( window, QUnit );
// Expose QUnit object
window.QUnit = QUnit;
}
// Extend QUnit object, // Extend QUnit object,
// these after set here because they should not be exposed as global functions // these after set here because they should not be exposed as global functions
extend( QUnit, { extend( QUnit, {
assert: assert,
config: config, config: config,
// Initialize the configuration options // Initialize the configuration options
@@ -681,7 +795,7 @@ extend( QUnit, {
autorun: false, autorun: false,
filter: "", filter: "",
queue: [], queue: [],
semaphore: 0 semaphore: 1
}); });
var tests, banner, result, var tests, banner, result,
@@ -689,7 +803,7 @@ extend( QUnit, {
if ( qunit ) { if ( qunit ) {
qunit.innerHTML = qunit.innerHTML =
"<h1 id='qunit-header'>" + escapeInnerText( document.title ) + "</h1>" + "<h1 id='qunit-header'>" + escapeText( document.title ) + "</h1>" +
"<h2 id='qunit-banner'></h2>" + "<h2 id='qunit-banner'></h2>" +
"<div id='qunit-testrunner-toolbar'></div>" + "<div id='qunit-testrunner-toolbar'></div>" +
"<h2 id='qunit-userAgent'></h2>" + "<h2 id='qunit-userAgent'></h2>" +
@@ -745,7 +859,7 @@ extend( QUnit, {
// Safe object type checking // Safe object type checking
is: function( type, obj ) { is: function( type, obj ) {
return QUnit.objectType( obj ) == type; return QUnit.objectType( obj ) === type;
}, },
objectType: function( obj ) { objectType: function( obj ) {
@@ -757,7 +871,8 @@ extend( QUnit, {
return "null"; return "null";
} }
var type = toString.call( obj ).match(/^\[object\s(.*)\]$/)[1] || ""; var match = toString.call( obj ).match(/^\[object\s(.*)\]$/),
type = match && match[1] || "";
switch ( type ) { switch ( type ) {
case "Number": case "Number":
@@ -794,16 +909,16 @@ extend( QUnit, {
expected: expected expected: expected
}; };
message = escapeInnerText( message ) || ( result ? "okay" : "failed" ); message = escapeText( message ) || ( result ? "okay" : "failed" );
message = "<span class='test-message'>" + message + "</span>"; message = "<span class='test-message'>" + message + "</span>";
output = message; output = message;
if ( !result ) { if ( !result ) {
expected = escapeInnerText( QUnit.jsDump.parse(expected) ); expected = escapeText( QUnit.jsDump.parse(expected) );
actual = escapeInnerText( QUnit.jsDump.parse(actual) ); actual = escapeText( QUnit.jsDump.parse(actual) );
output += "<table><tr class='test-expected'><th>Expected: </th><td><pre>" + expected + "</pre></td></tr>"; output += "<table><tr class='test-expected'><th>Expected: </th><td><pre>" + expected + "</pre></td></tr>";
if ( actual != expected ) { if ( actual !== expected ) {
output += "<tr class='test-actual'><th>Result: </th><td><pre>" + actual + "</pre></td></tr>"; output += "<tr class='test-actual'><th>Result: </th><td><pre>" + actual + "</pre></td></tr>";
output += "<tr class='test-diff'><th>Diff: </th><td><pre>" + QUnit.diff( expected, actual ) + "</pre></td></tr>"; output += "<tr class='test-diff'><th>Diff: </th><td><pre>" + QUnit.diff( expected, actual ) + "</pre></td></tr>";
} }
@@ -812,7 +927,7 @@ extend( QUnit, {
if ( source ) { if ( source ) {
details.source = source; details.source = source;
output += "<tr class='test-source'><th>Source: </th><td><pre>" + escapeInnerText( source ) + "</pre></td></tr>"; output += "<tr class='test-source'><th>Source: </th><td><pre>" + escapeText( source ) + "</pre></td></tr>";
} }
output += "</table>"; output += "</table>";
@@ -839,19 +954,19 @@ extend( QUnit, {
message: message message: message
}; };
message = escapeInnerText( message ) || "error"; message = escapeText( message ) || "error";
message = "<span class='test-message'>" + message + "</span>"; message = "<span class='test-message'>" + message + "</span>";
output = message; output = message;
output += "<table>"; output += "<table>";
if ( actual ) { if ( actual ) {
output += "<tr class='test-actual'><th>Result: </th><td><pre>" + escapeInnerText( actual ) + "</pre></td></tr>"; output += "<tr class='test-actual'><th>Result: </th><td><pre>" + escapeText( actual ) + "</pre></td></tr>";
} }
if ( source ) { if ( source ) {
details.source = source; details.source = source;
output += "<tr class='test-source'><th>Source: </th><td><pre>" + escapeInnerText( source ) + "</pre></td></tr>"; output += "<tr class='test-source'><th>Source: </th><td><pre>" + escapeText( source ) + "</pre></td></tr>";
} }
output += "</table>"; output += "</table>";
@@ -876,7 +991,8 @@ extend( QUnit, {
querystring += encodeURIComponent( key ) + "=" + querystring += encodeURIComponent( key ) + "=" +
encodeURIComponent( params[ key ] ) + "&"; encodeURIComponent( params[ key ] ) + "&";
} }
return window.location.pathname + querystring.slice( 0, -1 ); return window.location.protocol + "//" + window.location.host +
window.location.pathname + querystring.slice( 0, -1 );
}, },
extend: extend, extend: extend,
@@ -907,7 +1023,7 @@ extend( QUnit.constructor.prototype, {
// testStart: { name } // testStart: { name }
testStart: registerLoggingCallback( "testStart" ), testStart: registerLoggingCallback( "testStart" ),
// testDone: { name, failed, passed, total } // testDone: { name, failed, passed, total, duration }
testDone: registerLoggingCallback( "testDone" ), testDone: registerLoggingCallback( "testDone" ),
// moduleStart: { name } // moduleStart: { name }
@@ -925,9 +1041,10 @@ QUnit.load = function() {
runLoggingCallbacks( "begin", QUnit, {} ); runLoggingCallbacks( "begin", QUnit, {} );
// Initialize the config, saving the execution queue // Initialize the config, saving the execution queue
var banner, filter, i, label, len, main, ol, toolbar, userAgent, val, urlConfigCheckboxes, moduleFilter, var banner, filter, i, label, len, main, ol, toolbar, userAgent, val,
numModules = 0, urlConfigCheckboxesContainer, urlConfigCheckboxes, moduleFilter,
moduleFilterHtml = "", numModules = 0,
moduleFilterHtml = "",
urlConfigHtml = "", urlConfigHtml = "",
oldconfig = extend( {}, config ); oldconfig = extend( {}, config );
@@ -948,14 +1065,24 @@ QUnit.load = function() {
}; };
} }
config[ val.id ] = QUnit.urlParams[ val.id ]; config[ val.id ] = QUnit.urlParams[ val.id ];
urlConfigHtml += "<input id='qunit-urlconfig-" + val.id + "' name='" + val.id + "' type='checkbox'" + ( config[ val.id ] ? " checked='checked'" : "" ) + " title='" + val.tooltip + "'><label for='qunit-urlconfig-" + val.id + "' title='" + val.tooltip + "'>" + val.label + "</label>"; urlConfigHtml += "<input id='qunit-urlconfig-" + escapeText( val.id ) +
"' name='" + escapeText( val.id ) +
"' type='checkbox'" + ( config[ val.id ] ? " checked='checked'" : "" ) +
" title='" + escapeText( val.tooltip ) +
"'><label for='qunit-urlconfig-" + escapeText( val.id ) +
"' title='" + escapeText( val.tooltip ) + "'>" + val.label + "</label>";
} }
moduleFilterHtml += "<label for='qunit-modulefilter'>Module: </label><select id='qunit-modulefilter' name='modulefilter'><option value='' " + ( config.module === undefined ? "selected" : "" ) + ">< All Modules ></option>"; moduleFilterHtml += "<label for='qunit-modulefilter'>Module: </label><select id='qunit-modulefilter' name='modulefilter'><option value='' " +
( config.module === undefined ? "selected='selected'" : "" ) +
">< All Modules ></option>";
for ( i in config.modules ) { for ( i in config.modules ) {
if ( config.modules.hasOwnProperty( i ) ) { if ( config.modules.hasOwnProperty( i ) ) {
numModules += 1; numModules += 1;
moduleFilterHtml += "<option value='" + encodeURIComponent(i) + "' " + ( config.module === i ? "selected" : "" ) + ">" + i + "</option>"; moduleFilterHtml += "<option value='" + escapeText( encodeURIComponent(i) ) + "' " +
( config.module === i ? "selected='selected'" : "" ) +
">" + escapeText(i) + "</option>";
} }
} }
moduleFilterHtml += "</select>"; moduleFilterHtml += "</select>";
@@ -1014,22 +1141,28 @@ QUnit.load = function() {
label.innerHTML = "Hide passed tests"; label.innerHTML = "Hide passed tests";
toolbar.appendChild( label ); toolbar.appendChild( label );
urlConfigCheckboxes = document.createElement( 'span' ); urlConfigCheckboxesContainer = document.createElement("span");
urlConfigCheckboxes.innerHTML = urlConfigHtml; urlConfigCheckboxesContainer.innerHTML = urlConfigHtml;
addEvent( urlConfigCheckboxes, "change", function( event ) { urlConfigCheckboxes = urlConfigCheckboxesContainer.getElementsByTagName("input");
var params = {}; // For oldIE support:
params[ event.target.name ] = event.target.checked ? true : undefined; // * Add handlers to the individual elements instead of the container
// * Use "click" instead of "change"
// * Fallback from event.target to event.srcElement
addEvents( urlConfigCheckboxes, "click", function( event ) {
var params = {},
target = event.target || event.srcElement;
params[ target.name ] = target.checked ? true : undefined;
window.location = QUnit.url( params ); window.location = QUnit.url( params );
}); });
toolbar.appendChild( urlConfigCheckboxes ); toolbar.appendChild( urlConfigCheckboxesContainer );
if (numModules > 1) { if (numModules > 1) {
moduleFilter = document.createElement( 'span' ); moduleFilter = document.createElement( 'span' );
moduleFilter.setAttribute( 'id', 'qunit-modulefilter-container' ); moduleFilter.setAttribute( 'id', 'qunit-modulefilter-container' );
moduleFilter.innerHTML = moduleFilterHtml; moduleFilter.innerHTML = moduleFilterHtml;
addEvent( moduleFilter, "change", function() { addEvent( moduleFilter.lastChild, "change", function() {
var selectBox = moduleFilter.getElementsByTagName("select")[0], var selectBox = moduleFilter.getElementsByTagName("select")[0],
selectedModule = decodeURIComponent(selectBox.options[selectBox.selectedIndex].value); selectedModule = decodeURIComponent(selectBox.options[selectBox.selectedIndex].value);
window.location = QUnit.url( { module: ( selectedModule === "" ) ? undefined : selectedModule } ); window.location = QUnit.url( { module: ( selectedModule === "" ) ? undefined : selectedModule } );
}); });
@@ -1106,7 +1239,7 @@ function done() {
" milliseconds.<br/>", " milliseconds.<br/>",
"<span class='passed'>", "<span class='passed'>",
passed, passed,
"</span> tests of <span class='total'>", "</span> assertions of <span class='total'>",
config.stats.all, config.stats.all,
"</span> passed, <span class='failed'>", "</span> passed, <span class='failed'>",
config.stats.bad, config.stats.bad,
@@ -1199,7 +1332,7 @@ function validTest( test ) {
function extractStacktrace( e, offset ) { function extractStacktrace( e, offset ) {
offset = offset === undefined ? 3 : offset; offset = offset === undefined ? 3 : offset;
var stack, include, i, regex; var stack, include, i;
if ( e.stacktrace ) { if ( e.stacktrace ) {
// Opera // Opera
@@ -1213,7 +1346,7 @@ function extractStacktrace( e, offset ) {
if ( fileName ) { if ( fileName ) {
include = []; include = [];
for ( i = offset; i < stack.length; i++ ) { for ( i = offset; i < stack.length; i++ ) {
if ( stack[ i ].indexOf( fileName ) != -1 ) { if ( stack[ i ].indexOf( fileName ) !== -1 ) {
break; break;
} }
include.push( stack[ i ] ); include.push( stack[ i ] );
@@ -1242,17 +1375,27 @@ function sourceFromStacktrace( offset ) {
} }
} }
function escapeInnerText( s ) { /**
* Escape text for attribute or text content.
*/
function escapeText( s ) {
if ( !s ) { if ( !s ) {
return ""; return "";
} }
s = s + ""; s = s + "";
return s.replace( /[\&<>]/g, function( s ) { // Both single quotes and double quotes (for attributes)
return s.replace( /['"<>&]/g, function( s ) {
switch( s ) { switch( s ) {
case "&": return "&amp;"; case '\'':
case "<": return "&lt;"; return '&#039;';
case ">": return "&gt;"; case '"':
default: return s; return '&quot;';
case '<':
return '&lt;';
case '>':
return '&gt;';
case '&':
return '&amp;';
} }
}); });
} }
@@ -1300,7 +1443,7 @@ function saveGlobal() {
} }
} }
function checkPollution( name ) { function checkPollution() {
var newGlobals, var newGlobals,
deletedGlobals, deletedGlobals,
old = config.pollution; old = config.pollution;
@@ -1349,16 +1492,53 @@ function extend( a, b ) {
return a; return a;
} }
/**
* @param {HTMLElement} elem
* @param {string} type
* @param {Function} fn
*/
function addEvent( elem, type, fn ) { function addEvent( elem, type, fn ) {
// Standards-based browsers
if ( elem.addEventListener ) { if ( elem.addEventListener ) {
elem.addEventListener( type, fn, false ); elem.addEventListener( type, fn, false );
} else if ( elem.attachEvent ) { // IE
elem.attachEvent( "on" + type, fn );
} else { } else {
fn(); elem.attachEvent( "on" + type, fn );
} }
} }
/**
* @param {Array|NodeList} elems
* @param {string} type
* @param {Function} fn
*/
function addEvents( elems, type, fn ) {
var i = elems.length;
while ( i-- ) {
addEvent( elems[i], type, fn );
}
}
function hasClass( elem, name ) {
return (" " + elem.className + " ").indexOf(" " + name + " ") > -1;
}
function addClass( elem, name ) {
if ( !hasClass( elem, name ) ) {
elem.className += (elem.className ? " " : "") + name;
}
}
function removeClass( elem, name ) {
var set = " " + elem.className + " ";
// Class name may appear multiple times
while ( set.indexOf(" " + name + " ") > -1 ) {
set = set.replace(" " + name + " " , " ");
}
// If possible, trim it for prettiness, but not neccecarily
elem.className = window.jQuery ? jQuery.trim( set ) : ( set.trim ? set.trim() : set );
}
function id( name ) { function id( name ) {
return !!( typeof document !== "undefined" && document && document.getElementById ) && return !!( typeof document !== "undefined" && document && document.getElementById ) &&
document.getElementById( name ); document.getElementById( name );
@@ -1372,7 +1552,6 @@ function registerLoggingCallback( key ) {
// Supports deprecated method of completely overwriting logging callbacks // Supports deprecated method of completely overwriting logging callbacks
function runLoggingCallbacks( key, scope, args ) { function runLoggingCallbacks( key, scope, args ) {
//debugger;
var i, callbacks; var i, callbacks;
if ( QUnit.hasOwnProperty( key ) ) { if ( QUnit.hasOwnProperty( key ) ) {
QUnit[ key ].call(scope, args ); QUnit[ key ].call(scope, args );
@@ -1414,6 +1593,7 @@ QUnit.equiv = (function() {
// for string, boolean, number and null // for string, boolean, number and null
function useStrictEquality( b, a ) { function useStrictEquality( b, a ) {
/*jshint eqeqeq:false */
if ( b instanceof a.constructor || a instanceof b.constructor ) { if ( b instanceof a.constructor || a instanceof b.constructor ) {
// to catch short annotaion VS 'new' annotation of a // to catch short annotaion VS 'new' annotation of a
// declaration // declaration
@@ -1610,7 +1790,8 @@ QUnit.jsDump = (function() {
var reName = /^function (\w+)/, var reName = /^function (\w+)/,
jsDump = { jsDump = {
parse: function( obj, type, stack ) { //type is used mostly internally, you can fix a (custom)type in advance // type is used mostly internally, you can fix a (custom)type in advance
parse: function( obj, type, stack ) {
stack = stack || [ ]; stack = stack || [ ];
var inStack, res, var inStack, res,
parser = this.parsers[ type || this.typeOf(obj) ]; parser = this.parsers[ type || this.typeOf(obj) ];
@@ -1618,18 +1799,16 @@ QUnit.jsDump = (function() {
type = typeof parser; type = typeof parser;
inStack = inArray( obj, stack ); inStack = inArray( obj, stack );
if ( inStack != -1 ) { if ( inStack !== -1 ) {
return "recursion(" + (inStack - stack.length) + ")"; return "recursion(" + (inStack - stack.length) + ")";
} }
//else if ( type === "function" ) {
if ( type == "function" ) {
stack.push( obj ); stack.push( obj );
res = parser.call( this, obj, stack ); res = parser.call( this, obj, stack );
stack.pop(); stack.pop();
return res; return res;
} }
// else return ( type === "string" ) ? parser : this.parsers.error;
return ( type == "string" ) ? parser : this.parsers.error;
}, },
typeOf: function( obj ) { typeOf: function( obj ) {
var type; var type;
@@ -1656,6 +1835,8 @@ QUnit.jsDump = (function() {
( typeof obj.length === "number" && typeof obj.item !== "undefined" && ( obj.length ? obj.item(0) === obj[0] : ( obj.item( 0 ) === null && typeof obj[0] === "undefined" ) ) ) ( typeof obj.length === "number" && typeof obj.item !== "undefined" && ( obj.length ? obj.item(0) === obj[0] : ( obj.item( 0 ) === null && typeof obj[0] === "undefined" ) ) )
) { ) {
type = "array"; type = "array";
} else if ( obj.constructor === Error.prototype.constructor ) {
type = "error";
} else { } else {
type = typeof obj; type = typeof obj;
} }
@@ -1664,7 +1845,8 @@ QUnit.jsDump = (function() {
separator: function() { separator: function() {
return this.multiline ? this.HTML ? "<br />" : "\n" : this.HTML ? "&nbsp;" : " "; return this.multiline ? this.HTML ? "<br />" : "\n" : this.HTML ? "&nbsp;" : " ";
}, },
indent: function( extra ) {// extra can be a number, shortcut for increasing-calling-decreasing // extra can be a number, shortcut for increasing-calling-decreasing
indent: function( extra ) {
if ( !this.multiline ) { if ( !this.multiline ) {
return ""; return "";
} }
@@ -1693,13 +1875,16 @@ QUnit.jsDump = (function() {
parsers: { parsers: {
window: "[Window]", window: "[Window]",
document: "[Document]", document: "[Document]",
error: "[ERROR]", //when no parser is found, shouldn"t happen error: function(error) {
return "Error(\"" + error.message + "\")";
},
unknown: "[Unknown]", unknown: "[Unknown]",
"null": "null", "null": "null",
"undefined": "undefined", "undefined": "undefined",
"function": function( fn ) { "function": function( fn ) {
var ret = "function", var ret = "function",
name = "name" in fn ? fn.name : (reName.exec(fn) || [])[1];//functions never have name in IE // functions never have name in IE
name = "name" in fn ? fn.name : (reName.exec(fn) || [])[1];
if ( name ) { if ( name ) {
ret += " " + name; ret += " " + name;
@@ -1715,13 +1900,9 @@ QUnit.jsDump = (function() {
object: function( map, stack ) { object: function( map, stack ) {
var ret = [ ], keys, key, val, i; var ret = [ ], keys, key, val, i;
QUnit.jsDump.up(); QUnit.jsDump.up();
if ( Object.keys ) { keys = [];
keys = Object.keys( map ); for ( key in map ) {
} else { keys.push( key );
keys = [];
for ( key in map ) {
keys.push( key );
}
} }
keys.sort(); keys.sort();
for ( i = 0; i < keys.length; i++ ) { for ( i = 0; i < keys.length; i++ ) {
@@ -1733,21 +1914,34 @@ QUnit.jsDump = (function() {
return join( "{", ret, "}" ); return join( "{", ret, "}" );
}, },
node: function( node ) { node: function( node ) {
var a, val, var len, i, val,
open = QUnit.jsDump.HTML ? "&lt;" : "<", open = QUnit.jsDump.HTML ? "&lt;" : "<",
close = QUnit.jsDump.HTML ? "&gt;" : ">", close = QUnit.jsDump.HTML ? "&gt;" : ">",
tag = node.nodeName.toLowerCase(), tag = node.nodeName.toLowerCase(),
ret = open + tag; ret = open + tag,
attrs = node.attributes;
for ( a in QUnit.jsDump.DOMAttrs ) { if ( attrs ) {
val = node[ QUnit.jsDump.DOMAttrs[a] ]; for ( i = 0, len = attrs.length; i < len; i++ ) {
if ( val ) { val = attrs[i].nodeValue;
ret += " " + a + "=" + QUnit.jsDump.parse( val, "attribute" ); // IE6 includes all attributes in .attributes, even ones not explicitly set.
// Those have values like undefined, null, 0, false, "" or "inherit".
if ( val && val !== "inherit" ) {
ret += " " + attrs[i].nodeName + "=" + QUnit.jsDump.parse( val, "attribute" );
}
} }
} }
return ret + close + open + "/" + tag + close; ret += close;
// Show content of TextNode or CDATASection
if ( node.nodeType === 3 || node.nodeType === 4 ) {
ret += node.nodeValue;
}
return ret + open + "/" + tag + close;
}, },
functionArgs: function( fn ) {//function calls it internally, it's the arguments part of the function // function calls it internally, it's the arguments part of the function
functionArgs: function( fn ) {
var args, var args,
l = fn.length; l = fn.length;
@@ -1757,54 +1951,34 @@ QUnit.jsDump = (function() {
args = new Array(l); args = new Array(l);
while ( l-- ) { while ( l-- ) {
args[l] = String.fromCharCode(97+l);//97 is 'a' // 97 is 'a'
args[l] = String.fromCharCode(97+l);
} }
return " " + args.join( ", " ) + " "; return " " + args.join( ", " ) + " ";
}, },
key: quote, //object calls it internally, the key part of an item in a map // object calls it internally, the key part of an item in a map
functionCode: "[code]", //function calls it internally, it's the content of the function key: quote,
attribute: quote, //node calls it internally, it's an html attribute value // function calls it internally, it's the content of the function
functionCode: "[code]",
// node calls it internally, it's an html attribute value
attribute: quote,
string: quote, string: quote,
date: quote, date: quote,
regexp: literal, //regex regexp: literal,
number: literal, number: literal,
"boolean": literal "boolean": literal
}, },
DOMAttrs: { // if true, entities are escaped ( <, >, \t, space and \n )
//attributes to dump from nodes, name=>realName HTML: false,
id: "id", // indentation unit
name: "name", indentChar: " ",
"class": "className" // if true, items in a collection, are separated by a \n, else just a space.
}, multiline: true
HTML: false,//if true, entities are escaped ( <, >, \t, space and \n )
indentChar: " ",//indentation unit
multiline: true //if true, items in a collection, are separated by a \n, else just a space.
}; };
return jsDump; return jsDump;
}()); }());
// from Sizzle.js
function getText( elems ) {
var i, elem,
ret = "";
for ( i = 0; elems[i]; i++ ) {
elem = elems[i];
// Get the text from text nodes and CDATA nodes
if ( elem.nodeType === 3 || elem.nodeType === 4 ) {
ret += elem.nodeValue;
// Traverse everything else, except comment nodes
} else if ( elem.nodeType !== 8 ) {
ret += getText( elem.childNodes );
}
}
return ret;
}
// from jquery.js // from jquery.js
function inArray( elem, array ) { function inArray( elem, array ) {
if ( array.indexOf ) { if ( array.indexOf ) {
@@ -1835,13 +2009,14 @@ function inArray( elem, array ) {
* QUnit.diff( "the quick brown fox jumped over", "the quick fox jumps over" ) == "the quick <del>brown </del> fox <del>jumped </del><ins>jumps </ins> over" * QUnit.diff( "the quick brown fox jumped over", "the quick fox jumps over" ) == "the quick <del>brown </del> fox <del>jumped </del><ins>jumps </ins> over"
*/ */
QUnit.diff = (function() { QUnit.diff = (function() {
/*jshint eqeqeq:false, eqnull:true */
function diff( o, n ) { function diff( o, n ) {
var i, var i,
ns = {}, ns = {},
os = {}; os = {};
for ( i = 0; i < n.length; i++ ) { for ( i = 0; i < n.length; i++ ) {
if ( ns[ n[i] ] == null ) { if ( !hasOwn.call( ns, n[i] ) ) {
ns[ n[i] ] = { ns[ n[i] ] = {
rows: [], rows: [],
o: null o: null
@@ -1851,7 +2026,7 @@ QUnit.diff = (function() {
} }
for ( i = 0; i < o.length; i++ ) { for ( i = 0; i < o.length; i++ ) {
if ( os[ o[i] ] == null ) { if ( !hasOwn.call( os, o[i] ) ) {
os[ o[i] ] = { os[ o[i] ] = {
rows: [], rows: [],
n: null n: null
@@ -1864,7 +2039,7 @@ QUnit.diff = (function() {
if ( !hasOwn.call( ns, i ) ) { if ( !hasOwn.call( ns, i ) ) {
continue; continue;
} }
if ( ns[i].rows.length == 1 && typeof os[i] != "undefined" && os[i].rows.length == 1 ) { if ( ns[i].rows.length === 1 && hasOwn.call( os, i ) && os[i].rows.length === 1 ) {
n[ ns[i].rows[0] ] = { n[ ns[i].rows[0] ] = {
text: n[ ns[i].rows[0] ], text: n[ ns[i].rows[0] ],
row: os[i].rows[0] row: os[i].rows[0]
@@ -1970,7 +2145,7 @@ QUnit.diff = (function() {
// for CommonJS enviroments, export everything // for CommonJS enviroments, export everything
if ( typeof exports !== "undefined" ) { if ( typeof exports !== "undefined" ) {
extend(exports, QUnit); extend( exports, QUnit );
} }
// get at whatever the global object is, like window in browsers // get at whatever the global object is, like window in browsers

View File

@@ -1,18 +1,18 @@
/** vim: et:ts=4:sw=4:sts=4 /** vim: et:ts=4:sw=4:sts=4
* @license RequireJS 2.1.1 Copyright (c) 2010-2012, The Dojo Foundation All Rights Reserved. * @license RequireJS 2.1.5 Copyright (c) 2010-2012, The Dojo Foundation All Rights Reserved.
* Available via the MIT or new BSD license. * Available via the MIT or new BSD license.
* see: http://github.com/jrburke/requirejs for details * see: http://github.com/jrburke/requirejs for details
*/ */
//Not using strict: uneven strict support in browsers, #392, and causes //Not using strict: uneven strict support in browsers, #392, and causes
//problems with requirejs.exec()/transpiler plugins that may not be strict. //problems with requirejs.exec()/transpiler plugins that may not be strict.
/*jslint regexp: true, nomen: true, sloppy: true */ /*jslint regexp: true, nomen: true, sloppy: true */
/*global window, navigator, document, importScripts, jQuery, setTimeout, opera */ /*global window, navigator, document, importScripts, setTimeout, opera */
var requirejs, require, define; var requirejs, require, define;
(function (global) { (function (global) {
var req, s, head, baseElement, dataMain, src, var req, s, head, baseElement, dataMain, src,
interactiveScript, currentlyAddingScript, mainScript, subPath, interactiveScript, currentlyAddingScript, mainScript, subPath,
version = '2.1.1', version = '2.1.5',
commentRegExp = /(\/\*([\s\S]*?)\*\/|([^:]|^)\/\/(.*)$)/mg, commentRegExp = /(\/\*([\s\S]*?)\*\/|([^:]|^)\/\/(.*)$)/mg,
cjsRequireRegExp = /[^.]\s*require\s*\(\s*["']([^'"\s]+)["']\s*\)/g, cjsRequireRegExp = /[^.]\s*require\s*\(\s*["']([^'"\s]+)["']\s*\)/g,
jsSuffixRegExp = /\.js$/, jsSuffixRegExp = /\.js$/,
@@ -21,7 +21,6 @@ var requirejs, require, define;
ostring = op.toString, ostring = op.toString,
hasOwn = op.hasOwnProperty, hasOwn = op.hasOwnProperty,
ap = Array.prototype, ap = Array.prototype,
aps = ap.slice,
apsp = ap.splice, apsp = ap.splice,
isBrowser = !!(typeof window !== 'undefined' && navigator && document), isBrowser = !!(typeof window !== 'undefined' && navigator && document),
isWebWorker = !isBrowser && typeof importScripts !== 'undefined', isWebWorker = !isBrowser && typeof importScripts !== 'undefined',
@@ -81,6 +80,10 @@ var requirejs, require, define;
return hasOwn.call(obj, prop); return hasOwn.call(obj, prop);
} }
function getOwn(obj, prop) {
return hasProp(obj, prop) && obj[prop];
}
/** /**
* Cycles over properties in an object and calls a function for each * Cycles over properties in an object and calls a function for each
* property value. If the function returns a truthy value, then the * property value. If the function returns a truthy value, then the
@@ -89,7 +92,7 @@ var requirejs, require, define;
function eachProp(obj, func) { function eachProp(obj, func) {
var prop; var prop;
for (prop in obj) { for (prop in obj) {
if (obj.hasOwnProperty(prop)) { if (hasProp(obj, prop)) {
if (func(obj[prop], prop)) { if (func(obj[prop], prop)) {
break; break;
} }
@@ -188,15 +191,21 @@ var requirejs, require, define;
var inCheckLoaded, Module, context, handlers, var inCheckLoaded, Module, context, handlers,
checkLoadedTimeoutId, checkLoadedTimeoutId,
config = { config = {
//Defaults. Do not set a default for map
//config to speed up normalize(), which
//will run faster if there is no default.
waitSeconds: 7, waitSeconds: 7,
baseUrl: './', baseUrl: './',
paths: {}, paths: {},
pkgs: {}, pkgs: {},
shim: {}, shim: {},
map: {},
config: {} config: {}
}, },
registry = {}, registry = {},
//registry of just enabled modules, to speed
//cycle breaking code when lots of modules
//are registered, but not activated.
enabledRegistry = {},
undefEvents = {}, undefEvents = {},
defQueue = [], defQueue = [],
defined = {}, defined = {},
@@ -261,7 +270,7 @@ var requirejs, require, define;
//otherwise, assume it is a top-level require that will //otherwise, assume it is a top-level require that will
//be relative to baseUrl in the end. //be relative to baseUrl in the end.
if (baseName) { if (baseName) {
if (config.pkgs[baseName]) { if (getOwn(config.pkgs, baseName)) {
//If the baseName is a package name, then just treat it as one //If the baseName is a package name, then just treat it as one
//name to concat the name with. //name to concat the name with.
normalizedBaseParts = baseParts = [baseName]; normalizedBaseParts = baseParts = [baseName];
@@ -279,7 +288,7 @@ var requirejs, require, define;
//Some use of packages may use a . path to reference the //Some use of packages may use a . path to reference the
//'main' module name, so normalize for that. //'main' module name, so normalize for that.
pkgConfig = config.pkgs[(pkgName = name[0])]; pkgConfig = getOwn(config.pkgs, (pkgName = name[0]));
name = name.join('/'); name = name.join('/');
if (pkgConfig && name === pkgName + '/' + pkgConfig.main) { if (pkgConfig && name === pkgName + '/' + pkgConfig.main) {
name = pkgName; name = pkgName;
@@ -292,7 +301,7 @@ var requirejs, require, define;
} }
//Apply map config if available. //Apply map config if available.
if (applyMap && (baseParts || starMap) && map) { if (applyMap && map && (baseParts || starMap)) {
nameParts = name.split('/'); nameParts = name.split('/');
for (i = nameParts.length; i > 0; i -= 1) { for (i = nameParts.length; i > 0; i -= 1) {
@@ -302,12 +311,12 @@ var requirejs, require, define;
//Find the longest baseName segment match in the config. //Find the longest baseName segment match in the config.
//So, do joins on the biggest to smallest lengths of baseParts. //So, do joins on the biggest to smallest lengths of baseParts.
for (j = baseParts.length; j > 0; j -= 1) { for (j = baseParts.length; j > 0; j -= 1) {
mapValue = map[baseParts.slice(0, j).join('/')]; mapValue = getOwn(map, baseParts.slice(0, j).join('/'));
//baseName segment has config, find if it has one for //baseName segment has config, find if it has one for
//this name. //this name.
if (mapValue) { if (mapValue) {
mapValue = mapValue[nameSegment]; mapValue = getOwn(mapValue, nameSegment);
if (mapValue) { if (mapValue) {
//Match, update name to the new value. //Match, update name to the new value.
foundMap = mapValue; foundMap = mapValue;
@@ -325,8 +334,8 @@ var requirejs, require, define;
//Check for a star map match, but just hold on to it, //Check for a star map match, but just hold on to it,
//if there is a shorter segment match later in a matching //if there is a shorter segment match later in a matching
//config, then favor over this star map. //config, then favor over this star map.
if (!foundStarMap && starMap && starMap[nameSegment]) { if (!foundStarMap && starMap && getOwn(starMap, nameSegment)) {
foundStarMap = starMap[nameSegment]; foundStarMap = getOwn(starMap, nameSegment);
starI = i; starI = i;
} }
} }
@@ -358,7 +367,7 @@ var requirejs, require, define;
} }
function hasPathFallback(id) { function hasPathFallback(id) {
var pathConfig = config.paths[id]; var pathConfig = getOwn(config.paths, id);
if (pathConfig && isArray(pathConfig) && pathConfig.length > 1) { if (pathConfig && isArray(pathConfig) && pathConfig.length > 1) {
removeScript(id); removeScript(id);
//Pop off the first array value, since it failed, and //Pop off the first array value, since it failed, and
@@ -419,7 +428,7 @@ var requirejs, require, define;
if (prefix) { if (prefix) {
prefix = normalize(prefix, parentName, applyMap); prefix = normalize(prefix, parentName, applyMap);
pluginModule = defined[prefix]; pluginModule = getOwn(defined, prefix);
} }
//Account for relative paths if there is a base name. //Account for relative paths if there is a base name.
@@ -472,7 +481,7 @@ var requirejs, require, define;
function getModule(depMap) { function getModule(depMap) {
var id = depMap.id, var id = depMap.id,
mod = registry[id]; mod = getOwn(registry, id);
if (!mod) { if (!mod) {
mod = registry[id] = new context.Module(depMap); mod = registry[id] = new context.Module(depMap);
@@ -483,7 +492,7 @@ var requirejs, require, define;
function on(depMap, name, fn) { function on(depMap, name, fn) {
var id = depMap.id, var id = depMap.id,
mod = registry[id]; mod = getOwn(registry, id);
if (hasProp(defined, id) && if (hasProp(defined, id) &&
(!mod || mod.defineEmitComplete)) { (!mod || mod.defineEmitComplete)) {
@@ -503,7 +512,7 @@ var requirejs, require, define;
errback(err); errback(err);
} else { } else {
each(ids, function (id) { each(ids, function (id) {
var mod = registry[id]; var mod = getOwn(registry, id);
if (mod) { if (mod) {
//Set error on module, so it skips timeout checks. //Set error on module, so it skips timeout checks.
mod.error = err; mod.error = err;
@@ -562,7 +571,7 @@ var requirejs, require, define;
id: mod.map.id, id: mod.map.id,
uri: mod.map.url, uri: mod.map.url,
config: function () { config: function () {
return (config.config && config.config[mod.map.id]) || {}; return (config.config && getOwn(config.config, mod.map.id)) || {};
}, },
exports: defined[mod.map.id] exports: defined[mod.map.id]
}); });
@@ -573,6 +582,7 @@ var requirejs, require, define;
function cleanRegistry(id) { function cleanRegistry(id) {
//Clean up machinery used for waiting modules. //Clean up machinery used for waiting modules.
delete registry[id]; delete registry[id];
delete enabledRegistry[id];
} }
function breakCycle(mod, traced, processed) { function breakCycle(mod, traced, processed) {
@@ -584,14 +594,14 @@ var requirejs, require, define;
traced[id] = true; traced[id] = true;
each(mod.depMaps, function (depMap, i) { each(mod.depMaps, function (depMap, i) {
var depId = depMap.id, var depId = depMap.id,
dep = registry[depId]; dep = getOwn(registry, depId);
//Only force things that have not completed //Only force things that have not completed
//being defined, so still in the registry, //being defined, so still in the registry,
//and only if it has not been matched up //and only if it has not been matched up
//in the module already. //in the module already.
if (dep && !mod.depMatched[i] && !processed[depId]) { if (dep && !mod.depMatched[i] && !processed[depId]) {
if (traced[depId]) { if (getOwn(traced, depId)) {
mod.defineDep(i, defined[depId]); mod.defineDep(i, defined[depId]);
mod.check(); //pass false? mod.check(); //pass false?
} else { } else {
@@ -621,7 +631,7 @@ var requirejs, require, define;
inCheckLoaded = true; inCheckLoaded = true;
//Figure out the state of all the modules. //Figure out the state of all the modules.
eachProp(registry, function (mod) { eachProp(enabledRegistry, function (mod) {
map = mod.map; map = mod.map;
modId = map.id; modId = map.id;
@@ -691,9 +701,9 @@ var requirejs, require, define;
} }
Module = function (map) { Module = function (map) {
this.events = undefEvents[map.id] || {}; this.events = getOwn(undefEvents, map.id) || {};
this.map = map; this.map = map;
this.shim = config.shim[map.id]; this.shim = getOwn(config.shim, map.id);
this.depExports = []; this.depExports = [];
this.depMaps = []; this.depMaps = [];
this.depMatched = []; this.depMatched = [];
@@ -802,7 +812,7 @@ var requirejs, require, define;
}, },
/** /**
* Checks is the module is ready to define itself, and if so, * Checks if the module is ready to define itself, and if so,
* define it. * define it.
*/ */
check: function () { check: function () {
@@ -880,7 +890,7 @@ var requirejs, require, define;
} }
//Clean up //Clean up
delete registry[id]; cleanRegistry(id);
this.defined = true; this.defined = true;
} }
@@ -914,8 +924,7 @@ var requirejs, require, define;
name = this.map.name, name = this.map.name,
parentName = this.map.parentMap ? this.map.parentMap.name : null, parentName = this.map.parentMap ? this.map.parentMap.name : null,
localRequire = context.makeRequire(map.parentMap, { localRequire = context.makeRequire(map.parentMap, {
enableBuildCallback: true, enableBuildCallback: true
skipMap: true
}); });
//If current map is not normalized, wait for that //If current map is not normalized, wait for that
@@ -940,7 +949,7 @@ var requirejs, require, define;
}); });
})); }));
normalizedMod = registry[normalizedMap.id]; normalizedMod = getOwn(registry, normalizedMap.id);
if (normalizedMod) { if (normalizedMod) {
//Mark this as a dependency for this plugin, so it //Mark this as a dependency for this plugin, so it
//can be traced for cycles. //can be traced for cycles.
@@ -1005,11 +1014,19 @@ var requirejs, require, define;
//it. //it.
getModule(moduleMap); getModule(moduleMap);
//Transfer any config to this other module.
if (hasProp(config.config, id)) {
config.config[moduleName] = config.config[id];
}
try { try {
req.exec(text); req.exec(text);
} catch (e) { } catch (e) {
throw new Error('fromText eval for ' + moduleName + return onError(makeError('fromtexteval',
' failed: ' + e); 'fromText eval for ' + id +
' failed: ' + e,
e,
[id]));
} }
if (hasInteractive) { if (hasInteractive) {
@@ -1039,6 +1056,7 @@ var requirejs, require, define;
}, },
enable: function () { enable: function () {
enabledRegistry[this.map.id] = this;
this.enabled = true; this.enabled = true;
//Set flag mentioning that the module is enabling, //Set flag mentioning that the module is enabling,
@@ -1060,7 +1078,7 @@ var requirejs, require, define;
!this.skipMap); !this.skipMap);
this.depMaps[i] = depMap; this.depMaps[i] = depMap;
handler = handlers[depMap.id]; handler = getOwn(handlers, depMap.id);
if (handler) { if (handler) {
this.depExports[i] = handler(this); this.depExports[i] = handler(this);
@@ -1085,7 +1103,7 @@ var requirejs, require, define;
//Skip special modules like 'require', 'exports', 'module' //Skip special modules like 'require', 'exports', 'module'
//Also, don't call enable if it is already enabled, //Also, don't call enable if it is already enabled,
//important in circular dependency cases. //important in circular dependency cases.
if (!handlers[id] && mod && !mod.enabled) { if (!hasProp(handlers, id) && mod && !mod.enabled) {
context.enable(depMap, this); context.enable(depMap, this);
} }
})); }));
@@ -1093,7 +1111,7 @@ var requirejs, require, define;
//Enable each plugin that is used in //Enable each plugin that is used in
//a dependency //a dependency
eachProp(this.pluginMaps, bind(this, function (pluginMap) { eachProp(this.pluginMaps, bind(this, function (pluginMap) {
var mod = registry[pluginMap.id]; var mod = getOwn(registry, pluginMap.id);
if (mod && !mod.enabled) { if (mod && !mod.enabled) {
context.enable(pluginMap, this); context.enable(pluginMap, this);
} }
@@ -1126,7 +1144,10 @@ var requirejs, require, define;
}; };
function callGetModule(args) { function callGetModule(args) {
getModule(makeModuleMap(args[0], null, true)).init(args[1], args[2]); //Skip modules already defined.
if (!hasProp(defined, args[0])) {
getModule(makeModuleMap(args[0], null, true)).init(args[1], args[2]);
}
} }
function removeListener(node, func, name, ieName) { function removeListener(node, func, name, ieName) {
@@ -1195,6 +1216,7 @@ var requirejs, require, define;
Module: Module, Module: Module,
makeModuleMap: makeModuleMap, makeModuleMap: makeModuleMap,
nextTick: req.nextTick, nextTick: req.nextTick,
onError: onError,
/** /**
* Set a configuration for the context. * Set a configuration for the context.
@@ -1221,6 +1243,9 @@ var requirejs, require, define;
eachProp(cfg, function (value, prop) { eachProp(cfg, function (value, prop) {
if (objs[prop]) { if (objs[prop]) {
if (prop === 'map') { if (prop === 'map') {
if (!config.map) {
config.map = {};
}
mixin(config[prop], value, true, true); mixin(config[prop], value, true, true);
} else { } else {
mixin(config[prop], value, true); mixin(config[prop], value, true);
@@ -1239,7 +1264,7 @@ var requirejs, require, define;
deps: value deps: value
}; };
} }
if (value.exports && !value.exportsFn) { if ((value.exports || value.init) && !value.exportsFn) {
value.exportsFn = context.makeShimExports(value); value.exportsFn = context.makeShimExports(value);
} }
shim[id] = value; shim[id] = value;
@@ -1301,7 +1326,7 @@ var requirejs, require, define;
if (value.init) { if (value.init) {
ret = value.init.apply(global, arguments); ret = value.init.apply(global, arguments);
} }
return ret || getGlobal(value.exports); return ret || (value.exports && getGlobal(value.exports));
} }
return fn; return fn;
}, },
@@ -1325,14 +1350,14 @@ var requirejs, require, define;
//If require|exports|module are requested, get the //If require|exports|module are requested, get the
//value for them from the special handlers. Caveat: //value for them from the special handlers. Caveat:
//this only works while module is being defined. //this only works while module is being defined.
if (relMap && handlers[deps]) { if (relMap && hasProp(handlers, deps)) {
return handlers[deps](registry[relMap.id]); return handlers[deps](registry[relMap.id]);
} }
//Synchronous access to one module. If require.get is //Synchronous access to one module. If require.get is
//available (as in the Node adapter), prefer that. //available (as in the Node adapter), prefer that.
if (req.get) { if (req.get) {
return req.get(context, deps, relMap); return req.get(context, deps, relMap, localRequire);
} }
//Normalize module name, if it contains . or .. //Normalize module name, if it contains . or ..
@@ -1383,16 +1408,20 @@ var requirejs, require, define;
* plain URLs like nameToUrl. * plain URLs like nameToUrl.
*/ */
toUrl: function (moduleNamePlusExt) { toUrl: function (moduleNamePlusExt) {
var index = moduleNamePlusExt.lastIndexOf('.'), var ext,
ext = null; index = moduleNamePlusExt.lastIndexOf('.'),
segment = moduleNamePlusExt.split('/')[0],
isRelative = segment === '.' || segment === '..';
if (index !== -1) { //Have a file extension alias, and it is not the
//dots from a relative path.
if (index !== -1 && (!isRelative || index > 1)) {
ext = moduleNamePlusExt.substring(index, moduleNamePlusExt.length); ext = moduleNamePlusExt.substring(index, moduleNamePlusExt.length);
moduleNamePlusExt = moduleNamePlusExt.substring(0, index); moduleNamePlusExt = moduleNamePlusExt.substring(0, index);
} }
return context.nameToUrl(normalize(moduleNamePlusExt, return context.nameToUrl(normalize(moduleNamePlusExt,
relMap && relMap.id, true), ext); relMap && relMap.id, true), ext, true);
}, },
defined: function (id) { defined: function (id) {
@@ -1413,7 +1442,7 @@ var requirejs, require, define;
takeGlobalQueue(); takeGlobalQueue();
var map = makeModuleMap(id, relMap, true), var map = makeModuleMap(id, relMap, true),
mod = registry[id]; mod = getOwn(registry, id);
delete defined[id]; delete defined[id];
delete urlFetched[map.url]; delete urlFetched[map.url];
@@ -1437,11 +1466,12 @@ var requirejs, require, define;
/** /**
* Called to enable a module if it is still in the registry * Called to enable a module if it is still in the registry
* awaiting enablement. parent module is passed in for context, * awaiting enablement. A second arg, parent, the parent module,
* used by the optimizer. * is passed in for context, when this method is overriden by
* the optimizer. Not shown here to keep code compact.
*/ */
enable: function (depMap, parent) { enable: function (depMap) {
var mod = registry[depMap.id]; var mod = getOwn(registry, depMap.id);
if (mod) { if (mod) {
getModule(depMap).enable(); getModule(depMap).enable();
} }
@@ -1455,7 +1485,7 @@ var requirejs, require, define;
*/ */
completeLoad: function (moduleName) { completeLoad: function (moduleName) {
var found, args, mod, var found, args, mod,
shim = config.shim[moduleName] || {}, shim = getOwn(config.shim, moduleName) || {},
shExports = shim.exports; shExports = shim.exports;
takeGlobalQueue(); takeGlobalQueue();
@@ -1481,9 +1511,9 @@ var requirejs, require, define;
//Do this after the cycle of callGetModule in case the result //Do this after the cycle of callGetModule in case the result
//of those calls/init calls changes the registry. //of those calls/init calls changes the registry.
mod = registry[moduleName]; mod = getOwn(registry, moduleName);
if (!found && !defined[moduleName] && mod && !mod.inited) { if (!found && !hasProp(defined, moduleName) && mod && !mod.inited) {
if (config.enforceDefine && (!shExports || !getGlobal(shExports))) { if (config.enforceDefine && (!shExports || !getGlobal(shExports))) {
if (hasPathFallback(moduleName)) { if (hasPathFallback(moduleName)) {
return; return;
@@ -1510,7 +1540,7 @@ var requirejs, require, define;
* it is assumed to have already been normalized. This is an * it is assumed to have already been normalized. This is an
* internal API, not a public one. Use toUrl for the public API. * internal API, not a public one. Use toUrl for the public API.
*/ */
nameToUrl: function (moduleName, ext) { nameToUrl: function (moduleName, ext, skipExt) {
var paths, pkgs, pkg, pkgPath, syms, i, parentModule, url, var paths, pkgs, pkg, pkgPath, syms, i, parentModule, url,
parentPath; parentPath;
@@ -1534,8 +1564,8 @@ var requirejs, require, define;
//and work up from it. //and work up from it.
for (i = syms.length; i > 0; i -= 1) { for (i = syms.length; i > 0; i -= 1) {
parentModule = syms.slice(0, i).join('/'); parentModule = syms.slice(0, i).join('/');
pkg = pkgs[parentModule]; pkg = getOwn(pkgs, parentModule);
parentPath = paths[parentModule]; parentPath = getOwn(paths, parentModule);
if (parentPath) { if (parentPath) {
//If an array, it means there are a few choices, //If an array, it means there are a few choices,
//Choose the one that is desired //Choose the one that is desired
@@ -1559,7 +1589,7 @@ var requirejs, require, define;
//Join the path parts together, then figure out if baseUrl is needed. //Join the path parts together, then figure out if baseUrl is needed.
url = syms.join('/'); url = syms.join('/');
url += (ext || (/\?/.test(url) ? '' : '.js')); url += (ext || (/\?/.test(url) || skipExt ? '' : '.js'));
url = (url.charAt(0) === '/' || url.match(/^[\w\+\.\-]+:/) ? '' : config.baseUrl) + url; url = (url.charAt(0) === '/' || url.match(/^[\w\+\.\-]+:/) ? '' : config.baseUrl) + url;
} }
@@ -1660,7 +1690,7 @@ var requirejs, require, define;
contextName = config.context; contextName = config.context;
} }
context = contexts[contextName]; context = getOwn(contexts, contextName);
if (!context) { if (!context) {
context = contexts[contextName] = req.s.newContext(contextName); context = contexts[contextName] = req.s.newContext(contextName);
} }
@@ -1798,7 +1828,7 @@ var requirejs, require, define;
node.attachEvent('onreadystatechange', context.onScriptLoad); node.attachEvent('onreadystatechange', context.onScriptLoad);
//It would be great to add an error handler here to catch //It would be great to add an error handler here to catch
//404s in IE9+. However, onreadystatechange will fire before //404s in IE9+. However, onreadystatechange will fire before
//the error handler, so that does not help. If addEvenListener //the error handler, so that does not help. If addEventListener
//is used, then IE will fire error before load, but we cannot //is used, then IE will fire error before load, but we cannot
//use that pathway given the connect.microsoft.com issue //use that pathway given the connect.microsoft.com issue
//mentioned above about not doing the 'script execute, //mentioned above about not doing the 'script execute,
@@ -1827,16 +1857,24 @@ var requirejs, require, define;
return node; return node;
} else if (isWebWorker) { } else if (isWebWorker) {
//In a web worker, use importScripts. This is not a very try {
//efficient use of importScripts, importScripts will block until //In a web worker, use importScripts. This is not a very
//its script is downloaded and evaluated. However, if web workers //efficient use of importScripts, importScripts will block until
//are in play, the expectation that a build has been done so that //its script is downloaded and evaluated. However, if web workers
//only one script needs to be loaded anyway. This may need to be //are in play, the expectation that a build has been done so that
//reevaluated if other use cases become common. //only one script needs to be loaded anyway. This may need to be
importScripts(url); //reevaluated if other use cases become common.
importScripts(url);
//Account for anonymous modules //Account for anonymous modules
context.completeLoad(moduleName); context.completeLoad(moduleName);
} catch (e) {
context.onError(makeError('importscripts',
'importScripts failed for ' +
moduleName + ' at ' + url,
e,
[moduleName]));
}
} }
}; };

View File

@@ -1,4 +1,4 @@
Copyright (c) 2009-2012 Jeremy Ashkenas, DocumentCloud Copyright (c) 2009-2013 Jeremy Ashkenas, DocumentCloud
Permission is hereby granted, free of charge, to any person Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation obtaining a copy of this software and associated documentation

View File

@@ -55,18 +55,16 @@ $(document).ready(function() {
test("compact", function() { test("compact", function() {
equal(_.compact([0, 1, false, 2, false, 3]).length, 3, 'can trim out all falsy values'); equal(_.compact([0, 1, false, 2, false, 3]).length, 3, 'can trim out all falsy values');
var result = (function(){ return _(arguments).compact().length; })(0, 1, false, 2, false, 3); var result = (function(){ return _.compact(arguments).length; })(0, 1, false, 2, false, 3);
equal(result, 3, 'works on an arguments object'); equal(result, 3, 'works on an arguments object');
}); });
test("flatten", function() { test("flatten", function() {
if (window.JSON) { var list = [1, [2], [3, [[[4]]]]];
var list = [1, [2], [3, [[[4]]]]]; deepEqual(_.flatten(list), [1,2,3,4], 'can flatten nested arrays');
equal(JSON.stringify(_.flatten(list)), '[1,2,3,4]', 'can flatten nested arrays'); deepEqual(_.flatten(list, true), [1,2,3,[[[4]]]], 'can shallowly flatten nested arrays');
equal(JSON.stringify(_.flatten(list, true)), '[1,2,3,[[[4]]]]', 'can shallowly flatten nested arrays'); var result = (function(){ return _.flatten(arguments); })(1, [2], [3, [[[4]]]]);
var result = (function(){ return _.flatten(arguments); })(1, [2], [3, [[[4]]]]); deepEqual(result, [1,2,3,4], 'works on an arguments object');
equal(JSON.stringify(result), '[1,2,3,4]', 'works on an arguments object');
}
}); });
test("without", function() { test("without", function() {
@@ -184,7 +182,7 @@ $(document).ready(function() {
equal(_.indexOf(null, 2), -1, 'handles nulls properly'); equal(_.indexOf(null, 2), -1, 'handles nulls properly');
numbers = [1, 2, 3, 1, 2, 3, 1, 2, 3]; numbers = [1, 2, 3, 1, 2, 3, 1, 2, 3];
index = _.lastIndexOf(numbers, 2, 2); var index = _.lastIndexOf(numbers, 2, 2);
equal(index, 1, 'supports the fromIndex argument'); equal(index, 1, 'supports the fromIndex argument');
}); });

View File

@@ -22,7 +22,7 @@ $(document).ready(function() {
equal(answers.join(", "), 'one, two, three', 'iterating over objects works, and ignores the object prototype.'); equal(answers.join(", "), 'one, two, three', 'iterating over objects works, and ignores the object prototype.');
delete obj.constructor.prototype.four; delete obj.constructor.prototype.four;
answer = null; var answer = null;
_.each([1, 2, 3], function(num, index, arr){ if (_.include(arr, num)) answer = true; }); _.each([1, 2, 3], function(num, index, arr){ if (_.include(arr, num)) answer = true; });
ok(answer, 'can reference the original collection from inside the iterator'); ok(answer, 'can reference the original collection from inside the iterator');
@@ -260,6 +260,14 @@ $(document).ready(function() {
equal(result[0].a, 1); equal(result[0].a, 1);
}); });
test('findWhere', function() {
var list = [{a: 1, b: 2}, {a: 2, b: 2}, {a: 1, b: 3}, {a: 1, b: 4}, {a: 2, b: 4}];
var result = _.findWhere(list, {a: 1});
deepEqual(result, {a: 1, b: 2});
result = _.findWhere(list, {b: 4});
deepEqual(result, {a: 1, b: 4});
});
test('max', function() { test('max', function() {
equal(3, _.max([1, 2, 3]), 'can perform a regular Math.max'); equal(3, _.max([1, 2, 3]), 'can perform a regular Math.max');
@@ -268,6 +276,7 @@ $(document).ready(function() {
equal(-Infinity, _.max({}), 'Maximum value of an empty object'); equal(-Infinity, _.max({}), 'Maximum value of an empty object');
equal(-Infinity, _.max([]), 'Maximum value of an empty array'); equal(-Infinity, _.max([]), 'Maximum value of an empty array');
equal(_.max({'a': 'a'}), -Infinity, 'Maximum value of a non-numeric collection');
equal(299999, _.max(_.range(1,300000)), "Maximum value of a too-big array"); equal(299999, _.max(_.range(1,300000)), "Maximum value of a too-big array");
}); });
@@ -280,6 +289,7 @@ $(document).ready(function() {
equal(Infinity, _.min({}), 'Minimum value of an empty object'); equal(Infinity, _.min({}), 'Minimum value of an empty object');
equal(Infinity, _.min([]), 'Minimum value of an empty array'); equal(Infinity, _.min([]), 'Minimum value of an empty array');
equal(_.min({'a': 'a'}), Infinity, 'Minimum value of a non-numeric collection');
var now = new Date(9999999999); var now = new Date(9999999999);
var then = new Date(0); var then = new Date(0);
@@ -346,6 +356,11 @@ $(document).ready(function() {
var array = [{}]; var array = [{}];
_.groupBy(array, function(value, index, obj){ ok(obj === array); }); _.groupBy(array, function(value, index, obj){ ok(obj === array); });
var array = [1, 2, 1, 2, 3];
var grouped = _.groupBy(array);
equal(grouped['1'].length, 2);
equal(grouped['3'].length, 1);
}); });
test('countBy', function() { test('countBy', function() {
@@ -370,6 +385,11 @@ $(document).ready(function() {
var array = [{}]; var array = [{}];
_.countBy(array, function(value, index, obj){ ok(obj === array); }); _.countBy(array, function(value, index, obj){ ok(obj === array); });
var array = [1, 2, 1, 2, 3];
var grouped = _.countBy(array);
equal(grouped['1'], 2);
equal(grouped['3'], 1);
}); });
test('sortedIndex', function() { test('sortedIndex', function() {
@@ -406,6 +426,13 @@ $(document).ready(function() {
var numbers = _.toArray({one : 1, two : 2, three : 3}); var numbers = _.toArray({one : 1, two : 2, three : 3});
equal(numbers.join(', '), '1, 2, 3', 'object flattened into array'); equal(numbers.join(', '), '1, 2, 3', 'object flattened into array');
// test in IE < 9
try {
var actual = _.toArray(document.childNodes);
} catch(ex) { }
ok(_.isArray(actual), 'should not throw converting a node list');
}); });
test('size', function() { test('size', function() {

View File

@@ -18,10 +18,10 @@ $(document).ready(function() {
func = _.bind(func, this, 'hello'); func = _.bind(func, this, 'hello');
equal(func('moe'), 'hello: moe', 'the function was partially applied in advance'); equal(func('moe'), 'hello: moe', 'the function was partially applied in advance');
var func = _.bind(func, this, 'curly'); func = _.bind(func, this, 'curly');
equal(func(), 'hello: curly', 'the function was completely applied in advance'); equal(func(), 'hello: curly', 'the function was completely applied in advance');
var func = function(salutation, firstname, lastname) { return salutation + ': ' + firstname + ' ' + lastname; }; func = function(salutation, firstname, lastname) { return salutation + ': ' + firstname + ' ' + lastname; };
func = _.bind(func, this, 'hello', 'moe', 'curly'); func = _.bind(func, this, 'hello', 'moe', 'curly');
equal(func(), 'hello: moe curly', 'the function was partially applied in advance and can accept multiple arguments'); equal(func(), 'hello: moe curly', 'the function was partially applied in advance and can accept multiple arguments');
@@ -34,10 +34,17 @@ $(document).ready(function() {
// To test this with a modern browser, set underscore's nativeBind to undefined // To test this with a modern browser, set underscore's nativeBind to undefined
var F = function () { return this; }; var F = function () { return this; };
var Boundf = _.bind(F, {hello: "moe curly"}); var Boundf = _.bind(F, {hello: "moe curly"});
equal(new Boundf().hello, undefined, "function should not be bound to the context, to comply with ECMAScript 5");
equal(Boundf().hello, "moe curly", "When called without the new operator, it's OK to be bound to the context"); equal(Boundf().hello, "moe curly", "When called without the new operator, it's OK to be bound to the context");
}); });
test("partial", function() {
var obj = {name: 'moe'};
var func = function() { return this.name + ' ' + _.toArray(arguments).join(' '); };
obj.func = _.partial(func, 'a', 'b');
equal(obj.func('c', 'd'), 'moe a b c d', 'can partially apply');
});
test("bindAll", function() { test("bindAll", function() {
var curly = {name : 'curly'}, moe = { var curly = {name : 'curly'}, moe = {
name : 'moe', name : 'moe',
@@ -93,118 +100,117 @@ $(document).ready(function() {
asyncTest("throttle", 2, function() { asyncTest("throttle", 2, function() {
var counter = 0; var counter = 0;
var incr = function(){ counter++; }; var incr = function(){ counter++; };
var throttledIncr = _.throttle(incr, 100); var throttledIncr = _.throttle(incr, 32);
throttledIncr(); throttledIncr(); throttledIncr(); throttledIncr(); throttledIncr();
setTimeout(throttledIncr, 70);
setTimeout(throttledIncr, 120); equal(counter, 1, "incr was called immediately");
setTimeout(throttledIncr, 140); _.delay(function(){ equal(counter, 2, "incr was throttled"); start(); }, 64);
setTimeout(throttledIncr, 190);
setTimeout(throttledIncr, 220);
setTimeout(throttledIncr, 240);
_.delay(function(){ equal(counter, 1, "incr was called immediately"); }, 30);
_.delay(function(){ equal(counter, 4, "incr was throttled"); start(); }, 400);
}); });
asyncTest("throttle arguments", 2, function() { asyncTest("throttle arguments", 2, function() {
var value = 0; var value = 0;
var update = function(val){ value = val; }; var update = function(val){ value = val; };
var throttledUpdate = _.throttle(update, 100); var throttledUpdate = _.throttle(update, 32);
throttledUpdate(1); throttledUpdate(2); throttledUpdate(3); throttledUpdate(1); throttledUpdate(2);
setTimeout(function(){ throttledUpdate(4); }, 120); _.delay(function(){ throttledUpdate(3); }, 64);
setTimeout(function(){ throttledUpdate(5); }, 140); equal(value, 1, "updated to latest value");
setTimeout(function(){ throttledUpdate(6); }, 250); _.delay(function(){ equal(value, 3, "updated to latest value"); start(); }, 96);
_.delay(function(){ equal(value, 1, "updated to latest value"); }, 40);
_.delay(function(){ equal(value, 6, "updated to latest value"); start(); }, 400);
}); });
asyncTest("throttle once", 2, function() { asyncTest("throttle once", 2, function() {
var counter = 0; var counter = 0;
var incr = function(){ return ++counter; }; var incr = function(){ return ++counter; };
var throttledIncr = _.throttle(incr, 100); var throttledIncr = _.throttle(incr, 32);
var result = throttledIncr(); var result = throttledIncr();
_.delay(function(){ _.delay(function(){
equal(result, 1, "throttled functions return their value"); equal(result, 1, "throttled functions return their value");
equal(counter, 1, "incr was called once"); start(); equal(counter, 1, "incr was called once"); start();
}, 220); }, 64);
}); });
asyncTest("throttle twice", 1, function() { asyncTest("throttle twice", 1, function() {
var counter = 0; var counter = 0;
var incr = function(){ counter++; }; var incr = function(){ counter++; };
var throttledIncr = _.throttle(incr, 100); var throttledIncr = _.throttle(incr, 32);
throttledIncr(); throttledIncr(); throttledIncr(); throttledIncr();
_.delay(function(){ equal(counter, 2, "incr was called twice"); start(); }, 220); _.delay(function(){ equal(counter, 2, "incr was called twice"); start(); }, 64);
}); });
asyncTest("throttle repeatedly with results", 9, function() { asyncTest("throttle repeatedly with results", 6, function() {
var counter = 0; var counter = 0;
var incr = function(){ return ++counter; }; var incr = function(){ return ++counter; };
var throttledIncr = _.throttle(incr, 100); var throttledIncr = _.throttle(incr, 64);
var results = []; var results = [];
var saveResult = function() { results.push(throttledIncr()); }; var saveResult = function() { results.push(throttledIncr()); };
saveResult(); saveResult(); saveResult(); saveResult(); saveResult();
setTimeout(saveResult, 70); _.delay(saveResult, 32);
setTimeout(saveResult, 120); _.delay(saveResult, 80);
setTimeout(saveResult, 140); _.delay(saveResult, 96);
setTimeout(saveResult, 190); _.delay(saveResult, 144);
setTimeout(saveResult, 240);
setTimeout(saveResult, 260);
_.delay(function() { _.delay(function() {
equal(results[0], 1, "incr was called once"); equal(results[0], 1, "incr was called once");
equal(results[1], 1, "incr was throttled"); equal(results[1], 1, "incr was throttled");
equal(results[2], 1, "incr was throttled"); equal(results[2], 1, "incr was throttled");
equal(results[3], 1, "incr was throttled"); equal(results[3], 2, "incr was called twice");
equal(results[4], 2, "incr was called twice"); equal(results[4], 2, "incr was throttled");
equal(results[5], 2, "incr was throttled"); equal(results[5], 3, "incr was called trailing");
equal(results[6], 2, "incr was throttled");
equal(results[7], 3, "incr was called thrice");
equal(results[8], 3, "incr was throttled");
start(); start();
}, 400); }, 192);
});
asyncTest("throttle triggers trailing call when invoked repeatedly", 2, function() {
var counter = 0;
var limit = 48;
var incr = function(){ counter++; };
var throttledIncr = _.throttle(incr, 32);
var stamp = new Date;
while ((new Date - stamp) < limit) {
throttledIncr();
}
var lastCount = counter;
ok(counter > 1);
_.delay(function() {
ok(counter > lastCount);
start();
}, 96);
}); });
asyncTest("debounce", 1, function() { asyncTest("debounce", 1, function() {
var counter = 0; var counter = 0;
var incr = function(){ counter++; }; var incr = function(){ counter++; };
var debouncedIncr = _.debounce(incr, 50); var debouncedIncr = _.debounce(incr, 32);
debouncedIncr(); debouncedIncr(); debouncedIncr(); debouncedIncr(); debouncedIncr();
setTimeout(debouncedIncr, 30); _.delay(debouncedIncr, 16);
setTimeout(debouncedIncr, 60); _.delay(function(){ equal(counter, 1, "incr was debounced"); start(); }, 96);
setTimeout(debouncedIncr, 90);
setTimeout(debouncedIncr, 120);
setTimeout(debouncedIncr, 150);
_.delay(function(){ equal(counter, 1, "incr was debounced"); start(); }, 220);
}); });
asyncTest("debounce asap", 5, function() { asyncTest("debounce asap", 4, function() {
var a, b, c; var a, b;
var counter = 0; var counter = 0;
var incr = function(){ return ++counter; }; var incr = function(){ return ++counter; };
var debouncedIncr = _.debounce(incr, 50, true); var debouncedIncr = _.debounce(incr, 64, true);
a = debouncedIncr(); a = debouncedIncr();
b = debouncedIncr(); b = debouncedIncr();
c = debouncedIncr();
equal(a, 1); equal(a, 1);
equal(b, 1); equal(b, 1);
equal(c, 1);
equal(counter, 1, 'incr was called immediately'); equal(counter, 1, 'incr was called immediately');
setTimeout(debouncedIncr, 30); _.delay(debouncedIncr, 16);
setTimeout(debouncedIncr, 60); _.delay(debouncedIncr, 32);
setTimeout(debouncedIncr, 90); _.delay(debouncedIncr, 48);
setTimeout(debouncedIncr, 120); _.delay(function(){ equal(counter, 1, "incr was debounced"); start(); }, 128);
setTimeout(debouncedIncr, 150);
_.delay(function(){ equal(counter, 1, "incr was debounced"); start(); }, 220);
}); });
asyncTest("debounce asap recursively", 2, function() { asyncTest("debounce asap recursively", 2, function() {
var counter = 0; var counter = 0;
var debouncedIncr = _.debounce(function(){ var debouncedIncr = _.debounce(function(){
counter++; counter++;
if (counter < 5) debouncedIncr(); if (counter < 10) debouncedIncr();
}, 50, true); }, 32, true);
debouncedIncr(); debouncedIncr();
equal(counter, 1, 'incr was called immediately'); equal(counter, 1, "incr was called immediately");
_.delay(function(){ equal(counter, 1, "incr was debounced"); start(); }, 70); _.delay(function(){ equal(counter, 1, "incr was debounced"); start(); }, 96);
}); });
test("once", function() { test("once", function() {

View File

@@ -53,6 +53,13 @@ $(document).ready(function() {
ok(_.isEqual(result, {x:2, a:'b'}), 'extending from multiple source objects last property trumps'); ok(_.isEqual(result, {x:2, a:'b'}), 'extending from multiple source objects last property trumps');
result = _.extend({}, {a: void 0, b: null}); result = _.extend({}, {a: void 0, b: null});
equal(_.keys(result).join(''), 'ab', 'extend does not copy undefined values'); equal(_.keys(result).join(''), 'ab', 'extend does not copy undefined values');
try {
result = {};
_.extend(result, null, undefined, {a:1});
} catch(ex) {}
equal(result.a, 1, 'should not error on `null` or `undefined` sources');
}); });
test("pick", function() { test("pick", function() {
@@ -96,6 +103,13 @@ $(document).ready(function() {
equal(options.empty, "", 'value exists'); equal(options.empty, "", 'value exists');
ok(_.isNaN(options.nan), "NaN isn't overridden"); ok(_.isNaN(options.nan), "NaN isn't overridden");
equal(options.word, "word", 'new value is added, first one wins'); equal(options.word, "word", 'new value is added, first one wins');
try {
options = {};
_.defaults(options, null, undefined, {a:1});
} catch(ex) {}
equal(options.a, 1, 'should not error on `null` or `undefined` sources');
}); });
test("clone", function() { test("clone", function() {
@@ -337,16 +351,10 @@ $(document).ready(function() {
// Chaining. // Chaining.
ok(!_.isEqual(_({x: 1, y: undefined}).chain(), _({x: 1, z: 2}).chain()), 'Chained objects containing different values are not equal'); ok(!_.isEqual(_({x: 1, y: undefined}).chain(), _({x: 1, z: 2}).chain()), 'Chained objects containing different values are not equal');
equal(_({x: 1, y: 2}).chain().isEqual(_({x: 1, y: 2}).chain()).value(), true, '`isEqual` can be chained');
// Custom `isEqual` methods. a = _({x: 1, y: 2}).chain();
var isEqualObj = {isEqual: function (o) { return o.isEqual == this.isEqual; }, unique: {}}; b = _({x: 1, y: 2}).chain();
var isEqualObjClone = {isEqual: isEqualObj.isEqual, unique: {}}; equal(_.isEqual(a.isEqual(b), _(true)), true, '`isEqual` can be chained');
ok(_.isEqual(isEqualObj, isEqualObjClone), 'Both objects implement identical `isEqual` methods');
ok(_.isEqual(isEqualObjClone, isEqualObj), 'Commutative equality is implemented for objects with custom `isEqual` methods');
ok(!_.isEqual(isEqualObj, {}), 'Objects that do not implement equivalent `isEqual` methods are not equal');
ok(!_.isEqual({}, isEqualObj), 'Commutative equality is implemented for objects with different `isEqual` methods');
// Objects from another frame. // Objects from another frame.
ok(_.isEqual({}, iObject)); ok(_.isEqual({}, iObject));
@@ -547,4 +555,16 @@ $(document).ready(function() {
value(); value();
ok(returned == 6 && intercepted == 6, 'can use tapped objects in a chain'); ok(returned == 6 && intercepted == 6, 'can use tapped objects in a chain');
}); });
test("has", function () {
var obj = {foo: "bar", func: function () {} };
ok (_.has(obj, "foo"), "has() checks that the object has a property.");
ok (_.has(obj, "baz") == false, "has() returns false if the object doesn't have the property.");
ok (_.has(obj, "func"), "has() works for functions too.");
obj.hasOwnProperty = null;
ok (_.has(obj, "foo"), "has() works even when the hasOwnProperty method is deleted.");
var child = {};
child.prototype = obj;
ok (_.has(child, "foo") == false, "has() does not check the prototype chain for a property.")
});
}); });

View File

@@ -25,6 +25,20 @@ $(document).ready(function() {
equal(_.identity(moe), moe, 'moe is the same as his identity'); equal(_.identity(moe), moe, 'moe is the same as his identity');
}); });
test("random", function() {
var array = _.range(1000);
var min = Math.pow(2, 31);
var max = Math.pow(2, 62);
ok(_.every(array, function() {
return _.random(min, max) >= min;
}), "should produce a random number greater than or equal to the minimum number");
ok(_.some(array, function() {
return _.random(Number.MAX_VALUE) > 0;
}), "should produce a random number when passed `Number.MAX_VALUE`");
});
test("uniqueId", function() { test("uniqueId", function() {
var ids = [], i = 0; var ids = [], i = 0;
while(i++ < 100) ids.push(_.uniqueId()); while(i++ < 100) ids.push(_.uniqueId());
@@ -37,8 +51,10 @@ $(document).ready(function() {
ok(_.isEqual(vals, [0,1,2]), "is 0 indexed"); ok(_.isEqual(vals, [0,1,2]), "is 0 indexed");
// //
vals = []; vals = [];
_(3).times(function (i) { vals.push(i); }); _(3).times(function(i) { vals.push(i); });
ok(_.isEqual(vals, [0,1,2]), "works as a wrapper"); ok(_.isEqual(vals, [0,1,2]), "works as a wrapper");
// collects return values
ok(_.isEqual([0, 1, 2], _.times(3, function(i) { return i; })), "collects return values");
}); });
test("mixin", function() { test("mixin", function() {
@@ -80,7 +96,7 @@ $(document).ready(function() {
equal(escapeTemplate({a: true}), 'checked="checked"', 'can handle slash escapes in interpolations.'); equal(escapeTemplate({a: true}), 'checked="checked"', 'can handle slash escapes in interpolations.');
var fancyTemplate = _.template("<ul><% \ var fancyTemplate = _.template("<ul><% \
for (key in people) { \ for (var key in people) { \
%><li><%= people[key] %></li><% } %></ul>"); %><li><%= people[key] %></li><% } %></ul>");
result = fancyTemplate({people : {moe : "Moe", larry : "Larry", curly : "Curly"}}); result = fancyTemplate({people : {moe : "Moe", larry : "Larry", curly : "Curly"}});
equal(result, "<ul><li>Moe</li><li>Larry</li><li>Curly</li></ul>", 'can run arbitrary javascript in templates'); equal(result, "<ul><li>Moe</li><li>Larry</li><li>Curly</li></ul>", 'can run arbitrary javascript in templates');
@@ -135,7 +151,7 @@ $(document).ready(function() {
interpolate : /\{\{=([\s\S]+?)\}\}/g interpolate : /\{\{=([\s\S]+?)\}\}/g
}; };
var custom = _.template("<ul>{{ for (key in people) { }}<li>{{= people[key] }}</li>{{ } }}</ul>"); var custom = _.template("<ul>{{ for (var key in people) { }}<li>{{= people[key] }}</li>{{ } }}</ul>");
result = custom({people : {moe : "Moe", larry : "Larry", curly : "Curly"}}); result = custom({people : {moe : "Moe", larry : "Larry", curly : "Curly"}});
equal(result, "<ul><li>Moe</li><li>Larry</li><li>Curly</li></ul>", 'can run arbitrary javascript in templates'); equal(result, "<ul><li>Moe</li><li>Larry</li><li>Curly</li></ul>", 'can run arbitrary javascript in templates');
@@ -150,7 +166,7 @@ $(document).ready(function() {
interpolate : /<\?=([\s\S]+?)\?>/g interpolate : /<\?=([\s\S]+?)\?>/g
}; };
var customWithSpecialChars = _.template("<ul><? for (key in people) { ?><li><?= people[key] ?></li><? } ?></ul>"); var customWithSpecialChars = _.template("<ul><? for (var key in people) { ?><li><?= people[key] ?></li><? } ?></ul>");
result = customWithSpecialChars({people : {moe : "Moe", larry : "Larry", curly : "Curly"}}); result = customWithSpecialChars({people : {moe : "Moe", larry : "Larry", curly : "Curly"}});
equal(result, "<ul><li>Moe</li><li>Larry</li><li>Curly</li></ul>", 'can run arbitrary javascript in templates'); equal(result, "<ul><li>Moe</li><li>Larry</li><li>Curly</li></ul>", 'can run arbitrary javascript in templates');
@@ -173,10 +189,11 @@ $(document).ready(function() {
test('_.template provides the generated function source, when a SyntaxError occurs', function() { test('_.template provides the generated function source, when a SyntaxError occurs', function() {
try { try {
_.template('<b><%= if %></b>'); _.template('<b><%= if x %></b>');
} catch (e) { } catch (ex) {
ok(e.source.indexOf('( if )') > 0); var source = ex.source;
} }
ok(/__p/.test(source));
}); });
test('_.template handles \\u2028 & \\u2029', function() { test('_.template handles \\u2028 & \\u2029', function() {

File diff suppressed because one or more lines are too long

View File

@@ -1,6 +1,6 @@
// Underscore.js 1.4.2 // Underscore.js 1.4.4
// http://underscorejs.org // http://underscorejs.org
// (c) 2009-2012 Jeremy Ashkenas, DocumentCloud Inc. // (c) 2009-2013 Jeremy Ashkenas, DocumentCloud Inc.
// Underscore may be freely distributed under the MIT license. // Underscore may be freely distributed under the MIT license.
(function() { (function() {
@@ -24,7 +24,6 @@
var push = ArrayProto.push, var push = ArrayProto.push,
slice = ArrayProto.slice, slice = ArrayProto.slice,
concat = ArrayProto.concat, concat = ArrayProto.concat,
unshift = ArrayProto.unshift,
toString = ObjProto.toString, toString = ObjProto.toString,
hasOwnProperty = ObjProto.hasOwnProperty; hasOwnProperty = ObjProto.hasOwnProperty;
@@ -61,11 +60,11 @@
} }
exports._ = _; exports._ = _;
} else { } else {
root['_'] = _; root._ = _;
} }
// Current version. // Current version.
_.VERSION = '1.4.2'; _.VERSION = '1.4.4';
// Collection Functions // Collection Functions
// -------------------- // --------------------
@@ -102,6 +101,8 @@
return results; return results;
}; };
var reduceError = 'Reduce of empty array with no initial value';
// **Reduce** builds up a single result from a list of values, aka `inject`, // **Reduce** builds up a single result from a list of values, aka `inject`,
// or `foldl`. Delegates to **ECMAScript 5**'s native `reduce` if available. // or `foldl`. Delegates to **ECMAScript 5**'s native `reduce` if available.
_.reduce = _.foldl = _.inject = function(obj, iterator, memo, context) { _.reduce = _.foldl = _.inject = function(obj, iterator, memo, context) {
@@ -119,7 +120,7 @@
memo = iterator.call(context, memo, value, index, list); memo = iterator.call(context, memo, value, index, list);
} }
}); });
if (!initial) throw new TypeError('Reduce of empty array with no initial value'); if (!initial) throw new TypeError(reduceError);
return memo; return memo;
}; };
@@ -130,7 +131,7 @@
if (obj == null) obj = []; if (obj == null) obj = [];
if (nativeReduceRight && obj.reduceRight === nativeReduceRight) { if (nativeReduceRight && obj.reduceRight === nativeReduceRight) {
if (context) iterator = _.bind(iterator, context); if (context) iterator = _.bind(iterator, context);
return arguments.length > 2 ? obj.reduceRight(iterator, memo) : obj.reduceRight(iterator); return initial ? obj.reduceRight(iterator, memo) : obj.reduceRight(iterator);
} }
var length = obj.length; var length = obj.length;
if (length !== +length) { if (length !== +length) {
@@ -146,7 +147,7 @@
memo = iterator.call(context, memo, obj[index], index, list); memo = iterator.call(context, memo, obj[index], index, list);
} }
}); });
if (!initial) throw new TypeError('Reduce of empty array with no initial value'); if (!initial) throw new TypeError(reduceError);
return memo; return memo;
}; };
@@ -223,8 +224,9 @@
// Invoke a method (with arguments) on every item in a collection. // Invoke a method (with arguments) on every item in a collection.
_.invoke = function(obj, method) { _.invoke = function(obj, method) {
var args = slice.call(arguments, 2); var args = slice.call(arguments, 2);
var isFunc = _.isFunction(method);
return _.map(obj, function(value) { return _.map(obj, function(value) {
return (_.isFunction(method) ? method : value[method]).apply(value, args); return (isFunc ? method : value[method]).apply(value, args);
}); });
}; };
@@ -234,10 +236,10 @@
}; };
// Convenience version of a common use case of `filter`: selecting only objects // Convenience version of a common use case of `filter`: selecting only objects
// with specific `key:value` pairs. // containing specific `key:value` pairs.
_.where = function(obj, attrs) { _.where = function(obj, attrs, first) {
if (_.isEmpty(attrs)) return []; if (_.isEmpty(attrs)) return first ? null : [];
return _.filter(obj, function(value) { return _[first ? 'find' : 'filter'](obj, function(value) {
for (var key in attrs) { for (var key in attrs) {
if (attrs[key] !== value[key]) return false; if (attrs[key] !== value[key]) return false;
} }
@@ -245,6 +247,12 @@
}); });
}; };
// Convenience version of a common use case of `find`: getting the first object
// containing specific `key:value` pairs.
_.findWhere = function(obj, attrs) {
return _.where(obj, attrs, true);
};
// Return the maximum element or (element-based computation). // Return the maximum element or (element-based computation).
// Can't optimize arrays of integers longer than 65,535 elements. // Can't optimize arrays of integers longer than 65,535 elements.
// See: https://bugs.webkit.org/show_bug.cgi?id=80797 // See: https://bugs.webkit.org/show_bug.cgi?id=80797
@@ -253,7 +261,7 @@
return Math.max.apply(Math, obj); return Math.max.apply(Math, obj);
} }
if (!iterator && _.isEmpty(obj)) return -Infinity; if (!iterator && _.isEmpty(obj)) return -Infinity;
var result = {computed : -Infinity}; var result = {computed : -Infinity, value: -Infinity};
each(obj, function(value, index, list) { each(obj, function(value, index, list) {
var computed = iterator ? iterator.call(context, value, index, list) : value; var computed = iterator ? iterator.call(context, value, index, list) : value;
computed >= result.computed && (result = {value : value, computed : computed}); computed >= result.computed && (result = {value : value, computed : computed});
@@ -267,7 +275,7 @@
return Math.min.apply(Math, obj); return Math.min.apply(Math, obj);
} }
if (!iterator && _.isEmpty(obj)) return Infinity; if (!iterator && _.isEmpty(obj)) return Infinity;
var result = {computed : Infinity}; var result = {computed : Infinity, value: Infinity};
each(obj, function(value, index, list) { each(obj, function(value, index, list) {
var computed = iterator ? iterator.call(context, value, index, list) : value; var computed = iterator ? iterator.call(context, value, index, list) : value;
computed < result.computed && (result = {value : value, computed : computed}); computed < result.computed && (result = {value : value, computed : computed});
@@ -316,7 +324,7 @@
// An internal function used for aggregate "group by" operations. // An internal function used for aggregate "group by" operations.
var group = function(obj, value, context, behavior) { var group = function(obj, value, context, behavior) {
var result = {}; var result = {};
var iterator = lookupIterator(value); var iterator = lookupIterator(value || _.identity);
each(obj, function(value, index) { each(obj, function(value, index) {
var key = iterator.call(context, value, index, obj); var key = iterator.call(context, value, index, obj);
behavior(result, key, value); behavior(result, key, value);
@@ -336,7 +344,7 @@
// either a string attribute to count by, or a function that returns the // either a string attribute to count by, or a function that returns the
// criterion. // criterion.
_.countBy = function(obj, value, context) { _.countBy = function(obj, value, context) {
return group(obj, value, context, function(result, key, value) { return group(obj, value, context, function(result, key) {
if (!_.has(result, key)) result[key] = 0; if (!_.has(result, key)) result[key] = 0;
result[key]++; result[key]++;
}); });
@@ -358,7 +366,8 @@
// Safely convert anything iterable into a real, live array. // Safely convert anything iterable into a real, live array.
_.toArray = function(obj) { _.toArray = function(obj) {
if (!obj) return []; if (!obj) return [];
if (obj.length === +obj.length) return slice.call(obj); if (_.isArray(obj)) return slice.call(obj);
if (obj.length === +obj.length) return _.map(obj, _.identity);
return _.values(obj); return _.values(obj);
}; };
@@ -408,7 +417,7 @@
// Trim out all falsy values from an array. // Trim out all falsy values from an array.
_.compact = function(array) { _.compact = function(array) {
return _.filter(array, function(value){ return !!value; }); return _.filter(array, _.identity);
}; };
// Internal implementation of a recursive `flatten` function. // Internal implementation of a recursive `flatten` function.
@@ -565,25 +574,23 @@
// Function (ahem) Functions // Function (ahem) Functions
// ------------------ // ------------------
// Reusable constructor function for prototype setting.
var ctor = function(){};
// Create a function bound to a given object (assigning `this`, and arguments, // Create a function bound to a given object (assigning `this`, and arguments,
// optionally). Binding with arguments is also known as `curry`. // optionally). Delegates to **ECMAScript 5**'s native `Function.bind` if
// Delegates to **ECMAScript 5**'s native `Function.bind` if available. // available.
// We check for `func.bind` first, to fail fast when `func` is undefined. _.bind = function(func, context) {
_.bind = function bind(func, context) {
var bound, args;
if (func.bind === nativeBind && nativeBind) return nativeBind.apply(func, slice.call(arguments, 1)); if (func.bind === nativeBind && nativeBind) return nativeBind.apply(func, slice.call(arguments, 1));
if (!_.isFunction(func)) throw new TypeError; var args = slice.call(arguments, 2);
args = slice.call(arguments, 2); return function() {
return bound = function() { return func.apply(context, args.concat(slice.call(arguments)));
if (!(this instanceof bound)) return func.apply(context, args.concat(slice.call(arguments))); };
ctor.prototype = func.prototype; };
var self = new ctor;
var result = func.apply(self, args.concat(slice.call(arguments))); // Partially apply a function by creating a version that has had some of its
if (Object(result) === result) return result; // arguments pre-filled, without changing its dynamic `this` context.
return self; _.partial = function(func) {
var args = slice.call(arguments, 1);
return function() {
return func.apply(this, args.concat(slice.call(arguments)));
}; };
}; };
@@ -591,7 +598,7 @@
// all callbacks defined on an object belong to it. // all callbacks defined on an object belong to it.
_.bindAll = function(obj) { _.bindAll = function(obj) {
var funcs = slice.call(arguments, 1); var funcs = slice.call(arguments, 1);
if (funcs.length == 0) funcs = _.functions(obj); if (funcs.length === 0) funcs = _.functions(obj);
each(funcs, function(f) { obj[f] = _.bind(obj[f], obj); }); each(funcs, function(f) { obj[f] = _.bind(obj[f], obj); });
return obj; return obj;
}; };
@@ -636,6 +643,7 @@
args = arguments; args = arguments;
if (remaining <= 0) { if (remaining <= 0) {
clearTimeout(timeout); clearTimeout(timeout);
timeout = null;
previous = now; previous = now;
result = func.apply(context, args); result = func.apply(context, args);
} else if (!timeout) { } else if (!timeout) {
@@ -758,8 +766,10 @@
// Extend a given object with all the properties in passed-in object(s). // Extend a given object with all the properties in passed-in object(s).
_.extend = function(obj) { _.extend = function(obj) {
each(slice.call(arguments, 1), function(source) { each(slice.call(arguments, 1), function(source) {
for (var prop in source) { if (source) {
obj[prop] = source[prop]; for (var prop in source) {
obj[prop] = source[prop];
}
} }
}); });
return obj; return obj;
@@ -788,8 +798,10 @@
// Fill in a given object with default properties. // Fill in a given object with default properties.
_.defaults = function(obj) { _.defaults = function(obj) {
each(slice.call(arguments, 1), function(source) { each(slice.call(arguments, 1), function(source) {
for (var prop in source) { if (source) {
if (obj[prop] == null) obj[prop] = source[prop]; for (var prop in source) {
if (obj[prop] == null) obj[prop] = source[prop];
}
} }
}); });
return obj; return obj;
@@ -954,7 +966,7 @@
// Is a given object a finite number? // Is a given object a finite number?
_.isFinite = function(obj) { _.isFinite = function(obj) {
return isFinite( obj ) && !isNaN( parseFloat(obj) ); return isFinite(obj) && !isNaN(parseFloat(obj));
}; };
// Is the given value `NaN`? (NaN is the only number which does not equal itself). // Is the given value `NaN`? (NaN is the only number which does not equal itself).
@@ -1000,7 +1012,9 @@
// Run a function **n** times. // Run a function **n** times.
_.times = function(n, iterator, context) { _.times = function(n, iterator, context) {
for (var i = 0; i < n; i++) iterator.call(context, i); var accum = Array(n);
for (var i = 0; i < n; i++) accum[i] = iterator.call(context, i);
return accum;
}; };
// Return a random integer between min and max (inclusive). // Return a random integer between min and max (inclusive).
@@ -1009,7 +1023,7 @@
max = min; max = min;
min = 0; min = 0;
} }
return min + (0 | Math.random() * (max - min + 1)); return min + Math.floor(Math.random() * (max - min + 1));
}; };
// List of HTML entities for escaping. // List of HTML entities for escaping.
@@ -1065,7 +1079,7 @@
// Useful for temporary DOM ids. // Useful for temporary DOM ids.
var idCounter = 0; var idCounter = 0;
_.uniqueId = function(prefix) { _.uniqueId = function(prefix) {
var id = idCounter++; var id = ++idCounter + '';
return prefix ? prefix + id : id; return prefix ? prefix + id : id;
}; };
@@ -1100,6 +1114,7 @@
// Underscore templating handles arbitrary delimiters, preserves whitespace, // Underscore templating handles arbitrary delimiters, preserves whitespace,
// and correctly escapes quotes within interpolated code. // and correctly escapes quotes within interpolated code.
_.template = function(text, data, settings) { _.template = function(text, data, settings) {
var render;
settings = _.defaults({}, settings, _.templateSettings); settings = _.defaults({}, settings, _.templateSettings);
// Combine delimiters into one regular expression via alternation. // Combine delimiters into one regular expression via alternation.
@@ -1115,11 +1130,18 @@
text.replace(matcher, function(match, escape, interpolate, evaluate, offset) { text.replace(matcher, function(match, escape, interpolate, evaluate, offset) {
source += text.slice(index, offset) source += text.slice(index, offset)
.replace(escaper, function(match) { return '\\' + escapes[match]; }); .replace(escaper, function(match) { return '\\' + escapes[match]; });
source +=
escape ? "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'" : if (escape) {
interpolate ? "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'" : source += "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'";
evaluate ? "';\n" + evaluate + "\n__p+='" : ''; }
if (interpolate) {
source += "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'";
}
if (evaluate) {
source += "';\n" + evaluate + "\n__p+='";
}
index = offset + match.length; index = offset + match.length;
return match;
}); });
source += "';\n"; source += "';\n";
@@ -1131,7 +1153,7 @@
source + "return __p;\n"; source + "return __p;\n";
try { try {
var render = new Function(settings.variable || 'obj', '_', source); render = new Function(settings.variable || 'obj', '_', source);
} catch (e) { } catch (e) {
e.source = source; e.source = source;
throw e; throw e;