├── .gitignore
├── BRAINSTORM.md
├── Hom.js
├── LICENSE
├── README.md
├── Setup.hs
├── hom-lib.cabal
├── index.html
├── lib
├── .gitignore
├── .jshintrc
├── .travis.yml
├── Gruntfile.js
├── LICENSE-MIT
├── README.md
├── bundle.js
├── index.html
├── lib
│ └── hom-lib.js
├── package.json
└── test
│ └── lib_test.js
└── src
├── Hom
├── Animate.hs
├── App.hs
└── DOM.hs
└── Main.hs
/.gitignore:
--------------------------------------------------------------------------------
1 | dist
2 | cabal-dev
3 | *.o
4 | *.hi
5 | *.chi
6 | *.chs.h
7 |
8 | src/**/*.js
9 | .virtualenv
10 | .hsenv
11 | .cabal-sandbox/
12 | cabal.sandbox.config
13 | cabal.config
14 | main
15 | hom-lib-*
16 | ./*.js
17 |
--------------------------------------------------------------------------------
/BRAINSTORM.md:
--------------------------------------------------------------------------------
1 | # This file is my brainstorm file where I'm going to write down my thought stream.
2 |
3 |
4 | basically we want something like https://github.com/Matt-Esch/virtual-dom
5 |
6 | https://gist.github.com/Raynos/8414846 is a gist that lead to virtual-dom. with good explanations about the arch.
7 |
8 |
9 | We will have two threads:
10 |
11 | * an event dispatch thread on which we dispatch async events that will modify our State MVar.
12 |
13 | * a render thread which blocks on the State MVar until it sees a change. the MVar is a state-change witness here. So we know that that our state has changed if and only if we can take from the MVar.
14 |
15 | We then render a virtual dom with this new state and diff it against our old one. We retreive a list of 'patches' that instruct how
16 | we must modify the real DOM to execute this diff most efficiently. diffing tree is an O(n^3) problem but which can be approximated using
17 | heuristics pretty well. I'm just gonna re-use virtual-dom for this because although really interesting to write such an algorithm in haskell,
18 | it's way out of my current abilities.
19 |
20 |
21 |
22 | we want the virtual dom to be a "pure" function. so event handlers are just simple functions from state to state.
23 | how they are actually handeld and dispatched is upto the event dispatch thread. we as render thread ignore the fact that
24 | they are async or anything. it's not our responsibility.
25 |
26 |
27 | type EventCB state = EventData -> state -> state
28 |
29 | a := b = (a,b)
30 | type Prop = (JSString, JSString)
31 | type CB a= (JSString, EventCB a)
32 |
33 | -- creates a virtual domNode
34 | vnode :: JSString -> [Prop] -> [CB state] -> [VNode] -> VNode
35 |
36 | -- a simple counter widget might look like this:
37 |
38 | counterWidget count =
39 | vnode "div" [] []
40 | [ vnode "div" ["class":="boldText"] [] [ vtext . show $ count ]
41 | , vnode "button" [] [["onClick" := const (+1)] [ vtext "increase!"]
42 | ]
43 |
44 |
45 |
46 | ... to becontinued.
47 |
48 |
49 | what I need to do is interpret the DOM in the event-dispatch-thread as well to change these "pure state transitions" to effects on the state MVar. That way the render-thread witnesses a state-change and will update the DOM by diffing.
50 |
51 |
52 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2014 arianvp
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Hom
2 | ===
3 |
4 | Hom - React.JS for Haskell!
5 |
6 |
7 | currently we're doing something similar at:
8 |
9 | http://github.com/ghcjs/ghcjs-vdom
10 |
11 | https://github.com/purescript-contrib/purescript-virtual-dom
12 |
--------------------------------------------------------------------------------
/Setup.hs:
--------------------------------------------------------------------------------
1 | import Distribution.Simple
2 | main = defaultMain
3 |
--------------------------------------------------------------------------------
/hom-lib.cabal:
--------------------------------------------------------------------------------
1 | -- Initial hom-lib.cabal generated by cabal init. For further
2 | -- documentation, see http://haskell.org/cabal/users-guide/
3 |
4 | name: hom-lib
5 | version: 0.1.0.0
6 | -- synopsis:
7 | -- description:
8 | license: GPL-3
9 | license-file: LICENSE
10 | author: Arian van Putten
11 | maintainer: aeroboy94@gmail.com
12 | -- copyright:
13 | category: Web
14 | build-type: Simple
15 | -- extra-source-files:
16 | cabal-version: >=1.10
17 |
18 | library
19 | exposed-modules: Hom.DOM
20 | -- other-modules:
21 | -- other-extensions:
22 | build-depends: base >=4.6 && <4.7,
23 | haste-lib ==0.3, transformers >=0.3
24 | ghc-options: "--with-js=./lib/bundle.js"
25 | hs-source-dirs: src
26 | default-language: Haskell2010
27 |
28 | executable lol
29 | Main-Is: Main.hs
30 | hs-source-dirs: src
31 | ghc-options: "--with-js=./lib/bundle.js"
32 | build-depends: base >=4.6 && <4.7, haste-lib >=0.3, transformers >=0.3
33 | other-modules: Hom.DOM
34 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/lib/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 |
--------------------------------------------------------------------------------
/lib/.jshintrc:
--------------------------------------------------------------------------------
1 | {
2 | "curly": true,
3 | "eqeqeq": true,
4 | "immed": true,
5 | "latedef": "nofunc",
6 | "newcap": true,
7 | "noarg": true,
8 | "sub": true,
9 | "undef": true,
10 | "unused": true,
11 | "boss": true,
12 | "eqnull": true,
13 | "node": true
14 | }
15 |
--------------------------------------------------------------------------------
/lib/.travis.yml:
--------------------------------------------------------------------------------
1 | language: node_js
2 | node_js:
3 | - 0.8
4 | - '0.10'
5 | before_script:
6 | - npm install -g grunt-cli
7 |
--------------------------------------------------------------------------------
/lib/Gruntfile.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | module.exports = function(grunt) {
4 |
5 | // Project configuration.
6 | grunt.initConfig({
7 | // nodeunit: {
8 | // files: ['test/**/*_test.js'],
9 | // },
10 | jshint: {
11 | options: {
12 | jshintrc: '.jshintrc'
13 | },
14 | gruntfile: {
15 | src: 'Gruntfile.js'
16 | },
17 | lib: {
18 | src: ['lib/**/*.js']
19 | },
20 | // test: {
21 | //j src: ['test/**/*.js']
22 | // },
23 | },
24 | browserify: {
25 | all: {
26 | src: 'lib/**/*.js',
27 | dest: 'bundle.js'
28 | }
29 | },
30 | watch: {
31 | gruntfile: {
32 | files: '<%= jshint.gruntfile.src %>',
33 | tasks: ['jshint:gruntfile']
34 | },
35 | lib: {
36 | files: '<%= jshint.lib.src %>',
37 | tasks: ['jshint:lib', 'nodeunit']
38 | },
39 | test: {
40 | files: '<%= jshint.test.src %>',
41 | tasks: ['jshint:test', 'nodeunit']
42 | },
43 | },
44 | });
45 |
46 | // These plugins provide necessary tasks.
47 | grunt.loadNpmTasks('grunt-contrib-nodeunit');
48 | grunt.loadNpmTasks('grunt-contrib-jshint');
49 | grunt.loadNpmTasks('grunt-contrib-watch');
50 | grunt.loadNpmTasks('grunt-browserify');
51 | grunt.loadNpmTasks('grunt-file-append');
52 | // Default task.
53 | grunt.registerTask('default', ['jshint', 'browserify', ]);
54 |
55 | };
56 |
--------------------------------------------------------------------------------
/lib/LICENSE-MIT:
--------------------------------------------------------------------------------
1 | Copyright (c) 2014 Arian van Putten
2 |
3 | Permission is hereby granted, free of charge, to any person
4 | obtaining a copy of this software and associated documentation
5 | files (the "Software"), to deal in the Software without
6 | restriction, including without limitation the rights to use,
7 | copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | copies of the Software, and to permit persons to whom the
9 | Software is furnished to do so, subject to the following
10 | conditions:
11 |
12 | The above copyright notice and this permission notice shall be
13 | included in all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 | OTHER DEALINGS IN THE SOFTWARE.
23 |
--------------------------------------------------------------------------------
/lib/README.md:
--------------------------------------------------------------------------------
1 | # lib [](http://travis-ci.org/arian/lib)
2 |
3 | The best project ever.
4 |
5 | ## Getting Started
6 | Install the module with: `npm install lib`
7 |
8 | ```javascript
9 | var lib = require('lib');
10 | lib.awesome(); // "awesome"
11 | ```
12 |
13 | ## Documentation
14 | _(Coming soon)_
15 |
16 | ## Examples
17 | _(Coming soon)_
18 |
19 | ## Contributing
20 | In lieu of a formal styleguide, take care to maintain the existing coding style. Add unit tests for any new or changed functionality. Lint and test your code using [Grunt](http://gruntjs.com/).
21 |
22 | ## Release History
23 | _(Nothing yet)_
24 |
25 | ## License
26 | Copyright (c) 2014 Arian van Putten
27 | Licensed under the MIT license.
28 |
--------------------------------------------------------------------------------
/lib/bundle.js:
--------------------------------------------------------------------------------
1 | (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o 0) {
68 | var fn = queue.shift();
69 | fn();
70 | }
71 | }
72 | }, true);
73 |
74 | return function nextTick(fn) {
75 | queue.push(fn);
76 | window.postMessage('process-tick', '*');
77 | };
78 | }
79 |
80 | return function nextTick(fn) {
81 | setTimeout(fn, 0);
82 | };
83 | })();
84 |
85 | process.title = 'browser';
86 | process.browser = true;
87 | process.env = {};
88 | process.argv = [];
89 |
90 | function noop() {}
91 |
92 | process.on = noop;
93 | process.addListener = noop;
94 | process.once = noop;
95 | process.off = noop;
96 | process.removeListener = noop;
97 | process.removeAllListeners = noop;
98 | process.emit = noop;
99 |
100 | process.binding = function (name) {
101 | throw new Error('process.binding is not supported');
102 | }
103 |
104 | // TODO(shtylman)
105 | process.cwd = function () { return '/' };
106 | process.chdir = function (dir) {
107 | throw new Error('process.chdir is not supported');
108 | };
109 |
110 | },{}],4:[function(require,module,exports){
111 | var raf = require("raf")
112 | var vtreeDiff = require("vtree/diff")
113 | var vdomCreate = require("vdom/create-element")
114 | var vdomPatch = require("vdom/patch")
115 | var TypedError = require("error/typed")
116 |
117 | var InvalidUpdateInRender = TypedError({
118 | type: "main-loop.invalid.update.in-render",
119 | message: "main-loop: Unexpected update occurred in loop.\n" +
120 | "We are currently rendering a view, " +
121 | "you can't change state right now.\n" +
122 | "The diff is: {stringDiff}.\n" +
123 | "SUGGESTED FIX: find the state mutation in your view " +
124 | "or rendering function and remove it.\n" +
125 | "The view should not have any side effects.\n",
126 | diff: null,
127 | stringDiff: null
128 | })
129 |
130 | module.exports = main
131 |
132 | function main(initialState, view, opts) {
133 | opts = opts || {}
134 |
135 | var currentState = initialState
136 | var create = opts.create || vdomCreate
137 | var diff = opts.diff || vtreeDiff
138 | var patch = opts.patch || vdomPatch
139 | var redrawScheduled = false
140 |
141 | var tree = opts.initialTree || view(currentState)
142 | var target = opts.target || create(tree, opts)
143 | var inRenderingTransaction = false
144 |
145 | currentState = null
146 |
147 | return {
148 | target: target,
149 | update: update
150 | }
151 |
152 | function update(state) {
153 | if (inRenderingTransaction) {
154 | throw InvalidUpdateInRender({
155 | diff: state._diff,
156 | stringDiff: JSON.stringify(state._diff)
157 | })
158 | }
159 |
160 | if (currentState === null && !redrawScheduled) {
161 | redrawScheduled = true
162 | raf(redraw)
163 | }
164 |
165 | currentState = state
166 | }
167 |
168 | function redraw() {
169 | redrawScheduled = false;
170 | if (currentState === null) {
171 | return
172 | }
173 |
174 | inRenderingTransaction = true
175 | var newTree = view(currentState)
176 |
177 | if (opts.createOnly) {
178 | create(newTree, opts)
179 | } else {
180 | var patches = diff(tree, newTree, opts)
181 | target = patch(target, patches, opts)
182 | }
183 |
184 | inRenderingTransaction = false
185 | tree = newTree
186 | currentState = null
187 | }
188 | }
189 |
190 | },{"error/typed":17,"raf":144,"vdom/create-element":19,"vdom/patch":25,"vtree/diff":27}],5:[function(require,module,exports){
191 | // http://wiki.commonjs.org/wiki/Unit_Testing/1.0
192 | //
193 | // THIS IS NOT TESTED NOR LIKELY TO WORK OUTSIDE V8!
194 | //
195 | // Originally from narwhal.js (http://narwhaljs.org)
196 | // Copyright (c) 2009 Thomas Robinson <280north.com>
197 | //
198 | // Permission is hereby granted, free of charge, to any person obtaining a copy
199 | // of this software and associated documentation files (the 'Software'), to
200 | // deal in the Software without restriction, including without limitation the
201 | // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
202 | // sell copies of the Software, and to permit persons to whom the Software is
203 | // furnished to do so, subject to the following conditions:
204 | //
205 | // The above copyright notice and this permission notice shall be included in
206 | // all copies or substantial portions of the Software.
207 | //
208 | // THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
209 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
210 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
211 | // AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
212 | // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
213 | // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
214 |
215 | // when used in node, this will actually load the util module we depend on
216 | // versus loading the builtin util module as happens otherwise
217 | // this is a bug in node module loading as far as I am concerned
218 | var util = require('util/');
219 |
220 | var pSlice = Array.prototype.slice;
221 | var hasOwn = Object.prototype.hasOwnProperty;
222 |
223 | // 1. The assert module provides functions that throw
224 | // AssertionError's when particular conditions are not met. The
225 | // assert module must conform to the following interface.
226 |
227 | var assert = module.exports = ok;
228 |
229 | // 2. The AssertionError is defined in assert.
230 | // new assert.AssertionError({ message: message,
231 | // actual: actual,
232 | // expected: expected })
233 |
234 | assert.AssertionError = function AssertionError(options) {
235 | this.name = 'AssertionError';
236 | this.actual = options.actual;
237 | this.expected = options.expected;
238 | this.operator = options.operator;
239 | if (options.message) {
240 | this.message = options.message;
241 | this.generatedMessage = false;
242 | } else {
243 | this.message = getMessage(this);
244 | this.generatedMessage = true;
245 | }
246 | var stackStartFunction = options.stackStartFunction || fail;
247 |
248 | if (Error.captureStackTrace) {
249 | Error.captureStackTrace(this, stackStartFunction);
250 | }
251 | else {
252 | // non v8 browsers so we can have a stacktrace
253 | var err = new Error();
254 | if (err.stack) {
255 | var out = err.stack;
256 |
257 | // try to strip useless frames
258 | var fn_name = stackStartFunction.name;
259 | var idx = out.indexOf('\n' + fn_name);
260 | if (idx >= 0) {
261 | // once we have located the function frame
262 | // we need to strip out everything before it (and its line)
263 | var next_line = out.indexOf('\n', idx + 1);
264 | out = out.substring(next_line + 1);
265 | }
266 |
267 | this.stack = out;
268 | }
269 | }
270 | };
271 |
272 | // assert.AssertionError instanceof Error
273 | util.inherits(assert.AssertionError, Error);
274 |
275 | function replacer(key, value) {
276 | if (util.isUndefined(value)) {
277 | return '' + value;
278 | }
279 | if (util.isNumber(value) && (isNaN(value) || !isFinite(value))) {
280 | return value.toString();
281 | }
282 | if (util.isFunction(value) || util.isRegExp(value)) {
283 | return value.toString();
284 | }
285 | return value;
286 | }
287 |
288 | function truncate(s, n) {
289 | if (util.isString(s)) {
290 | return s.length < n ? s : s.slice(0, n);
291 | } else {
292 | return s;
293 | }
294 | }
295 |
296 | function getMessage(self) {
297 | return truncate(JSON.stringify(self.actual, replacer), 128) + ' ' +
298 | self.operator + ' ' +
299 | truncate(JSON.stringify(self.expected, replacer), 128);
300 | }
301 |
302 | // At present only the three keys mentioned above are used and
303 | // understood by the spec. Implementations or sub modules can pass
304 | // other keys to the AssertionError's constructor - they will be
305 | // ignored.
306 |
307 | // 3. All of the following functions must throw an AssertionError
308 | // when a corresponding condition is not met, with a message that
309 | // may be undefined if not provided. All assertion methods provide
310 | // both the actual and expected values to the assertion error for
311 | // display purposes.
312 |
313 | function fail(actual, expected, message, operator, stackStartFunction) {
314 | throw new assert.AssertionError({
315 | message: message,
316 | actual: actual,
317 | expected: expected,
318 | operator: operator,
319 | stackStartFunction: stackStartFunction
320 | });
321 | }
322 |
323 | // EXTENSION! allows for well behaved errors defined elsewhere.
324 | assert.fail = fail;
325 |
326 | // 4. Pure assertion tests whether a value is truthy, as determined
327 | // by !!guard.
328 | // assert.ok(guard, message_opt);
329 | // This statement is equivalent to assert.equal(true, !!guard,
330 | // message_opt);. To test strictly for the value true, use
331 | // assert.strictEqual(true, guard, message_opt);.
332 |
333 | function ok(value, message) {
334 | if (!value) fail(value, true, message, '==', assert.ok);
335 | }
336 | assert.ok = ok;
337 |
338 | // 5. The equality assertion tests shallow, coercive equality with
339 | // ==.
340 | // assert.equal(actual, expected, message_opt);
341 |
342 | assert.equal = function equal(actual, expected, message) {
343 | if (actual != expected) fail(actual, expected, message, '==', assert.equal);
344 | };
345 |
346 | // 6. The non-equality assertion tests for whether two objects are not equal
347 | // with != assert.notEqual(actual, expected, message_opt);
348 |
349 | assert.notEqual = function notEqual(actual, expected, message) {
350 | if (actual == expected) {
351 | fail(actual, expected, message, '!=', assert.notEqual);
352 | }
353 | };
354 |
355 | // 7. The equivalence assertion tests a deep equality relation.
356 | // assert.deepEqual(actual, expected, message_opt);
357 |
358 | assert.deepEqual = function deepEqual(actual, expected, message) {
359 | if (!_deepEqual(actual, expected)) {
360 | fail(actual, expected, message, 'deepEqual', assert.deepEqual);
361 | }
362 | };
363 |
364 | function _deepEqual(actual, expected) {
365 | // 7.1. All identical values are equivalent, as determined by ===.
366 | if (actual === expected) {
367 | return true;
368 |
369 | } else if (util.isBuffer(actual) && util.isBuffer(expected)) {
370 | if (actual.length != expected.length) return false;
371 |
372 | for (var i = 0; i < actual.length; i++) {
373 | if (actual[i] !== expected[i]) return false;
374 | }
375 |
376 | return true;
377 |
378 | // 7.2. If the expected value is a Date object, the actual value is
379 | // equivalent if it is also a Date object that refers to the same time.
380 | } else if (util.isDate(actual) && util.isDate(expected)) {
381 | return actual.getTime() === expected.getTime();
382 |
383 | // 7.3 If the expected value is a RegExp object, the actual value is
384 | // equivalent if it is also a RegExp object with the same source and
385 | // properties (`global`, `multiline`, `lastIndex`, `ignoreCase`).
386 | } else if (util.isRegExp(actual) && util.isRegExp(expected)) {
387 | return actual.source === expected.source &&
388 | actual.global === expected.global &&
389 | actual.multiline === expected.multiline &&
390 | actual.lastIndex === expected.lastIndex &&
391 | actual.ignoreCase === expected.ignoreCase;
392 |
393 | // 7.4. Other pairs that do not both pass typeof value == 'object',
394 | // equivalence is determined by ==.
395 | } else if (!util.isObject(actual) && !util.isObject(expected)) {
396 | return actual == expected;
397 |
398 | // 7.5 For all other Object pairs, including Array objects, equivalence is
399 | // determined by having the same number of owned properties (as verified
400 | // with Object.prototype.hasOwnProperty.call), the same set of keys
401 | // (although not necessarily the same order), equivalent values for every
402 | // corresponding key, and an identical 'prototype' property. Note: this
403 | // accounts for both named and indexed properties on Arrays.
404 | } else {
405 | return objEquiv(actual, expected);
406 | }
407 | }
408 |
409 | function isArguments(object) {
410 | return Object.prototype.toString.call(object) == '[object Arguments]';
411 | }
412 |
413 | function objEquiv(a, b) {
414 | if (util.isNullOrUndefined(a) || util.isNullOrUndefined(b))
415 | return false;
416 | // an identical 'prototype' property.
417 | if (a.prototype !== b.prototype) return false;
418 | //~~~I've managed to break Object.keys through screwy arguments passing.
419 | // Converting to array solves the problem.
420 | if (isArguments(a)) {
421 | if (!isArguments(b)) {
422 | return false;
423 | }
424 | a = pSlice.call(a);
425 | b = pSlice.call(b);
426 | return _deepEqual(a, b);
427 | }
428 | try {
429 | var ka = objectKeys(a),
430 | kb = objectKeys(b),
431 | key, i;
432 | } catch (e) {//happens when one is a string literal and the other isn't
433 | return false;
434 | }
435 | // having the same number of owned properties (keys incorporates
436 | // hasOwnProperty)
437 | if (ka.length != kb.length)
438 | return false;
439 | //the same set of keys (although not necessarily the same order),
440 | ka.sort();
441 | kb.sort();
442 | //~~~cheap key test
443 | for (i = ka.length - 1; i >= 0; i--) {
444 | if (ka[i] != kb[i])
445 | return false;
446 | }
447 | //equivalent values for every corresponding key, and
448 | //~~~possibly expensive deep test
449 | for (i = ka.length - 1; i >= 0; i--) {
450 | key = ka[i];
451 | if (!_deepEqual(a[key], b[key])) return false;
452 | }
453 | return true;
454 | }
455 |
456 | // 8. The non-equivalence assertion tests for any deep inequality.
457 | // assert.notDeepEqual(actual, expected, message_opt);
458 |
459 | assert.notDeepEqual = function notDeepEqual(actual, expected, message) {
460 | if (_deepEqual(actual, expected)) {
461 | fail(actual, expected, message, 'notDeepEqual', assert.notDeepEqual);
462 | }
463 | };
464 |
465 | // 9. The strict equality assertion tests strict equality, as determined by ===.
466 | // assert.strictEqual(actual, expected, message_opt);
467 |
468 | assert.strictEqual = function strictEqual(actual, expected, message) {
469 | if (actual !== expected) {
470 | fail(actual, expected, message, '===', assert.strictEqual);
471 | }
472 | };
473 |
474 | // 10. The strict non-equality assertion tests for strict inequality, as
475 | // determined by !==. assert.notStrictEqual(actual, expected, message_opt);
476 |
477 | assert.notStrictEqual = function notStrictEqual(actual, expected, message) {
478 | if (actual === expected) {
479 | fail(actual, expected, message, '!==', assert.notStrictEqual);
480 | }
481 | };
482 |
483 | function expectedException(actual, expected) {
484 | if (!actual || !expected) {
485 | return false;
486 | }
487 |
488 | if (Object.prototype.toString.call(expected) == '[object RegExp]') {
489 | return expected.test(actual);
490 | } else if (actual instanceof expected) {
491 | return true;
492 | } else if (expected.call({}, actual) === true) {
493 | return true;
494 | }
495 |
496 | return false;
497 | }
498 |
499 | function _throws(shouldThrow, block, expected, message) {
500 | var actual;
501 |
502 | if (util.isString(expected)) {
503 | message = expected;
504 | expected = null;
505 | }
506 |
507 | try {
508 | block();
509 | } catch (e) {
510 | actual = e;
511 | }
512 |
513 | message = (expected && expected.name ? ' (' + expected.name + ').' : '.') +
514 | (message ? ' ' + message : '.');
515 |
516 | if (shouldThrow && !actual) {
517 | fail(actual, expected, 'Missing expected exception' + message);
518 | }
519 |
520 | if (!shouldThrow && expectedException(actual, expected)) {
521 | fail(actual, expected, 'Got unwanted exception' + message);
522 | }
523 |
524 | if ((shouldThrow && actual && expected &&
525 | !expectedException(actual, expected)) || (!shouldThrow && actual)) {
526 | throw actual;
527 | }
528 | }
529 |
530 | // 11. Expected to throw an error:
531 | // assert.throws(block, Error_opt, message_opt);
532 |
533 | assert.throws = function(block, /*optional*/error, /*optional*/message) {
534 | _throws.apply(this, [true].concat(pSlice.call(arguments)));
535 | };
536 |
537 | // EXTENSION! This is annoying to write outside this module.
538 | assert.doesNotThrow = function(block, /*optional*/message) {
539 | _throws.apply(this, [false].concat(pSlice.call(arguments)));
540 | };
541 |
542 | assert.ifError = function(err) { if (err) {throw err;}};
543 |
544 | var objectKeys = Object.keys || function (obj) {
545 | var keys = [];
546 | for (var key in obj) {
547 | if (hasOwn.call(obj, key)) keys.push(key);
548 | }
549 | return keys;
550 | };
551 |
552 | },{"util/":8}],6:[function(require,module,exports){
553 | if (typeof Object.create === 'function') {
554 | // implementation from standard node.js 'util' module
555 | module.exports = function inherits(ctor, superCtor) {
556 | ctor.super_ = superCtor
557 | ctor.prototype = Object.create(superCtor.prototype, {
558 | constructor: {
559 | value: ctor,
560 | enumerable: false,
561 | writable: true,
562 | configurable: true
563 | }
564 | });
565 | };
566 | } else {
567 | // old school shim for old browsers
568 | module.exports = function inherits(ctor, superCtor) {
569 | ctor.super_ = superCtor
570 | var TempCtor = function () {}
571 | TempCtor.prototype = superCtor.prototype
572 | ctor.prototype = new TempCtor()
573 | ctor.prototype.constructor = ctor
574 | }
575 | }
576 |
577 | },{}],7:[function(require,module,exports){
578 | module.exports = function isBuffer(arg) {
579 | return arg && typeof arg === 'object'
580 | && typeof arg.copy === 'function'
581 | && typeof arg.fill === 'function'
582 | && typeof arg.readUInt8 === 'function';
583 | }
584 | },{}],8:[function(require,module,exports){
585 | (function (process,global){
586 | // Copyright Joyent, Inc. and other Node contributors.
587 | //
588 | // Permission is hereby granted, free of charge, to any person obtaining a
589 | // copy of this software and associated documentation files (the
590 | // "Software"), to deal in the Software without restriction, including
591 | // without limitation the rights to use, copy, modify, merge, publish,
592 | // distribute, sublicense, and/or sell copies of the Software, and to permit
593 | // persons to whom the Software is furnished to do so, subject to the
594 | // following conditions:
595 | //
596 | // The above copyright notice and this permission notice shall be included
597 | // in all copies or substantial portions of the Software.
598 | //
599 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
600 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
601 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
602 | // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
603 | // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
604 | // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
605 | // USE OR OTHER DEALINGS IN THE SOFTWARE.
606 |
607 | var formatRegExp = /%[sdj%]/g;
608 | exports.format = function(f) {
609 | if (!isString(f)) {
610 | var objects = [];
611 | for (var i = 0; i < arguments.length; i++) {
612 | objects.push(inspect(arguments[i]));
613 | }
614 | return objects.join(' ');
615 | }
616 |
617 | var i = 1;
618 | var args = arguments;
619 | var len = args.length;
620 | var str = String(f).replace(formatRegExp, function(x) {
621 | if (x === '%%') return '%';
622 | if (i >= len) return x;
623 | switch (x) {
624 | case '%s': return String(args[i++]);
625 | case '%d': return Number(args[i++]);
626 | case '%j':
627 | try {
628 | return JSON.stringify(args[i++]);
629 | } catch (_) {
630 | return '[Circular]';
631 | }
632 | default:
633 | return x;
634 | }
635 | });
636 | for (var x = args[i]; i < len; x = args[++i]) {
637 | if (isNull(x) || !isObject(x)) {
638 | str += ' ' + x;
639 | } else {
640 | str += ' ' + inspect(x);
641 | }
642 | }
643 | return str;
644 | };
645 |
646 |
647 | // Mark that a method should not be used.
648 | // Returns a modified function which warns once by default.
649 | // If --no-deprecation is set, then it is a no-op.
650 | exports.deprecate = function(fn, msg) {
651 | // Allow for deprecating things in the process of starting up.
652 | if (isUndefined(global.process)) {
653 | return function() {
654 | return exports.deprecate(fn, msg).apply(this, arguments);
655 | };
656 | }
657 |
658 | if (process.noDeprecation === true) {
659 | return fn;
660 | }
661 |
662 | var warned = false;
663 | function deprecated() {
664 | if (!warned) {
665 | if (process.throwDeprecation) {
666 | throw new Error(msg);
667 | } else if (process.traceDeprecation) {
668 | console.trace(msg);
669 | } else {
670 | console.error(msg);
671 | }
672 | warned = true;
673 | }
674 | return fn.apply(this, arguments);
675 | }
676 |
677 | return deprecated;
678 | };
679 |
680 |
681 | var debugs = {};
682 | var debugEnviron;
683 | exports.debuglog = function(set) {
684 | if (isUndefined(debugEnviron))
685 | debugEnviron = process.env.NODE_DEBUG || '';
686 | set = set.toUpperCase();
687 | if (!debugs[set]) {
688 | if (new RegExp('\\b' + set + '\\b', 'i').test(debugEnviron)) {
689 | var pid = process.pid;
690 | debugs[set] = function() {
691 | var msg = exports.format.apply(exports, arguments);
692 | console.error('%s %d: %s', set, pid, msg);
693 | };
694 | } else {
695 | debugs[set] = function() {};
696 | }
697 | }
698 | return debugs[set];
699 | };
700 |
701 |
702 | /**
703 | * Echos the value of a value. Trys to print the value out
704 | * in the best way possible given the different types.
705 | *
706 | * @param {Object} obj The object to print out.
707 | * @param {Object} opts Optional options object that alters the output.
708 | */
709 | /* legacy: obj, showHidden, depth, colors*/
710 | function inspect(obj, opts) {
711 | // default options
712 | var ctx = {
713 | seen: [],
714 | stylize: stylizeNoColor
715 | };
716 | // legacy...
717 | if (arguments.length >= 3) ctx.depth = arguments[2];
718 | if (arguments.length >= 4) ctx.colors = arguments[3];
719 | if (isBoolean(opts)) {
720 | // legacy...
721 | ctx.showHidden = opts;
722 | } else if (opts) {
723 | // got an "options" object
724 | exports._extend(ctx, opts);
725 | }
726 | // set default options
727 | if (isUndefined(ctx.showHidden)) ctx.showHidden = false;
728 | if (isUndefined(ctx.depth)) ctx.depth = 2;
729 | if (isUndefined(ctx.colors)) ctx.colors = false;
730 | if (isUndefined(ctx.customInspect)) ctx.customInspect = true;
731 | if (ctx.colors) ctx.stylize = stylizeWithColor;
732 | return formatValue(ctx, obj, ctx.depth);
733 | }
734 | exports.inspect = inspect;
735 |
736 |
737 | // http://en.wikipedia.org/wiki/ANSI_escape_code#graphics
738 | inspect.colors = {
739 | 'bold' : [1, 22],
740 | 'italic' : [3, 23],
741 | 'underline' : [4, 24],
742 | 'inverse' : [7, 27],
743 | 'white' : [37, 39],
744 | 'grey' : [90, 39],
745 | 'black' : [30, 39],
746 | 'blue' : [34, 39],
747 | 'cyan' : [36, 39],
748 | 'green' : [32, 39],
749 | 'magenta' : [35, 39],
750 | 'red' : [31, 39],
751 | 'yellow' : [33, 39]
752 | };
753 |
754 | // Don't use 'blue' not visible on cmd.exe
755 | inspect.styles = {
756 | 'special': 'cyan',
757 | 'number': 'yellow',
758 | 'boolean': 'yellow',
759 | 'undefined': 'grey',
760 | 'null': 'bold',
761 | 'string': 'green',
762 | 'date': 'magenta',
763 | // "name": intentionally not styling
764 | 'regexp': 'red'
765 | };
766 |
767 |
768 | function stylizeWithColor(str, styleType) {
769 | var style = inspect.styles[styleType];
770 |
771 | if (style) {
772 | return '\u001b[' + inspect.colors[style][0] + 'm' + str +
773 | '\u001b[' + inspect.colors[style][1] + 'm';
774 | } else {
775 | return str;
776 | }
777 | }
778 |
779 |
780 | function stylizeNoColor(str, styleType) {
781 | return str;
782 | }
783 |
784 |
785 | function arrayToHash(array) {
786 | var hash = {};
787 |
788 | array.forEach(function(val, idx) {
789 | hash[val] = true;
790 | });
791 |
792 | return hash;
793 | }
794 |
795 |
796 | function formatValue(ctx, value, recurseTimes) {
797 | // Provide a hook for user-specified inspect functions.
798 | // Check that value is an object with an inspect function on it
799 | if (ctx.customInspect &&
800 | value &&
801 | isFunction(value.inspect) &&
802 | // Filter out the util module, it's inspect function is special
803 | value.inspect !== exports.inspect &&
804 | // Also filter out any prototype objects using the circular check.
805 | !(value.constructor && value.constructor.prototype === value)) {
806 | var ret = value.inspect(recurseTimes, ctx);
807 | if (!isString(ret)) {
808 | ret = formatValue(ctx, ret, recurseTimes);
809 | }
810 | return ret;
811 | }
812 |
813 | // Primitive types cannot have properties
814 | var primitive = formatPrimitive(ctx, value);
815 | if (primitive) {
816 | return primitive;
817 | }
818 |
819 | // Look up the keys of the object.
820 | var keys = Object.keys(value);
821 | var visibleKeys = arrayToHash(keys);
822 |
823 | if (ctx.showHidden) {
824 | keys = Object.getOwnPropertyNames(value);
825 | }
826 |
827 | // IE doesn't make error fields non-enumerable
828 | // http://msdn.microsoft.com/en-us/library/ie/dww52sbt(v=vs.94).aspx
829 | if (isError(value)
830 | && (keys.indexOf('message') >= 0 || keys.indexOf('description') >= 0)) {
831 | return formatError(value);
832 | }
833 |
834 | // Some type of object without properties can be shortcutted.
835 | if (keys.length === 0) {
836 | if (isFunction(value)) {
837 | var name = value.name ? ': ' + value.name : '';
838 | return ctx.stylize('[Function' + name + ']', 'special');
839 | }
840 | if (isRegExp(value)) {
841 | return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');
842 | }
843 | if (isDate(value)) {
844 | return ctx.stylize(Date.prototype.toString.call(value), 'date');
845 | }
846 | if (isError(value)) {
847 | return formatError(value);
848 | }
849 | }
850 |
851 | var base = '', array = false, braces = ['{', '}'];
852 |
853 | // Make Array say that they are Array
854 | if (isArray(value)) {
855 | array = true;
856 | braces = ['[', ']'];
857 | }
858 |
859 | // Make functions say that they are functions
860 | if (isFunction(value)) {
861 | var n = value.name ? ': ' + value.name : '';
862 | base = ' [Function' + n + ']';
863 | }
864 |
865 | // Make RegExps say that they are RegExps
866 | if (isRegExp(value)) {
867 | base = ' ' + RegExp.prototype.toString.call(value);
868 | }
869 |
870 | // Make dates with properties first say the date
871 | if (isDate(value)) {
872 | base = ' ' + Date.prototype.toUTCString.call(value);
873 | }
874 |
875 | // Make error with message first say the error
876 | if (isError(value)) {
877 | base = ' ' + formatError(value);
878 | }
879 |
880 | if (keys.length === 0 && (!array || value.length == 0)) {
881 | return braces[0] + base + braces[1];
882 | }
883 |
884 | if (recurseTimes < 0) {
885 | if (isRegExp(value)) {
886 | return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');
887 | } else {
888 | return ctx.stylize('[Object]', 'special');
889 | }
890 | }
891 |
892 | ctx.seen.push(value);
893 |
894 | var output;
895 | if (array) {
896 | output = formatArray(ctx, value, recurseTimes, visibleKeys, keys);
897 | } else {
898 | output = keys.map(function(key) {
899 | return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array);
900 | });
901 | }
902 |
903 | ctx.seen.pop();
904 |
905 | return reduceToSingleString(output, base, braces);
906 | }
907 |
908 |
909 | function formatPrimitive(ctx, value) {
910 | if (isUndefined(value))
911 | return ctx.stylize('undefined', 'undefined');
912 | if (isString(value)) {
913 | var simple = '\'' + JSON.stringify(value).replace(/^"|"$/g, '')
914 | .replace(/'/g, "\\'")
915 | .replace(/\\"/g, '"') + '\'';
916 | return ctx.stylize(simple, 'string');
917 | }
918 | if (isNumber(value))
919 | return ctx.stylize('' + value, 'number');
920 | if (isBoolean(value))
921 | return ctx.stylize('' + value, 'boolean');
922 | // For some reason typeof null is "object", so special case here.
923 | if (isNull(value))
924 | return ctx.stylize('null', 'null');
925 | }
926 |
927 |
928 | function formatError(value) {
929 | return '[' + Error.prototype.toString.call(value) + ']';
930 | }
931 |
932 |
933 | function formatArray(ctx, value, recurseTimes, visibleKeys, keys) {
934 | var output = [];
935 | for (var i = 0, l = value.length; i < l; ++i) {
936 | if (hasOwnProperty(value, String(i))) {
937 | output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,
938 | String(i), true));
939 | } else {
940 | output.push('');
941 | }
942 | }
943 | keys.forEach(function(key) {
944 | if (!key.match(/^\d+$/)) {
945 | output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,
946 | key, true));
947 | }
948 | });
949 | return output;
950 | }
951 |
952 |
953 | function formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) {
954 | var name, str, desc;
955 | desc = Object.getOwnPropertyDescriptor(value, key) || { value: value[key] };
956 | if (desc.get) {
957 | if (desc.set) {
958 | str = ctx.stylize('[Getter/Setter]', 'special');
959 | } else {
960 | str = ctx.stylize('[Getter]', 'special');
961 | }
962 | } else {
963 | if (desc.set) {
964 | str = ctx.stylize('[Setter]', 'special');
965 | }
966 | }
967 | if (!hasOwnProperty(visibleKeys, key)) {
968 | name = '[' + key + ']';
969 | }
970 | if (!str) {
971 | if (ctx.seen.indexOf(desc.value) < 0) {
972 | if (isNull(recurseTimes)) {
973 | str = formatValue(ctx, desc.value, null);
974 | } else {
975 | str = formatValue(ctx, desc.value, recurseTimes - 1);
976 | }
977 | if (str.indexOf('\n') > -1) {
978 | if (array) {
979 | str = str.split('\n').map(function(line) {
980 | return ' ' + line;
981 | }).join('\n').substr(2);
982 | } else {
983 | str = '\n' + str.split('\n').map(function(line) {
984 | return ' ' + line;
985 | }).join('\n');
986 | }
987 | }
988 | } else {
989 | str = ctx.stylize('[Circular]', 'special');
990 | }
991 | }
992 | if (isUndefined(name)) {
993 | if (array && key.match(/^\d+$/)) {
994 | return str;
995 | }
996 | name = JSON.stringify('' + key);
997 | if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) {
998 | name = name.substr(1, name.length - 2);
999 | name = ctx.stylize(name, 'name');
1000 | } else {
1001 | name = name.replace(/'/g, "\\'")
1002 | .replace(/\\"/g, '"')
1003 | .replace(/(^"|"$)/g, "'");
1004 | name = ctx.stylize(name, 'string');
1005 | }
1006 | }
1007 |
1008 | return name + ': ' + str;
1009 | }
1010 |
1011 |
1012 | function reduceToSingleString(output, base, braces) {
1013 | var numLinesEst = 0;
1014 | var length = output.reduce(function(prev, cur) {
1015 | numLinesEst++;
1016 | if (cur.indexOf('\n') >= 0) numLinesEst++;
1017 | return prev + cur.replace(/\u001b\[\d\d?m/g, '').length + 1;
1018 | }, 0);
1019 |
1020 | if (length > 60) {
1021 | return braces[0] +
1022 | (base === '' ? '' : base + '\n ') +
1023 | ' ' +
1024 | output.join(',\n ') +
1025 | ' ' +
1026 | braces[1];
1027 | }
1028 |
1029 | return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];
1030 | }
1031 |
1032 |
1033 | // NOTE: These type checking functions intentionally don't use `instanceof`
1034 | // because it is fragile and can be easily faked with `Object.create()`.
1035 | function isArray(ar) {
1036 | return Array.isArray(ar);
1037 | }
1038 | exports.isArray = isArray;
1039 |
1040 | function isBoolean(arg) {
1041 | return typeof arg === 'boolean';
1042 | }
1043 | exports.isBoolean = isBoolean;
1044 |
1045 | function isNull(arg) {
1046 | return arg === null;
1047 | }
1048 | exports.isNull = isNull;
1049 |
1050 | function isNullOrUndefined(arg) {
1051 | return arg == null;
1052 | }
1053 | exports.isNullOrUndefined = isNullOrUndefined;
1054 |
1055 | function isNumber(arg) {
1056 | return typeof arg === 'number';
1057 | }
1058 | exports.isNumber = isNumber;
1059 |
1060 | function isString(arg) {
1061 | return typeof arg === 'string';
1062 | }
1063 | exports.isString = isString;
1064 |
1065 | function isSymbol(arg) {
1066 | return typeof arg === 'symbol';
1067 | }
1068 | exports.isSymbol = isSymbol;
1069 |
1070 | function isUndefined(arg) {
1071 | return arg === void 0;
1072 | }
1073 | exports.isUndefined = isUndefined;
1074 |
1075 | function isRegExp(re) {
1076 | return isObject(re) && objectToString(re) === '[object RegExp]';
1077 | }
1078 | exports.isRegExp = isRegExp;
1079 |
1080 | function isObject(arg) {
1081 | return typeof arg === 'object' && arg !== null;
1082 | }
1083 | exports.isObject = isObject;
1084 |
1085 | function isDate(d) {
1086 | return isObject(d) && objectToString(d) === '[object Date]';
1087 | }
1088 | exports.isDate = isDate;
1089 |
1090 | function isError(e) {
1091 | return isObject(e) &&
1092 | (objectToString(e) === '[object Error]' || e instanceof Error);
1093 | }
1094 | exports.isError = isError;
1095 |
1096 | function isFunction(arg) {
1097 | return typeof arg === 'function';
1098 | }
1099 | exports.isFunction = isFunction;
1100 |
1101 | function isPrimitive(arg) {
1102 | return arg === null ||
1103 | typeof arg === 'boolean' ||
1104 | typeof arg === 'number' ||
1105 | typeof arg === 'string' ||
1106 | typeof arg === 'symbol' || // ES6 symbol
1107 | typeof arg === 'undefined';
1108 | }
1109 | exports.isPrimitive = isPrimitive;
1110 |
1111 | exports.isBuffer = require('./support/isBuffer');
1112 |
1113 | function objectToString(o) {
1114 | return Object.prototype.toString.call(o);
1115 | }
1116 |
1117 |
1118 | function pad(n) {
1119 | return n < 10 ? '0' + n.toString(10) : n.toString(10);
1120 | }
1121 |
1122 |
1123 | var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
1124 | 'Oct', 'Nov', 'Dec'];
1125 |
1126 | // 26 Feb 16:19:34
1127 | function timestamp() {
1128 | var d = new Date();
1129 | var time = [pad(d.getHours()),
1130 | pad(d.getMinutes()),
1131 | pad(d.getSeconds())].join(':');
1132 | return [d.getDate(), months[d.getMonth()], time].join(' ');
1133 | }
1134 |
1135 |
1136 | // log is just a thin wrapper to console.log that prepends a timestamp
1137 | exports.log = function() {
1138 | console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments));
1139 | };
1140 |
1141 |
1142 | /**
1143 | * Inherit the prototype methods from one constructor into another.
1144 | *
1145 | * The Function.prototype.inherits from lang.js rewritten as a standalone
1146 | * function (not on Function.prototype). NOTE: If this file is to be loaded
1147 | * during bootstrapping this function needs to be rewritten using some native
1148 | * functions as prototype setup using normal JavaScript does not work as
1149 | * expected during bootstrapping (see mirror.js in r114903).
1150 | *
1151 | * @param {function} ctor Constructor function which needs to inherit the
1152 | * prototype.
1153 | * @param {function} superCtor Constructor function to inherit prototype from.
1154 | */
1155 | exports.inherits = require('inherits');
1156 |
1157 | exports._extend = function(origin, add) {
1158 | // Don't do anything if add isn't an object
1159 | if (!add || !isObject(add)) return origin;
1160 |
1161 | var keys = Object.keys(add);
1162 | var i = keys.length;
1163 | while (i--) {
1164 | origin[keys[i]] = add[keys[i]];
1165 | }
1166 | return origin;
1167 | };
1168 |
1169 | function hasOwnProperty(obj, prop) {
1170 | return Object.prototype.hasOwnProperty.call(obj, prop);
1171 | }
1172 |
1173 | }).call(this,require("JkpR2F"),typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
1174 | },{"./support/isBuffer":7,"JkpR2F":3,"inherits":6}],9:[function(require,module,exports){
1175 | module.exports = function(obj) {
1176 | if (typeof obj === 'string') return camelCase(obj);
1177 | return walk(obj);
1178 | };
1179 |
1180 | function walk (obj) {
1181 | if (!obj || typeof obj !== 'object') return obj;
1182 | if (isArray(obj)) return map(obj, walk);
1183 | return reduce(objectKeys(obj), function (acc, key) {
1184 | var camel = camelCase(key);
1185 | acc[camel] = walk(obj[key]);
1186 | return acc;
1187 | }, {});
1188 | }
1189 |
1190 | function camelCase(str) {
1191 | return str.replace(/[_.-](\w|$)/g, function (_,x) {
1192 | return x.toUpperCase()
1193 | });
1194 | }
1195 |
1196 | var isArray = Array.isArray || function (obj) {
1197 | return Object.prototype.toString.call(obj) === '[object Array]';
1198 | };
1199 |
1200 | var has = Object.prototype.hasOwnProperty;
1201 | var objectKeys = Object.keys || function (obj) {
1202 | var keys = [];
1203 | for (var key in obj) {
1204 | if (has.call(obj, key)) keys.push(key);
1205 | }
1206 | return keys;
1207 | };
1208 |
1209 | function map (xs, f) {
1210 | if (xs.map) return xs.map(f);
1211 | var res = [];
1212 | for (var i = 0; i < xs.length; i++) {
1213 | res.push(f(xs[i], i));
1214 | }
1215 | return res;
1216 | }
1217 |
1218 | function reduce (xs, f, acc) {
1219 | if (xs.reduce) return xs.reduce(f, acc);
1220 | for (var i = 0; i < xs.length; i++) {
1221 | acc = f(acc, xs[i], i);
1222 | }
1223 | return acc;
1224 | }
1225 |
1226 | },{}],10:[function(require,module,exports){
1227 | var nargs = /\{([0-9a-zA-Z]+)\}/g
1228 | var slice = Array.prototype.slice
1229 |
1230 | module.exports = template
1231 |
1232 | function template(string) {
1233 | var args
1234 |
1235 | if (arguments.length === 2 && typeof arguments[1] === "object") {
1236 | args = arguments[1]
1237 | } else {
1238 | args = slice.call(arguments, 1)
1239 | }
1240 |
1241 | if (!args || !args.hasOwnProperty) {
1242 | args = {}
1243 | }
1244 |
1245 | return string.replace(nargs, function replaceArg(match, i, index) {
1246 | var result
1247 |
1248 | if (string[index - 1] === "{" &&
1249 | string[index + match.length] === "}") {
1250 | return i
1251 | } else {
1252 | result = args.hasOwnProperty(i) ? args[i] : null
1253 | if (result === null || result === undefined) {
1254 | return ""
1255 | }
1256 |
1257 | return result
1258 | }
1259 | })
1260 | }
1261 | },{}],11:[function(require,module,exports){
1262 | module.exports = hasKeys
1263 |
1264 | function hasKeys(source) {
1265 | return source !== null &&
1266 | (typeof source === "object" ||
1267 | typeof source === "function")
1268 | }
1269 |
1270 | },{}],12:[function(require,module,exports){
1271 | var Keys = require("object-keys")
1272 | var hasKeys = require("./has-keys")
1273 |
1274 | module.exports = extend
1275 |
1276 | function extend(target) {
1277 | var sources = [].slice.call(arguments, 1)
1278 |
1279 | for (var i = 0; i < sources.length; i++) {
1280 | var source = sources[i]
1281 |
1282 | if (!hasKeys(source)) {
1283 | continue
1284 | }
1285 |
1286 | var keys = Keys(source)
1287 |
1288 | for (var j = 0; j < keys.length; j++) {
1289 | var name = keys[j]
1290 | target[name] = source[name]
1291 | }
1292 | }
1293 |
1294 | return target
1295 | }
1296 |
1297 | },{"./has-keys":11,"object-keys":14}],13:[function(require,module,exports){
1298 | var hasOwn = Object.prototype.hasOwnProperty;
1299 | var toString = Object.prototype.toString;
1300 |
1301 | var isFunction = function (fn) {
1302 | var isFunc = (typeof fn === 'function' && !(fn instanceof RegExp)) || toString.call(fn) === '[object Function]';
1303 | if (!isFunc && typeof window !== 'undefined') {
1304 | isFunc = fn === window.setTimeout || fn === window.alert || fn === window.confirm || fn === window.prompt;
1305 | }
1306 | return isFunc;
1307 | };
1308 |
1309 | module.exports = function forEach(obj, fn) {
1310 | if (!isFunction(fn)) {
1311 | throw new TypeError('iterator must be a function');
1312 | }
1313 | var i, k,
1314 | isString = typeof obj === 'string',
1315 | l = obj.length,
1316 | context = arguments.length > 2 ? arguments[2] : null;
1317 | if (l === +l) {
1318 | for (i = 0; i < l; i++) {
1319 | if (context === null) {
1320 | fn(isString ? obj.charAt(i) : obj[i], i, obj);
1321 | } else {
1322 | fn.call(context, isString ? obj.charAt(i) : obj[i], i, obj);
1323 | }
1324 | }
1325 | } else {
1326 | for (k in obj) {
1327 | if (hasOwn.call(obj, k)) {
1328 | if (context === null) {
1329 | fn(obj[k], k, obj);
1330 | } else {
1331 | fn.call(context, obj[k], k, obj);
1332 | }
1333 | }
1334 | }
1335 | }
1336 | };
1337 |
1338 |
1339 | },{}],14:[function(require,module,exports){
1340 | module.exports = Object.keys || require('./shim');
1341 |
1342 |
1343 | },{"./shim":16}],15:[function(require,module,exports){
1344 | var toString = Object.prototype.toString;
1345 |
1346 | module.exports = function isArguments(value) {
1347 | var str = toString.call(value);
1348 | var isArguments = str === '[object Arguments]';
1349 | if (!isArguments) {
1350 | isArguments = str !== '[object Array]'
1351 | && value !== null
1352 | && typeof value === 'object'
1353 | && typeof value.length === 'number'
1354 | && value.length >= 0
1355 | && toString.call(value.callee) === '[object Function]';
1356 | }
1357 | return isArguments;
1358 | };
1359 |
1360 |
1361 | },{}],16:[function(require,module,exports){
1362 | (function () {
1363 | "use strict";
1364 |
1365 | // modified from https://github.com/kriskowal/es5-shim
1366 | var has = Object.prototype.hasOwnProperty,
1367 | toString = Object.prototype.toString,
1368 | forEach = require('./foreach'),
1369 | isArgs = require('./isArguments'),
1370 | hasDontEnumBug = !({'toString': null}).propertyIsEnumerable('toString'),
1371 | hasProtoEnumBug = (function () {}).propertyIsEnumerable('prototype'),
1372 | dontEnums = [
1373 | "toString",
1374 | "toLocaleString",
1375 | "valueOf",
1376 | "hasOwnProperty",
1377 | "isPrototypeOf",
1378 | "propertyIsEnumerable",
1379 | "constructor"
1380 | ],
1381 | keysShim;
1382 |
1383 | keysShim = function keys(object) {
1384 | var isObject = object !== null && typeof object === 'object',
1385 | isFunction = toString.call(object) === '[object Function]',
1386 | isArguments = isArgs(object),
1387 | theKeys = [];
1388 |
1389 | if (!isObject && !isFunction && !isArguments) {
1390 | throw new TypeError("Object.keys called on a non-object");
1391 | }
1392 |
1393 | if (isArguments) {
1394 | forEach(object, function (value) {
1395 | theKeys.push(value);
1396 | });
1397 | } else {
1398 | var name,
1399 | skipProto = hasProtoEnumBug && isFunction;
1400 |
1401 | for (name in object) {
1402 | if (!(skipProto && name === 'prototype') && has.call(object, name)) {
1403 | theKeys.push(name);
1404 | }
1405 | }
1406 | }
1407 |
1408 | if (hasDontEnumBug) {
1409 | var ctor = object.constructor,
1410 | skipConstructor = ctor && ctor.prototype === object;
1411 |
1412 | forEach(dontEnums, function (dontEnum) {
1413 | if (!(skipConstructor && dontEnum === 'constructor') && has.call(object, dontEnum)) {
1414 | theKeys.push(dontEnum);
1415 | }
1416 | });
1417 | }
1418 | return theKeys;
1419 | };
1420 |
1421 | module.exports = keysShim;
1422 | }());
1423 |
1424 |
1425 | },{"./foreach":13,"./isArguments":15}],17:[function(require,module,exports){
1426 | var assert = require("assert/")
1427 | var camelize = require("camelize")
1428 | var template = require("string-template")
1429 | var extend = require("xtend/mutable")
1430 |
1431 | module.exports = TypedError
1432 |
1433 | function TypedError(args) {
1434 | assert(args, "args is required");
1435 | assert(args.type, "args.type is required")
1436 | assert(args.message, "args.message is required")
1437 |
1438 | var message = args.message
1439 |
1440 | if (args.type && !args.name) {
1441 | var errorName = camelize(args.type) + "Error"
1442 | args.name = errorName[0].toUpperCase() + errorName.substr(1)
1443 | }
1444 |
1445 | createError.type = args.type;
1446 | createError._name = args.name;
1447 |
1448 | return createError;
1449 |
1450 | function createError(opts) {
1451 | var result = new Error()
1452 |
1453 | Object.defineProperty(result, "type", {
1454 | value: result.type,
1455 | enumerable: true,
1456 | writable: true,
1457 | configurable: true
1458 | })
1459 |
1460 | var options = extend({}, args, opts)
1461 |
1462 | extend(result, options)
1463 | result.message = template(message, options)
1464 |
1465 | return result
1466 | }
1467 | }
1468 |
1469 |
1470 | },{"assert/":5,"camelize":9,"string-template":10,"xtend/mutable":12}],18:[function(require,module,exports){
1471 | var isObject = require("is-object")
1472 | var isHook = require("vtree/is-vhook")
1473 |
1474 | module.exports = applyProperties
1475 |
1476 | function applyProperties(node, props, previous) {
1477 | for (var propName in props) {
1478 | var propValue = props[propName]
1479 |
1480 | if (propValue === undefined) {
1481 | removeProperty(node, props, previous, propName);
1482 | } else if (isHook(propValue)) {
1483 | propValue.hook(node,
1484 | propName,
1485 | previous ? previous[propName] : undefined)
1486 | } else {
1487 | if (isObject(propValue)) {
1488 | patchObject(node, props, previous, propName, propValue);
1489 | } else if (propValue !== undefined) {
1490 | node[propName] = propValue
1491 | }
1492 | }
1493 | }
1494 | }
1495 |
1496 | function removeProperty(node, props, previous, propName) {
1497 | if (previous) {
1498 | var previousValue = previous[propName]
1499 |
1500 | if (!isHook(previousValue)) {
1501 | if (propName === "style") {
1502 | for (var i in previousValue) {
1503 | node.style[i] = ""
1504 | }
1505 | } else if (typeof previousValue === "string") {
1506 | node[propName] = ""
1507 | } else {
1508 | node[propName] = null
1509 | }
1510 | }
1511 | }
1512 | }
1513 |
1514 | function patchObject(node, props, previous, propName, propValue) {
1515 | if(previous && isObject(previous[propName]) &&
1516 | getPrototype(previous[propName]) !== getPrototype(propValue)) {
1517 | node[propName] = previousValue
1518 | return
1519 | }
1520 |
1521 | if (!isObject(node[propName])) {
1522 | node[propName] = {}
1523 | }
1524 |
1525 | var replacer = propName === "style" ? "" : undefined
1526 |
1527 | for (var k in propValue) {
1528 | var value = propValue[k]
1529 | node[propName][k] = (value === undefined) ? replacer : value
1530 | }
1531 | }
1532 |
1533 | function getPrototype(value) {
1534 | if (Object.getPrototypeOf) {
1535 | return Object.getPrototypeOf(value)
1536 | } else if (value.__proto__) {
1537 | return value.__proto__
1538 | } else if (value.constructor) {
1539 | return value.constructor.prototype
1540 | }
1541 | }
1542 |
1543 | },{"is-object":22,"vtree/is-vhook":30}],19:[function(require,module,exports){
1544 | var document = require("global/document")
1545 |
1546 | var applyProperties = require("./apply-properties")
1547 |
1548 | var isVNode = require("vtree/is-vnode")
1549 | var isVText = require("vtree/is-vtext")
1550 | var isWidget = require("vtree/is-widget")
1551 | var handleThunk = require("vtree/handle-thunk")
1552 |
1553 | module.exports = createElement
1554 |
1555 | function createElement(vnode, opts) {
1556 | var doc = opts ? opts.document || document : document
1557 | var warn = opts ? opts.warn : null
1558 |
1559 | vnode = handleThunk(vnode).a
1560 |
1561 | if (isWidget(vnode)) {
1562 | return vnode.init()
1563 | } else if (isVText(vnode)) {
1564 | return doc.createTextNode(vnode.text)
1565 | } else if (!isVNode(vnode)) {
1566 | if (warn) {
1567 | warn("Item is not a valid virtual dom node", vnode)
1568 | }
1569 | return null
1570 | }
1571 |
1572 | var node = (vnode.namespace === null) ?
1573 | doc.createElement(vnode.tagName) :
1574 | doc.createElementNS(vnode.namespace, vnode.tagName)
1575 |
1576 | var props = vnode.properties
1577 | applyProperties(node, props)
1578 |
1579 | var children = vnode.children
1580 |
1581 | for (var i = 0; i < children.length; i++) {
1582 | var childNode = createElement(children[i], opts)
1583 | if (childNode) {
1584 | node.appendChild(childNode)
1585 | }
1586 | }
1587 |
1588 | return node
1589 | }
1590 |
1591 | },{"./apply-properties":18,"global/document":21,"vtree/handle-thunk":28,"vtree/is-vnode":31,"vtree/is-vtext":32,"vtree/is-widget":33}],20:[function(require,module,exports){
1592 | // Maps a virtual DOM tree onto a real DOM tree in an efficient manner.
1593 | // We don't want to read all of the DOM nodes in the tree so we use
1594 | // the in-order tree indexing to eliminate recursion down certain branches.
1595 | // We only recurse into a DOM node if we know that it contains a child of
1596 | // interest.
1597 |
1598 | var noChild = {}
1599 |
1600 | module.exports = domIndex
1601 |
1602 | function domIndex(rootNode, tree, indices, nodes) {
1603 | if (!indices || indices.length === 0) {
1604 | return {}
1605 | } else {
1606 | indices.sort(ascending)
1607 | return recurse(rootNode, tree, indices, nodes, 0)
1608 | }
1609 | }
1610 |
1611 | function recurse(rootNode, tree, indices, nodes, rootIndex) {
1612 | nodes = nodes || {}
1613 |
1614 |
1615 | if (rootNode) {
1616 | if (indexInRange(indices, rootIndex, rootIndex)) {
1617 | nodes[rootIndex] = rootNode
1618 | }
1619 |
1620 | var vChildren = tree.children
1621 |
1622 | if (vChildren) {
1623 |
1624 | var childNodes = rootNode.childNodes
1625 |
1626 | for (var i = 0; i < tree.children.length; i++) {
1627 | rootIndex += 1
1628 |
1629 | var vChild = vChildren[i] || noChild
1630 | var nextIndex = rootIndex + (vChild.count || 0)
1631 |
1632 | // skip recursion down the tree if there are no nodes down here
1633 | if (indexInRange(indices, rootIndex, nextIndex)) {
1634 | recurse(childNodes[i], vChild, indices, nodes, rootIndex)
1635 | }
1636 |
1637 | rootIndex = nextIndex
1638 | }
1639 | }
1640 | }
1641 |
1642 | return nodes
1643 | }
1644 |
1645 | // Binary search for an index in the interval [left, right]
1646 | function indexInRange(indices, left, right) {
1647 | if (indices.length === 0) {
1648 | return false
1649 | }
1650 |
1651 | var minIndex = 0
1652 | var maxIndex = indices.length - 1
1653 | var currentIndex
1654 | var currentItem
1655 |
1656 | while (minIndex <= maxIndex) {
1657 | currentIndex = ((maxIndex + minIndex) / 2) >> 0
1658 | currentItem = indices[currentIndex]
1659 |
1660 | if (minIndex === maxIndex) {
1661 | return currentItem >= left && currentItem <= right
1662 | } else if (currentItem < left) {
1663 | minIndex = currentIndex + 1
1664 | } else if (currentItem > right) {
1665 | maxIndex = currentIndex - 1
1666 | } else {
1667 | return true
1668 | }
1669 | }
1670 |
1671 | return false;
1672 | }
1673 |
1674 | function ascending(a, b) {
1675 | return a > b ? 1 : -1
1676 | }
1677 |
1678 | },{}],21:[function(require,module,exports){
1679 | (function (global){
1680 | var topLevel = typeof global !== 'undefined' ? global :
1681 | typeof window !== 'undefined' ? window : {}
1682 | var minDoc = require('min-document');
1683 |
1684 | if (typeof document !== 'undefined') {
1685 | module.exports = document;
1686 | } else {
1687 | var doccy = topLevel['__GLOBAL_DOCUMENT_CACHE@4'];
1688 |
1689 | if (!doccy) {
1690 | doccy = topLevel['__GLOBAL_DOCUMENT_CACHE@4'] = minDoc;
1691 | }
1692 |
1693 | module.exports = doccy;
1694 | }
1695 |
1696 | }).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
1697 | },{"min-document":2}],22:[function(require,module,exports){
1698 | module.exports = isObject
1699 |
1700 | function isObject(x) {
1701 | return typeof x === "object" && x !== null
1702 | }
1703 |
1704 | },{}],23:[function(require,module,exports){
1705 | var nativeIsArray = Array.isArray
1706 | var toString = Object.prototype.toString
1707 |
1708 | module.exports = nativeIsArray || isArray
1709 |
1710 | function isArray(obj) {
1711 | return toString.call(obj) === "[object Array]"
1712 | }
1713 |
1714 | },{}],24:[function(require,module,exports){
1715 | var applyProperties = require("./apply-properties")
1716 |
1717 | var isWidget = require("vtree/is-widget")
1718 | var VPatch = require("vtree/vpatch")
1719 |
1720 | var render = require("./create-element")
1721 | var updateWidget = require("./update-widget")
1722 |
1723 | module.exports = applyPatch
1724 |
1725 | function applyPatch(vpatch, domNode, renderOptions) {
1726 | var type = vpatch.type
1727 | var vNode = vpatch.vNode
1728 | var patch = vpatch.patch
1729 |
1730 | switch (type) {
1731 | case VPatch.REMOVE:
1732 | return removeNode(domNode, vNode)
1733 | case VPatch.INSERT:
1734 | return insertNode(domNode, patch, renderOptions)
1735 | case VPatch.VTEXT:
1736 | return stringPatch(domNode, vNode, patch, renderOptions)
1737 | case VPatch.WIDGET:
1738 | return widgetPatch(domNode, vNode, patch, renderOptions)
1739 | case VPatch.VNODE:
1740 | return vNodePatch(domNode, vNode, patch, renderOptions)
1741 | case VPatch.ORDER:
1742 | reorderChildren(domNode, patch)
1743 | return domNode
1744 | case VPatch.PROPS:
1745 | applyProperties(domNode, patch, vNode.properties)
1746 | return domNode
1747 | case VPatch.THUNK:
1748 | return replaceRoot(domNode,
1749 | renderOptions.patch(domNode, patch, renderOptions))
1750 | default:
1751 | return domNode
1752 | }
1753 | }
1754 |
1755 | function removeNode(domNode, vNode) {
1756 | var parentNode = domNode.parentNode
1757 |
1758 | if (parentNode) {
1759 | parentNode.removeChild(domNode)
1760 | }
1761 |
1762 | destroyWidget(domNode, vNode);
1763 |
1764 | return null
1765 | }
1766 |
1767 | function insertNode(parentNode, vNode, renderOptions) {
1768 | var newNode = render(vNode, renderOptions)
1769 |
1770 | if (parentNode) {
1771 | parentNode.appendChild(newNode)
1772 | }
1773 |
1774 | return parentNode
1775 | }
1776 |
1777 | function stringPatch(domNode, leftVNode, vText, renderOptions) {
1778 | var newNode
1779 |
1780 | if (domNode.nodeType === 3) {
1781 | domNode.replaceData(0, domNode.length, vText.text)
1782 | newNode = domNode
1783 | } else {
1784 | var parentNode = domNode.parentNode
1785 | newNode = render(vText, renderOptions)
1786 |
1787 | if (parentNode) {
1788 | parentNode.replaceChild(newNode, domNode)
1789 | }
1790 | }
1791 |
1792 | destroyWidget(domNode, leftVNode)
1793 |
1794 | return newNode
1795 | }
1796 |
1797 | function widgetPatch(domNode, leftVNode, widget, renderOptions) {
1798 | if (updateWidget(leftVNode, widget)) {
1799 | return widget.update(leftVNode, domNode) || domNode
1800 | }
1801 |
1802 | var parentNode = domNode.parentNode
1803 | var newWidget = render(widget, renderOptions)
1804 |
1805 | if (parentNode) {
1806 | parentNode.replaceChild(newWidget, domNode)
1807 | }
1808 |
1809 | destroyWidget(domNode, leftVNode)
1810 |
1811 | return newWidget
1812 | }
1813 |
1814 | function vNodePatch(domNode, leftVNode, vNode, renderOptions) {
1815 | var parentNode = domNode.parentNode
1816 | var newNode = render(vNode, renderOptions)
1817 |
1818 | if (parentNode) {
1819 | parentNode.replaceChild(newNode, domNode)
1820 | }
1821 |
1822 | destroyWidget(domNode, leftVNode)
1823 |
1824 | return newNode
1825 | }
1826 |
1827 | function destroyWidget(domNode, w) {
1828 | if (typeof w.destroy === "function" && isWidget(w)) {
1829 | w.destroy(domNode)
1830 | }
1831 | }
1832 |
1833 | function reorderChildren(domNode, bIndex) {
1834 | var children = []
1835 | var childNodes = domNode.childNodes
1836 | var len = childNodes.length
1837 | var i
1838 | var reverseIndex = bIndex.reverse
1839 |
1840 | for (i = 0; i < len; i++) {
1841 | children.push(domNode.childNodes[i])
1842 | }
1843 |
1844 | var insertOffset = 0
1845 | var move
1846 | var node
1847 | var insertNode
1848 | for (i = 0; i < len; i++) {
1849 | move = bIndex[i]
1850 | if (move !== undefined && move !== i) {
1851 | // the element currently at this index will be moved later so increase the insert offset
1852 | if (reverseIndex[i] > i) {
1853 | insertOffset++
1854 | }
1855 |
1856 | node = children[move]
1857 | insertNode = childNodes[i + insertOffset]
1858 | if (node !== insertNode) {
1859 | domNode.insertBefore(node, insertNode)
1860 | }
1861 |
1862 | // the moved element came from the front of the array so reduce the insert offset
1863 | if (move < i) {
1864 | insertOffset--
1865 | }
1866 | }
1867 |
1868 | // element at this index is scheduled to be removed so increase insert offset
1869 | if (i in bIndex.removes) {
1870 | insertOffset++
1871 | }
1872 | }
1873 | }
1874 |
1875 | function replaceRoot(oldRoot, newRoot) {
1876 | if (oldRoot && newRoot && oldRoot !== newRoot && oldRoot.parentNode) {
1877 | console.log(oldRoot)
1878 | oldRoot.parentNode.replaceChild(newRoot, oldRoot)
1879 | }
1880 |
1881 | return newRoot;
1882 | }
1883 |
1884 | },{"./apply-properties":18,"./create-element":19,"./update-widget":26,"vtree/is-widget":33,"vtree/vpatch":37}],25:[function(require,module,exports){
1885 | var document = require("global/document")
1886 | var isArray = require("x-is-array")
1887 |
1888 | var domIndex = require("./dom-index")
1889 | var patchOp = require("./patch-op")
1890 | module.exports = patch
1891 |
1892 | function patch(rootNode, patches) {
1893 | return patchRecursive(rootNode, patches)
1894 | }
1895 |
1896 | function patchRecursive(rootNode, patches, renderOptions) {
1897 | var indices = patchIndices(patches)
1898 |
1899 | if (indices.length === 0) {
1900 | return rootNode
1901 | }
1902 |
1903 | var index = domIndex(rootNode, patches.a, indices)
1904 | var ownerDocument = rootNode.ownerDocument
1905 |
1906 | if (!renderOptions) {
1907 | renderOptions = { patch: patchRecursive }
1908 | if (ownerDocument !== document) {
1909 | renderOptions.document = ownerDocument
1910 | }
1911 | }
1912 |
1913 | for (var i = 0; i < indices.length; i++) {
1914 | var nodeIndex = indices[i]
1915 | rootNode = applyPatch(rootNode,
1916 | index[nodeIndex],
1917 | patches[nodeIndex],
1918 | renderOptions)
1919 | }
1920 |
1921 | return rootNode
1922 | }
1923 |
1924 | function applyPatch(rootNode, domNode, patchList, renderOptions) {
1925 | if (!domNode) {
1926 | return rootNode
1927 | }
1928 |
1929 | var newNode
1930 |
1931 | if (isArray(patchList)) {
1932 | for (var i = 0; i < patchList.length; i++) {
1933 | newNode = patchOp(patchList[i], domNode, renderOptions)
1934 |
1935 | if (domNode === rootNode) {
1936 | rootNode = newNode
1937 | }
1938 | }
1939 | } else {
1940 | newNode = patchOp(patchList, domNode, renderOptions)
1941 |
1942 | if (domNode === rootNode) {
1943 | rootNode = newNode
1944 | }
1945 | }
1946 |
1947 | return rootNode
1948 | }
1949 |
1950 | function patchIndices(patches) {
1951 | var indices = []
1952 |
1953 | for (var key in patches) {
1954 | if (key !== "a") {
1955 | indices.push(Number(key))
1956 | }
1957 | }
1958 |
1959 | return indices
1960 | }
1961 |
1962 | },{"./dom-index":20,"./patch-op":24,"global/document":21,"x-is-array":23}],26:[function(require,module,exports){
1963 | var isWidget = require("vtree/is-widget")
1964 |
1965 | module.exports = updateWidget
1966 |
1967 | function updateWidget(a, b) {
1968 | if (isWidget(a) && isWidget(b)) {
1969 | if ("name" in a && "name" in b) {
1970 | return a.id === b.id
1971 | } else {
1972 | return a.init === b.init
1973 | }
1974 | }
1975 |
1976 | return false
1977 | }
1978 |
1979 | },{"vtree/is-widget":33}],27:[function(require,module,exports){
1980 | var isArray = require("x-is-array")
1981 | var isObject = require("is-object")
1982 |
1983 | var VPatch = require("./vpatch")
1984 | var isVNode = require("./is-vnode")
1985 | var isVText = require("./is-vtext")
1986 | var isWidget = require("./is-widget")
1987 | var isThunk = require("./is-thunk")
1988 | var handleThunk = require("./handle-thunk")
1989 |
1990 | module.exports = diff
1991 |
1992 | function diff(a, b) {
1993 | var patch = { a: a }
1994 | walk(a, b, patch, 0)
1995 | return patch
1996 | }
1997 |
1998 | function walk(a, b, patch, index) {
1999 | if (a === b) {
2000 | if (isThunk(a) || isThunk(b)) {
2001 | thunks(a, b, patch, index)
2002 | } else {
2003 | hooks(b, patch, index)
2004 | }
2005 | return
2006 | }
2007 |
2008 | var apply = patch[index]
2009 |
2010 | if (b == null) {
2011 | apply = appendPatch(apply, new VPatch(VPatch.REMOVE, a, b))
2012 | destroyWidgets(a, patch, index)
2013 | } else if (isThunk(a) || isThunk(b)) {
2014 | thunks(a, b, patch, index)
2015 | } else if (isVNode(b)) {
2016 | if (isVNode(a)) {
2017 | if (a.tagName === b.tagName &&
2018 | a.namespace === b.namespace &&
2019 | a.key === b.key) {
2020 | var propsPatch = diffProps(a.properties, b.properties, b.hooks)
2021 | if (propsPatch) {
2022 | apply = appendPatch(apply,
2023 | new VPatch(VPatch.PROPS, a, propsPatch))
2024 | }
2025 | } else {
2026 | apply = appendPatch(apply, new VPatch(VPatch.VNODE, a, b))
2027 | destroyWidgets(a, patch, index)
2028 | }
2029 |
2030 | apply = diffChildren(a, b, patch, apply, index)
2031 | } else {
2032 | apply = appendPatch(apply, new VPatch(VPatch.VNODE, a, b))
2033 | destroyWidgets(a, patch, index)
2034 | }
2035 | } else if (isVText(b)) {
2036 | if (!isVText(a)) {
2037 | apply = appendPatch(apply, new VPatch(VPatch.VTEXT, a, b))
2038 | destroyWidgets(a, patch, index)
2039 | } else if (a.text !== b.text) {
2040 | apply = appendPatch(apply, new VPatch(VPatch.VTEXT, a, b))
2041 | }
2042 | } else if (isWidget(b)) {
2043 | apply = appendPatch(apply, new VPatch(VPatch.WIDGET, a, b))
2044 |
2045 | if (!isWidget(a)) {
2046 | destroyWidgets(a, patch, index)
2047 | }
2048 | }
2049 |
2050 | if (apply) {
2051 | patch[index] = apply
2052 | }
2053 | }
2054 |
2055 | function diffProps(a, b, hooks) {
2056 | var diff
2057 |
2058 | for (var aKey in a) {
2059 | if (!(aKey in b)) {
2060 | diff = diff || {}
2061 | diff[aKey] = undefined
2062 | }
2063 |
2064 | var aValue = a[aKey]
2065 | var bValue = b[aKey]
2066 |
2067 | if (hooks && aKey in hooks) {
2068 | diff = diff || {}
2069 | diff[aKey] = bValue
2070 | } else {
2071 | if (isObject(aValue) && isObject(bValue)) {
2072 | if (getPrototype(bValue) !== getPrototype(aValue)) {
2073 | diff = diff || {}
2074 | diff[aKey] = bValue
2075 | } else {
2076 | var objectDiff = diffProps(aValue, bValue)
2077 | if (objectDiff) {
2078 | diff = diff || {}
2079 | diff[aKey] = objectDiff
2080 | }
2081 | }
2082 | } else if (aValue !== bValue) {
2083 | diff = diff || {}
2084 | diff[aKey] = bValue
2085 | }
2086 | }
2087 | }
2088 |
2089 | for (var bKey in b) {
2090 | if (!(bKey in a)) {
2091 | diff = diff || {}
2092 | diff[bKey] = b[bKey]
2093 | }
2094 | }
2095 |
2096 | return diff
2097 | }
2098 |
2099 | function getPrototype(value) {
2100 | if (Object.getPrototypeOf) {
2101 | return Object.getPrototypeOf(value)
2102 | } else if (value.__proto__) {
2103 | return value.__proto__
2104 | } else if (value.constructor) {
2105 | return value.constructor.prototype
2106 | }
2107 | }
2108 |
2109 | function diffChildren(a, b, patch, apply, index) {
2110 | var aChildren = a.children
2111 | var bChildren = reorder(aChildren, b.children)
2112 |
2113 | var aLen = aChildren.length
2114 | var bLen = bChildren.length
2115 | var len = aLen > bLen ? aLen : bLen
2116 |
2117 | for (var i = 0; i < len; i++) {
2118 | var leftNode = aChildren[i]
2119 | var rightNode = bChildren[i]
2120 | index += 1
2121 |
2122 | if (!leftNode) {
2123 | if (rightNode) {
2124 | // Excess nodes in b need to be added
2125 | apply = appendPatch(apply,
2126 | new VPatch(VPatch.INSERT, null, rightNode))
2127 | }
2128 | } else if (!rightNode) {
2129 | if (leftNode) {
2130 | // Excess nodes in a need to be removed
2131 | patch[index] = new VPatch(VPatch.REMOVE, leftNode, null)
2132 | destroyWidgets(leftNode, patch, index)
2133 | }
2134 | } else {
2135 | walk(leftNode, rightNode, patch, index)
2136 | }
2137 |
2138 | if (isVNode(leftNode) && leftNode.count) {
2139 | index += leftNode.count
2140 | }
2141 | }
2142 |
2143 | if (bChildren.moves) {
2144 | // Reorder nodes last
2145 | apply = appendPatch(apply, new VPatch(VPatch.ORDER, a, bChildren.moves))
2146 | }
2147 |
2148 | return apply
2149 | }
2150 |
2151 | // Patch records for all destroyed widgets must be added because we need
2152 | // a DOM node reference for the destroy function
2153 | function destroyWidgets(vNode, patch, index) {
2154 | if (isWidget(vNode)) {
2155 | if (typeof vNode.destroy === "function") {
2156 | patch[index] = new VPatch(VPatch.REMOVE, vNode, null)
2157 | }
2158 | } else if (isVNode(vNode) && vNode.hasWidgets) {
2159 | var children = vNode.children
2160 | var len = children.length
2161 | for (var i = 0; i < len; i++) {
2162 | var child = children[i]
2163 | index += 1
2164 |
2165 | destroyWidgets(child, patch, index)
2166 |
2167 | if (isVNode(child) && child.count) {
2168 | index += child.count
2169 | }
2170 | }
2171 | }
2172 | }
2173 |
2174 | // Create a sub-patch for thunks
2175 | function thunks(a, b, patch, index) {
2176 | var nodes = handleThunk(a, b);
2177 | var thunkPatch = diff(nodes.a, nodes.b)
2178 | if (hasPatches(thunkPatch)) {
2179 | patch[index] = new VPatch(VPatch.THUNK, null, thunkPatch)
2180 | }
2181 | }
2182 |
2183 | function hasPatches(patch) {
2184 | for (var index in patch) {
2185 | if (index !== "a") {
2186 | return true;
2187 | }
2188 | }
2189 |
2190 | return false;
2191 | }
2192 |
2193 | // Execute hooks when two nodes are identical
2194 | function hooks(vNode, patch, index) {
2195 | if (isVNode(vNode)) {
2196 | if (vNode.hooks) {
2197 | patch[index] = new VPatch(VPatch.PROPS, vNode.hooks, vNode.hooks)
2198 | }
2199 |
2200 | if (vNode.descendantHooks) {
2201 | var children = vNode.children
2202 | var len = children.length
2203 | for (var i = 0; i < len; i++) {
2204 | var child = children[i]
2205 | index += 1
2206 |
2207 | hooks(child, patch, index)
2208 |
2209 | if (isVNode(child) && child.count) {
2210 | index += child.count
2211 | }
2212 | }
2213 | }
2214 | }
2215 | }
2216 |
2217 | // List diff, naive left to right reordering
2218 | function reorder(aChildren, bChildren) {
2219 |
2220 | var bKeys = keyIndex(bChildren)
2221 |
2222 | if (!bKeys) {
2223 | return bChildren
2224 | }
2225 |
2226 | var aKeys = keyIndex(aChildren)
2227 |
2228 | if (!aKeys) {
2229 | return bChildren
2230 | }
2231 |
2232 | var bMatch = {}, aMatch = {}
2233 |
2234 | for (var key in bKeys) {
2235 | bMatch[bKeys[key]] = aKeys[key]
2236 | }
2237 |
2238 | for (var key in aKeys) {
2239 | aMatch[aKeys[key]] = bKeys[key]
2240 | }
2241 |
2242 | var aLen = aChildren.length
2243 | var bLen = bChildren.length
2244 | var len = aLen > bLen ? aLen : bLen
2245 | var shuffle = []
2246 | var freeIndex = 0
2247 | var i = 0
2248 | var moveIndex = 0
2249 | var moves = {}
2250 | var removes = moves.removes = {}
2251 | var reverse = moves.reverse = {}
2252 | var hasMoves = false
2253 |
2254 | while (freeIndex < len) {
2255 | var move = aMatch[i]
2256 | if (move !== undefined) {
2257 | shuffle[i] = bChildren[move]
2258 | if (move !== moveIndex) {
2259 | moves[move] = moveIndex
2260 | reverse[moveIndex] = move
2261 | hasMoves = true
2262 | }
2263 | moveIndex++
2264 | } else if (i in aMatch) {
2265 | shuffle[i] = undefined
2266 | removes[i] = moveIndex++
2267 | hasMoves = true
2268 | } else {
2269 | while (bMatch[freeIndex] !== undefined) {
2270 | freeIndex++
2271 | }
2272 |
2273 | if (freeIndex < len) {
2274 | var freeChild = bChildren[freeIndex]
2275 | if (freeChild) {
2276 | shuffle[i] = freeChild
2277 | if (freeIndex !== moveIndex) {
2278 | hasMoves = true
2279 | moves[freeIndex] = moveIndex
2280 | reverse[moveIndex] = freeIndex
2281 | }
2282 | moveIndex++
2283 | }
2284 | freeIndex++
2285 | }
2286 | }
2287 | i++
2288 | }
2289 |
2290 | if (hasMoves) {
2291 | shuffle.moves = moves
2292 | }
2293 |
2294 | return shuffle
2295 | }
2296 |
2297 | function keyIndex(children) {
2298 | var i, keys
2299 |
2300 | for (i = 0; i < children.length; i++) {
2301 | var child = children[i]
2302 |
2303 | if (child.key !== undefined) {
2304 | keys = keys || {}
2305 | keys[child.key] = i
2306 | }
2307 | }
2308 |
2309 | return keys
2310 | }
2311 |
2312 | function appendPatch(apply, patch) {
2313 | if (apply) {
2314 | if (isArray(apply)) {
2315 | apply.push(patch)
2316 | } else {
2317 | apply = [apply, patch]
2318 | }
2319 |
2320 | return apply
2321 | } else {
2322 | return patch
2323 | }
2324 | }
2325 |
2326 | },{"./handle-thunk":28,"./is-thunk":29,"./is-vnode":31,"./is-vtext":32,"./is-widget":33,"./vpatch":37,"is-object":34,"x-is-array":35}],28:[function(require,module,exports){
2327 | var isVNode = require("./is-vnode")
2328 | var isVText = require("./is-vtext")
2329 | var isWidget = require("./is-widget")
2330 | var isThunk = require("./is-thunk")
2331 |
2332 | module.exports = handleThunk
2333 |
2334 | function handleThunk(a, b) {
2335 | var renderedA = a
2336 | var renderedB = b
2337 |
2338 | if (isThunk(b)) {
2339 | renderedB = renderThunk(b, a)
2340 | }
2341 |
2342 | if (isThunk(a)) {
2343 | renderedA = renderThunk(a, null)
2344 | }
2345 |
2346 | return {
2347 | a: renderedA,
2348 | b: renderedB
2349 | }
2350 | }
2351 |
2352 | function renderThunk(thunk, previous) {
2353 | var renderedThunk = thunk.vnode
2354 |
2355 | if (!renderedThunk) {
2356 | renderedThunk = thunk.vnode = thunk.render(previous)
2357 | }
2358 |
2359 | if (!(isVNode(renderedThunk) ||
2360 | isVText(renderedThunk) ||
2361 | isWidget(renderedThunk))) {
2362 | throw new Error("thunk did not return a valid node");
2363 | }
2364 |
2365 | return renderedThunk
2366 | }
2367 |
2368 | },{"./is-thunk":29,"./is-vnode":31,"./is-vtext":32,"./is-widget":33}],29:[function(require,module,exports){
2369 | module.exports = isThunk
2370 |
2371 | function isThunk(t) {
2372 | return t && t.type === "Thunk"
2373 | }
2374 |
2375 | },{}],30:[function(require,module,exports){
2376 | module.exports = isHook
2377 |
2378 | function isHook(hook) {
2379 | return hook && typeof hook.hook === "function" &&
2380 | !hook.hasOwnProperty("hook")
2381 | }
2382 |
2383 | },{}],31:[function(require,module,exports){
2384 | var version = require("./version")
2385 |
2386 | module.exports = isVirtualNode
2387 |
2388 | function isVirtualNode(x) {
2389 | return x && x.type === "VirtualNode" && x.version === version
2390 | }
2391 |
2392 | },{"./version":36}],32:[function(require,module,exports){
2393 | var version = require("./version")
2394 |
2395 | module.exports = isVirtualText
2396 |
2397 | function isVirtualText(x) {
2398 | return x && x.type === "VirtualText" && x.version === version
2399 | }
2400 |
2401 | },{"./version":36}],33:[function(require,module,exports){
2402 | module.exports = isWidget
2403 |
2404 | function isWidget(w) {
2405 | return w && w.type === "Widget"
2406 | }
2407 |
2408 | },{}],34:[function(require,module,exports){
2409 | module.exports=require(22)
2410 | },{}],35:[function(require,module,exports){
2411 | module.exports=require(23)
2412 | },{}],36:[function(require,module,exports){
2413 | module.exports = "1"
2414 |
2415 | },{}],37:[function(require,module,exports){
2416 | var version = require("./version")
2417 |
2418 | VirtualPatch.NONE = 0
2419 | VirtualPatch.VTEXT = 1
2420 | VirtualPatch.VNODE = 2
2421 | VirtualPatch.WIDGET = 3
2422 | VirtualPatch.PROPS = 4
2423 | VirtualPatch.ORDER = 5
2424 | VirtualPatch.INSERT = 6
2425 | VirtualPatch.REMOVE = 7
2426 | VirtualPatch.THUNK = 8
2427 |
2428 | module.exports = VirtualPatch
2429 |
2430 | function VirtualPatch(type, vNode, patch) {
2431 | this.type = Number(type)
2432 | this.vNode = vNode
2433 | this.patch = patch
2434 | }
2435 |
2436 | VirtualPatch.prototype.version = version
2437 | VirtualPatch.prototype.type = "VirtualPatch"
2438 |
2439 | },{"./version":36}],38:[function(require,module,exports){
2440 | var SingleEvent = require("geval/single")
2441 | var MultipleEvent = require("geval/multiple")
2442 |
2443 | /*
2444 | Pro tip: Don't require `mercury` itself.
2445 | require and depend on all these modules directly!
2446 | */
2447 | var mercury = module.exports = {
2448 | // Entry
2449 | main: require("main-loop"),
2450 | app: app,
2451 |
2452 | // Input
2453 | Delegator: require("dom-delegator"),
2454 | input: input,
2455 | event: require("value-event/event"),
2456 | valueEvent: require("value-event/value"),
2457 | submitEvent: require("value-event/submit"),
2458 | changeEvent: require("value-event/change"),
2459 | keyEvent: require("value-event/key"),
2460 |
2461 | // State
2462 | array: require("observ-array"),
2463 | struct: require("observ-struct"),
2464 | // alias struct as hash for back compat
2465 | hash: require("observ-struct"),
2466 | varhash: require("observ-varhash"),
2467 | value: require("observ"),
2468 |
2469 | // Render
2470 | diff: require("vtree/diff"),
2471 | patch: require("vdom/patch"),
2472 | partial: require("vdom-thunk"),
2473 | create: require("vdom/create-element"),
2474 | h: require("virtual-hyperscript"),
2475 | svg: require("virtual-hyperscript/svg"),
2476 |
2477 | // Utilities
2478 | computed: require("observ/computed"),
2479 | watch: require("observ/watch")
2480 | }
2481 |
2482 | function input(names) {
2483 | if (!names) {
2484 | return SingleEvent()
2485 | }
2486 |
2487 | return MultipleEvent(names)
2488 | }
2489 |
2490 | function app(elem, observ, render, opts) {
2491 | mercury.Delegator(opts);
2492 | var loop = mercury.main(observ(), render, opts)
2493 | if (elem) {
2494 | elem.appendChild(loop.target)
2495 | }
2496 | return observ(loop.update)
2497 | }
2498 |
2499 | },{"dom-delegator":41,"geval/multiple":53,"geval/single":54,"main-loop":55,"observ":81,"observ-array":73,"observ-struct":76,"observ-varhash":78,"observ/computed":80,"observ/watch":82,"value-event/change":83,"value-event/event":84,"value-event/key":85,"value-event/submit":91,"value-event/value":92,"vdom-thunk":94,"vdom/create-element":98,"vdom/patch":104,"virtual-hyperscript":110,"virtual-hyperscript/svg":130,"vtree/diff":131}],39:[function(require,module,exports){
2500 | var DataSet = require("data-set")
2501 |
2502 | module.exports = addEvent
2503 |
2504 | function addEvent(target, type, handler) {
2505 | var ds = DataSet(target)
2506 | var events = ds[type]
2507 |
2508 | if (!events) {
2509 | ds[type] = handler
2510 | } else if (Array.isArray(events)) {
2511 | if (events.indexOf(handler) === -1) {
2512 | events.push(handler)
2513 | }
2514 | } else if (events !== handler) {
2515 | ds[type] = [events, handler]
2516 | }
2517 | }
2518 |
2519 | },{"data-set":44}],40:[function(require,module,exports){
2520 | var globalDocument = require("global/document")
2521 | var DataSet = require("data-set")
2522 |
2523 | var addEvent = require("./add-event.js")
2524 | var removeEvent = require("./remove-event.js")
2525 | var ProxyEvent = require("./proxy-event.js")
2526 |
2527 | module.exports = DOMDelegator
2528 |
2529 | function DOMDelegator(document) {
2530 | document = document || globalDocument
2531 |
2532 | this.target = document.documentElement
2533 | this.events = {}
2534 | this.rawEventListeners = {}
2535 | this.globalListeners = {}
2536 | }
2537 |
2538 | DOMDelegator.prototype.addEventListener = addEvent
2539 | DOMDelegator.prototype.removeEventListener = removeEvent
2540 |
2541 | DOMDelegator.prototype.addGlobalEventListener =
2542 | function addGlobalEventListener(eventName, fn) {
2543 | var listeners = this.globalListeners[eventName]
2544 | if (!listeners) {
2545 | listeners = this.globalListeners[eventName] = []
2546 | }
2547 |
2548 | if (listeners.indexOf(fn) === -1) {
2549 | listeners.push(fn)
2550 | }
2551 | }
2552 |
2553 | DOMDelegator.prototype.removeGlobalEventListener =
2554 | function removeGlobalEventListener(eventName, fn) {
2555 | var listeners = this.globalListeners[eventName]
2556 | if (!listeners) {
2557 | return
2558 | }
2559 |
2560 | var index = listeners.indexOf(fn)
2561 | if (index !== -1) {
2562 | listeners.splice(index, 1)
2563 | }
2564 | }
2565 |
2566 | DOMDelegator.prototype.listenTo = function listenTo(eventName) {
2567 | if (this.events[eventName]) {
2568 | return
2569 | }
2570 |
2571 | this.events[eventName] = true
2572 | listen(this, eventName)
2573 | }
2574 |
2575 | DOMDelegator.prototype.unlistenTo = function unlistenTo(eventName) {
2576 | if (!this.events[eventName]) {
2577 | return
2578 | }
2579 |
2580 | this.events[eventName] = false
2581 | unlisten(this, eventName)
2582 | }
2583 |
2584 | function listen(delegator, eventName) {
2585 | var listener = delegator.rawEventListeners[eventName]
2586 |
2587 | if (!listener) {
2588 | listener = delegator.rawEventListeners[eventName] =
2589 | createHandler(eventName, delegator.globalListeners)
2590 | }
2591 |
2592 | delegator.target.addEventListener(eventName, listener, true)
2593 | }
2594 |
2595 | function unlisten(delegator, eventName) {
2596 | var listener = delegator.rawEventListeners[eventName]
2597 |
2598 | if (!listener) {
2599 | throw new Error("dom-delegator#unlistenTo: cannot " +
2600 | "unlisten to " + eventName)
2601 | }
2602 |
2603 | delegator.target.removeEventListener(eventName, listener, true)
2604 | }
2605 |
2606 | function createHandler(eventName, globalListeners) {
2607 | return handler
2608 |
2609 | function handler(ev) {
2610 | var globalHandlers = globalListeners[eventName] || []
2611 | var listener = getListener(ev.target, eventName)
2612 |
2613 | var handlers = globalHandlers
2614 | .concat(listener ? listener.handlers : [])
2615 | if (handlers.length === 0) {
2616 | return
2617 | }
2618 |
2619 | var arg = new ProxyEvent(ev, listener)
2620 |
2621 | handlers.forEach(function (handler) {
2622 | typeof handler === "function" ?
2623 | handler(arg) : handler.handleEvent(arg)
2624 | })
2625 | }
2626 | }
2627 |
2628 | function getListener(target, type) {
2629 | // terminate recursion if parent is `null`
2630 | if (target === null) {
2631 | return null
2632 | }
2633 |
2634 | var ds = DataSet(target)
2635 | // fetch list of handler fns for this event
2636 | var handler = ds[type]
2637 | var allHandler = ds.event
2638 |
2639 | if (!handler && !allHandler) {
2640 | return getListener(target.parentNode, type)
2641 | }
2642 |
2643 | var handlers = [].concat(handler || [], allHandler || [])
2644 | return new Listener(target, handlers)
2645 | }
2646 |
2647 | function Listener(target, handlers) {
2648 | this.currentTarget = target
2649 | this.handlers = handlers
2650 | }
2651 |
2652 | },{"./add-event.js":39,"./proxy-event.js":50,"./remove-event.js":51,"data-set":44,"global/document":47}],41:[function(require,module,exports){
2653 | var Individual = require("individual")
2654 | var cuid = require("cuid")
2655 | var globalDocument = require("global/document")
2656 |
2657 | var DOMDelegator = require("./dom-delegator.js")
2658 |
2659 | var delegatorCache = Individual("__DOM_DELEGATOR_CACHE@9", {
2660 | delegators: {}
2661 | })
2662 | var commonEvents = [
2663 | "blur", "change", "click", "contextmenu", "dblclick",
2664 | "error","focus", "focusin", "focusout", "input", "keydown",
2665 | "keypress", "keyup", "load", "mousedown", "mouseup",
2666 | "resize", "scroll", "select", "submit", "unload"
2667 | ]
2668 |
2669 | /* Delegator is a thin wrapper around a singleton `DOMDelegator`
2670 | instance.
2671 |
2672 | Only one DOMDelegator should exist because we do not want
2673 | duplicate event listeners bound to the DOM.
2674 |
2675 | `Delegator` will also `listenTo()` all events unless
2676 | every caller opts out of it
2677 | */
2678 | module.exports = Delegator
2679 |
2680 | function Delegator(opts) {
2681 | opts = opts || {}
2682 | var document = opts.document || globalDocument
2683 |
2684 | var cacheKey = document["__DOM_DELEGATOR_CACHE_TOKEN@9"]
2685 |
2686 | if (!cacheKey) {
2687 | cacheKey =
2688 | document["__DOM_DELEGATOR_CACHE_TOKEN@9"] = cuid()
2689 | }
2690 |
2691 | var delegator = delegatorCache.delegators[cacheKey]
2692 |
2693 | if (!delegator) {
2694 | delegator = delegatorCache.delegators[cacheKey] =
2695 | new DOMDelegator(document)
2696 | }
2697 |
2698 | if (opts.defaultEvents !== false) {
2699 | for (var i = 0; i < commonEvents.length; i++) {
2700 | delegator.listenTo(commonEvents[i])
2701 | }
2702 | }
2703 |
2704 | return delegator
2705 | }
2706 |
2707 |
2708 |
2709 | },{"./dom-delegator.js":40,"cuid":42,"global/document":47,"individual":48}],42:[function(require,module,exports){
2710 | /**
2711 | * cuid.js
2712 | * Collision-resistant UID generator for browsers and node.
2713 | * Sequential for fast db lookups and recency sorting.
2714 | * Safe for element IDs and server-side lookups.
2715 | *
2716 | * Extracted from CLCTR
2717 | *
2718 | * Copyright (c) Eric Elliott 2012
2719 | * MIT License
2720 | */
2721 |
2722 | /*global window, navigator, document, require, process, module */
2723 | (function (app) {
2724 | 'use strict';
2725 | var namespace = 'cuid',
2726 | c = 0,
2727 | blockSize = 4,
2728 | base = 36,
2729 | discreteValues = Math.pow(base, blockSize),
2730 |
2731 | pad = function pad(num, size) {
2732 | var s = "000000000" + num;
2733 | return s.substr(s.length-size);
2734 | },
2735 |
2736 | randomBlock = function randomBlock() {
2737 | return pad((Math.random() *
2738 | discreteValues << 0)
2739 | .toString(base), blockSize);
2740 | },
2741 |
2742 | safeCounter = function () {
2743 | c = (c < discreteValues) ? c : 0;
2744 | c++; // this is not subliminal
2745 | return c - 1;
2746 | },
2747 |
2748 | api = function cuid() {
2749 | // Starting with a lowercase letter makes
2750 | // it HTML element ID friendly.
2751 | var letter = 'c', // hard-coded allows for sequential access
2752 |
2753 | // timestamp
2754 | // warning: this exposes the exact date and time
2755 | // that the uid was created.
2756 | timestamp = (new Date().getTime()).toString(base),
2757 |
2758 | // Prevent same-machine collisions.
2759 | counter,
2760 |
2761 | // A few chars to generate distinct ids for different
2762 | // clients (so different computers are far less
2763 | // likely to generate the same id)
2764 | fingerprint = api.fingerprint(),
2765 |
2766 | // Grab some more chars from Math.random()
2767 | random = randomBlock() + randomBlock();
2768 |
2769 | counter = pad(safeCounter().toString(base), blockSize);
2770 |
2771 | return (letter + timestamp + counter + fingerprint + random);
2772 | };
2773 |
2774 | api.slug = function slug() {
2775 | var date = new Date().getTime().toString(36),
2776 | counter,
2777 | print = api.fingerprint().slice(0,1) +
2778 | api.fingerprint().slice(-1),
2779 | random = randomBlock().slice(-2);
2780 |
2781 | counter = safeCounter().toString(36).slice(-4);
2782 |
2783 | return date.slice(-2) +
2784 | counter + print + random;
2785 | };
2786 |
2787 | api.globalCount = function globalCount() {
2788 | // We want to cache the results of this
2789 | var cache = (function calc() {
2790 | var i,
2791 | count = 0;
2792 |
2793 | for (i in window) {
2794 | count++;
2795 | }
2796 |
2797 | return count;
2798 | }());
2799 |
2800 | api.globalCount = function () { return cache; };
2801 | return cache;
2802 | };
2803 |
2804 | api.fingerprint = function browserPrint() {
2805 | return pad((navigator.mimeTypes.length +
2806 | navigator.userAgent.length).toString(36) +
2807 | api.globalCount().toString(36), 4);
2808 | };
2809 |
2810 | // don't change anything from here down.
2811 | if (app.register) {
2812 | app.register(namespace, api);
2813 | } else if (typeof module !== 'undefined') {
2814 | module.exports = api;
2815 | } else {
2816 | app[namespace] = api;
2817 | }
2818 |
2819 | }(this.applitude || this));
2820 |
2821 | },{}],43:[function(require,module,exports){
2822 | module.exports = createHash
2823 |
2824 | function createHash(elem) {
2825 | var attributes = elem.attributes
2826 | var hash = {}
2827 |
2828 | if (attributes === null || attributes === undefined) {
2829 | return hash
2830 | }
2831 |
2832 | for (var i = 0; i < attributes.length; i++) {
2833 | var attr = attributes[i]
2834 |
2835 | if (attr.name.substr(0,5) !== "data-") {
2836 | continue
2837 | }
2838 |
2839 | hash[attr.name.substr(5)] = attr.value
2840 | }
2841 |
2842 | return hash
2843 | }
2844 |
2845 | },{}],44:[function(require,module,exports){
2846 | var createStore = require("weakmap-shim/create-store")
2847 | var Individual = require("individual")
2848 |
2849 | var createHash = require("./create-hash.js")
2850 |
2851 | var hashStore = Individual("__DATA_SET_WEAKMAP@3", createStore())
2852 |
2853 | module.exports = DataSet
2854 |
2855 | function DataSet(elem) {
2856 | var store = hashStore(elem)
2857 |
2858 | if (!store.hash) {
2859 | store.hash = createHash(elem)
2860 | }
2861 |
2862 | return store.hash
2863 | }
2864 |
2865 | },{"./create-hash.js":43,"individual":48,"weakmap-shim/create-store":45}],45:[function(require,module,exports){
2866 | var hiddenStore = require('./hidden-store.js');
2867 |
2868 | module.exports = createStore;
2869 |
2870 | function createStore() {
2871 | var key = {};
2872 |
2873 | return function (obj) {
2874 | if (typeof obj !== 'object' || obj === null) {
2875 | throw new Error('Weakmap-shim: Key must be object')
2876 | }
2877 |
2878 | var store = obj.valueOf(key);
2879 | return store && store.identity === key ?
2880 | store : hiddenStore(obj, key);
2881 | };
2882 | }
2883 |
2884 | },{"./hidden-store.js":46}],46:[function(require,module,exports){
2885 | module.exports = hiddenStore;
2886 |
2887 | function hiddenStore(obj, key) {
2888 | var store = { identity: key };
2889 | var valueOf = obj.valueOf;
2890 |
2891 | Object.defineProperty(obj, "valueOf", {
2892 | value: function (value) {
2893 | return value !== key ?
2894 | valueOf.apply(this, arguments) : store;
2895 | },
2896 | writable: true
2897 | });
2898 |
2899 | return store;
2900 | }
2901 |
2902 | },{}],47:[function(require,module,exports){
2903 | module.exports=require(21)
2904 | },{"min-document":2}],48:[function(require,module,exports){
2905 | (function (global){
2906 | var root = typeof window !== 'undefined' ?
2907 | window : typeof global !== 'undefined' ?
2908 | global : {};
2909 |
2910 | module.exports = Individual
2911 |
2912 | function Individual(key, value) {
2913 | if (root[key]) {
2914 | return root[key]
2915 | }
2916 |
2917 | Object.defineProperty(root, key, {
2918 | value: value
2919 | , configurable: true
2920 | })
2921 |
2922 | return value
2923 | }
2924 |
2925 | }).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
2926 | },{}],49:[function(require,module,exports){
2927 | module.exports=require(6)
2928 | },{}],50:[function(require,module,exports){
2929 | var inherits = require("inherits")
2930 |
2931 | var ALL_PROPS = [
2932 | "altKey", "bubbles", "cancelable", "ctrlKey",
2933 | "eventPhase", "metaKey", "relatedTarget", "shiftKey",
2934 | "target", "timeStamp", "type", "view", "which"
2935 | ]
2936 | var KEY_PROPS = ["char", "charCode", "key", "keyCode"]
2937 | var MOUSE_PROPS = [
2938 | "button", "buttons", "clientX", "clientY", "layerX",
2939 | "layerY", "offsetX", "offsetY", "pageX", "pageY",
2940 | "screenX", "screenY", "toElement"
2941 | ]
2942 |
2943 | var rkeyEvent = /^key|input/
2944 | var rmouseEvent = /^(?:mouse|pointer|contextmenu)|click/
2945 |
2946 | module.exports = ProxyEvent
2947 |
2948 | function ProxyEvent(ev, listener) {
2949 | if (!(this instanceof ProxyEvent)) {
2950 | return new ProxyEvent(ev, listener)
2951 | }
2952 |
2953 | if (rkeyEvent.test(ev.type)) {
2954 | return new KeyEvent(ev, listener)
2955 | } else if (rmouseEvent.test(ev.type)) {
2956 | return new MouseEvent(ev, listener)
2957 | }
2958 |
2959 | for (var i = 0; i < ALL_PROPS.length; i++) {
2960 | var propKey = ALL_PROPS[i]
2961 | this[propKey] = ev[propKey]
2962 | }
2963 |
2964 | this._rawEvent = ev
2965 | this.currentTarget = listener ? listener.currentTarget : null
2966 | }
2967 |
2968 | ProxyEvent.prototype.preventDefault = function () {
2969 | this._rawEvent.preventDefault()
2970 | }
2971 |
2972 | function MouseEvent(ev, listener) {
2973 | for (var i = 0; i < ALL_PROPS.length; i++) {
2974 | var propKey = ALL_PROPS[i]
2975 | this[propKey] = ev[propKey]
2976 | }
2977 |
2978 | for (var j = 0; j < MOUSE_PROPS.length; j++) {
2979 | var mousePropKey = MOUSE_PROPS[j]
2980 | this[mousePropKey] = ev[mousePropKey]
2981 | }
2982 |
2983 | this._rawEvent = ev
2984 | this.currentTarget = listener ? listener.currentTarget : null
2985 | }
2986 |
2987 | inherits(MouseEvent, ProxyEvent)
2988 |
2989 | function KeyEvent(ev, listener) {
2990 | for (var i = 0; i < ALL_PROPS.length; i++) {
2991 | var propKey = ALL_PROPS[i]
2992 | this[propKey] = ev[propKey]
2993 | }
2994 |
2995 | for (var j = 0; j < KEY_PROPS.length; j++) {
2996 | var keyPropKey = KEY_PROPS[j]
2997 | this[keyPropKey] = ev[keyPropKey]
2998 | }
2999 |
3000 | this._rawEvent = ev
3001 | this.currentTarget = listener ? listener.currentTarget : null
3002 | }
3003 |
3004 | inherits(KeyEvent, ProxyEvent)
3005 |
3006 | },{"inherits":49}],51:[function(require,module,exports){
3007 | var DataSet = require("data-set")
3008 |
3009 | module.exports = removeEvent
3010 |
3011 | function removeEvent(target, type, handler) {
3012 | var ds = DataSet(target)
3013 | var events = ds[type]
3014 |
3015 | if (!events) {
3016 | return
3017 | } else if (Array.isArray(events)) {
3018 | var index = events.indexOf(handler)
3019 | if (index !== -1) {
3020 | events.splice(index, 1)
3021 | }
3022 | } else if (events === handler) {
3023 | ds[type] = null
3024 | }
3025 | }
3026 |
3027 | },{"data-set":44}],52:[function(require,module,exports){
3028 | module.exports = Event
3029 |
3030 | function Event() {
3031 | var listeners = []
3032 |
3033 | return { broadcast: broadcast, listen: event }
3034 |
3035 | function broadcast(value) {
3036 | for (var i = 0; i < listeners.length; i++) {
3037 | listeners[i](value)
3038 | }
3039 | }
3040 |
3041 | function event(listener) {
3042 | listeners.push(listener)
3043 |
3044 | return removeListener
3045 |
3046 | function removeListener() {
3047 | var index = listeners.indexOf(listener)
3048 | if (index !== -1) {
3049 | listeners.splice(index, 1)
3050 | }
3051 | }
3052 | }
3053 | }
3054 |
3055 | },{}],53:[function(require,module,exports){
3056 | var event = require("./single.js")
3057 |
3058 | module.exports = multiple
3059 |
3060 | function multiple(names) {
3061 | return names.reduce(function (acc, name) {
3062 | acc[name] = event()
3063 | return acc
3064 | }, {})
3065 | }
3066 |
3067 | },{"./single.js":54}],54:[function(require,module,exports){
3068 | var Event = require('./event.js')
3069 |
3070 | module.exports = Single
3071 |
3072 | function Single() {
3073 | var tuple = Event()
3074 |
3075 | return function event(value) {
3076 | if (typeof value === "function") {
3077 | return tuple.listen(value)
3078 | } else {
3079 | return tuple.broadcast(value)
3080 | }
3081 | }
3082 | }
3083 |
3084 | },{"./event.js":52}],55:[function(require,module,exports){
3085 | module.exports=require(4)
3086 | },{"error/typed":68,"raf":69,"vdom/create-element":98,"vdom/patch":104,"vtree/diff":131}],56:[function(require,module,exports){
3087 | module.exports=require(5)
3088 | },{"util/":59}],57:[function(require,module,exports){
3089 | module.exports=require(6)
3090 | },{}],58:[function(require,module,exports){
3091 | module.exports=require(7)
3092 | },{}],59:[function(require,module,exports){
3093 | module.exports=require(8)
3094 | },{"./support/isBuffer":58,"JkpR2F":3,"inherits":57}],60:[function(require,module,exports){
3095 | module.exports=require(9)
3096 | },{}],61:[function(require,module,exports){
3097 | module.exports=require(10)
3098 | },{}],62:[function(require,module,exports){
3099 | module.exports=require(11)
3100 | },{}],63:[function(require,module,exports){
3101 | module.exports=require(12)
3102 | },{"./has-keys":62,"object-keys":65}],64:[function(require,module,exports){
3103 | module.exports=require(13)
3104 | },{}],65:[function(require,module,exports){
3105 | module.exports=require(14)
3106 | },{"./shim":67}],66:[function(require,module,exports){
3107 | module.exports=require(15)
3108 | },{}],67:[function(require,module,exports){
3109 | module.exports=require(16)
3110 | },{"./foreach":64,"./isArguments":66}],68:[function(require,module,exports){
3111 | module.exports=require(17)
3112 | },{"assert/":56,"camelize":60,"string-template":61,"xtend/mutable":63}],69:[function(require,module,exports){
3113 | var now = require('performance-now')
3114 | , global = typeof window === 'undefined' ? {} : window
3115 | , vendors = ['moz', 'webkit']
3116 | , suffix = 'AnimationFrame'
3117 | , raf = global['request' + suffix]
3118 | , caf = global['cancel' + suffix] || global['cancelRequest' + suffix]
3119 |
3120 | for(var i = 0; i < vendors.length && !raf; i++) {
3121 | raf = global[vendors[i] + 'Request' + suffix]
3122 | caf = global[vendors[i] + 'Cancel' + suffix]
3123 | || global[vendors[i] + 'CancelRequest' + suffix]
3124 | }
3125 |
3126 | // Some versions of FF have rAF but not cAF
3127 | if(!raf || !caf) {
3128 | var last = 0
3129 | , id = 0
3130 | , queue = []
3131 | , frameDuration = 1000 / 60
3132 |
3133 | raf = function(callback) {
3134 | if(queue.length === 0) {
3135 | var _now = now()
3136 | , next = Math.max(0, frameDuration - (_now - last))
3137 | last = next + _now
3138 | setTimeout(function() {
3139 | var cp = queue.slice(0)
3140 | // Clear queue here to prevent
3141 | // callbacks from appending listeners
3142 | // to the current frame's queue
3143 | queue.length = 0
3144 | for (var i = 0; i < cp.length; i++) {
3145 | if (!cp[i].cancelled) {
3146 | cp[i].callback(last)
3147 | }
3148 | }
3149 | }, next)
3150 | }
3151 | queue.push({
3152 | handle: ++id,
3153 | callback: callback,
3154 | cancelled: false
3155 | })
3156 | return id
3157 | }
3158 |
3159 | caf = function(handle) {
3160 | for(var i = 0; i < queue.length; i++) {
3161 | if(queue[i].handle === handle) {
3162 | queue[i].cancelled = true
3163 | }
3164 | }
3165 | }
3166 | }
3167 |
3168 | module.exports = function() {
3169 | // Wrap in a new function to prevent
3170 | // `cancel` potentially being assigned
3171 | // to the native rAF function
3172 | return raf.apply(global, arguments)
3173 | }
3174 | module.exports.cancel = function() {
3175 | caf.apply(global, arguments)
3176 | }
3177 |
3178 | },{"performance-now":70}],70:[function(require,module,exports){
3179 | (function (process){
3180 | // Generated by CoffeeScript 1.6.3
3181 | (function() {
3182 | var getNanoSeconds, hrtime, loadTime;
3183 |
3184 | if ((typeof performance !== "undefined" && performance !== null) && performance.now) {
3185 | module.exports = function() {
3186 | return performance.now();
3187 | };
3188 | } else if ((typeof process !== "undefined" && process !== null) && process.hrtime) {
3189 | module.exports = function() {
3190 | return (getNanoSeconds() - loadTime) / 1e6;
3191 | };
3192 | hrtime = process.hrtime;
3193 | getNanoSeconds = function() {
3194 | var hr;
3195 | hr = hrtime();
3196 | return hr[0] * 1e9 + hr[1];
3197 | };
3198 | loadTime = getNanoSeconds();
3199 | } else if (Date.now) {
3200 | module.exports = function() {
3201 | return Date.now() - loadTime;
3202 | };
3203 | loadTime = Date.now();
3204 | } else {
3205 | module.exports = function() {
3206 | return new Date().getTime() - loadTime;
3207 | };
3208 | loadTime = new Date().getTime();
3209 | }
3210 |
3211 | }).call(this);
3212 |
3213 | /*
3214 | //@ sourceMappingURL=performance-now.map
3215 | */
3216 |
3217 | }).call(this,require("JkpR2F"))
3218 | },{"JkpR2F":3}],71:[function(require,module,exports){
3219 | var setNonEnumerable = require("./lib/set-non-enumerable.js");
3220 |
3221 | module.exports = addListener
3222 |
3223 | function addListener(observArray, observ) {
3224 | var list = observArray._list
3225 |
3226 | return observ(function (value) {
3227 | var valueList = observArray().slice()
3228 | var index = list.indexOf(observ)
3229 |
3230 | // This code path should never hit. If this happens
3231 | // there's a bug in the cleanup code
3232 | if (index === -1) {
3233 | var message = "observ-array: Unremoved observ listener"
3234 | var err = new Error(message)
3235 | err.list = list
3236 | err.index = index
3237 | err.observ = observ
3238 | throw err
3239 | }
3240 |
3241 | valueList.splice(index, 1, value)
3242 | setNonEnumerable(valueList, "_diff", [index, 1, value])
3243 |
3244 | observArray.set(valueList)
3245 | })
3246 | }
3247 |
3248 | },{"./lib/set-non-enumerable.js":74}],72:[function(require,module,exports){
3249 | var ObservArray = require("./index.js")
3250 |
3251 | var slice = Array.prototype.slice
3252 |
3253 | var ARRAY_METHODS = [
3254 | "concat", "slice", "every", "filter", "forEach", "indexOf",
3255 | "join", "lastIndexOf", "map", "reduce", "reduceRight",
3256 | "some", "toString", "toLocaleString"
3257 | ]
3258 |
3259 | var methods = ARRAY_METHODS.map(function (name) {
3260 | return [name, function () {
3261 | var res = this._list[name].apply(this._list, arguments)
3262 |
3263 | if (res && Array.isArray(res)) {
3264 | res = ObservArray(res)
3265 | }
3266 |
3267 | return res
3268 | }]
3269 | })
3270 |
3271 | module.exports = ArrayMethods
3272 |
3273 | function ArrayMethods(obs) {
3274 | obs.push = observArrayPush
3275 | obs.pop = observArrayPop
3276 | obs.shift = observArrayShift
3277 | obs.unshift = observArrayUnshift
3278 | obs.reverse = notImplemented
3279 | obs.sort = notImplemented
3280 |
3281 | methods.forEach(function (tuple) {
3282 | obs[tuple[0]] = tuple[1]
3283 | })
3284 | return obs
3285 | }
3286 |
3287 |
3288 |
3289 | function observArrayPush() {
3290 | var args = slice.call(arguments)
3291 | args.unshift(this._list.length, 0)
3292 | this.splice.apply(this, args)
3293 |
3294 | return this._list.length
3295 | }
3296 | function observArrayPop() {
3297 | return this.splice(this._list.length - 1, 1)[0]
3298 | }
3299 | function observArrayShift() {
3300 | return this.splice(0, 1)[0]
3301 | }
3302 | function observArrayUnshift() {
3303 | var args = slice.call(arguments)
3304 | args.unshift(0, 0)
3305 | this.splice.apply(this, args)
3306 |
3307 | return this._list.length
3308 | }
3309 |
3310 |
3311 | function notImplemented() {
3312 | throw new Error("Pull request welcome")
3313 | }
3314 |
3315 | },{"./index.js":73}],73:[function(require,module,exports){
3316 | var Observ = require("observ")
3317 |
3318 | // circular dep between ArrayMethods & this file
3319 | module.exports = ObservArray
3320 |
3321 | var splice = require("./splice.js")
3322 | var ArrayMethods = require("./array-methods.js")
3323 | var addListener = require("./add-listener.js")
3324 |
3325 | /* ObservArray := (Array) => Observ<
3326 | Array & { _diff: Array }
3327 | > & {
3328 | splice: (index: Number, amount: Number, rest...: T) =>
3329 | Array,
3330 | push: (values...: T) => Number,
3331 | filter: (lambda: Function, thisValue: Any) => Array,
3332 | indexOf: (item: T, fromIndex: Number) => Number
3333 | }
3334 |
3335 | Fix to make it more like ObservHash.
3336 |
3337 | I.e. you write observables into it.
3338 | reading methods take plain JS objects to read
3339 | and the value of the array is always an array of plain
3340 | objsect.
3341 |
3342 | The observ array instance itself would have indexed
3343 | properties that are the observables
3344 | */
3345 | function ObservArray(initialList) {
3346 | // list is the internal mutable list observ instances that
3347 | // all methods on `obs` dispatch to.
3348 | var list = initialList
3349 | var initialState = []
3350 |
3351 | // copy state out of initialList into initialState
3352 | list.forEach(function (observ, index) {
3353 | initialState[index] = typeof observ === "function" ?
3354 | observ() : observ
3355 | })
3356 |
3357 | var obs = Observ(initialState)
3358 | obs.splice = splice
3359 |
3360 | obs.get = get
3361 | obs.getLength = getLength
3362 | obs.put = put
3363 |
3364 | // you better not mutate this list directly
3365 | // this is the list of observs instances
3366 | obs._list = list
3367 |
3368 | var removeListeners = list.map(function (observ) {
3369 | return typeof observ === "function" ?
3370 | addListener(obs, observ) :
3371 | null
3372 | });
3373 | // this is a list of removal functions that must be called
3374 | // when observ instances are removed from `obs.list`
3375 | // not calling this means we do not GC our observ change
3376 | // listeners. Which causes rage bugs
3377 | obs._removeListeners = removeListeners
3378 |
3379 | return ArrayMethods(obs, list)
3380 | }
3381 |
3382 | function get(index) {
3383 | return this._list[index]
3384 | }
3385 |
3386 | function put(index, value) {
3387 | this.splice(index, 1, value)
3388 | }
3389 |
3390 | function getLength() {
3391 | return this._list.length
3392 | }
3393 |
3394 | },{"./add-listener.js":71,"./array-methods.js":72,"./splice.js":75,"observ":81}],74:[function(require,module,exports){
3395 | module.exports = setNonEnumerable;
3396 |
3397 | function setNonEnumerable(object, key, value) {
3398 | Object.defineProperty(object, key, {
3399 | value: value,
3400 | writable: true,
3401 | configurable: true,
3402 | enumerable: false
3403 | });
3404 | }
3405 |
3406 | },{}],75:[function(require,module,exports){
3407 | var slice = Array.prototype.slice
3408 |
3409 | var addListener = require("./add-listener.js")
3410 | var setNonEnumerable = require("./lib/set-non-enumerable.js");
3411 |
3412 | module.exports = splice
3413 |
3414 | // `obs.splice` is a mutable implementation of `splice()`
3415 | // that mutates both `list` and the internal `valueList` that
3416 | // is the current value of `obs` itself
3417 | function splice(index, amount) {
3418 | var obs = this
3419 | var args = slice.call(arguments, 0)
3420 | var valueList = obs().slice()
3421 |
3422 | // generate a list of args to mutate the internal
3423 | // list of only obs
3424 | var valueArgs = args.map(function (value, index) {
3425 | if (index === 0 || index === 1) {
3426 | return value
3427 | }
3428 |
3429 | // must unpack observables that we are adding
3430 | return typeof value === "function" ? value() : value
3431 | })
3432 |
3433 | valueList.splice.apply(valueList, valueArgs)
3434 | // we remove the observs that we remove
3435 | var removed = obs._list.splice.apply(obs._list, args)
3436 |
3437 | var extraRemoveListeners = args.slice(2).map(function (observ) {
3438 | return typeof observ === "function" ?
3439 | addListener(obs, observ) :
3440 | null
3441 | })
3442 | extraRemoveListeners.unshift(args[0], args[1])
3443 | var removedListeners = obs._removeListeners.splice
3444 | .apply(obs._removeListeners, extraRemoveListeners)
3445 |
3446 | removedListeners.forEach(function (removeObservListener) {
3447 | if (removeObservListener) {
3448 | removeObservListener()
3449 | }
3450 | })
3451 |
3452 | setNonEnumerable(valueList, "_diff", valueArgs)
3453 |
3454 | obs.set(valueList)
3455 | return removed
3456 | }
3457 |
3458 | },{"./add-listener.js":71,"./lib/set-non-enumerable.js":74}],76:[function(require,module,exports){
3459 | var Observ = require("observ")
3460 | var extend = require("xtend")
3461 |
3462 | var blackList = ["name", "_diff", "_type", "_version"]
3463 | var blackListReasons = {
3464 | "name": "Clashes with `Function.prototype.name`.\n",
3465 | "_diff": "_diff is reserved key of observ-struct.\n",
3466 | "_type": "_type is reserved key of observ-struct.\n",
3467 | "_version": "_version is reserved key of observ-struct.\n"
3468 | }
3469 | var NO_TRANSACTION = {}
3470 |
3471 | /* ObservStruct := (Object>) =>
3472 | Object> &
3473 | Observ