├── vec.png
├── bg@2x.png
├── README.md
├── index.html
├── vec.js
└── includes
└── immutable.js
/vec.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tonsky/vec/HEAD/vec.png
--------------------------------------------------------------------------------
/bg@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tonsky/vec/HEAD/bg@2x.png
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # React.js + Immutable.js vector editor example
2 |
3 | App written during http://dou.ua/calendar/7213/
4 |
5 | - Immutable model
6 | - Fast reference-comparison `shouldComponentUpdate` on everything
7 | - Speculative rendering
8 | - Undo/redo
9 | - `localStorage` persistence
10 | - vanilla.js
11 |
12 | Check out [vec.js](https://github.com/tonsky/vec/blob/gh-pages/vec.js), it’s decently commented.
13 |
14 | Read more [about approach](http://tonsky.me/talks/2015-codefest/) (in Russian).
15 |
16 | Video (in Russian): [code walkthrough](http://www.youtube.com/watch?v=lDkrXTDwbJQ), [Q&A session](http://www.youtube.com/watch?v=tUtLe1VlkYc)
17 |
18 | [Live version](http://tonsky.me/vec/)
19 |
20 | [
](http://tonsky.me/vec/)
21 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Vector editor
6 |
7 |
8 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/vec.js:
--------------------------------------------------------------------------------
1 | // UTILS
2 |
3 |
4 | // Multimethods are flexible polymorphic construct, decoulped from class, open for extension
5 |
6 | function defmulti(name, dispatch_fn) {
7 | var dispatch_table_name = "_" + name + "_mm";
8 | window[dispatch_table_name] = {};
9 | window[name] = function() {
10 | var fun = window[dispatch_table_name][dispatch_fn.apply(null, arguments)];
11 | if (fun !== undefined)
12 | return fun.apply(null, arguments);
13 | }
14 | }
15 |
16 | function defmethod(name, dispatch_value, fn) {
17 | window["_" + name + "_mm"][dispatch_value] = fn;
18 | }
19 |
20 |
21 | // Atom is a mutable reference with listeners (watchers)
22 |
23 | function atom(value) {
24 | return {value: value,
25 | listeners: []};
26 | }
27 |
28 | function add_watch(atom, cb) {
29 | atom.listeners.push(cb);
30 | }
31 |
32 | function reset(atom, value) {
33 | var old = atom.value;
34 | atom.value = value;
35 | for (var i = 0; i < atom.listeners.length; ++i) {
36 | atom.listeners[i](atom, old, value);
37 | }
38 | }
39 |
40 |
41 | // Some shortcuts to ease immutable structs construction
42 |
43 | var list = function() { return Immutable.List.of.apply(Immutable.List, arguments); },
44 | map = function() { return Immutable.Map.apply(Immutable, arguments); },
45 | set = function() { return Immutable.Set.of.apply(Immutable.Set, arguments); },
46 | eq = function(a, b) { return Immutable.is(a,b); };
47 |
48 |
49 | // Tracking window size
50 |
51 | function current_viewport() {
52 | return map({w: document.body.clientWidth, h: document.body.clientHeight});
53 | }
54 |
55 | window.addEventListener("resize", function(e) {
56 | reset(world_ref, world_ref.value.set("viewport", current_viewport()));
57 | } );
58 |
59 |
60 | // Compares set of immutable props via Immutable.is() — fast pointer comparison
61 | function should_update(name, from, to, props) {
62 | for (var i = 0; i < props.length; ++i) {
63 | var prop = props[i];
64 | if (!eq(from[prop], to[prop])) {
65 | // console.log(name + "." + prop + " changed");
66 | return true;
67 | }
68 | };
69 | // console.log(name + " // skip");
70 | return false;
71 | }
72 |
73 |
74 | // HISTORY
75 |
76 | // Everything we render is kept in a single atom, including auxiliary stuff like click positions
77 | // and window size
78 | var world_ref = atom(new_world());
79 |
80 | function new_world() {
81 | var empty_model = map({ tool: "select",
82 | figures: list(),
83 | selection: set() });
84 | return map({ history: list(empty_model), // collection of models
85 | at: 0, // position in history
86 | viewport: current_viewport() });
87 | }
88 |
89 |
90 | // Model we’re looking at right now
91 | function current_model(w) {
92 | var world = w || world_ref.value;
93 | return world.get("history").get(world.get("at"));
94 | }
95 |
96 |
97 | // Edit “mutates” current model, either pushing new model to the history or replacing it inplace
98 | // All changes to model go through this place only
99 | function edit_model(model) {
100 | // create new history record only if figures have changed
101 | if (!eq(model.get("figures"), current_model().get("figures"))) {
102 | var history = world_ref.value.get("history"),
103 | at = world_ref.value.get("at"),
104 | new_history = history.setSize(at+1).push(model),
105 | new_at = at+1;
106 |
107 | // limiting history size
108 | var skip = new_history.size - 50;
109 | if (skip > 0) {
110 | new_at -= skip;
111 | new_history = new_history.skip(skip);
112 | }
113 |
114 | reset(world_ref, world_ref.value.set("history", new_history).set("at", new_at));
115 | } else {
116 | var world = world_ref.value;
117 | reset(world_ref, world.setIn(["history", world.get("at")], model));
118 | }
119 | }
120 |
121 |
122 | // Note how plain dead trivial undo/redo are
123 | function undo() {
124 | var at = world_ref.value.get("at");
125 | if (at > 0)
126 | reset(world_ref, world_ref.value.set("at", at-1));
127 | }
128 |
129 | function redo() {
130 | var history = world_ref.value.get("history"),
131 | at = world_ref.value.get("at");
132 | if (at < history.size-1)
133 | reset(world_ref, world_ref.value.set("at", at+1));
134 | }
135 |
136 |
137 |
138 | // FIGURES
139 | // mostly trivial code, some math and stuff
140 |
141 | defmulti("render_figure", function(fig, selected, key) { return fig.get("type"); });
142 | defmulti("inside_figure", function(fig, point) { return fig.get("type"); });
143 | defmulti("inside_stroke", function(fig, point) { return fig.get("type"); });
144 | defmulti("move_figure", function(fig, delta) { return fig.get("type"); });
145 | defmulti("figure_from_bb", function(type, p1, p2) { return type; });
146 |
147 | function find_selected(figures, point) {
148 | var by_stroke = figures.find(function(fig) { return inside_stroke(fig, point); });
149 | // if (by_stroke !== undefined)
150 | return by_stroke;
151 | // return figures.find(function(fig) { return inside_figure(fig, point); });
152 | }
153 |
154 | var selection_treshold = 8;
155 |
156 | // RECT
157 |
158 | defmethod("render_figure", "rect", function(fig, selected, key) {
159 | return React.createElement(
160 | "rect",
161 | { key: key,
162 | className: selected ? "figure selected" : "figure",
163 | width: fig.get("w"),
164 | height: fig.get("h"),
165 | x: fig.get("x"),
166 | y: fig.get("y") });
167 | });
168 |
169 | defmethod("inside_figure", "rect", function(fig, point) {
170 | return fig.get("x") <= point.get("x") &&
171 | fig.get("x") + fig.get("w") >= point.get("x") &&
172 | fig.get("y") <= point.get("y") &&
173 | fig.get("y") + fig.get("h") >= point.get("y");
174 | });
175 |
176 | defmethod("inside_stroke", "rect", function(fig, point) {
177 | var x1 = fig.get("x"),
178 | y1 = fig.get("y"),
179 | x2 = fig.get("x") + fig.get("w"),
180 | y2 = fig.get("y") + fig.get("h"),
181 | x = point.get("x"),
182 | y = point.get("y"),
183 | t = selection_treshold;
184 |
185 | return ( y1 - t <= y && y <= y2 + t &&
186 | ((x1 - t <= x && x <= x1 + t) ||
187 | (x2 - t <= x && x <= x2 + t))) ||
188 | ( x1 - t <= x && x <= x2 + t &&
189 | ((y1 - t <= y && y <= y1 + t) ||
190 | (y2 - t <= y && y <= y2 + t)));
191 | });
192 |
193 | defmethod("figure_from_bb", "rect", function(type, p1, p2) {
194 | return map({
195 | type: "rect",
196 | x: Math.min(p1.get("x"), p2.get("x")),
197 | y: Math.min(p1.get("y"), p2.get("y")),
198 | w: Math.abs(p1.get("x") - p2.get("x")),
199 | h: Math.abs(p1.get("y") - p2.get("y"))
200 | });
201 | });
202 |
203 | defmethod("move_figure", "rect", function(fig, delta) {
204 | return map({
205 | type: "rect",
206 | x: fig.get("x") + delta.get("x"),
207 | y: fig.get("y") + delta.get("y"),
208 | w: fig.get("w"),
209 | h: fig.get("h")
210 | });
211 | });
212 |
213 |
214 | // OVAL
215 |
216 | defmethod("render_figure", "oval", function(fig, selected, key) {
217 | return React.createElement(
218 | "ellipse",
219 | { key: key,
220 | className: selected ? "figure selected" : "figure",
221 | cx: fig.get("cx"),
222 | cy: fig.get("cy"),
223 | rx: fig.get("rx"),
224 | ry: fig.get("ry") });
225 | });
226 |
227 |
228 | function inside_ellipse(x, y, cx, cy, rx, ry) {
229 | return (x-cx)*(x-cx)/(rx*rx) + (y-cy)*(y-cy)/(ry*ry) <= 1;
230 | }
231 |
232 | defmethod("inside_figure", "oval", function(fig, point) {
233 | return inside_ellipse(point.get("x"), point.get("y"), fig.get("cx"), fig.get("cy"), fig.get("rx"), fig.get("ry"));
234 | });
235 |
236 |
237 | defmethod("inside_stroke", "oval", function(fig, point) {
238 | var x = point.get("x"),
239 | y = point.get("y"),
240 | cx = fig.get("cx"),
241 | cy = fig.get("cy"),
242 | rx = fig.get("rx"),
243 | ry = fig.get("ry"),
244 | t = selection_treshold;
245 | return inside_ellipse(x, y, cx, cy, rx+t, ry+t) && (rx <= t || ry <= t || !inside_ellipse(x, y, cx, cy, rx-t, ry-t));
246 | });
247 |
248 |
249 |
250 | defmethod("figure_from_bb", "oval", function(type, p1, p2) {
251 | return map({
252 | type: "oval",
253 | cx: (p1.get("x") + p2.get("x"))/2,
254 | cy: (p1.get("y") + p2.get("y"))/2,
255 | rx: Math.abs(p1.get("x") - p2.get("x"))/2,
256 | ry: Math.abs(p1.get("y") - p2.get("y"))/2
257 | });
258 | });
259 |
260 | defmethod("move_figure", "oval", function(fig, delta) {
261 | return map({
262 | type: "oval",
263 | cx: fig.get("cx") + delta.get("x"),
264 | cy: fig.get("cy") + delta.get("y"),
265 | rx: fig.get("rx"),
266 | ry: fig.get("ry")
267 | });
268 | });
269 |
270 |
271 | // LINE
272 |
273 | defmethod("render_figure", "line", function(fig, selected, key) {
274 | return React.createElement("line",
275 | { key: key,
276 | className: selected ? "figure selected" : "figure",
277 | x1: fig.get("x1"),
278 | y1: fig.get("y1"),
279 | x2: fig.get("x2"),
280 | y2: fig.get("y2") });
281 | });
282 |
283 | defmethod("inside_stroke", "line", function(fig, point) {
284 | var x1 = fig.get("x1"),
285 | y1 = fig.get("y1"),
286 | x2 = fig.get("x2"),
287 | y2 = fig.get("y2"),
288 | x = point.get("x"),
289 | y = point.get("y");
290 |
291 | if (Math.min(x1, x2) <= x &&
292 | Math.max(x1, x2) >= x &&
293 | Math.min(y1, y2) <= y &&
294 | Math.max(y1, y2) >= y)
295 | return Math.abs((y2 - y1) * x - (x2 - x1) * y + x2 * y1 - y2 * x1) /
296 | Math.sqrt((y2-y1) * (y2-y1) + (x2 - x1) * (x2 - x1)) <= selection_treshold;
297 | });
298 |
299 | defmethod("figure_from_bb", "line", function(type, p1, p2) {
300 | return map({ type: "line", x1: p1.get("x"), y1: p1.get("y"), x2: p2.get("x"), y2: p2.get("y") });
301 | });
302 |
303 | defmethod("move_figure", "line", function(fig, delta) {
304 | return map({
305 | type: "line",
306 | x1: fig.get("x1") + delta.get("x"),
307 | y1: fig.get("y1") + delta.get("y"),
308 | x2: fig.get("x2") + delta.get("x"),
309 | y2: fig.get("y2") + delta.get("y")
310 | });
311 | });
312 |
313 |
314 | // TOOLS
315 |
316 | // round mouse position for “snap to grid” behaviour
317 | function mouse_pos(e) {
318 | return map({x: 10 * Math.round(e.clientX / 10),
319 | y: 10 * Math.round(e.clientY / 10)});
320 | }
321 |
322 | // These multimethods take current model and return new model
323 | // They are pure and don’t mutate anything
324 | // This allows us to use them for speculative rendering
325 | defmulti("tool_on_click", function(tool, model, point, e) { return tool; });
326 | defmulti("tool_on_drag", function(tool, model, p1, p2, e) { return tool; });
327 |
328 | // Select changes “selection” set of a model
329 | defmethod("tool_on_click", "select",
330 | function(tool, model, point, e) {
331 | var fig = find_selected(model.get("figures"), point),
332 | multi = e.shiftKey,
333 | selection = model.get("selection");
334 | if (fig !== undefined && multi && selection.contains(fig))
335 | return model.set("selection", selection.delete(fig));
336 | else if (fig !== undefined && multi && !selection.contains(fig))
337 | return model.set("selection", selection.add(fig));
338 | else if (fig !== undefined && !multi)
339 | return model.set("selection", set(fig));
340 | else if (fig === undefined && !multi)
341 | return model.set("selection", set());
342 | });
343 |
344 | // or moves figures
345 | defmethod("tool_on_drag", "select",
346 | function(tool, model, p1, p2, e) {
347 | var delta = map({x: p2.get("x") - p1.get("x"), y: p2.get("y") - p1.get("y")}),
348 | selection = model.get("selection"),
349 | scene = model.get("figures");
350 |
351 | if (find_selected(selection, p1) === undefined) {
352 | var fig = find_selected(scene, p1);
353 | if (fig !== undefined) {
354 | selection = set(fig);
355 | model = model.set("selection", selection);
356 | }
357 | }
358 |
359 | if (find_selected(selection, p1) !== undefined) {
360 | return model
361 | .set("figures", scene.map(function(fig) {
362 | return selection.contains(fig) ? move_figure(fig, delta) : fig;
363 | }))
364 | .set("selection", selection.map(function(fig) { return move_figure(fig, delta); }));
365 | }
366 | });
367 |
368 | // figures just add new figure on drag
369 | function fig_drag_fn(tool, model, p1, p2, e) {
370 | if (!eq(p1, p2)) {
371 | var scene = model.get("figures");
372 | var instance = figure_from_bb(tool, p1, p2);
373 | return model.set("figures", scene.push(instance))
374 | .set("selection", set(instance));
375 | }
376 | }
377 |
378 | defmethod("tool_on_drag", "rect", fig_drag_fn);
379 | defmethod("tool_on_drag", "oval", fig_drag_fn);
380 | defmethod("tool_on_drag", "line", fig_drag_fn);
381 |
382 |
383 | // REACT COMPONENTS
384 |
385 | var tool_keys = list(
386 | ["select", "V"],
387 | ["rect", "R"],
388 | ["oval", "O"],
389 | ["line", "L"]
390 | );
391 |
392 |
393 | var Tool = React.createClass({
394 | // Component will only be updated whenever props it depends on change
395 | shouldComponentUpdate: function(next_props) {
396 | return should_update(" Tool_" + this.props.code, this.props, next_props, ["code", "shortcut", "offset", "selected"]);
397 | },
398 | render: function() {
399 | var code = this.props.code,
400 | shortcut = this.props.shortcut,
401 | offset = 40 * this.props.offset;
402 |
403 | return React.createElement("g",
404 | { className: "tool_" + code + (this.props.selected ? " selected" : ""),
405 | transform: "translate(" + offset + ",0)",
406 | onClick: function(e) {
407 | edit_model(current_model().set("tool", code));
408 | e.stopPropagation();
409 | } },
410 | React.createElement("rect", {x: 0, y: 0, width: 40, height: 40}),
411 | React.createElement("text", {textAnchor: "middle", x: 20, y: 27}, shortcut));
412 | }
413 | });
414 |
415 |
416 | var Toolbar = React.createClass({
417 | shouldComponentUpdate: function(next_props) {
418 | return should_update(" Toolbar", this.props, next_props, ["tool"]);
419 | },
420 | render: function() {
421 | var tool = this.props.tool;
422 | return React.createElement("g",
423 | { id: "toolbar", transform: "translate(10,10)" },
424 | tool_keys.map(function(t, i) {
425 | return React.createElement(Tool, {key: t[0], code: t[0], shortcut: t[1], selected: tool === t[0], offset: i})
426 | }));
427 | }
428 | });
429 |
430 |
431 | var Scene = React.createClass({
432 | shouldComponentUpdate: function(next_props) {
433 | return should_update(" Scene", this.props, next_props, ["figures", "selection"]);
434 | },
435 | render: function() {
436 | var figures = this.props.figures,
437 | selection = this.props.selection,
438 | render = function(fig, i) { return render_figure(fig, selection.contains(fig), i); };
439 | return React.createElement("g", {}, figures.map(render));
440 | }
441 | });
442 |
443 |
444 | var History = React.createClass({
445 | shouldComponentUpdate: function(next_props) {
446 | return should_update(" History", this.props, next_props, ["history", "at", "viewport"]);
447 | },
448 | render: function() {
449 | var history = this.props.history,
450 | at = this.props.at,
451 | viewport = this.props.viewport,
452 | render = function(m, i) {
453 | return React.createElement("rect", {
454 | key: i,
455 | className: i === at ? "selected" : "",
456 | x: i*14 + 10,
457 | y: viewport.get("h") - 20,
458 | width: 12,
459 | height: 12,
460 | onClick: function(e) {
461 | reset(world_ref, world_ref.value.set("at", i));
462 | },
463 | onMouseOver: function(e) { render_ui(world_ref.value.set("at", i)); },
464 | onMouseOut: function(e) { render_ui(world_ref.value); },
465 | });
466 | };
467 | return React.createElement("g", { id: "history" }, this.props.history.map(render));
468 | }
469 | });
470 |
471 |
472 | // Rendering is top-down. Components implement shouldComponentUpdate to decide whether
473 | // they should be updated on this particular change or not
474 | var UI = React.createClass({
475 | shouldComponentUpdate: function(next_props) {
476 | return should_update("UI", this.props, next_props, ["world"]);
477 | },
478 | render: function() {
479 | var world = this.props.world,
480 | model = current_model(world);
481 | return React.createElement("svg",
482 | { id: "canvas" },
483 | React.createElement(Toolbar, { tool: model.get("tool") }),
484 | React.createElement(History, { history: world.get("history"),
485 | at: world.get("at"),
486 | viewport: world.get("viewport") }),
487 | React.createElement(Scene,
488 | { figures: model.get("figures"),
489 | selection: model.get("selection") }));
490 | }
491 | });
492 |
493 | function render_ui(world) {
494 | React.render(React.createElement(UI, { world: world }), document.body);
495 | }
496 |
497 | // We do not call render_ui explicitly. Every change gets applied to world_ref
498 | // and re-render fires from its watcher
499 | add_watch(world_ref, function(world, old, _new) {
500 | render_ui(_new);
501 | });
502 |
503 |
504 | // MOUSE HANDLING
505 |
506 | function canvas_mouse_down(e) {
507 | if (world_ref.value.get("click_pos") === undefined)
508 | reset(world_ref, world_ref.value.set("click_pos", mouse_pos(e)));
509 | }
510 |
511 | function canvas_mouse_move(e) {
512 | var click_pos = world_ref.value.get("click_pos"),
513 | drag_pos = world_ref.value.get("drag_pos"),
514 | pos = mouse_pos(e);
515 | if (click_pos !== undefined &&
516 | (drag_pos !== undefined || !eq(click_pos, pos))) {
517 | reset(world_ref, world_ref.value.set("drag_pos", pos));
518 |
519 | // if we’re in the process of the dragging, we render not a model stored in history,
520 | // but the one tool_on_drag() call return. This model is auxiliary and ephemeral, it is
521 | // not stored anywhere. It’s used to show intermediate states of figures move or creation.
522 | // No other code knows anything about that. Everybody expects a model, and they get a model
523 |
524 | var model = current_model(),
525 | new_model = tool_on_drag(model.get("tool"), model, click_pos, pos, e);
526 | if (new_model !== undefined)
527 | render_ui(world_ref.value.setIn(["history", world_ref.value.get("at")], new_model));
528 | }
529 | }
530 |
531 | function canvas_mouse_up(e) {
532 | var model = current_model(),
533 | tool = model.get("tool"),
534 | click_pos = world_ref.value.get("click_pos"),
535 | drag_pos = world_ref.value.get("drag_pos"),
536 | pos = mouse_pos(e);
537 |
538 | // On mouse up we’re reusing tool_on_drag() and tool_on_click()
539 | // to commit new model to the history
540 | if (click_pos !== undefined) {
541 | if (drag_pos !== undefined) {
542 | var new_model = tool_on_drag(tool, model, click_pos, drag_pos, e);
543 | if (new_model !== undefined)
544 | edit_model(new_model);
545 | } else {
546 | var new_model = tool_on_click(tool, model, click_pos, e);
547 | if (new_model !== undefined)
548 | edit_model(new_model);
549 | }
550 | }
551 | reset(world_ref, world_ref.value.delete("click_pos").delete("drag_pos"));
552 | }
553 |
554 | document.addEventListener("mousedown", canvas_mouse_down);
555 | document.addEventListener("mousemove", canvas_mouse_move);
556 | document.addEventListener("mouseup", canvas_mouse_up);
557 |
558 |
559 | // KEYBOARD HANDLING
560 |
561 | document.addEventListener("keydown", function(e) {
562 | if (!e.ctrlKey && !e.shiftKey && !e.metaKey) {
563 | var tool = tool_keys.find(function(t) { return t[1].charCodeAt(0) === e.keyCode });
564 | if (tool !== undefined)
565 | edit_model(current_model().set("tool", tool[0]));
566 | }
567 | switch (e.keyCode) {
568 | case 27: // escape
569 | reset(world_ref, world_ref.value.delete("click_pos").delete("drag_pos"));
570 | break;
571 | case 8: // backspace
572 | case 46: // delete
573 | var model = current_model(),
574 | scene = model.get("figures"),
575 | selection = model.get("selection"),
576 | selected = function(fig) { return selection.contains(fig); };
577 | edit_model(model.set("figures", scene.filterNot(selected)));
578 | e.preventDefault();
579 | break;
580 | case 90: // Z
581 | if (e.metaKey || e.ctrlKey) {
582 | if (e.shiftKey) redo(); else undo();
583 | }
584 | e.preventDefault();
585 | break;
586 | }
587 | });
588 |
589 |
590 |
591 | // LocalStorage-powered persistence
592 | // We’re using “smart” serialization: each figure is stored only once (cache),
593 | // and models are referencing figures by ids instead of serializing their body
594 | function world_to_js(world) {
595 | var cache = list(),
596 | obj_id = function (o) {
597 | var idx = cache.indexOf(o);
598 | if (idx === -1) {
599 | cache = cache.push(o);
600 | return cache.size - 1;
601 | } else
602 | return idx;
603 | },
604 | history = [];
605 | world.get("history").forEach(function(model, i) {
606 | history.push({ tool: model.get("tool"),
607 | selection: model.get("selection").map(obj_id).toArray(),
608 | figures: model.get("figures").map(obj_id).toArray() });
609 | });
610 | return { history: history,
611 | at: world.get("at"),
612 | figures: cache.map(function(o) { return o.toJS(); }).toArray() };
613 | }
614 |
615 | function world_from_js(json) {
616 | var figures = Immutable.List(json.figures).map(Immutable.Map),
617 | get_fig = function(i) { return figures.get(i); },
618 | history = Immutable.List(json.history).map(function(m) {
619 | return map({
620 | tool: m.tool,
621 | selection: Immutable.List(m.selection).map(get_fig),
622 | figures: Immutable.List(m.figures).map(get_fig)
623 | })});
624 | return new_world().set("history", history).set("at", json.at);
625 | }
626 |
627 | // Whenever interesting parts of the world change, we store it
628 | add_watch(world_ref, function(world, old, _new) {
629 | if (!eq(old.get("history"), _new.get("history")) || !eq(old.get("at"), _new.get("at")))
630 | localStorage.setItem("vec/world", JSON.stringify(world_to_js(_new)));
631 | });
632 |
633 | // load stored world or build initial built-in scene
634 | if (localStorage.getItem("vec/world") !== null) {
635 | reset(world_ref, world_from_js(JSON.parse(localStorage.getItem("vec/world"))));
636 | } else {
637 | list(
638 | figure_from_bb("oval", map({x: 110, y: 115}), map({x: 120, y: 125})),
639 | figure_from_bb("oval", map({x: 130, y: 115}), map({x: 140, y: 125})),
640 | figure_from_bb("oval", map({x: 150, y: 115}), map({x: 160, y: 125})),
641 | figure_from_bb("line", map({x: 100, y: 140}), map({x: 170, y: 140})),
642 | figure_from_bb("line", map({x: 170, y: 140}), map({x: 180, y: 110})),
643 | figure_from_bb("line", map({x: 180, y: 110}), map({x: 280, y: 110})),
644 | figure_from_bb("line", map({x: 280, y: 110}), map({x: 290, y: 140})),
645 | figure_from_bb("line", map({x: 290, y: 140}), map({x: 600, y: 140})),
646 | figure_from_bb("line", map({x: 100, y: 180}), map({x: 600, y: 180})),
647 | figure_from_bb("rect", map({x: 100, y: 100}), map({x: 600, y: 400}))
648 | ).forEach(function(fig) {
649 | edit_model(current_model().set("figures", current_model().get("figures").push(fig)));
650 | });
651 | }
652 |
653 |
654 |
655 |
656 |
657 |
--------------------------------------------------------------------------------
/includes/immutable.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2014-2015, Facebook, Inc.
3 | * All rights reserved.
4 | *
5 | * This source code is licensed under the BSD-style license found in the
6 | * LICENSE file in the root directory of this source tree. An additional grant
7 | * of patent rights can be found in the PATENTS file in the same directory.
8 | */
9 | (function (global, factory) {
10 | typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
11 | typeof define === 'function' && define.amd ? define(factory) :
12 | global.Immutable = factory()
13 | }(this, function () { 'use strict';var SLICE$0 = Array.prototype.slice;
14 |
15 | function createClass(ctor, superClass) {
16 | if (superClass) {
17 | ctor.prototype = Object.create(superClass.prototype);
18 | }
19 | ctor.prototype.constructor = ctor;
20 | }
21 |
22 | // Used for setting prototype methods that IE8 chokes on.
23 | var DELETE = 'delete';
24 |
25 | // Constants describing the size of trie nodes.
26 | var SHIFT = 5; // Resulted in best performance after ______?
27 | var SIZE = 1 << SHIFT;
28 | var MASK = SIZE - 1;
29 |
30 | // A consistent shared value representing "not set" which equals nothing other
31 | // than itself, and nothing that could be provided externally.
32 | var NOT_SET = {};
33 |
34 | // Boolean references, Rough equivalent of `bool &`.
35 | var CHANGE_LENGTH = { value: false };
36 | var DID_ALTER = { value: false };
37 |
38 | function MakeRef(ref) {
39 | ref.value = false;
40 | return ref;
41 | }
42 |
43 | function SetRef(ref) {
44 | ref && (ref.value = true);
45 | }
46 |
47 | // A function which returns a value representing an "owner" for transient writes
48 | // to tries. The return value will only ever equal itself, and will not equal
49 | // the return of any subsequent call of this function.
50 | function OwnerID() {}
51 |
52 | // http://jsperf.com/copy-array-inline
53 | function arrCopy(arr, offset) {
54 | offset = offset || 0;
55 | var len = Math.max(0, arr.length - offset);
56 | var newArr = new Array(len);
57 | for (var ii = 0; ii < len; ii++) {
58 | newArr[ii] = arr[ii + offset];
59 | }
60 | return newArr;
61 | }
62 |
63 | function ensureSize(iter) {
64 | if (iter.size === undefined) {
65 | iter.size = iter.__iterate(returnTrue);
66 | }
67 | return iter.size;
68 | }
69 |
70 | function wrapIndex(iter, index) {
71 | return index >= 0 ? (+index) : ensureSize(iter) + (+index);
72 | }
73 |
74 | function returnTrue() {
75 | return true;
76 | }
77 |
78 | function wholeSlice(begin, end, size) {
79 | return (begin === 0 || (size !== undefined && begin <= -size)) &&
80 | (end === undefined || (size !== undefined && end >= size));
81 | }
82 |
83 | function resolveBegin(begin, size) {
84 | return resolveIndex(begin, size, 0);
85 | }
86 |
87 | function resolveEnd(end, size) {
88 | return resolveIndex(end, size, size);
89 | }
90 |
91 | function resolveIndex(index, size, defaultIndex) {
92 | return index === undefined ?
93 | defaultIndex :
94 | index < 0 ?
95 | Math.max(0, size + index) :
96 | size === undefined ?
97 | index :
98 | Math.min(size, index);
99 | }
100 |
101 | function Iterable(value) {
102 | return isIterable(value) ? value : Seq(value);
103 | }
104 |
105 |
106 | createClass(KeyedIterable, Iterable);
107 | function KeyedIterable(value) {
108 | return isKeyed(value) ? value : KeyedSeq(value);
109 | }
110 |
111 |
112 | createClass(IndexedIterable, Iterable);
113 | function IndexedIterable(value) {
114 | return isIndexed(value) ? value : IndexedSeq(value);
115 | }
116 |
117 |
118 | createClass(SetIterable, Iterable);
119 | function SetIterable(value) {
120 | return isIterable(value) && !isAssociative(value) ? value : SetSeq(value);
121 | }
122 |
123 |
124 |
125 | function isIterable(maybeIterable) {
126 | return !!(maybeIterable && maybeIterable[IS_ITERABLE_SENTINEL]);
127 | }
128 |
129 | function isKeyed(maybeKeyed) {
130 | return !!(maybeKeyed && maybeKeyed[IS_KEYED_SENTINEL]);
131 | }
132 |
133 | function isIndexed(maybeIndexed) {
134 | return !!(maybeIndexed && maybeIndexed[IS_INDEXED_SENTINEL]);
135 | }
136 |
137 | function isAssociative(maybeAssociative) {
138 | return isKeyed(maybeAssociative) || isIndexed(maybeAssociative);
139 | }
140 |
141 | function isOrdered(maybeOrdered) {
142 | return !!(maybeOrdered && maybeOrdered[IS_ORDERED_SENTINEL]);
143 | }
144 |
145 | Iterable.isIterable = isIterable;
146 | Iterable.isKeyed = isKeyed;
147 | Iterable.isIndexed = isIndexed;
148 | Iterable.isAssociative = isAssociative;
149 | Iterable.isOrdered = isOrdered;
150 |
151 | Iterable.Keyed = KeyedIterable;
152 | Iterable.Indexed = IndexedIterable;
153 | Iterable.Set = SetIterable;
154 |
155 |
156 | var IS_ITERABLE_SENTINEL = '@@__IMMUTABLE_ITERABLE__@@';
157 | var IS_KEYED_SENTINEL = '@@__IMMUTABLE_KEYED__@@';
158 | var IS_INDEXED_SENTINEL = '@@__IMMUTABLE_INDEXED__@@';
159 | var IS_ORDERED_SENTINEL = '@@__IMMUTABLE_ORDERED__@@';
160 |
161 | /* global Symbol */
162 |
163 | var ITERATE_KEYS = 0;
164 | var ITERATE_VALUES = 1;
165 | var ITERATE_ENTRIES = 2;
166 |
167 | var REAL_ITERATOR_SYMBOL = typeof Symbol === 'function' && Symbol.iterator;
168 | var FAUX_ITERATOR_SYMBOL = '@@iterator';
169 |
170 | var ITERATOR_SYMBOL = REAL_ITERATOR_SYMBOL || FAUX_ITERATOR_SYMBOL;
171 |
172 |
173 | function src_Iterator__Iterator(next) {
174 | this.next = next;
175 | }
176 |
177 | src_Iterator__Iterator.prototype.toString = function() {
178 | return '[Iterator]';
179 | };
180 |
181 |
182 | src_Iterator__Iterator.KEYS = ITERATE_KEYS;
183 | src_Iterator__Iterator.VALUES = ITERATE_VALUES;
184 | src_Iterator__Iterator.ENTRIES = ITERATE_ENTRIES;
185 |
186 | src_Iterator__Iterator.prototype.inspect =
187 | src_Iterator__Iterator.prototype.toSource = function () { return this.toString(); }
188 | src_Iterator__Iterator.prototype[ITERATOR_SYMBOL] = function () {
189 | return this;
190 | };
191 |
192 |
193 | function iteratorValue(type, k, v, iteratorResult) {
194 | var value = type === 0 ? k : type === 1 ? v : [k, v];
195 | iteratorResult ? (iteratorResult.value = value) : (iteratorResult = {
196 | value: value, done: false
197 | });
198 | return iteratorResult;
199 | }
200 |
201 | function iteratorDone() {
202 | return { value: undefined, done: true };
203 | }
204 |
205 | function hasIterator(maybeIterable) {
206 | return !!getIteratorFn(maybeIterable);
207 | }
208 |
209 | function isIterator(maybeIterator) {
210 | return maybeIterator && typeof maybeIterator.next === 'function';
211 | }
212 |
213 | function getIterator(iterable) {
214 | var iteratorFn = getIteratorFn(iterable);
215 | return iteratorFn && iteratorFn.call(iterable);
216 | }
217 |
218 | function getIteratorFn(iterable) {
219 | var iteratorFn = iterable && (
220 | (REAL_ITERATOR_SYMBOL && iterable[REAL_ITERATOR_SYMBOL]) ||
221 | iterable[FAUX_ITERATOR_SYMBOL]
222 | );
223 | if (typeof iteratorFn === 'function') {
224 | return iteratorFn;
225 | }
226 | }
227 |
228 | function isArrayLike(value) {
229 | return value && typeof value.length === 'number';
230 | }
231 |
232 | createClass(Seq, Iterable);
233 | function Seq(value) {
234 | return value === null || value === undefined ? emptySequence() :
235 | isIterable(value) ? value.toSeq() : seqFromValue(value);
236 | }
237 |
238 | Seq.of = function(/*...values*/) {
239 | return Seq(arguments);
240 | };
241 |
242 | Seq.prototype.toSeq = function() {
243 | return this;
244 | };
245 |
246 | Seq.prototype.toString = function() {
247 | return this.__toString('Seq {', '}');
248 | };
249 |
250 | Seq.prototype.cacheResult = function() {
251 | if (!this._cache && this.__iterateUncached) {
252 | this._cache = this.entrySeq().toArray();
253 | this.size = this._cache.length;
254 | }
255 | return this;
256 | };
257 |
258 | // abstract __iterateUncached(fn, reverse)
259 |
260 | Seq.prototype.__iterate = function(fn, reverse) {
261 | return seqIterate(this, fn, reverse, true);
262 | };
263 |
264 | // abstract __iteratorUncached(type, reverse)
265 |
266 | Seq.prototype.__iterator = function(type, reverse) {
267 | return seqIterator(this, type, reverse, true);
268 | };
269 |
270 |
271 |
272 | createClass(KeyedSeq, Seq);
273 | function KeyedSeq(value) {
274 | return value === null || value === undefined ?
275 | emptySequence().toKeyedSeq() :
276 | isIterable(value) ?
277 | (isKeyed(value) ? value.toSeq() : value.fromEntrySeq()) :
278 | keyedSeqFromValue(value);
279 | }
280 |
281 | KeyedSeq.prototype.toKeyedSeq = function() {
282 | return this;
283 | };
284 |
285 |
286 |
287 | createClass(IndexedSeq, Seq);
288 | function IndexedSeq(value) {
289 | return value === null || value === undefined ? emptySequence() :
290 | !isIterable(value) ? indexedSeqFromValue(value) :
291 | isKeyed(value) ? value.entrySeq() : value.toIndexedSeq();
292 | }
293 |
294 | IndexedSeq.of = function(/*...values*/) {
295 | return IndexedSeq(arguments);
296 | };
297 |
298 | IndexedSeq.prototype.toIndexedSeq = function() {
299 | return this;
300 | };
301 |
302 | IndexedSeq.prototype.toString = function() {
303 | return this.__toString('Seq [', ']');
304 | };
305 |
306 | IndexedSeq.prototype.__iterate = function(fn, reverse) {
307 | return seqIterate(this, fn, reverse, false);
308 | };
309 |
310 | IndexedSeq.prototype.__iterator = function(type, reverse) {
311 | return seqIterator(this, type, reverse, false);
312 | };
313 |
314 |
315 |
316 | createClass(SetSeq, Seq);
317 | function SetSeq(value) {
318 | return (
319 | value === null || value === undefined ? emptySequence() :
320 | !isIterable(value) ? indexedSeqFromValue(value) :
321 | isKeyed(value) ? value.entrySeq() : value
322 | ).toSetSeq();
323 | }
324 |
325 | SetSeq.of = function(/*...values*/) {
326 | return SetSeq(arguments);
327 | };
328 |
329 | SetSeq.prototype.toSetSeq = function() {
330 | return this;
331 | };
332 |
333 |
334 |
335 | Seq.isSeq = isSeq;
336 | Seq.Keyed = KeyedSeq;
337 | Seq.Set = SetSeq;
338 | Seq.Indexed = IndexedSeq;
339 |
340 | var IS_SEQ_SENTINEL = '@@__IMMUTABLE_SEQ__@@';
341 |
342 | Seq.prototype[IS_SEQ_SENTINEL] = true;
343 |
344 |
345 |
346 | // #pragma Root Sequences
347 |
348 | createClass(ArraySeq, IndexedSeq);
349 | function ArraySeq(array) {
350 | this._array = array;
351 | this.size = array.length;
352 | }
353 |
354 | ArraySeq.prototype.get = function(index, notSetValue) {
355 | return this.has(index) ? this._array[wrapIndex(this, index)] : notSetValue;
356 | };
357 |
358 | ArraySeq.prototype.__iterate = function(fn, reverse) {
359 | var array = this._array;
360 | var maxIndex = array.length - 1;
361 | for (var ii = 0; ii <= maxIndex; ii++) {
362 | if (fn(array[reverse ? maxIndex - ii : ii], ii, this) === false) {
363 | return ii + 1;
364 | }
365 | }
366 | return ii;
367 | };
368 |
369 | ArraySeq.prototype.__iterator = function(type, reverse) {
370 | var array = this._array;
371 | var maxIndex = array.length - 1;
372 | var ii = 0;
373 | return new src_Iterator__Iterator(function()
374 | {return ii > maxIndex ?
375 | iteratorDone() :
376 | iteratorValue(type, ii, array[reverse ? maxIndex - ii++ : ii++])}
377 | );
378 | };
379 |
380 |
381 |
382 | createClass(ObjectSeq, KeyedSeq);
383 | function ObjectSeq(object) {
384 | var keys = Object.keys(object);
385 | this._object = object;
386 | this._keys = keys;
387 | this.size = keys.length;
388 | }
389 |
390 | ObjectSeq.prototype.get = function(key, notSetValue) {
391 | if (notSetValue !== undefined && !this.has(key)) {
392 | return notSetValue;
393 | }
394 | return this._object[key];
395 | };
396 |
397 | ObjectSeq.prototype.has = function(key) {
398 | return this._object.hasOwnProperty(key);
399 | };
400 |
401 | ObjectSeq.prototype.__iterate = function(fn, reverse) {
402 | var object = this._object;
403 | var keys = this._keys;
404 | var maxIndex = keys.length - 1;
405 | for (var ii = 0; ii <= maxIndex; ii++) {
406 | var key = keys[reverse ? maxIndex - ii : ii];
407 | if (fn(object[key], key, this) === false) {
408 | return ii + 1;
409 | }
410 | }
411 | return ii;
412 | };
413 |
414 | ObjectSeq.prototype.__iterator = function(type, reverse) {
415 | var object = this._object;
416 | var keys = this._keys;
417 | var maxIndex = keys.length - 1;
418 | var ii = 0;
419 | return new src_Iterator__Iterator(function() {
420 | var key = keys[reverse ? maxIndex - ii : ii];
421 | return ii++ > maxIndex ?
422 | iteratorDone() :
423 | iteratorValue(type, key, object[key]);
424 | });
425 | };
426 |
427 | ObjectSeq.prototype[IS_ORDERED_SENTINEL] = true;
428 |
429 |
430 | createClass(IterableSeq, IndexedSeq);
431 | function IterableSeq(iterable) {
432 | this._iterable = iterable;
433 | this.size = iterable.length || iterable.size;
434 | }
435 |
436 | IterableSeq.prototype.__iterateUncached = function(fn, reverse) {
437 | if (reverse) {
438 | return this.cacheResult().__iterate(fn, reverse);
439 | }
440 | var iterable = this._iterable;
441 | var iterator = getIterator(iterable);
442 | var iterations = 0;
443 | if (isIterator(iterator)) {
444 | var step;
445 | while (!(step = iterator.next()).done) {
446 | if (fn(step.value, iterations++, this) === false) {
447 | break;
448 | }
449 | }
450 | }
451 | return iterations;
452 | };
453 |
454 | IterableSeq.prototype.__iteratorUncached = function(type, reverse) {
455 | if (reverse) {
456 | return this.cacheResult().__iterator(type, reverse);
457 | }
458 | var iterable = this._iterable;
459 | var iterator = getIterator(iterable);
460 | if (!isIterator(iterator)) {
461 | return new src_Iterator__Iterator(iteratorDone);
462 | }
463 | var iterations = 0;
464 | return new src_Iterator__Iterator(function() {
465 | var step = iterator.next();
466 | return step.done ? step : iteratorValue(type, iterations++, step.value);
467 | });
468 | };
469 |
470 |
471 |
472 | createClass(IteratorSeq, IndexedSeq);
473 | function IteratorSeq(iterator) {
474 | this._iterator = iterator;
475 | this._iteratorCache = [];
476 | }
477 |
478 | IteratorSeq.prototype.__iterateUncached = function(fn, reverse) {
479 | if (reverse) {
480 | return this.cacheResult().__iterate(fn, reverse);
481 | }
482 | var iterator = this._iterator;
483 | var cache = this._iteratorCache;
484 | var iterations = 0;
485 | while (iterations < cache.length) {
486 | if (fn(cache[iterations], iterations++, this) === false) {
487 | return iterations;
488 | }
489 | }
490 | var step;
491 | while (!(step = iterator.next()).done) {
492 | var val = step.value;
493 | cache[iterations] = val;
494 | if (fn(val, iterations++, this) === false) {
495 | break;
496 | }
497 | }
498 | return iterations;
499 | };
500 |
501 | IteratorSeq.prototype.__iteratorUncached = function(type, reverse) {
502 | if (reverse) {
503 | return this.cacheResult().__iterator(type, reverse);
504 | }
505 | var iterator = this._iterator;
506 | var cache = this._iteratorCache;
507 | var iterations = 0;
508 | return new src_Iterator__Iterator(function() {
509 | if (iterations >= cache.length) {
510 | var step = iterator.next();
511 | if (step.done) {
512 | return step;
513 | }
514 | cache[iterations] = step.value;
515 | }
516 | return iteratorValue(type, iterations, cache[iterations++]);
517 | });
518 | };
519 |
520 |
521 |
522 |
523 | // # pragma Helper functions
524 |
525 | function isSeq(maybeSeq) {
526 | return !!(maybeSeq && maybeSeq[IS_SEQ_SENTINEL]);
527 | }
528 |
529 | var EMPTY_SEQ;
530 |
531 | function emptySequence() {
532 | return EMPTY_SEQ || (EMPTY_SEQ = new ArraySeq([]));
533 | }
534 |
535 | function keyedSeqFromValue(value) {
536 | var seq =
537 | Array.isArray(value) ? new ArraySeq(value).fromEntrySeq() :
538 | isIterator(value) ? new IteratorSeq(value).fromEntrySeq() :
539 | hasIterator(value) ? new IterableSeq(value).fromEntrySeq() :
540 | typeof value === 'object' ? new ObjectSeq(value) :
541 | undefined;
542 | if (!seq) {
543 | throw new TypeError(
544 | 'Expected Array or iterable object of [k, v] entries, '+
545 | 'or keyed object: ' + value
546 | );
547 | }
548 | return seq;
549 | }
550 |
551 | function indexedSeqFromValue(value) {
552 | var seq = maybeIndexedSeqFromValue(value);
553 | if (!seq) {
554 | throw new TypeError(
555 | 'Expected Array or iterable object of values: ' + value
556 | );
557 | }
558 | return seq;
559 | }
560 |
561 | function seqFromValue(value) {
562 | var seq = maybeIndexedSeqFromValue(value) ||
563 | (typeof value === 'object' && new ObjectSeq(value));
564 | if (!seq) {
565 | throw new TypeError(
566 | 'Expected Array or iterable object of values, or keyed object: ' + value
567 | );
568 | }
569 | return seq;
570 | }
571 |
572 | function maybeIndexedSeqFromValue(value) {
573 | return (
574 | isArrayLike(value) ? new ArraySeq(value) :
575 | isIterator(value) ? new IteratorSeq(value) :
576 | hasIterator(value) ? new IterableSeq(value) :
577 | undefined
578 | );
579 | }
580 |
581 | function seqIterate(seq, fn, reverse, useKeys) {
582 | var cache = seq._cache;
583 | if (cache) {
584 | var maxIndex = cache.length - 1;
585 | for (var ii = 0; ii <= maxIndex; ii++) {
586 | var entry = cache[reverse ? maxIndex - ii : ii];
587 | if (fn(entry[1], useKeys ? entry[0] : ii, seq) === false) {
588 | return ii + 1;
589 | }
590 | }
591 | return ii;
592 | }
593 | return seq.__iterateUncached(fn, reverse);
594 | }
595 |
596 | function seqIterator(seq, type, reverse, useKeys) {
597 | var cache = seq._cache;
598 | if (cache) {
599 | var maxIndex = cache.length - 1;
600 | var ii = 0;
601 | return new src_Iterator__Iterator(function() {
602 | var entry = cache[reverse ? maxIndex - ii : ii];
603 | return ii++ > maxIndex ?
604 | iteratorDone() :
605 | iteratorValue(type, useKeys ? entry[0] : ii - 1, entry[1]);
606 | });
607 | }
608 | return seq.__iteratorUncached(type, reverse);
609 | }
610 |
611 | createClass(Collection, Iterable);
612 | function Collection() {
613 | throw TypeError('Abstract');
614 | }
615 |
616 |
617 | createClass(KeyedCollection, Collection);function KeyedCollection() {}
618 |
619 | createClass(IndexedCollection, Collection);function IndexedCollection() {}
620 |
621 | createClass(SetCollection, Collection);function SetCollection() {}
622 |
623 |
624 | Collection.Keyed = KeyedCollection;
625 | Collection.Indexed = IndexedCollection;
626 | Collection.Set = SetCollection;
627 |
628 | /**
629 | * An extension of the "same-value" algorithm as [described for use by ES6 Map
630 | * and Set](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map#Key_equality)
631 | *
632 | * NaN is considered the same as NaN, however -0 and 0 are considered the same
633 | * value, which is different from the algorithm described by
634 | * [`Object.is`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is).
635 | *
636 | * This is extended further to allow Objects to describe the values they
637 | * represent, by way of `valueOf` or `equals` (and `hashCode`).
638 | *
639 | * Note: because of this extension, the key equality of Immutable.Map and the
640 | * value equality of Immutable.Set will differ from ES6 Map and Set.
641 | *
642 | * ### Defining custom values
643 | *
644 | * The easiest way to describe the value an object represents is by implementing
645 | * `valueOf`. For example, `Date` represents a value by returning a unix
646 | * timestamp for `valueOf`:
647 | *
648 | * var date1 = new Date(1234567890000); // Fri Feb 13 2009 ...
649 | * var date2 = new Date(1234567890000);
650 | * date1.valueOf(); // 1234567890000
651 | * assert( date1 !== date2 );
652 | * assert( Immutable.is( date1, date2 ) );
653 | *
654 | * Note: overriding `valueOf` may have other implications if you use this object
655 | * where JavaScript expects a primitive, such as implicit string coercion.
656 | *
657 | * For more complex types, especially collections, implementing `valueOf` may
658 | * not be performant. An alternative is to implement `equals` and `hashCode`.
659 | *
660 | * `equals` takes another object, presumably of similar type, and returns true
661 | * if the it is equal. Equality is symmetrical, so the same result should be
662 | * returned if this and the argument are flipped.
663 | *
664 | * assert( a.equals(b) === b.equals(a) );
665 | *
666 | * `hashCode` returns a 32bit integer number representing the object which will
667 | * be used to determine how to store the value object in a Map or Set. You must
668 | * provide both or neither methods, one must not exist without the other.
669 | *
670 | * Also, an important relationship between these methods must be upheld: if two
671 | * values are equal, they *must* return the same hashCode. If the values are not
672 | * equal, they might have the same hashCode; this is called a hash collision,
673 | * and while undesirable for performance reasons, it is acceptable.
674 | *
675 | * if (a.equals(b)) {
676 | * assert( a.hashCode() === b.hashCode() );
677 | * }
678 | *
679 | * All Immutable collections implement `equals` and `hashCode`.
680 | *
681 | */
682 | function is(valueA, valueB) {
683 | if (valueA === valueB || (valueA !== valueA && valueB !== valueB)) {
684 | return true;
685 | }
686 | if (!valueA || !valueB) {
687 | return false;
688 | }
689 | if (typeof valueA.valueOf === 'function' &&
690 | typeof valueB.valueOf === 'function') {
691 | valueA = valueA.valueOf();
692 | valueB = valueB.valueOf();
693 | if (valueA === valueB || (valueA !== valueA && valueB !== valueB)) {
694 | return true;
695 | }
696 | if (!valueA || !valueB) {
697 | return false;
698 | }
699 | }
700 | if (typeof valueA.equals === 'function' &&
701 | typeof valueB.equals === 'function' &&
702 | valueA.equals(valueB)) {
703 | return true;
704 | }
705 | return false;
706 | }
707 |
708 | function fromJS(json, converter) {
709 | return converter ?
710 | fromJSWith(converter, json, '', {'': json}) :
711 | fromJSDefault(json);
712 | }
713 |
714 | function fromJSWith(converter, json, key, parentJSON) {
715 | if (Array.isArray(json)) {
716 | return converter.call(parentJSON, key, IndexedSeq(json).map(function(v, k) {return fromJSWith(converter, v, k, json)}));
717 | }
718 | if (isPlainObj(json)) {
719 | return converter.call(parentJSON, key, KeyedSeq(json).map(function(v, k) {return fromJSWith(converter, v, k, json)}));
720 | }
721 | return json;
722 | }
723 |
724 | function fromJSDefault(json) {
725 | if (Array.isArray(json)) {
726 | return IndexedSeq(json).map(fromJSDefault).toList();
727 | }
728 | if (isPlainObj(json)) {
729 | return KeyedSeq(json).map(fromJSDefault).toMap();
730 | }
731 | return json;
732 | }
733 |
734 | function isPlainObj(value) {
735 | return value && (value.constructor === Object || value.constructor === undefined);
736 | }
737 |
738 | var src_Math__imul =
739 | typeof Math.imul === 'function' && Math.imul(0xffffffff, 2) === -2 ?
740 | Math.imul :
741 | function imul(a, b) {
742 | a = a | 0; // int
743 | b = b | 0; // int
744 | var c = a & 0xffff;
745 | var d = b & 0xffff;
746 | // Shift by 0 fixes the sign on the high part.
747 | return (c * d) + ((((a >>> 16) * d + c * (b >>> 16)) << 16) >>> 0) | 0; // int
748 | };
749 |
750 | // v8 has an optimization for storing 31-bit signed numbers.
751 | // Values which have either 00 or 11 as the high order bits qualify.
752 | // This function drops the highest order bit in a signed number, maintaining
753 | // the sign bit.
754 | function smi(i32) {
755 | return ((i32 >>> 1) & 0x40000000) | (i32 & 0xBFFFFFFF);
756 | }
757 |
758 | function hash(o) {
759 | if (o === false || o === null || o === undefined) {
760 | return 0;
761 | }
762 | if (typeof o.valueOf === 'function') {
763 | o = o.valueOf();
764 | if (o === false || o === null || o === undefined) {
765 | return 0;
766 | }
767 | }
768 | if (o === true) {
769 | return 1;
770 | }
771 | var type = typeof o;
772 | if (type === 'number') {
773 | var h = o | 0;
774 | if (h !== o) {
775 | h ^= o * 0xFFFFFFFF;
776 | }
777 | while (o > 0xFFFFFFFF) {
778 | o /= 0xFFFFFFFF;
779 | h ^= o;
780 | }
781 | return smi(h);
782 | }
783 | if (type === 'string') {
784 | return o.length > STRING_HASH_CACHE_MIN_STRLEN ? cachedHashString(o) : hashString(o);
785 | }
786 | if (typeof o.hashCode === 'function') {
787 | return o.hashCode();
788 | }
789 | return hashJSObj(o);
790 | }
791 |
792 | function cachedHashString(string) {
793 | var hash = stringHashCache[string];
794 | if (hash === undefined) {
795 | hash = hashString(string);
796 | if (STRING_HASH_CACHE_SIZE === STRING_HASH_CACHE_MAX_SIZE) {
797 | STRING_HASH_CACHE_SIZE = 0;
798 | stringHashCache = {};
799 | }
800 | STRING_HASH_CACHE_SIZE++;
801 | stringHashCache[string] = hash;
802 | }
803 | return hash;
804 | }
805 |
806 | // http://jsperf.com/hashing-strings
807 | function hashString(string) {
808 | // This is the hash from JVM
809 | // The hash code for a string is computed as
810 | // s[0] * 31 ^ (n - 1) + s[1] * 31 ^ (n - 2) + ... + s[n - 1],
811 | // where s[i] is the ith character of the string and n is the length of
812 | // the string. We "mod" the result to make it between 0 (inclusive) and 2^31
813 | // (exclusive) by dropping high bits.
814 | var hash = 0;
815 | for (var ii = 0; ii < string.length; ii++) {
816 | hash = 31 * hash + string.charCodeAt(ii) | 0;
817 | }
818 | return smi(hash);
819 | }
820 |
821 | function hashJSObj(obj) {
822 | var hash;
823 | if (usingWeakMap) {
824 | hash = weakMap.get(obj);
825 | if (hash !== undefined) {
826 | return hash;
827 | }
828 | }
829 |
830 | hash = obj[UID_HASH_KEY];
831 | if (hash !== undefined) {
832 | return hash;
833 | }
834 |
835 | if (!canDefineProperty) {
836 | hash = obj.propertyIsEnumerable && obj.propertyIsEnumerable[UID_HASH_KEY];
837 | if (hash !== undefined) {
838 | return hash;
839 | }
840 |
841 | hash = getIENodeHash(obj);
842 | if (hash !== undefined) {
843 | return hash;
844 | }
845 | }
846 |
847 | hash = ++objHashUID;
848 | if (objHashUID & 0x40000000) {
849 | objHashUID = 0;
850 | }
851 |
852 | if (usingWeakMap) {
853 | weakMap.set(obj, hash);
854 | } else if (isExtensible !== undefined && isExtensible(obj) === false) {
855 | throw new Error('Non-extensible objects are not allowed as keys.');
856 | } else if (canDefineProperty) {
857 | Object.defineProperty(obj, UID_HASH_KEY, {
858 | 'enumerable': false,
859 | 'configurable': false,
860 | 'writable': false,
861 | 'value': hash
862 | });
863 | } else if (obj.propertyIsEnumerable !== undefined &&
864 | obj.propertyIsEnumerable === obj.constructor.prototype.propertyIsEnumerable) {
865 | // Since we can't define a non-enumerable property on the object
866 | // we'll hijack one of the less-used non-enumerable properties to
867 | // save our hash on it. Since this is a function it will not show up in
868 | // `JSON.stringify` which is what we want.
869 | obj.propertyIsEnumerable = function() {
870 | return this.constructor.prototype.propertyIsEnumerable.apply(this, arguments);
871 | };
872 | obj.propertyIsEnumerable[UID_HASH_KEY] = hash;
873 | } else if (obj.nodeType !== undefined) {
874 | // At this point we couldn't get the IE `uniqueID` to use as a hash
875 | // and we couldn't use a non-enumerable property to exploit the
876 | // dontEnum bug so we simply add the `UID_HASH_KEY` on the node
877 | // itself.
878 | obj[UID_HASH_KEY] = hash;
879 | } else {
880 | throw new Error('Unable to set a non-enumerable property on object.');
881 | }
882 |
883 | return hash;
884 | }
885 |
886 | // Get references to ES5 object methods.
887 | var isExtensible = Object.isExtensible;
888 |
889 | // True if Object.defineProperty works as expected. IE8 fails this test.
890 | var canDefineProperty = (function() {
891 | try {
892 | Object.defineProperty({}, '@', {});
893 | return true;
894 | } catch (e) {
895 | return false;
896 | }
897 | }());
898 |
899 | // IE has a `uniqueID` property on DOM nodes. We can construct the hash from it
900 | // and avoid memory leaks from the IE cloneNode bug.
901 | function getIENodeHash(node) {
902 | if (node && node.nodeType > 0) {
903 | switch (node.nodeType) {
904 | case 1: // Element
905 | return node.uniqueID;
906 | case 9: // Document
907 | return node.documentElement && node.documentElement.uniqueID;
908 | }
909 | }
910 | }
911 |
912 | // If possible, use a WeakMap.
913 | var usingWeakMap = typeof WeakMap === 'function';
914 | var weakMap;
915 | if (usingWeakMap) {
916 | weakMap = new WeakMap();
917 | }
918 |
919 | var objHashUID = 0;
920 |
921 | var UID_HASH_KEY = '__immutablehash__';
922 | if (typeof Symbol === 'function') {
923 | UID_HASH_KEY = Symbol(UID_HASH_KEY);
924 | }
925 |
926 | var STRING_HASH_CACHE_MIN_STRLEN = 16;
927 | var STRING_HASH_CACHE_MAX_SIZE = 255;
928 | var STRING_HASH_CACHE_SIZE = 0;
929 | var stringHashCache = {};
930 |
931 | function invariant(condition, error) {
932 | if (!condition) throw new Error(error);
933 | }
934 |
935 | function assertNotInfinite(size) {
936 | invariant(
937 | size !== Infinity,
938 | 'Cannot perform this action with an infinite size.'
939 | );
940 | }
941 |
942 | createClass(ToKeyedSequence, KeyedSeq);
943 | function ToKeyedSequence(indexed, useKeys) {
944 | this._iter = indexed;
945 | this._useKeys = useKeys;
946 | this.size = indexed.size;
947 | }
948 |
949 | ToKeyedSequence.prototype.get = function(key, notSetValue) {
950 | return this._iter.get(key, notSetValue);
951 | };
952 |
953 | ToKeyedSequence.prototype.has = function(key) {
954 | return this._iter.has(key);
955 | };
956 |
957 | ToKeyedSequence.prototype.valueSeq = function() {
958 | return this._iter.valueSeq();
959 | };
960 |
961 | ToKeyedSequence.prototype.reverse = function() {var this$0 = this;
962 | var reversedSequence = reverseFactory(this, true);
963 | if (!this._useKeys) {
964 | reversedSequence.valueSeq = function() {return this$0._iter.toSeq().reverse()};
965 | }
966 | return reversedSequence;
967 | };
968 |
969 | ToKeyedSequence.prototype.map = function(mapper, context) {var this$0 = this;
970 | var mappedSequence = mapFactory(this, mapper, context);
971 | if (!this._useKeys) {
972 | mappedSequence.valueSeq = function() {return this$0._iter.toSeq().map(mapper, context)};
973 | }
974 | return mappedSequence;
975 | };
976 |
977 | ToKeyedSequence.prototype.__iterate = function(fn, reverse) {var this$0 = this;
978 | var ii;
979 | return this._iter.__iterate(
980 | this._useKeys ?
981 | function(v, k) {return fn(v, k, this$0)} :
982 | ((ii = reverse ? resolveSize(this) : 0),
983 | function(v ) {return fn(v, reverse ? --ii : ii++, this$0)}),
984 | reverse
985 | );
986 | };
987 |
988 | ToKeyedSequence.prototype.__iterator = function(type, reverse) {
989 | if (this._useKeys) {
990 | return this._iter.__iterator(type, reverse);
991 | }
992 | var iterator = this._iter.__iterator(ITERATE_VALUES, reverse);
993 | var ii = reverse ? resolveSize(this) : 0;
994 | return new src_Iterator__Iterator(function() {
995 | var step = iterator.next();
996 | return step.done ? step :
997 | iteratorValue(type, reverse ? --ii : ii++, step.value, step);
998 | });
999 | };
1000 |
1001 | ToKeyedSequence.prototype[IS_ORDERED_SENTINEL] = true;
1002 |
1003 |
1004 | createClass(ToIndexedSequence, IndexedSeq);
1005 | function ToIndexedSequence(iter) {
1006 | this._iter = iter;
1007 | this.size = iter.size;
1008 | }
1009 |
1010 | ToIndexedSequence.prototype.includes = function(value) {
1011 | return this._iter.includes(value);
1012 | };
1013 |
1014 | ToIndexedSequence.prototype.__iterate = function(fn, reverse) {var this$0 = this;
1015 | var iterations = 0;
1016 | return this._iter.__iterate(function(v ) {return fn(v, iterations++, this$0)}, reverse);
1017 | };
1018 |
1019 | ToIndexedSequence.prototype.__iterator = function(type, reverse) {
1020 | var iterator = this._iter.__iterator(ITERATE_VALUES, reverse);
1021 | var iterations = 0;
1022 | return new src_Iterator__Iterator(function() {
1023 | var step = iterator.next();
1024 | return step.done ? step :
1025 | iteratorValue(type, iterations++, step.value, step)
1026 | });
1027 | };
1028 |
1029 |
1030 |
1031 | createClass(ToSetSequence, SetSeq);
1032 | function ToSetSequence(iter) {
1033 | this._iter = iter;
1034 | this.size = iter.size;
1035 | }
1036 |
1037 | ToSetSequence.prototype.has = function(key) {
1038 | return this._iter.includes(key);
1039 | };
1040 |
1041 | ToSetSequence.prototype.__iterate = function(fn, reverse) {var this$0 = this;
1042 | return this._iter.__iterate(function(v ) {return fn(v, v, this$0)}, reverse);
1043 | };
1044 |
1045 | ToSetSequence.prototype.__iterator = function(type, reverse) {
1046 | var iterator = this._iter.__iterator(ITERATE_VALUES, reverse);
1047 | return new src_Iterator__Iterator(function() {
1048 | var step = iterator.next();
1049 | return step.done ? step :
1050 | iteratorValue(type, step.value, step.value, step);
1051 | });
1052 | };
1053 |
1054 |
1055 |
1056 | createClass(FromEntriesSequence, KeyedSeq);
1057 | function FromEntriesSequence(entries) {
1058 | this._iter = entries;
1059 | this.size = entries.size;
1060 | }
1061 |
1062 | FromEntriesSequence.prototype.entrySeq = function() {
1063 | return this._iter.toSeq();
1064 | };
1065 |
1066 | FromEntriesSequence.prototype.__iterate = function(fn, reverse) {var this$0 = this;
1067 | return this._iter.__iterate(function(entry ) {
1068 | // Check if entry exists first so array access doesn't throw for holes
1069 | // in the parent iteration.
1070 | if (entry) {
1071 | validateEntry(entry);
1072 | var indexedIterable = isIterable(entry);
1073 | return fn(
1074 | indexedIterable ? entry.get(1) : entry[1],
1075 | indexedIterable ? entry.get(0) : entry[0],
1076 | this$0
1077 | );
1078 | }
1079 | }, reverse);
1080 | };
1081 |
1082 | FromEntriesSequence.prototype.__iterator = function(type, reverse) {
1083 | var iterator = this._iter.__iterator(ITERATE_VALUES, reverse);
1084 | return new src_Iterator__Iterator(function() {
1085 | while (true) {
1086 | var step = iterator.next();
1087 | if (step.done) {
1088 | return step;
1089 | }
1090 | var entry = step.value;
1091 | // Check if entry exists first so array access doesn't throw for holes
1092 | // in the parent iteration.
1093 | if (entry) {
1094 | validateEntry(entry);
1095 | var indexedIterable = isIterable(entry);
1096 | return iteratorValue(
1097 | type,
1098 | indexedIterable ? entry.get(0) : entry[0],
1099 | indexedIterable ? entry.get(1) : entry[1],
1100 | step
1101 | );
1102 | }
1103 | }
1104 | });
1105 | };
1106 |
1107 |
1108 | ToIndexedSequence.prototype.cacheResult =
1109 | ToKeyedSequence.prototype.cacheResult =
1110 | ToSetSequence.prototype.cacheResult =
1111 | FromEntriesSequence.prototype.cacheResult =
1112 | cacheResultThrough;
1113 |
1114 |
1115 | function flipFactory(iterable) {
1116 | var flipSequence = makeSequence(iterable);
1117 | flipSequence._iter = iterable;
1118 | flipSequence.size = iterable.size;
1119 | flipSequence.flip = function() {return iterable};
1120 | flipSequence.reverse = function () {
1121 | var reversedSequence = iterable.reverse.apply(this); // super.reverse()
1122 | reversedSequence.flip = function() {return iterable.reverse()};
1123 | return reversedSequence;
1124 | };
1125 | flipSequence.has = function(key ) {return iterable.includes(key)};
1126 | flipSequence.includes = function(key ) {return iterable.has(key)};
1127 | flipSequence.cacheResult = cacheResultThrough;
1128 | flipSequence.__iterateUncached = function (fn, reverse) {var this$0 = this;
1129 | return iterable.__iterate(function(v, k) {return fn(k, v, this$0) !== false}, reverse);
1130 | }
1131 | flipSequence.__iteratorUncached = function(type, reverse) {
1132 | if (type === ITERATE_ENTRIES) {
1133 | var iterator = iterable.__iterator(type, reverse);
1134 | return new src_Iterator__Iterator(function() {
1135 | var step = iterator.next();
1136 | if (!step.done) {
1137 | var k = step.value[0];
1138 | step.value[0] = step.value[1];
1139 | step.value[1] = k;
1140 | }
1141 | return step;
1142 | });
1143 | }
1144 | return iterable.__iterator(
1145 | type === ITERATE_VALUES ? ITERATE_KEYS : ITERATE_VALUES,
1146 | reverse
1147 | );
1148 | }
1149 | return flipSequence;
1150 | }
1151 |
1152 |
1153 | function mapFactory(iterable, mapper, context) {
1154 | var mappedSequence = makeSequence(iterable);
1155 | mappedSequence.size = iterable.size;
1156 | mappedSequence.has = function(key ) {return iterable.has(key)};
1157 | mappedSequence.get = function(key, notSetValue) {
1158 | var v = iterable.get(key, NOT_SET);
1159 | return v === NOT_SET ?
1160 | notSetValue :
1161 | mapper.call(context, v, key, iterable);
1162 | };
1163 | mappedSequence.__iterateUncached = function (fn, reverse) {var this$0 = this;
1164 | return iterable.__iterate(
1165 | function(v, k, c) {return fn(mapper.call(context, v, k, c), k, this$0) !== false},
1166 | reverse
1167 | );
1168 | }
1169 | mappedSequence.__iteratorUncached = function (type, reverse) {
1170 | var iterator = iterable.__iterator(ITERATE_ENTRIES, reverse);
1171 | return new src_Iterator__Iterator(function() {
1172 | var step = iterator.next();
1173 | if (step.done) {
1174 | return step;
1175 | }
1176 | var entry = step.value;
1177 | var key = entry[0];
1178 | return iteratorValue(
1179 | type,
1180 | key,
1181 | mapper.call(context, entry[1], key, iterable),
1182 | step
1183 | );
1184 | });
1185 | }
1186 | return mappedSequence;
1187 | }
1188 |
1189 |
1190 | function reverseFactory(iterable, useKeys) {
1191 | var reversedSequence = makeSequence(iterable);
1192 | reversedSequence._iter = iterable;
1193 | reversedSequence.size = iterable.size;
1194 | reversedSequence.reverse = function() {return iterable};
1195 | if (iterable.flip) {
1196 | reversedSequence.flip = function () {
1197 | var flipSequence = flipFactory(iterable);
1198 | flipSequence.reverse = function() {return iterable.flip()};
1199 | return flipSequence;
1200 | };
1201 | }
1202 | reversedSequence.get = function(key, notSetValue)
1203 | {return iterable.get(useKeys ? key : -1 - key, notSetValue)};
1204 | reversedSequence.has = function(key )
1205 | {return iterable.has(useKeys ? key : -1 - key)};
1206 | reversedSequence.includes = function(value ) {return iterable.includes(value)};
1207 | reversedSequence.cacheResult = cacheResultThrough;
1208 | reversedSequence.__iterate = function (fn, reverse) {var this$0 = this;
1209 | return iterable.__iterate(function(v, k) {return fn(v, k, this$0)}, !reverse);
1210 | };
1211 | reversedSequence.__iterator =
1212 | function(type, reverse) {return iterable.__iterator(type, !reverse)};
1213 | return reversedSequence;
1214 | }
1215 |
1216 |
1217 | function filterFactory(iterable, predicate, context, useKeys) {
1218 | var filterSequence = makeSequence(iterable);
1219 | if (useKeys) {
1220 | filterSequence.has = function(key ) {
1221 | var v = iterable.get(key, NOT_SET);
1222 | return v !== NOT_SET && !!predicate.call(context, v, key, iterable);
1223 | };
1224 | filterSequence.get = function(key, notSetValue) {
1225 | var v = iterable.get(key, NOT_SET);
1226 | return v !== NOT_SET && predicate.call(context, v, key, iterable) ?
1227 | v : notSetValue;
1228 | };
1229 | }
1230 | filterSequence.__iterateUncached = function (fn, reverse) {var this$0 = this;
1231 | var iterations = 0;
1232 | iterable.__iterate(function(v, k, c) {
1233 | if (predicate.call(context, v, k, c)) {
1234 | iterations++;
1235 | return fn(v, useKeys ? k : iterations - 1, this$0);
1236 | }
1237 | }, reverse);
1238 | return iterations;
1239 | };
1240 | filterSequence.__iteratorUncached = function (type, reverse) {
1241 | var iterator = iterable.__iterator(ITERATE_ENTRIES, reverse);
1242 | var iterations = 0;
1243 | return new src_Iterator__Iterator(function() {
1244 | while (true) {
1245 | var step = iterator.next();
1246 | if (step.done) {
1247 | return step;
1248 | }
1249 | var entry = step.value;
1250 | var key = entry[0];
1251 | var value = entry[1];
1252 | if (predicate.call(context, value, key, iterable)) {
1253 | return iteratorValue(type, useKeys ? key : iterations++, value, step);
1254 | }
1255 | }
1256 | });
1257 | }
1258 | return filterSequence;
1259 | }
1260 |
1261 |
1262 | function countByFactory(iterable, grouper, context) {
1263 | var groups = src_Map__Map().asMutable();
1264 | iterable.__iterate(function(v, k) {
1265 | groups.update(
1266 | grouper.call(context, v, k, iterable),
1267 | 0,
1268 | function(a ) {return a + 1}
1269 | );
1270 | });
1271 | return groups.asImmutable();
1272 | }
1273 |
1274 |
1275 | function groupByFactory(iterable, grouper, context) {
1276 | var isKeyedIter = isKeyed(iterable);
1277 | var groups = (isOrdered(iterable) ? OrderedMap() : src_Map__Map()).asMutable();
1278 | iterable.__iterate(function(v, k) {
1279 | groups.update(
1280 | grouper.call(context, v, k, iterable),
1281 | function(a ) {return (a = a || [], a.push(isKeyedIter ? [k, v] : v), a)}
1282 | );
1283 | });
1284 | var coerce = iterableClass(iterable);
1285 | return groups.map(function(arr ) {return reify(iterable, coerce(arr))});
1286 | }
1287 |
1288 |
1289 | function sliceFactory(iterable, begin, end, useKeys) {
1290 | var originalSize = iterable.size;
1291 |
1292 | if (wholeSlice(begin, end, originalSize)) {
1293 | return iterable;
1294 | }
1295 |
1296 | var resolvedBegin = resolveBegin(begin, originalSize);
1297 | var resolvedEnd = resolveEnd(end, originalSize);
1298 |
1299 | // begin or end will be NaN if they were provided as negative numbers and
1300 | // this iterable's size is unknown. In that case, cache first so there is
1301 | // a known size and these do not resolve to NaN.
1302 | if (resolvedBegin !== resolvedBegin || resolvedEnd !== resolvedEnd) {
1303 | return sliceFactory(iterable.toSeq().cacheResult(), begin, end, useKeys);
1304 | }
1305 |
1306 | // Note: resolvedEnd is undefined when the original sequence's length is
1307 | // unknown and this slice did not supply an end and should contain all
1308 | // elements after resolvedBegin.
1309 | // In that case, resolvedSize will be NaN and sliceSize will remain undefined.
1310 | var resolvedSize = resolvedEnd - resolvedBegin;
1311 | var sliceSize;
1312 | if (resolvedSize === resolvedSize) {
1313 | sliceSize = resolvedSize < 0 ? 0 : resolvedSize;
1314 | }
1315 |
1316 | var sliceSeq = makeSequence(iterable);
1317 |
1318 | sliceSeq.size = sliceSize;
1319 |
1320 | if (!useKeys && isSeq(iterable) && sliceSize >= 0) {
1321 | sliceSeq.get = function (index, notSetValue) {
1322 | index = wrapIndex(this, index);
1323 | return index >= 0 && index < sliceSize ?
1324 | iterable.get(index + resolvedBegin, notSetValue) :
1325 | notSetValue;
1326 | }
1327 | }
1328 |
1329 | sliceSeq.__iterateUncached = function(fn, reverse) {var this$0 = this;
1330 | if (sliceSize === 0) {
1331 | return 0;
1332 | }
1333 | if (reverse) {
1334 | return this.cacheResult().__iterate(fn, reverse);
1335 | }
1336 | var skipped = 0;
1337 | var isSkipping = true;
1338 | var iterations = 0;
1339 | iterable.__iterate(function(v, k) {
1340 | if (!(isSkipping && (isSkipping = skipped++ < resolvedBegin))) {
1341 | iterations++;
1342 | return fn(v, useKeys ? k : iterations - 1, this$0) !== false &&
1343 | iterations !== sliceSize;
1344 | }
1345 | });
1346 | return iterations;
1347 | };
1348 |
1349 | sliceSeq.__iteratorUncached = function(type, reverse) {
1350 | if (sliceSize !== 0 && reverse) {
1351 | return this.cacheResult().__iterator(type, reverse);
1352 | }
1353 | // Don't bother instantiating parent iterator if taking 0.
1354 | var iterator = sliceSize !== 0 && iterable.__iterator(type, reverse);
1355 | var skipped = 0;
1356 | var iterations = 0;
1357 | return new src_Iterator__Iterator(function() {
1358 | while (skipped++ < resolvedBegin) {
1359 | iterator.next();
1360 | }
1361 | if (++iterations > sliceSize) {
1362 | return iteratorDone();
1363 | }
1364 | var step = iterator.next();
1365 | if (useKeys || type === ITERATE_VALUES) {
1366 | return step;
1367 | } else if (type === ITERATE_KEYS) {
1368 | return iteratorValue(type, iterations - 1, undefined, step);
1369 | } else {
1370 | return iteratorValue(type, iterations - 1, step.value[1], step);
1371 | }
1372 | });
1373 | }
1374 |
1375 | return sliceSeq;
1376 | }
1377 |
1378 |
1379 | function takeWhileFactory(iterable, predicate, context) {
1380 | var takeSequence = makeSequence(iterable);
1381 | takeSequence.__iterateUncached = function(fn, reverse) {var this$0 = this;
1382 | if (reverse) {
1383 | return this.cacheResult().__iterate(fn, reverse);
1384 | }
1385 | var iterations = 0;
1386 | iterable.__iterate(function(v, k, c)
1387 | {return predicate.call(context, v, k, c) && ++iterations && fn(v, k, this$0)}
1388 | );
1389 | return iterations;
1390 | };
1391 | takeSequence.__iteratorUncached = function(type, reverse) {var this$0 = this;
1392 | if (reverse) {
1393 | return this.cacheResult().__iterator(type, reverse);
1394 | }
1395 | var iterator = iterable.__iterator(ITERATE_ENTRIES, reverse);
1396 | var iterating = true;
1397 | return new src_Iterator__Iterator(function() {
1398 | if (!iterating) {
1399 | return iteratorDone();
1400 | }
1401 | var step = iterator.next();
1402 | if (step.done) {
1403 | return step;
1404 | }
1405 | var entry = step.value;
1406 | var k = entry[0];
1407 | var v = entry[1];
1408 | if (!predicate.call(context, v, k, this$0)) {
1409 | iterating = false;
1410 | return iteratorDone();
1411 | }
1412 | return type === ITERATE_ENTRIES ? step :
1413 | iteratorValue(type, k, v, step);
1414 | });
1415 | };
1416 | return takeSequence;
1417 | }
1418 |
1419 |
1420 | function skipWhileFactory(iterable, predicate, context, useKeys) {
1421 | var skipSequence = makeSequence(iterable);
1422 | skipSequence.__iterateUncached = function (fn, reverse) {var this$0 = this;
1423 | if (reverse) {
1424 | return this.cacheResult().__iterate(fn, reverse);
1425 | }
1426 | var isSkipping = true;
1427 | var iterations = 0;
1428 | iterable.__iterate(function(v, k, c) {
1429 | if (!(isSkipping && (isSkipping = predicate.call(context, v, k, c)))) {
1430 | iterations++;
1431 | return fn(v, useKeys ? k : iterations - 1, this$0);
1432 | }
1433 | });
1434 | return iterations;
1435 | };
1436 | skipSequence.__iteratorUncached = function(type, reverse) {var this$0 = this;
1437 | if (reverse) {
1438 | return this.cacheResult().__iterator(type, reverse);
1439 | }
1440 | var iterator = iterable.__iterator(ITERATE_ENTRIES, reverse);
1441 | var skipping = true;
1442 | var iterations = 0;
1443 | return new src_Iterator__Iterator(function() {
1444 | var step, k, v;
1445 | do {
1446 | step = iterator.next();
1447 | if (step.done) {
1448 | if (useKeys || type === ITERATE_VALUES) {
1449 | return step;
1450 | } else if (type === ITERATE_KEYS) {
1451 | return iteratorValue(type, iterations++, undefined, step);
1452 | } else {
1453 | return iteratorValue(type, iterations++, step.value[1], step);
1454 | }
1455 | }
1456 | var entry = step.value;
1457 | k = entry[0];
1458 | v = entry[1];
1459 | skipping && (skipping = predicate.call(context, v, k, this$0));
1460 | } while (skipping);
1461 | return type === ITERATE_ENTRIES ? step :
1462 | iteratorValue(type, k, v, step);
1463 | });
1464 | };
1465 | return skipSequence;
1466 | }
1467 |
1468 |
1469 | function concatFactory(iterable, values) {
1470 | var isKeyedIterable = isKeyed(iterable);
1471 | var iters = [iterable].concat(values).map(function(v ) {
1472 | if (!isIterable(v)) {
1473 | v = isKeyedIterable ?
1474 | keyedSeqFromValue(v) :
1475 | indexedSeqFromValue(Array.isArray(v) ? v : [v]);
1476 | } else if (isKeyedIterable) {
1477 | v = KeyedIterable(v);
1478 | }
1479 | return v;
1480 | }).filter(function(v ) {return v.size !== 0});
1481 |
1482 | if (iters.length === 0) {
1483 | return iterable;
1484 | }
1485 |
1486 | if (iters.length === 1) {
1487 | var singleton = iters[0];
1488 | if (singleton === iterable ||
1489 | isKeyedIterable && isKeyed(singleton) ||
1490 | isIndexed(iterable) && isIndexed(singleton)) {
1491 | return singleton;
1492 | }
1493 | }
1494 |
1495 | var concatSeq = new ArraySeq(iters);
1496 | if (isKeyedIterable) {
1497 | concatSeq = concatSeq.toKeyedSeq();
1498 | } else if (!isIndexed(iterable)) {
1499 | concatSeq = concatSeq.toSetSeq();
1500 | }
1501 | concatSeq = concatSeq.flatten(true);
1502 | concatSeq.size = iters.reduce(
1503 | function(sum, seq) {
1504 | if (sum !== undefined) {
1505 | var size = seq.size;
1506 | if (size !== undefined) {
1507 | return sum + size;
1508 | }
1509 | }
1510 | },
1511 | 0
1512 | );
1513 | return concatSeq;
1514 | }
1515 |
1516 |
1517 | function flattenFactory(iterable, depth, useKeys) {
1518 | var flatSequence = makeSequence(iterable);
1519 | flatSequence.__iterateUncached = function(fn, reverse) {
1520 | var iterations = 0;
1521 | var stopped = false;
1522 | function flatDeep(iter, currentDepth) {var this$0 = this;
1523 | iter.__iterate(function(v, k) {
1524 | if ((!depth || currentDepth < depth) && isIterable(v)) {
1525 | flatDeep(v, currentDepth + 1);
1526 | } else if (fn(v, useKeys ? k : iterations++, this$0) === false) {
1527 | stopped = true;
1528 | }
1529 | return !stopped;
1530 | }, reverse);
1531 | }
1532 | flatDeep(iterable, 0);
1533 | return iterations;
1534 | }
1535 | flatSequence.__iteratorUncached = function(type, reverse) {
1536 | var iterator = iterable.__iterator(type, reverse);
1537 | var stack = [];
1538 | var iterations = 0;
1539 | return new src_Iterator__Iterator(function() {
1540 | while (iterator) {
1541 | var step = iterator.next();
1542 | if (step.done !== false) {
1543 | iterator = stack.pop();
1544 | continue;
1545 | }
1546 | var v = step.value;
1547 | if (type === ITERATE_ENTRIES) {
1548 | v = v[1];
1549 | }
1550 | if ((!depth || stack.length < depth) && isIterable(v)) {
1551 | stack.push(iterator);
1552 | iterator = v.__iterator(type, reverse);
1553 | } else {
1554 | return useKeys ? step : iteratorValue(type, iterations++, v, step);
1555 | }
1556 | }
1557 | return iteratorDone();
1558 | });
1559 | }
1560 | return flatSequence;
1561 | }
1562 |
1563 |
1564 | function flatMapFactory(iterable, mapper, context) {
1565 | var coerce = iterableClass(iterable);
1566 | return iterable.toSeq().map(
1567 | function(v, k) {return coerce(mapper.call(context, v, k, iterable))}
1568 | ).flatten(true);
1569 | }
1570 |
1571 |
1572 | function interposeFactory(iterable, separator) {
1573 | var interposedSequence = makeSequence(iterable);
1574 | interposedSequence.size = iterable.size && iterable.size * 2 -1;
1575 | interposedSequence.__iterateUncached = function(fn, reverse) {var this$0 = this;
1576 | var iterations = 0;
1577 | iterable.__iterate(function(v, k)
1578 | {return (!iterations || fn(separator, iterations++, this$0) !== false) &&
1579 | fn(v, iterations++, this$0) !== false},
1580 | reverse
1581 | );
1582 | return iterations;
1583 | };
1584 | interposedSequence.__iteratorUncached = function(type, reverse) {
1585 | var iterator = iterable.__iterator(ITERATE_VALUES, reverse);
1586 | var iterations = 0;
1587 | var step;
1588 | return new src_Iterator__Iterator(function() {
1589 | if (!step || iterations % 2) {
1590 | step = iterator.next();
1591 | if (step.done) {
1592 | return step;
1593 | }
1594 | }
1595 | return iterations % 2 ?
1596 | iteratorValue(type, iterations++, separator) :
1597 | iteratorValue(type, iterations++, step.value, step);
1598 | });
1599 | };
1600 | return interposedSequence;
1601 | }
1602 |
1603 |
1604 | function sortFactory(iterable, comparator, mapper) {
1605 | if (!comparator) {
1606 | comparator = defaultComparator;
1607 | }
1608 | var isKeyedIterable = isKeyed(iterable);
1609 | var index = 0;
1610 | var entries = iterable.toSeq().map(
1611 | function(v, k) {return [k, v, index++, mapper ? mapper(v, k, iterable) : v]}
1612 | ).toArray();
1613 | entries.sort(function(a, b) {return comparator(a[3], b[3]) || a[2] - b[2]}).forEach(
1614 | isKeyedIterable ?
1615 | function(v, i) { entries[i].length = 2; } :
1616 | function(v, i) { entries[i] = v[1]; }
1617 | );
1618 | return isKeyedIterable ? KeyedSeq(entries) :
1619 | isIndexed(iterable) ? IndexedSeq(entries) :
1620 | SetSeq(entries);
1621 | }
1622 |
1623 |
1624 | function maxFactory(iterable, comparator, mapper) {
1625 | if (!comparator) {
1626 | comparator = defaultComparator;
1627 | }
1628 | if (mapper) {
1629 | var entry = iterable.toSeq()
1630 | .map(function(v, k) {return [v, mapper(v, k, iterable)]})
1631 | .reduce(function(a, b) {return maxCompare(comparator, a[1], b[1]) ? b : a});
1632 | return entry && entry[0];
1633 | } else {
1634 | return iterable.reduce(function(a, b) {return maxCompare(comparator, a, b) ? b : a});
1635 | }
1636 | }
1637 |
1638 | function maxCompare(comparator, a, b) {
1639 | var comp = comparator(b, a);
1640 | // b is considered the new max if the comparator declares them equal, but
1641 | // they are not equal and b is in fact a nullish value.
1642 | return (comp === 0 && b !== a && (b === undefined || b === null || b !== b)) || comp > 0;
1643 | }
1644 |
1645 |
1646 | function zipWithFactory(keyIter, zipper, iters) {
1647 | var zipSequence = makeSequence(keyIter);
1648 | zipSequence.size = new ArraySeq(iters).map(function(i ) {return i.size}).min();
1649 | // Note: this a generic base implementation of __iterate in terms of
1650 | // __iterator which may be more generically useful in the future.
1651 | zipSequence.__iterate = function(fn, reverse) {
1652 | /* generic:
1653 | var iterator = this.__iterator(ITERATE_ENTRIES, reverse);
1654 | var step;
1655 | var iterations = 0;
1656 | while (!(step = iterator.next()).done) {
1657 | iterations++;
1658 | if (fn(step.value[1], step.value[0], this) === false) {
1659 | break;
1660 | }
1661 | }
1662 | return iterations;
1663 | */
1664 | // indexed:
1665 | var iterator = this.__iterator(ITERATE_VALUES, reverse);
1666 | var step;
1667 | var iterations = 0;
1668 | while (!(step = iterator.next()).done) {
1669 | if (fn(step.value, iterations++, this) === false) {
1670 | break;
1671 | }
1672 | }
1673 | return iterations;
1674 | };
1675 | zipSequence.__iteratorUncached = function(type, reverse) {
1676 | var iterators = iters.map(function(i )
1677 | {return (i = Iterable(i), getIterator(reverse ? i.reverse() : i))}
1678 | );
1679 | var iterations = 0;
1680 | var isDone = false;
1681 | return new src_Iterator__Iterator(function() {
1682 | var steps;
1683 | if (!isDone) {
1684 | steps = iterators.map(function(i ) {return i.next()});
1685 | isDone = steps.some(function(s ) {return s.done});
1686 | }
1687 | if (isDone) {
1688 | return iteratorDone();
1689 | }
1690 | return iteratorValue(
1691 | type,
1692 | iterations++,
1693 | zipper.apply(null, steps.map(function(s ) {return s.value}))
1694 | );
1695 | });
1696 | };
1697 | return zipSequence
1698 | }
1699 |
1700 |
1701 | // #pragma Helper Functions
1702 |
1703 | function reify(iter, seq) {
1704 | return isSeq(iter) ? seq : iter.constructor(seq);
1705 | }
1706 |
1707 | function validateEntry(entry) {
1708 | if (entry !== Object(entry)) {
1709 | throw new TypeError('Expected [K, V] tuple: ' + entry);
1710 | }
1711 | }
1712 |
1713 | function resolveSize(iter) {
1714 | assertNotInfinite(iter.size);
1715 | return ensureSize(iter);
1716 | }
1717 |
1718 | function iterableClass(iterable) {
1719 | return isKeyed(iterable) ? KeyedIterable :
1720 | isIndexed(iterable) ? IndexedIterable :
1721 | SetIterable;
1722 | }
1723 |
1724 | function makeSequence(iterable) {
1725 | return Object.create(
1726 | (
1727 | isKeyed(iterable) ? KeyedSeq :
1728 | isIndexed(iterable) ? IndexedSeq :
1729 | SetSeq
1730 | ).prototype
1731 | );
1732 | }
1733 |
1734 | function cacheResultThrough() {
1735 | if (this._iter.cacheResult) {
1736 | this._iter.cacheResult();
1737 | this.size = this._iter.size;
1738 | return this;
1739 | } else {
1740 | return Seq.prototype.cacheResult.call(this);
1741 | }
1742 | }
1743 |
1744 | function defaultComparator(a, b) {
1745 | return a > b ? 1 : a < b ? -1 : 0;
1746 | }
1747 |
1748 | function forceIterator(keyPath) {
1749 | var iter = getIterator(keyPath);
1750 | if (!iter) {
1751 | // Array might not be iterable in this environment, so we need a fallback
1752 | // to our wrapped type.
1753 | if (!isArrayLike(keyPath)) {
1754 | throw new TypeError('Expected iterable or array-like: ' + keyPath);
1755 | }
1756 | iter = getIterator(Iterable(keyPath));
1757 | }
1758 | return iter;
1759 | }
1760 |
1761 | createClass(src_Map__Map, KeyedCollection);
1762 |
1763 | // @pragma Construction
1764 |
1765 | function src_Map__Map(value) {
1766 | return value === null || value === undefined ? emptyMap() :
1767 | isMap(value) ? value :
1768 | emptyMap().withMutations(function(map ) {
1769 | var iter = KeyedIterable(value);
1770 | assertNotInfinite(iter.size);
1771 | iter.forEach(function(v, k) {return map.set(k, v)});
1772 | });
1773 | }
1774 |
1775 | src_Map__Map.prototype.toString = function() {
1776 | return this.__toString('Map {', '}');
1777 | };
1778 |
1779 | // @pragma Access
1780 |
1781 | src_Map__Map.prototype.get = function(k, notSetValue) {
1782 | return this._root ?
1783 | this._root.get(0, undefined, k, notSetValue) :
1784 | notSetValue;
1785 | };
1786 |
1787 | // @pragma Modification
1788 |
1789 | src_Map__Map.prototype.set = function(k, v) {
1790 | return updateMap(this, k, v);
1791 | };
1792 |
1793 | src_Map__Map.prototype.setIn = function(keyPath, v) {
1794 | return this.updateIn(keyPath, NOT_SET, function() {return v});
1795 | };
1796 |
1797 | src_Map__Map.prototype.remove = function(k) {
1798 | return updateMap(this, k, NOT_SET);
1799 | };
1800 |
1801 | src_Map__Map.prototype.deleteIn = function(keyPath) {
1802 | return this.updateIn(keyPath, function() {return NOT_SET});
1803 | };
1804 |
1805 | src_Map__Map.prototype.update = function(k, notSetValue, updater) {
1806 | return arguments.length === 1 ?
1807 | k(this) :
1808 | this.updateIn([k], notSetValue, updater);
1809 | };
1810 |
1811 | src_Map__Map.prototype.updateIn = function(keyPath, notSetValue, updater) {
1812 | if (!updater) {
1813 | updater = notSetValue;
1814 | notSetValue = undefined;
1815 | }
1816 | var updatedValue = updateInDeepMap(
1817 | this,
1818 | forceIterator(keyPath),
1819 | notSetValue,
1820 | updater
1821 | );
1822 | return updatedValue === NOT_SET ? undefined : updatedValue;
1823 | };
1824 |
1825 | src_Map__Map.prototype.clear = function() {
1826 | if (this.size === 0) {
1827 | return this;
1828 | }
1829 | if (this.__ownerID) {
1830 | this.size = 0;
1831 | this._root = null;
1832 | this.__hash = undefined;
1833 | this.__altered = true;
1834 | return this;
1835 | }
1836 | return emptyMap();
1837 | };
1838 |
1839 | // @pragma Composition
1840 |
1841 | src_Map__Map.prototype.merge = function(/*...iters*/) {
1842 | return mergeIntoMapWith(this, undefined, arguments);
1843 | };
1844 |
1845 | src_Map__Map.prototype.mergeWith = function(merger) {var iters = SLICE$0.call(arguments, 1);
1846 | return mergeIntoMapWith(this, merger, iters);
1847 | };
1848 |
1849 | src_Map__Map.prototype.mergeIn = function(keyPath) {var iters = SLICE$0.call(arguments, 1);
1850 | return this.updateIn(keyPath, emptyMap(), function(m ) {return m.merge.apply(m, iters)});
1851 | };
1852 |
1853 | src_Map__Map.prototype.mergeDeep = function(/*...iters*/) {
1854 | return mergeIntoMapWith(this, deepMerger(undefined), arguments);
1855 | };
1856 |
1857 | src_Map__Map.prototype.mergeDeepWith = function(merger) {var iters = SLICE$0.call(arguments, 1);
1858 | return mergeIntoMapWith(this, deepMerger(merger), iters);
1859 | };
1860 |
1861 | src_Map__Map.prototype.mergeDeepIn = function(keyPath) {var iters = SLICE$0.call(arguments, 1);
1862 | return this.updateIn(keyPath, emptyMap(), function(m ) {return m.mergeDeep.apply(m, iters)});
1863 | };
1864 |
1865 | src_Map__Map.prototype.sort = function(comparator) {
1866 | // Late binding
1867 | return OrderedMap(sortFactory(this, comparator));
1868 | };
1869 |
1870 | src_Map__Map.prototype.sortBy = function(mapper, comparator) {
1871 | // Late binding
1872 | return OrderedMap(sortFactory(this, comparator, mapper));
1873 | };
1874 |
1875 | // @pragma Mutability
1876 |
1877 | src_Map__Map.prototype.withMutations = function(fn) {
1878 | var mutable = this.asMutable();
1879 | fn(mutable);
1880 | return mutable.wasAltered() ? mutable.__ensureOwner(this.__ownerID) : this;
1881 | };
1882 |
1883 | src_Map__Map.prototype.asMutable = function() {
1884 | return this.__ownerID ? this : this.__ensureOwner(new OwnerID());
1885 | };
1886 |
1887 | src_Map__Map.prototype.asImmutable = function() {
1888 | return this.__ensureOwner();
1889 | };
1890 |
1891 | src_Map__Map.prototype.wasAltered = function() {
1892 | return this.__altered;
1893 | };
1894 |
1895 | src_Map__Map.prototype.__iterator = function(type, reverse) {
1896 | return new MapIterator(this, type, reverse);
1897 | };
1898 |
1899 | src_Map__Map.prototype.__iterate = function(fn, reverse) {var this$0 = this;
1900 | var iterations = 0;
1901 | this._root && this._root.iterate(function(entry ) {
1902 | iterations++;
1903 | return fn(entry[1], entry[0], this$0);
1904 | }, reverse);
1905 | return iterations;
1906 | };
1907 |
1908 | src_Map__Map.prototype.__ensureOwner = function(ownerID) {
1909 | if (ownerID === this.__ownerID) {
1910 | return this;
1911 | }
1912 | if (!ownerID) {
1913 | this.__ownerID = ownerID;
1914 | this.__altered = false;
1915 | return this;
1916 | }
1917 | return makeMap(this.size, this._root, ownerID, this.__hash);
1918 | };
1919 |
1920 |
1921 | function isMap(maybeMap) {
1922 | return !!(maybeMap && maybeMap[IS_MAP_SENTINEL]);
1923 | }
1924 |
1925 | src_Map__Map.isMap = isMap;
1926 |
1927 | var IS_MAP_SENTINEL = '@@__IMMUTABLE_MAP__@@';
1928 |
1929 | var MapPrototype = src_Map__Map.prototype;
1930 | MapPrototype[IS_MAP_SENTINEL] = true;
1931 | MapPrototype[DELETE] = MapPrototype.remove;
1932 | MapPrototype.removeIn = MapPrototype.deleteIn;
1933 |
1934 |
1935 | // #pragma Trie Nodes
1936 |
1937 |
1938 |
1939 | function ArrayMapNode(ownerID, entries) {
1940 | this.ownerID = ownerID;
1941 | this.entries = entries;
1942 | }
1943 |
1944 | ArrayMapNode.prototype.get = function(shift, keyHash, key, notSetValue) {
1945 | var entries = this.entries;
1946 | for (var ii = 0, len = entries.length; ii < len; ii++) {
1947 | if (is(key, entries[ii][0])) {
1948 | return entries[ii][1];
1949 | }
1950 | }
1951 | return notSetValue;
1952 | };
1953 |
1954 | ArrayMapNode.prototype.update = function(ownerID, shift, keyHash, key, value, didChangeSize, didAlter) {
1955 | var removed = value === NOT_SET;
1956 |
1957 | var entries = this.entries;
1958 | var idx = 0;
1959 | for (var len = entries.length; idx < len; idx++) {
1960 | if (is(key, entries[idx][0])) {
1961 | break;
1962 | }
1963 | }
1964 | var exists = idx < len;
1965 |
1966 | if (exists ? entries[idx][1] === value : removed) {
1967 | return this;
1968 | }
1969 |
1970 | SetRef(didAlter);
1971 | (removed || !exists) && SetRef(didChangeSize);
1972 |
1973 | if (removed && entries.length === 1) {
1974 | return; // undefined
1975 | }
1976 |
1977 | if (!exists && !removed && entries.length >= MAX_ARRAY_MAP_SIZE) {
1978 | return createNodes(ownerID, entries, key, value);
1979 | }
1980 |
1981 | var isEditable = ownerID && ownerID === this.ownerID;
1982 | var newEntries = isEditable ? entries : arrCopy(entries);
1983 |
1984 | if (exists) {
1985 | if (removed) {
1986 | idx === len - 1 ? newEntries.pop() : (newEntries[idx] = newEntries.pop());
1987 | } else {
1988 | newEntries[idx] = [key, value];
1989 | }
1990 | } else {
1991 | newEntries.push([key, value]);
1992 | }
1993 |
1994 | if (isEditable) {
1995 | this.entries = newEntries;
1996 | return this;
1997 | }
1998 |
1999 | return new ArrayMapNode(ownerID, newEntries);
2000 | };
2001 |
2002 |
2003 |
2004 |
2005 | function BitmapIndexedNode(ownerID, bitmap, nodes) {
2006 | this.ownerID = ownerID;
2007 | this.bitmap = bitmap;
2008 | this.nodes = nodes;
2009 | }
2010 |
2011 | BitmapIndexedNode.prototype.get = function(shift, keyHash, key, notSetValue) {
2012 | if (keyHash === undefined) {
2013 | keyHash = hash(key);
2014 | }
2015 | var bit = (1 << ((shift === 0 ? keyHash : keyHash >>> shift) & MASK));
2016 | var bitmap = this.bitmap;
2017 | return (bitmap & bit) === 0 ? notSetValue :
2018 | this.nodes[popCount(bitmap & (bit - 1))].get(shift + SHIFT, keyHash, key, notSetValue);
2019 | };
2020 |
2021 | BitmapIndexedNode.prototype.update = function(ownerID, shift, keyHash, key, value, didChangeSize, didAlter) {
2022 | if (keyHash === undefined) {
2023 | keyHash = hash(key);
2024 | }
2025 | var keyHashFrag = (shift === 0 ? keyHash : keyHash >>> shift) & MASK;
2026 | var bit = 1 << keyHashFrag;
2027 | var bitmap = this.bitmap;
2028 | var exists = (bitmap & bit) !== 0;
2029 |
2030 | if (!exists && value === NOT_SET) {
2031 | return this;
2032 | }
2033 |
2034 | var idx = popCount(bitmap & (bit - 1));
2035 | var nodes = this.nodes;
2036 | var node = exists ? nodes[idx] : undefined;
2037 | var newNode = updateNode(node, ownerID, shift + SHIFT, keyHash, key, value, didChangeSize, didAlter);
2038 |
2039 | if (newNode === node) {
2040 | return this;
2041 | }
2042 |
2043 | if (!exists && newNode && nodes.length >= MAX_BITMAP_INDEXED_SIZE) {
2044 | return expandNodes(ownerID, nodes, bitmap, keyHashFrag, newNode);
2045 | }
2046 |
2047 | if (exists && !newNode && nodes.length === 2 && isLeafNode(nodes[idx ^ 1])) {
2048 | return nodes[idx ^ 1];
2049 | }
2050 |
2051 | if (exists && newNode && nodes.length === 1 && isLeafNode(newNode)) {
2052 | return newNode;
2053 | }
2054 |
2055 | var isEditable = ownerID && ownerID === this.ownerID;
2056 | var newBitmap = exists ? newNode ? bitmap : bitmap ^ bit : bitmap | bit;
2057 | var newNodes = exists ? newNode ?
2058 | setIn(nodes, idx, newNode, isEditable) :
2059 | spliceOut(nodes, idx, isEditable) :
2060 | spliceIn(nodes, idx, newNode, isEditable);
2061 |
2062 | if (isEditable) {
2063 | this.bitmap = newBitmap;
2064 | this.nodes = newNodes;
2065 | return this;
2066 | }
2067 |
2068 | return new BitmapIndexedNode(ownerID, newBitmap, newNodes);
2069 | };
2070 |
2071 |
2072 |
2073 |
2074 | function HashArrayMapNode(ownerID, count, nodes) {
2075 | this.ownerID = ownerID;
2076 | this.count = count;
2077 | this.nodes = nodes;
2078 | }
2079 |
2080 | HashArrayMapNode.prototype.get = function(shift, keyHash, key, notSetValue) {
2081 | if (keyHash === undefined) {
2082 | keyHash = hash(key);
2083 | }
2084 | var idx = (shift === 0 ? keyHash : keyHash >>> shift) & MASK;
2085 | var node = this.nodes[idx];
2086 | return node ? node.get(shift + SHIFT, keyHash, key, notSetValue) : notSetValue;
2087 | };
2088 |
2089 | HashArrayMapNode.prototype.update = function(ownerID, shift, keyHash, key, value, didChangeSize, didAlter) {
2090 | if (keyHash === undefined) {
2091 | keyHash = hash(key);
2092 | }
2093 | var idx = (shift === 0 ? keyHash : keyHash >>> shift) & MASK;
2094 | var removed = value === NOT_SET;
2095 | var nodes = this.nodes;
2096 | var node = nodes[idx];
2097 |
2098 | if (removed && !node) {
2099 | return this;
2100 | }
2101 |
2102 | var newNode = updateNode(node, ownerID, shift + SHIFT, keyHash, key, value, didChangeSize, didAlter);
2103 | if (newNode === node) {
2104 | return this;
2105 | }
2106 |
2107 | var newCount = this.count;
2108 | if (!node) {
2109 | newCount++;
2110 | } else if (!newNode) {
2111 | newCount--;
2112 | if (newCount < MIN_HASH_ARRAY_MAP_SIZE) {
2113 | return packNodes(ownerID, nodes, newCount, idx);
2114 | }
2115 | }
2116 |
2117 | var isEditable = ownerID && ownerID === this.ownerID;
2118 | var newNodes = setIn(nodes, idx, newNode, isEditable);
2119 |
2120 | if (isEditable) {
2121 | this.count = newCount;
2122 | this.nodes = newNodes;
2123 | return this;
2124 | }
2125 |
2126 | return new HashArrayMapNode(ownerID, newCount, newNodes);
2127 | };
2128 |
2129 |
2130 |
2131 |
2132 | function HashCollisionNode(ownerID, keyHash, entries) {
2133 | this.ownerID = ownerID;
2134 | this.keyHash = keyHash;
2135 | this.entries = entries;
2136 | }
2137 |
2138 | HashCollisionNode.prototype.get = function(shift, keyHash, key, notSetValue) {
2139 | var entries = this.entries;
2140 | for (var ii = 0, len = entries.length; ii < len; ii++) {
2141 | if (is(key, entries[ii][0])) {
2142 | return entries[ii][1];
2143 | }
2144 | }
2145 | return notSetValue;
2146 | };
2147 |
2148 | HashCollisionNode.prototype.update = function(ownerID, shift, keyHash, key, value, didChangeSize, didAlter) {
2149 | if (keyHash === undefined) {
2150 | keyHash = hash(key);
2151 | }
2152 |
2153 | var removed = value === NOT_SET;
2154 |
2155 | if (keyHash !== this.keyHash) {
2156 | if (removed) {
2157 | return this;
2158 | }
2159 | SetRef(didAlter);
2160 | SetRef(didChangeSize);
2161 | return mergeIntoNode(this, ownerID, shift, keyHash, [key, value]);
2162 | }
2163 |
2164 | var entries = this.entries;
2165 | var idx = 0;
2166 | for (var len = entries.length; idx < len; idx++) {
2167 | if (is(key, entries[idx][0])) {
2168 | break;
2169 | }
2170 | }
2171 | var exists = idx < len;
2172 |
2173 | if (exists ? entries[idx][1] === value : removed) {
2174 | return this;
2175 | }
2176 |
2177 | SetRef(didAlter);
2178 | (removed || !exists) && SetRef(didChangeSize);
2179 |
2180 | if (removed && len === 2) {
2181 | return new ValueNode(ownerID, this.keyHash, entries[idx ^ 1]);
2182 | }
2183 |
2184 | var isEditable = ownerID && ownerID === this.ownerID;
2185 | var newEntries = isEditable ? entries : arrCopy(entries);
2186 |
2187 | if (exists) {
2188 | if (removed) {
2189 | idx === len - 1 ? newEntries.pop() : (newEntries[idx] = newEntries.pop());
2190 | } else {
2191 | newEntries[idx] = [key, value];
2192 | }
2193 | } else {
2194 | newEntries.push([key, value]);
2195 | }
2196 |
2197 | if (isEditable) {
2198 | this.entries = newEntries;
2199 | return this;
2200 | }
2201 |
2202 | return new HashCollisionNode(ownerID, this.keyHash, newEntries);
2203 | };
2204 |
2205 |
2206 |
2207 |
2208 | function ValueNode(ownerID, keyHash, entry) {
2209 | this.ownerID = ownerID;
2210 | this.keyHash = keyHash;
2211 | this.entry = entry;
2212 | }
2213 |
2214 | ValueNode.prototype.get = function(shift, keyHash, key, notSetValue) {
2215 | return is(key, this.entry[0]) ? this.entry[1] : notSetValue;
2216 | };
2217 |
2218 | ValueNode.prototype.update = function(ownerID, shift, keyHash, key, value, didChangeSize, didAlter) {
2219 | var removed = value === NOT_SET;
2220 | var keyMatch = is(key, this.entry[0]);
2221 | if (keyMatch ? value === this.entry[1] : removed) {
2222 | return this;
2223 | }
2224 |
2225 | SetRef(didAlter);
2226 |
2227 | if (removed) {
2228 | SetRef(didChangeSize);
2229 | return; // undefined
2230 | }
2231 |
2232 | if (keyMatch) {
2233 | if (ownerID && ownerID === this.ownerID) {
2234 | this.entry[1] = value;
2235 | return this;
2236 | }
2237 | return new ValueNode(ownerID, this.keyHash, [key, value]);
2238 | }
2239 |
2240 | SetRef(didChangeSize);
2241 | return mergeIntoNode(this, ownerID, shift, hash(key), [key, value]);
2242 | };
2243 |
2244 |
2245 |
2246 | // #pragma Iterators
2247 |
2248 | ArrayMapNode.prototype.iterate =
2249 | HashCollisionNode.prototype.iterate = function (fn, reverse) {
2250 | var entries = this.entries;
2251 | for (var ii = 0, maxIndex = entries.length - 1; ii <= maxIndex; ii++) {
2252 | if (fn(entries[reverse ? maxIndex - ii : ii]) === false) {
2253 | return false;
2254 | }
2255 | }
2256 | }
2257 |
2258 | BitmapIndexedNode.prototype.iterate =
2259 | HashArrayMapNode.prototype.iterate = function (fn, reverse) {
2260 | var nodes = this.nodes;
2261 | for (var ii = 0, maxIndex = nodes.length - 1; ii <= maxIndex; ii++) {
2262 | var node = nodes[reverse ? maxIndex - ii : ii];
2263 | if (node && node.iterate(fn, reverse) === false) {
2264 | return false;
2265 | }
2266 | }
2267 | }
2268 |
2269 | ValueNode.prototype.iterate = function (fn, reverse) {
2270 | return fn(this.entry);
2271 | }
2272 |
2273 | createClass(MapIterator, src_Iterator__Iterator);
2274 |
2275 | function MapIterator(map, type, reverse) {
2276 | this._type = type;
2277 | this._reverse = reverse;
2278 | this._stack = map._root && mapIteratorFrame(map._root);
2279 | }
2280 |
2281 | MapIterator.prototype.next = function() {
2282 | var type = this._type;
2283 | var stack = this._stack;
2284 | while (stack) {
2285 | var node = stack.node;
2286 | var index = stack.index++;
2287 | var maxIndex;
2288 | if (node.entry) {
2289 | if (index === 0) {
2290 | return mapIteratorValue(type, node.entry);
2291 | }
2292 | } else if (node.entries) {
2293 | maxIndex = node.entries.length - 1;
2294 | if (index <= maxIndex) {
2295 | return mapIteratorValue(type, node.entries[this._reverse ? maxIndex - index : index]);
2296 | }
2297 | } else {
2298 | maxIndex = node.nodes.length - 1;
2299 | if (index <= maxIndex) {
2300 | var subNode = node.nodes[this._reverse ? maxIndex - index : index];
2301 | if (subNode) {
2302 | if (subNode.entry) {
2303 | return mapIteratorValue(type, subNode.entry);
2304 | }
2305 | stack = this._stack = mapIteratorFrame(subNode, stack);
2306 | }
2307 | continue;
2308 | }
2309 | }
2310 | stack = this._stack = this._stack.__prev;
2311 | }
2312 | return iteratorDone();
2313 | };
2314 |
2315 |
2316 | function mapIteratorValue(type, entry) {
2317 | return iteratorValue(type, entry[0], entry[1]);
2318 | }
2319 |
2320 | function mapIteratorFrame(node, prev) {
2321 | return {
2322 | node: node,
2323 | index: 0,
2324 | __prev: prev
2325 | };
2326 | }
2327 |
2328 | function makeMap(size, root, ownerID, hash) {
2329 | var map = Object.create(MapPrototype);
2330 | map.size = size;
2331 | map._root = root;
2332 | map.__ownerID = ownerID;
2333 | map.__hash = hash;
2334 | map.__altered = false;
2335 | return map;
2336 | }
2337 |
2338 | var EMPTY_MAP;
2339 | function emptyMap() {
2340 | return EMPTY_MAP || (EMPTY_MAP = makeMap(0));
2341 | }
2342 |
2343 | function updateMap(map, k, v) {
2344 | var newRoot;
2345 | var newSize;
2346 | if (!map._root) {
2347 | if (v === NOT_SET) {
2348 | return map;
2349 | }
2350 | newSize = 1;
2351 | newRoot = new ArrayMapNode(map.__ownerID, [[k, v]]);
2352 | } else {
2353 | var didChangeSize = MakeRef(CHANGE_LENGTH);
2354 | var didAlter = MakeRef(DID_ALTER);
2355 | newRoot = updateNode(map._root, map.__ownerID, 0, undefined, k, v, didChangeSize, didAlter);
2356 | if (!didAlter.value) {
2357 | return map;
2358 | }
2359 | newSize = map.size + (didChangeSize.value ? v === NOT_SET ? -1 : 1 : 0);
2360 | }
2361 | if (map.__ownerID) {
2362 | map.size = newSize;
2363 | map._root = newRoot;
2364 | map.__hash = undefined;
2365 | map.__altered = true;
2366 | return map;
2367 | }
2368 | return newRoot ? makeMap(newSize, newRoot) : emptyMap();
2369 | }
2370 |
2371 | function updateNode(node, ownerID, shift, keyHash, key, value, didChangeSize, didAlter) {
2372 | if (!node) {
2373 | if (value === NOT_SET) {
2374 | return node;
2375 | }
2376 | SetRef(didAlter);
2377 | SetRef(didChangeSize);
2378 | return new ValueNode(ownerID, keyHash, [key, value]);
2379 | }
2380 | return node.update(ownerID, shift, keyHash, key, value, didChangeSize, didAlter);
2381 | }
2382 |
2383 | function isLeafNode(node) {
2384 | return node.constructor === ValueNode || node.constructor === HashCollisionNode;
2385 | }
2386 |
2387 | function mergeIntoNode(node, ownerID, shift, keyHash, entry) {
2388 | if (node.keyHash === keyHash) {
2389 | return new HashCollisionNode(ownerID, keyHash, [node.entry, entry]);
2390 | }
2391 |
2392 | var idx1 = (shift === 0 ? node.keyHash : node.keyHash >>> shift) & MASK;
2393 | var idx2 = (shift === 0 ? keyHash : keyHash >>> shift) & MASK;
2394 |
2395 | var newNode;
2396 | var nodes = idx1 === idx2 ?
2397 | [mergeIntoNode(node, ownerID, shift + SHIFT, keyHash, entry)] :
2398 | ((newNode = new ValueNode(ownerID, keyHash, entry)), idx1 < idx2 ? [node, newNode] : [newNode, node]);
2399 |
2400 | return new BitmapIndexedNode(ownerID, (1 << idx1) | (1 << idx2), nodes);
2401 | }
2402 |
2403 | function createNodes(ownerID, entries, key, value) {
2404 | if (!ownerID) {
2405 | ownerID = new OwnerID();
2406 | }
2407 | var node = new ValueNode(ownerID, hash(key), [key, value]);
2408 | for (var ii = 0; ii < entries.length; ii++) {
2409 | var entry = entries[ii];
2410 | node = node.update(ownerID, 0, undefined, entry[0], entry[1]);
2411 | }
2412 | return node;
2413 | }
2414 |
2415 | function packNodes(ownerID, nodes, count, excluding) {
2416 | var bitmap = 0;
2417 | var packedII = 0;
2418 | var packedNodes = new Array(count);
2419 | for (var ii = 0, bit = 1, len = nodes.length; ii < len; ii++, bit <<= 1) {
2420 | var node = nodes[ii];
2421 | if (node !== undefined && ii !== excluding) {
2422 | bitmap |= bit;
2423 | packedNodes[packedII++] = node;
2424 | }
2425 | }
2426 | return new BitmapIndexedNode(ownerID, bitmap, packedNodes);
2427 | }
2428 |
2429 | function expandNodes(ownerID, nodes, bitmap, including, node) {
2430 | var count = 0;
2431 | var expandedNodes = new Array(SIZE);
2432 | for (var ii = 0; bitmap !== 0; ii++, bitmap >>>= 1) {
2433 | expandedNodes[ii] = bitmap & 1 ? nodes[count++] : undefined;
2434 | }
2435 | expandedNodes[including] = node;
2436 | return new HashArrayMapNode(ownerID, count + 1, expandedNodes);
2437 | }
2438 |
2439 | function mergeIntoMapWith(map, merger, iterables) {
2440 | var iters = [];
2441 | for (var ii = 0; ii < iterables.length; ii++) {
2442 | var value = iterables[ii];
2443 | var iter = KeyedIterable(value);
2444 | if (!isIterable(value)) {
2445 | iter = iter.map(function(v ) {return fromJS(v)});
2446 | }
2447 | iters.push(iter);
2448 | }
2449 | return mergeIntoCollectionWith(map, merger, iters);
2450 | }
2451 |
2452 | function deepMerger(merger) {
2453 | return function(existing, value, key)
2454 | {return existing && existing.mergeDeepWith && isIterable(value) ?
2455 | existing.mergeDeepWith(merger, value) :
2456 | merger ? merger(existing, value, key) : value};
2457 | }
2458 |
2459 | function mergeIntoCollectionWith(collection, merger, iters) {
2460 | iters = iters.filter(function(x ) {return x.size !== 0});
2461 | if (iters.length === 0) {
2462 | return collection;
2463 | }
2464 | if (collection.size === 0 && !collection.__ownerID && iters.length === 1) {
2465 | return collection.constructor(iters[0]);
2466 | }
2467 | return collection.withMutations(function(collection ) {
2468 | var mergeIntoMap = merger ?
2469 | function(value, key) {
2470 | collection.update(key, NOT_SET, function(existing )
2471 | {return existing === NOT_SET ? value : merger(existing, value, key)}
2472 | );
2473 | } :
2474 | function(value, key) {
2475 | collection.set(key, value);
2476 | }
2477 | for (var ii = 0; ii < iters.length; ii++) {
2478 | iters[ii].forEach(mergeIntoMap);
2479 | }
2480 | });
2481 | }
2482 |
2483 | function updateInDeepMap(existing, keyPathIter, notSetValue, updater) {
2484 | var isNotSet = existing === NOT_SET;
2485 | var step = keyPathIter.next();
2486 | if (step.done) {
2487 | var existingValue = isNotSet ? notSetValue : existing;
2488 | var newValue = updater(existingValue);
2489 | return newValue === existingValue ? existing : newValue;
2490 | }
2491 | invariant(
2492 | isNotSet || (existing && existing.set),
2493 | 'invalid keyPath'
2494 | );
2495 | var key = step.value;
2496 | var nextExisting = isNotSet ? NOT_SET : existing.get(key, NOT_SET);
2497 | var nextUpdated = updateInDeepMap(
2498 | nextExisting,
2499 | keyPathIter,
2500 | notSetValue,
2501 | updater
2502 | );
2503 | return nextUpdated === nextExisting ? existing :
2504 | nextUpdated === NOT_SET ? existing.remove(key) :
2505 | (isNotSet ? emptyMap() : existing).set(key, nextUpdated);
2506 | }
2507 |
2508 | function popCount(x) {
2509 | x = x - ((x >> 1) & 0x55555555);
2510 | x = (x & 0x33333333) + ((x >> 2) & 0x33333333);
2511 | x = (x + (x >> 4)) & 0x0f0f0f0f;
2512 | x = x + (x >> 8);
2513 | x = x + (x >> 16);
2514 | return x & 0x7f;
2515 | }
2516 |
2517 | function setIn(array, idx, val, canEdit) {
2518 | var newArray = canEdit ? array : arrCopy(array);
2519 | newArray[idx] = val;
2520 | return newArray;
2521 | }
2522 |
2523 | function spliceIn(array, idx, val, canEdit) {
2524 | var newLen = array.length + 1;
2525 | if (canEdit && idx + 1 === newLen) {
2526 | array[idx] = val;
2527 | return array;
2528 | }
2529 | var newArray = new Array(newLen);
2530 | var after = 0;
2531 | for (var ii = 0; ii < newLen; ii++) {
2532 | if (ii === idx) {
2533 | newArray[ii] = val;
2534 | after = -1;
2535 | } else {
2536 | newArray[ii] = array[ii + after];
2537 | }
2538 | }
2539 | return newArray;
2540 | }
2541 |
2542 | function spliceOut(array, idx, canEdit) {
2543 | var newLen = array.length - 1;
2544 | if (canEdit && idx === newLen) {
2545 | array.pop();
2546 | return array;
2547 | }
2548 | var newArray = new Array(newLen);
2549 | var after = 0;
2550 | for (var ii = 0; ii < newLen; ii++) {
2551 | if (ii === idx) {
2552 | after = 1;
2553 | }
2554 | newArray[ii] = array[ii + after];
2555 | }
2556 | return newArray;
2557 | }
2558 |
2559 | var MAX_ARRAY_MAP_SIZE = SIZE / 4;
2560 | var MAX_BITMAP_INDEXED_SIZE = SIZE / 2;
2561 | var MIN_HASH_ARRAY_MAP_SIZE = SIZE / 4;
2562 |
2563 | createClass(List, IndexedCollection);
2564 |
2565 | // @pragma Construction
2566 |
2567 | function List(value) {
2568 | var empty = emptyList();
2569 | if (value === null || value === undefined) {
2570 | return empty;
2571 | }
2572 | if (isList(value)) {
2573 | return value;
2574 | }
2575 | var iter = IndexedIterable(value);
2576 | var size = iter.size;
2577 | if (size === 0) {
2578 | return empty;
2579 | }
2580 | assertNotInfinite(size);
2581 | if (size > 0 && size < SIZE) {
2582 | return makeList(0, size, SHIFT, null, new VNode(iter.toArray()));
2583 | }
2584 | return empty.withMutations(function(list ) {
2585 | list.setSize(size);
2586 | iter.forEach(function(v, i) {return list.set(i, v)});
2587 | });
2588 | }
2589 |
2590 | List.of = function(/*...values*/) {
2591 | return this(arguments);
2592 | };
2593 |
2594 | List.prototype.toString = function() {
2595 | return this.__toString('List [', ']');
2596 | };
2597 |
2598 | // @pragma Access
2599 |
2600 | List.prototype.get = function(index, notSetValue) {
2601 | index = wrapIndex(this, index);
2602 | if (index < 0 || index >= this.size) {
2603 | return notSetValue;
2604 | }
2605 | index += this._origin;
2606 | var node = listNodeFor(this, index);
2607 | return node && node.array[index & MASK];
2608 | };
2609 |
2610 | // @pragma Modification
2611 |
2612 | List.prototype.set = function(index, value) {
2613 | return updateList(this, index, value);
2614 | };
2615 |
2616 | List.prototype.remove = function(index) {
2617 | return !this.has(index) ? this :
2618 | index === 0 ? this.shift() :
2619 | index === this.size - 1 ? this.pop() :
2620 | this.splice(index, 1);
2621 | };
2622 |
2623 | List.prototype.clear = function() {
2624 | if (this.size === 0) {
2625 | return this;
2626 | }
2627 | if (this.__ownerID) {
2628 | this.size = this._origin = this._capacity = 0;
2629 | this._level = SHIFT;
2630 | this._root = this._tail = null;
2631 | this.__hash = undefined;
2632 | this.__altered = true;
2633 | return this;
2634 | }
2635 | return emptyList();
2636 | };
2637 |
2638 | List.prototype.push = function(/*...values*/) {
2639 | var values = arguments;
2640 | var oldSize = this.size;
2641 | return this.withMutations(function(list ) {
2642 | setListBounds(list, 0, oldSize + values.length);
2643 | for (var ii = 0; ii < values.length; ii++) {
2644 | list.set(oldSize + ii, values[ii]);
2645 | }
2646 | });
2647 | };
2648 |
2649 | List.prototype.pop = function() {
2650 | return setListBounds(this, 0, -1);
2651 | };
2652 |
2653 | List.prototype.unshift = function(/*...values*/) {
2654 | var values = arguments;
2655 | return this.withMutations(function(list ) {
2656 | setListBounds(list, -values.length);
2657 | for (var ii = 0; ii < values.length; ii++) {
2658 | list.set(ii, values[ii]);
2659 | }
2660 | });
2661 | };
2662 |
2663 | List.prototype.shift = function() {
2664 | return setListBounds(this, 1);
2665 | };
2666 |
2667 | // @pragma Composition
2668 |
2669 | List.prototype.merge = function(/*...iters*/) {
2670 | return mergeIntoListWith(this, undefined, arguments);
2671 | };
2672 |
2673 | List.prototype.mergeWith = function(merger) {var iters = SLICE$0.call(arguments, 1);
2674 | return mergeIntoListWith(this, merger, iters);
2675 | };
2676 |
2677 | List.prototype.mergeDeep = function(/*...iters*/) {
2678 | return mergeIntoListWith(this, deepMerger(undefined), arguments);
2679 | };
2680 |
2681 | List.prototype.mergeDeepWith = function(merger) {var iters = SLICE$0.call(arguments, 1);
2682 | return mergeIntoListWith(this, deepMerger(merger), iters);
2683 | };
2684 |
2685 | List.prototype.setSize = function(size) {
2686 | return setListBounds(this, 0, size);
2687 | };
2688 |
2689 | // @pragma Iteration
2690 |
2691 | List.prototype.slice = function(begin, end) {
2692 | var size = this.size;
2693 | if (wholeSlice(begin, end, size)) {
2694 | return this;
2695 | }
2696 | return setListBounds(
2697 | this,
2698 | resolveBegin(begin, size),
2699 | resolveEnd(end, size)
2700 | );
2701 | };
2702 |
2703 | List.prototype.__iterator = function(type, reverse) {
2704 | var index = 0;
2705 | var values = iterateList(this, reverse);
2706 | return new src_Iterator__Iterator(function() {
2707 | var value = values();
2708 | return value === DONE ?
2709 | iteratorDone() :
2710 | iteratorValue(type, index++, value);
2711 | });
2712 | };
2713 |
2714 | List.prototype.__iterate = function(fn, reverse) {
2715 | var index = 0;
2716 | var values = iterateList(this, reverse);
2717 | var value;
2718 | while ((value = values()) !== DONE) {
2719 | if (fn(value, index++, this) === false) {
2720 | break;
2721 | }
2722 | }
2723 | return index;
2724 | };
2725 |
2726 | List.prototype.__ensureOwner = function(ownerID) {
2727 | if (ownerID === this.__ownerID) {
2728 | return this;
2729 | }
2730 | if (!ownerID) {
2731 | this.__ownerID = ownerID;
2732 | return this;
2733 | }
2734 | return makeList(this._origin, this._capacity, this._level, this._root, this._tail, ownerID, this.__hash);
2735 | };
2736 |
2737 |
2738 | function isList(maybeList) {
2739 | return !!(maybeList && maybeList[IS_LIST_SENTINEL]);
2740 | }
2741 |
2742 | List.isList = isList;
2743 |
2744 | var IS_LIST_SENTINEL = '@@__IMMUTABLE_LIST__@@';
2745 |
2746 | var ListPrototype = List.prototype;
2747 | ListPrototype[IS_LIST_SENTINEL] = true;
2748 | ListPrototype[DELETE] = ListPrototype.remove;
2749 | ListPrototype.setIn = MapPrototype.setIn;
2750 | ListPrototype.deleteIn =
2751 | ListPrototype.removeIn = MapPrototype.removeIn;
2752 | ListPrototype.update = MapPrototype.update;
2753 | ListPrototype.updateIn = MapPrototype.updateIn;
2754 | ListPrototype.mergeIn = MapPrototype.mergeIn;
2755 | ListPrototype.mergeDeepIn = MapPrototype.mergeDeepIn;
2756 | ListPrototype.withMutations = MapPrototype.withMutations;
2757 | ListPrototype.asMutable = MapPrototype.asMutable;
2758 | ListPrototype.asImmutable = MapPrototype.asImmutable;
2759 | ListPrototype.wasAltered = MapPrototype.wasAltered;
2760 |
2761 |
2762 |
2763 | function VNode(array, ownerID) {
2764 | this.array = array;
2765 | this.ownerID = ownerID;
2766 | }
2767 |
2768 | // TODO: seems like these methods are very similar
2769 |
2770 | VNode.prototype.removeBefore = function(ownerID, level, index) {
2771 | if (index === level ? 1 << level : 0 || this.array.length === 0) {
2772 | return this;
2773 | }
2774 | var originIndex = (index >>> level) & MASK;
2775 | if (originIndex >= this.array.length) {
2776 | return new VNode([], ownerID);
2777 | }
2778 | var removingFirst = originIndex === 0;
2779 | var newChild;
2780 | if (level > 0) {
2781 | var oldChild = this.array[originIndex];
2782 | newChild = oldChild && oldChild.removeBefore(ownerID, level - SHIFT, index);
2783 | if (newChild === oldChild && removingFirst) {
2784 | return this;
2785 | }
2786 | }
2787 | if (removingFirst && !newChild) {
2788 | return this;
2789 | }
2790 | var editable = editableVNode(this, ownerID);
2791 | if (!removingFirst) {
2792 | for (var ii = 0; ii < originIndex; ii++) {
2793 | editable.array[ii] = undefined;
2794 | }
2795 | }
2796 | if (newChild) {
2797 | editable.array[originIndex] = newChild;
2798 | }
2799 | return editable;
2800 | };
2801 |
2802 | VNode.prototype.removeAfter = function(ownerID, level, index) {
2803 | if (index === level ? 1 << level : 0 || this.array.length === 0) {
2804 | return this;
2805 | }
2806 | var sizeIndex = ((index - 1) >>> level) & MASK;
2807 | if (sizeIndex >= this.array.length) {
2808 | return this;
2809 | }
2810 | var removingLast = sizeIndex === this.array.length - 1;
2811 | var newChild;
2812 | if (level > 0) {
2813 | var oldChild = this.array[sizeIndex];
2814 | newChild = oldChild && oldChild.removeAfter(ownerID, level - SHIFT, index);
2815 | if (newChild === oldChild && removingLast) {
2816 | return this;
2817 | }
2818 | }
2819 | if (removingLast && !newChild) {
2820 | return this;
2821 | }
2822 | var editable = editableVNode(this, ownerID);
2823 | if (!removingLast) {
2824 | editable.array.pop();
2825 | }
2826 | if (newChild) {
2827 | editable.array[sizeIndex] = newChild;
2828 | }
2829 | return editable;
2830 | };
2831 |
2832 |
2833 |
2834 | var DONE = {};
2835 |
2836 | function iterateList(list, reverse) {
2837 | var left = list._origin;
2838 | var right = list._capacity;
2839 | var tailPos = getTailOffset(right);
2840 | var tail = list._tail;
2841 |
2842 | return iterateNodeOrLeaf(list._root, list._level, 0);
2843 |
2844 | function iterateNodeOrLeaf(node, level, offset) {
2845 | return level === 0 ?
2846 | iterateLeaf(node, offset) :
2847 | iterateNode(node, level, offset);
2848 | }
2849 |
2850 | function iterateLeaf(node, offset) {
2851 | var array = offset === tailPos ? tail && tail.array : node && node.array;
2852 | var from = offset > left ? 0 : left - offset;
2853 | var to = right - offset;
2854 | if (to > SIZE) {
2855 | to = SIZE;
2856 | }
2857 | return function() {
2858 | if (from === to) {
2859 | return DONE;
2860 | }
2861 | var idx = reverse ? --to : from++;
2862 | return array && array[idx];
2863 | };
2864 | }
2865 |
2866 | function iterateNode(node, level, offset) {
2867 | var values;
2868 | var array = node && node.array;
2869 | var from = offset > left ? 0 : (left - offset) >> level;
2870 | var to = ((right - offset) >> level) + 1;
2871 | if (to > SIZE) {
2872 | to = SIZE;
2873 | }
2874 | return function() {
2875 | do {
2876 | if (values) {
2877 | var value = values();
2878 | if (value !== DONE) {
2879 | return value;
2880 | }
2881 | values = null;
2882 | }
2883 | if (from === to) {
2884 | return DONE;
2885 | }
2886 | var idx = reverse ? --to : from++;
2887 | values = iterateNodeOrLeaf(
2888 | array && array[idx], level - SHIFT, offset + (idx << level)
2889 | );
2890 | } while (true);
2891 | };
2892 | }
2893 | }
2894 |
2895 | function makeList(origin, capacity, level, root, tail, ownerID, hash) {
2896 | var list = Object.create(ListPrototype);
2897 | list.size = capacity - origin;
2898 | list._origin = origin;
2899 | list._capacity = capacity;
2900 | list._level = level;
2901 | list._root = root;
2902 | list._tail = tail;
2903 | list.__ownerID = ownerID;
2904 | list.__hash = hash;
2905 | list.__altered = false;
2906 | return list;
2907 | }
2908 |
2909 | var EMPTY_LIST;
2910 | function emptyList() {
2911 | return EMPTY_LIST || (EMPTY_LIST = makeList(0, 0, SHIFT));
2912 | }
2913 |
2914 | function updateList(list, index, value) {
2915 | index = wrapIndex(list, index);
2916 |
2917 | if (index >= list.size || index < 0) {
2918 | return list.withMutations(function(list ) {
2919 | index < 0 ?
2920 | setListBounds(list, index).set(0, value) :
2921 | setListBounds(list, 0, index + 1).set(index, value)
2922 | });
2923 | }
2924 |
2925 | index += list._origin;
2926 |
2927 | var newTail = list._tail;
2928 | var newRoot = list._root;
2929 | var didAlter = MakeRef(DID_ALTER);
2930 | if (index >= getTailOffset(list._capacity)) {
2931 | newTail = updateVNode(newTail, list.__ownerID, 0, index, value, didAlter);
2932 | } else {
2933 | newRoot = updateVNode(newRoot, list.__ownerID, list._level, index, value, didAlter);
2934 | }
2935 |
2936 | if (!didAlter.value) {
2937 | return list;
2938 | }
2939 |
2940 | if (list.__ownerID) {
2941 | list._root = newRoot;
2942 | list._tail = newTail;
2943 | list.__hash = undefined;
2944 | list.__altered = true;
2945 | return list;
2946 | }
2947 | return makeList(list._origin, list._capacity, list._level, newRoot, newTail);
2948 | }
2949 |
2950 | function updateVNode(node, ownerID, level, index, value, didAlter) {
2951 | var idx = (index >>> level) & MASK;
2952 | var nodeHas = node && idx < node.array.length;
2953 | if (!nodeHas && value === undefined) {
2954 | return node;
2955 | }
2956 |
2957 | var newNode;
2958 |
2959 | if (level > 0) {
2960 | var lowerNode = node && node.array[idx];
2961 | var newLowerNode = updateVNode(lowerNode, ownerID, level - SHIFT, index, value, didAlter);
2962 | if (newLowerNode === lowerNode) {
2963 | return node;
2964 | }
2965 | newNode = editableVNode(node, ownerID);
2966 | newNode.array[idx] = newLowerNode;
2967 | return newNode;
2968 | }
2969 |
2970 | if (nodeHas && node.array[idx] === value) {
2971 | return node;
2972 | }
2973 |
2974 | SetRef(didAlter);
2975 |
2976 | newNode = editableVNode(node, ownerID);
2977 | if (value === undefined && idx === newNode.array.length - 1) {
2978 | newNode.array.pop();
2979 | } else {
2980 | newNode.array[idx] = value;
2981 | }
2982 | return newNode;
2983 | }
2984 |
2985 | function editableVNode(node, ownerID) {
2986 | if (ownerID && node && ownerID === node.ownerID) {
2987 | return node;
2988 | }
2989 | return new VNode(node ? node.array.slice() : [], ownerID);
2990 | }
2991 |
2992 | function listNodeFor(list, rawIndex) {
2993 | if (rawIndex >= getTailOffset(list._capacity)) {
2994 | return list._tail;
2995 | }
2996 | if (rawIndex < 1 << (list._level + SHIFT)) {
2997 | var node = list._root;
2998 | var level = list._level;
2999 | while (node && level > 0) {
3000 | node = node.array[(rawIndex >>> level) & MASK];
3001 | level -= SHIFT;
3002 | }
3003 | return node;
3004 | }
3005 | }
3006 |
3007 | function setListBounds(list, begin, end) {
3008 | var owner = list.__ownerID || new OwnerID();
3009 | var oldOrigin = list._origin;
3010 | var oldCapacity = list._capacity;
3011 | var newOrigin = oldOrigin + begin;
3012 | var newCapacity = end === undefined ? oldCapacity : end < 0 ? oldCapacity + end : oldOrigin + end;
3013 | if (newOrigin === oldOrigin && newCapacity === oldCapacity) {
3014 | return list;
3015 | }
3016 |
3017 | // If it's going to end after it starts, it's empty.
3018 | if (newOrigin >= newCapacity) {
3019 | return list.clear();
3020 | }
3021 |
3022 | var newLevel = list._level;
3023 | var newRoot = list._root;
3024 |
3025 | // New origin might require creating a higher root.
3026 | var offsetShift = 0;
3027 | while (newOrigin + offsetShift < 0) {
3028 | newRoot = new VNode(newRoot && newRoot.array.length ? [undefined, newRoot] : [], owner);
3029 | newLevel += SHIFT;
3030 | offsetShift += 1 << newLevel;
3031 | }
3032 | if (offsetShift) {
3033 | newOrigin += offsetShift;
3034 | oldOrigin += offsetShift;
3035 | newCapacity += offsetShift;
3036 | oldCapacity += offsetShift;
3037 | }
3038 |
3039 | var oldTailOffset = getTailOffset(oldCapacity);
3040 | var newTailOffset = getTailOffset(newCapacity);
3041 |
3042 | // New size might require creating a higher root.
3043 | while (newTailOffset >= 1 << (newLevel + SHIFT)) {
3044 | newRoot = new VNode(newRoot && newRoot.array.length ? [newRoot] : [], owner);
3045 | newLevel += SHIFT;
3046 | }
3047 |
3048 | // Locate or create the new tail.
3049 | var oldTail = list._tail;
3050 | var newTail = newTailOffset < oldTailOffset ?
3051 | listNodeFor(list, newCapacity - 1) :
3052 | newTailOffset > oldTailOffset ? new VNode([], owner) : oldTail;
3053 |
3054 | // Merge Tail into tree.
3055 | if (oldTail && newTailOffset > oldTailOffset && newOrigin < oldCapacity && oldTail.array.length) {
3056 | newRoot = editableVNode(newRoot, owner);
3057 | var node = newRoot;
3058 | for (var level = newLevel; level > SHIFT; level -= SHIFT) {
3059 | var idx = (oldTailOffset >>> level) & MASK;
3060 | node = node.array[idx] = editableVNode(node.array[idx], owner);
3061 | }
3062 | node.array[(oldTailOffset >>> SHIFT) & MASK] = oldTail;
3063 | }
3064 |
3065 | // If the size has been reduced, there's a chance the tail needs to be trimmed.
3066 | if (newCapacity < oldCapacity) {
3067 | newTail = newTail && newTail.removeAfter(owner, 0, newCapacity);
3068 | }
3069 |
3070 | // If the new origin is within the tail, then we do not need a root.
3071 | if (newOrigin >= newTailOffset) {
3072 | newOrigin -= newTailOffset;
3073 | newCapacity -= newTailOffset;
3074 | newLevel = SHIFT;
3075 | newRoot = null;
3076 | newTail = newTail && newTail.removeBefore(owner, 0, newOrigin);
3077 |
3078 | // Otherwise, if the root has been trimmed, garbage collect.
3079 | } else if (newOrigin > oldOrigin || newTailOffset < oldTailOffset) {
3080 | offsetShift = 0;
3081 |
3082 | // Identify the new top root node of the subtree of the old root.
3083 | while (newRoot) {
3084 | var beginIndex = (newOrigin >>> newLevel) & MASK;
3085 | if (beginIndex !== (newTailOffset >>> newLevel) & MASK) {
3086 | break;
3087 | }
3088 | if (beginIndex) {
3089 | offsetShift += (1 << newLevel) * beginIndex;
3090 | }
3091 | newLevel -= SHIFT;
3092 | newRoot = newRoot.array[beginIndex];
3093 | }
3094 |
3095 | // Trim the new sides of the new root.
3096 | if (newRoot && newOrigin > oldOrigin) {
3097 | newRoot = newRoot.removeBefore(owner, newLevel, newOrigin - offsetShift);
3098 | }
3099 | if (newRoot && newTailOffset < oldTailOffset) {
3100 | newRoot = newRoot.removeAfter(owner, newLevel, newTailOffset - offsetShift);
3101 | }
3102 | if (offsetShift) {
3103 | newOrigin -= offsetShift;
3104 | newCapacity -= offsetShift;
3105 | }
3106 | }
3107 |
3108 | if (list.__ownerID) {
3109 | list.size = newCapacity - newOrigin;
3110 | list._origin = newOrigin;
3111 | list._capacity = newCapacity;
3112 | list._level = newLevel;
3113 | list._root = newRoot;
3114 | list._tail = newTail;
3115 | list.__hash = undefined;
3116 | list.__altered = true;
3117 | return list;
3118 | }
3119 | return makeList(newOrigin, newCapacity, newLevel, newRoot, newTail);
3120 | }
3121 |
3122 | function mergeIntoListWith(list, merger, iterables) {
3123 | var iters = [];
3124 | var maxSize = 0;
3125 | for (var ii = 0; ii < iterables.length; ii++) {
3126 | var value = iterables[ii];
3127 | var iter = IndexedIterable(value);
3128 | if (iter.size > maxSize) {
3129 | maxSize = iter.size;
3130 | }
3131 | if (!isIterable(value)) {
3132 | iter = iter.map(function(v ) {return fromJS(v)});
3133 | }
3134 | iters.push(iter);
3135 | }
3136 | if (maxSize > list.size) {
3137 | list = list.setSize(maxSize);
3138 | }
3139 | return mergeIntoCollectionWith(list, merger, iters);
3140 | }
3141 |
3142 | function getTailOffset(size) {
3143 | return size < SIZE ? 0 : (((size - 1) >>> SHIFT) << SHIFT);
3144 | }
3145 |
3146 | createClass(OrderedMap, src_Map__Map);
3147 |
3148 | // @pragma Construction
3149 |
3150 | function OrderedMap(value) {
3151 | return value === null || value === undefined ? emptyOrderedMap() :
3152 | isOrderedMap(value) ? value :
3153 | emptyOrderedMap().withMutations(function(map ) {
3154 | var iter = KeyedIterable(value);
3155 | assertNotInfinite(iter.size);
3156 | iter.forEach(function(v, k) {return map.set(k, v)});
3157 | });
3158 | }
3159 |
3160 | OrderedMap.of = function(/*...values*/) {
3161 | return this(arguments);
3162 | };
3163 |
3164 | OrderedMap.prototype.toString = function() {
3165 | return this.__toString('OrderedMap {', '}');
3166 | };
3167 |
3168 | // @pragma Access
3169 |
3170 | OrderedMap.prototype.get = function(k, notSetValue) {
3171 | var index = this._map.get(k);
3172 | return index !== undefined ? this._list.get(index)[1] : notSetValue;
3173 | };
3174 |
3175 | // @pragma Modification
3176 |
3177 | OrderedMap.prototype.clear = function() {
3178 | if (this.size === 0) {
3179 | return this;
3180 | }
3181 | if (this.__ownerID) {
3182 | this.size = 0;
3183 | this._map.clear();
3184 | this._list.clear();
3185 | return this;
3186 | }
3187 | return emptyOrderedMap();
3188 | };
3189 |
3190 | OrderedMap.prototype.set = function(k, v) {
3191 | return updateOrderedMap(this, k, v);
3192 | };
3193 |
3194 | OrderedMap.prototype.remove = function(k) {
3195 | return updateOrderedMap(this, k, NOT_SET);
3196 | };
3197 |
3198 | OrderedMap.prototype.wasAltered = function() {
3199 | return this._map.wasAltered() || this._list.wasAltered();
3200 | };
3201 |
3202 | OrderedMap.prototype.__iterate = function(fn, reverse) {var this$0 = this;
3203 | return this._list.__iterate(
3204 | function(entry ) {return entry && fn(entry[1], entry[0], this$0)},
3205 | reverse
3206 | );
3207 | };
3208 |
3209 | OrderedMap.prototype.__iterator = function(type, reverse) {
3210 | return this._list.fromEntrySeq().__iterator(type, reverse);
3211 | };
3212 |
3213 | OrderedMap.prototype.__ensureOwner = function(ownerID) {
3214 | if (ownerID === this.__ownerID) {
3215 | return this;
3216 | }
3217 | var newMap = this._map.__ensureOwner(ownerID);
3218 | var newList = this._list.__ensureOwner(ownerID);
3219 | if (!ownerID) {
3220 | this.__ownerID = ownerID;
3221 | this._map = newMap;
3222 | this._list = newList;
3223 | return this;
3224 | }
3225 | return makeOrderedMap(newMap, newList, ownerID, this.__hash);
3226 | };
3227 |
3228 |
3229 | function isOrderedMap(maybeOrderedMap) {
3230 | return isMap(maybeOrderedMap) && isOrdered(maybeOrderedMap);
3231 | }
3232 |
3233 | OrderedMap.isOrderedMap = isOrderedMap;
3234 |
3235 | OrderedMap.prototype[IS_ORDERED_SENTINEL] = true;
3236 | OrderedMap.prototype[DELETE] = OrderedMap.prototype.remove;
3237 |
3238 |
3239 |
3240 | function makeOrderedMap(map, list, ownerID, hash) {
3241 | var omap = Object.create(OrderedMap.prototype);
3242 | omap.size = map ? map.size : 0;
3243 | omap._map = map;
3244 | omap._list = list;
3245 | omap.__ownerID = ownerID;
3246 | omap.__hash = hash;
3247 | return omap;
3248 | }
3249 |
3250 | var EMPTY_ORDERED_MAP;
3251 | function emptyOrderedMap() {
3252 | return EMPTY_ORDERED_MAP || (EMPTY_ORDERED_MAP = makeOrderedMap(emptyMap(), emptyList()));
3253 | }
3254 |
3255 | function updateOrderedMap(omap, k, v) {
3256 | var map = omap._map;
3257 | var list = omap._list;
3258 | var i = map.get(k);
3259 | var has = i !== undefined;
3260 | var newMap;
3261 | var newList;
3262 | if (v === NOT_SET) { // removed
3263 | if (!has) {
3264 | return omap;
3265 | }
3266 | if (list.size >= SIZE && list.size >= map.size * 2) {
3267 | newList = list.filter(function(entry, idx) {return entry !== undefined && i !== idx});
3268 | newMap = newList.toKeyedSeq().map(function(entry ) {return entry[0]}).flip().toMap();
3269 | if (omap.__ownerID) {
3270 | newMap.__ownerID = newList.__ownerID = omap.__ownerID;
3271 | }
3272 | } else {
3273 | newMap = map.remove(k);
3274 | newList = i === list.size - 1 ? list.pop() : list.set(i, undefined);
3275 | }
3276 | } else {
3277 | if (has) {
3278 | if (v === list.get(i)[1]) {
3279 | return omap;
3280 | }
3281 | newMap = map;
3282 | newList = list.set(i, [k, v]);
3283 | } else {
3284 | newMap = map.set(k, list.size);
3285 | newList = list.set(list.size, [k, v]);
3286 | }
3287 | }
3288 | if (omap.__ownerID) {
3289 | omap.size = newMap.size;
3290 | omap._map = newMap;
3291 | omap._list = newList;
3292 | omap.__hash = undefined;
3293 | return omap;
3294 | }
3295 | return makeOrderedMap(newMap, newList);
3296 | }
3297 |
3298 | createClass(Stack, IndexedCollection);
3299 |
3300 | // @pragma Construction
3301 |
3302 | function Stack(value) {
3303 | return value === null || value === undefined ? emptyStack() :
3304 | isStack(value) ? value :
3305 | emptyStack().unshiftAll(value);
3306 | }
3307 |
3308 | Stack.of = function(/*...values*/) {
3309 | return this(arguments);
3310 | };
3311 |
3312 | Stack.prototype.toString = function() {
3313 | return this.__toString('Stack [', ']');
3314 | };
3315 |
3316 | // @pragma Access
3317 |
3318 | Stack.prototype.get = function(index, notSetValue) {
3319 | var head = this._head;
3320 | index = wrapIndex(this, index);
3321 | while (head && index--) {
3322 | head = head.next;
3323 | }
3324 | return head ? head.value : notSetValue;
3325 | };
3326 |
3327 | Stack.prototype.peek = function() {
3328 | return this._head && this._head.value;
3329 | };
3330 |
3331 | // @pragma Modification
3332 |
3333 | Stack.prototype.push = function(/*...values*/) {
3334 | if (arguments.length === 0) {
3335 | return this;
3336 | }
3337 | var newSize = this.size + arguments.length;
3338 | var head = this._head;
3339 | for (var ii = arguments.length - 1; ii >= 0; ii--) {
3340 | head = {
3341 | value: arguments[ii],
3342 | next: head
3343 | };
3344 | }
3345 | if (this.__ownerID) {
3346 | this.size = newSize;
3347 | this._head = head;
3348 | this.__hash = undefined;
3349 | this.__altered = true;
3350 | return this;
3351 | }
3352 | return makeStack(newSize, head);
3353 | };
3354 |
3355 | Stack.prototype.pushAll = function(iter) {
3356 | iter = IndexedIterable(iter);
3357 | if (iter.size === 0) {
3358 | return this;
3359 | }
3360 | assertNotInfinite(iter.size);
3361 | var newSize = this.size;
3362 | var head = this._head;
3363 | iter.reverse().forEach(function(value ) {
3364 | newSize++;
3365 | head = {
3366 | value: value,
3367 | next: head
3368 | };
3369 | });
3370 | if (this.__ownerID) {
3371 | this.size = newSize;
3372 | this._head = head;
3373 | this.__hash = undefined;
3374 | this.__altered = true;
3375 | return this;
3376 | }
3377 | return makeStack(newSize, head);
3378 | };
3379 |
3380 | Stack.prototype.pop = function() {
3381 | return this.slice(1);
3382 | };
3383 |
3384 | Stack.prototype.unshift = function(/*...values*/) {
3385 | return this.push.apply(this, arguments);
3386 | };
3387 |
3388 | Stack.prototype.unshiftAll = function(iter) {
3389 | return this.pushAll(iter);
3390 | };
3391 |
3392 | Stack.prototype.shift = function() {
3393 | return this.pop.apply(this, arguments);
3394 | };
3395 |
3396 | Stack.prototype.clear = function() {
3397 | if (this.size === 0) {
3398 | return this;
3399 | }
3400 | if (this.__ownerID) {
3401 | this.size = 0;
3402 | this._head = undefined;
3403 | this.__hash = undefined;
3404 | this.__altered = true;
3405 | return this;
3406 | }
3407 | return emptyStack();
3408 | };
3409 |
3410 | Stack.prototype.slice = function(begin, end) {
3411 | if (wholeSlice(begin, end, this.size)) {
3412 | return this;
3413 | }
3414 | var resolvedBegin = resolveBegin(begin, this.size);
3415 | var resolvedEnd = resolveEnd(end, this.size);
3416 | if (resolvedEnd !== this.size) {
3417 | // super.slice(begin, end);
3418 | return IndexedCollection.prototype.slice.call(this, begin, end);
3419 | }
3420 | var newSize = this.size - resolvedBegin;
3421 | var head = this._head;
3422 | while (resolvedBegin--) {
3423 | head = head.next;
3424 | }
3425 | if (this.__ownerID) {
3426 | this.size = newSize;
3427 | this._head = head;
3428 | this.__hash = undefined;
3429 | this.__altered = true;
3430 | return this;
3431 | }
3432 | return makeStack(newSize, head);
3433 | };
3434 |
3435 | // @pragma Mutability
3436 |
3437 | Stack.prototype.__ensureOwner = function(ownerID) {
3438 | if (ownerID === this.__ownerID) {
3439 | return this;
3440 | }
3441 | if (!ownerID) {
3442 | this.__ownerID = ownerID;
3443 | this.__altered = false;
3444 | return this;
3445 | }
3446 | return makeStack(this.size, this._head, ownerID, this.__hash);
3447 | };
3448 |
3449 | // @pragma Iteration
3450 |
3451 | Stack.prototype.__iterate = function(fn, reverse) {
3452 | if (reverse) {
3453 | return this.reverse().__iterate(fn);
3454 | }
3455 | var iterations = 0;
3456 | var node = this._head;
3457 | while (node) {
3458 | if (fn(node.value, iterations++, this) === false) {
3459 | break;
3460 | }
3461 | node = node.next;
3462 | }
3463 | return iterations;
3464 | };
3465 |
3466 | Stack.prototype.__iterator = function(type, reverse) {
3467 | if (reverse) {
3468 | return this.reverse().__iterator(type);
3469 | }
3470 | var iterations = 0;
3471 | var node = this._head;
3472 | return new src_Iterator__Iterator(function() {
3473 | if (node) {
3474 | var value = node.value;
3475 | node = node.next;
3476 | return iteratorValue(type, iterations++, value);
3477 | }
3478 | return iteratorDone();
3479 | });
3480 | };
3481 |
3482 |
3483 | function isStack(maybeStack) {
3484 | return !!(maybeStack && maybeStack[IS_STACK_SENTINEL]);
3485 | }
3486 |
3487 | Stack.isStack = isStack;
3488 |
3489 | var IS_STACK_SENTINEL = '@@__IMMUTABLE_STACK__@@';
3490 |
3491 | var StackPrototype = Stack.prototype;
3492 | StackPrototype[IS_STACK_SENTINEL] = true;
3493 | StackPrototype.withMutations = MapPrototype.withMutations;
3494 | StackPrototype.asMutable = MapPrototype.asMutable;
3495 | StackPrototype.asImmutable = MapPrototype.asImmutable;
3496 | StackPrototype.wasAltered = MapPrototype.wasAltered;
3497 |
3498 |
3499 | function makeStack(size, head, ownerID, hash) {
3500 | var map = Object.create(StackPrototype);
3501 | map.size = size;
3502 | map._head = head;
3503 | map.__ownerID = ownerID;
3504 | map.__hash = hash;
3505 | map.__altered = false;
3506 | return map;
3507 | }
3508 |
3509 | var EMPTY_STACK;
3510 | function emptyStack() {
3511 | return EMPTY_STACK || (EMPTY_STACK = makeStack(0));
3512 | }
3513 |
3514 | createClass(src_Set__Set, SetCollection);
3515 |
3516 | // @pragma Construction
3517 |
3518 | function src_Set__Set(value) {
3519 | return value === null || value === undefined ? emptySet() :
3520 | isSet(value) ? value :
3521 | emptySet().withMutations(function(set ) {
3522 | var iter = SetIterable(value);
3523 | assertNotInfinite(iter.size);
3524 | iter.forEach(function(v ) {return set.add(v)});
3525 | });
3526 | }
3527 |
3528 | src_Set__Set.of = function(/*...values*/) {
3529 | return this(arguments);
3530 | };
3531 |
3532 | src_Set__Set.fromKeys = function(value) {
3533 | return this(KeyedIterable(value).keySeq());
3534 | };
3535 |
3536 | src_Set__Set.prototype.toString = function() {
3537 | return this.__toString('Set {', '}');
3538 | };
3539 |
3540 | // @pragma Access
3541 |
3542 | src_Set__Set.prototype.has = function(value) {
3543 | return this._map.has(value);
3544 | };
3545 |
3546 | // @pragma Modification
3547 |
3548 | src_Set__Set.prototype.add = function(value) {
3549 | return updateSet(this, this._map.set(value, true));
3550 | };
3551 |
3552 | src_Set__Set.prototype.remove = function(value) {
3553 | return updateSet(this, this._map.remove(value));
3554 | };
3555 |
3556 | src_Set__Set.prototype.clear = function() {
3557 | return updateSet(this, this._map.clear());
3558 | };
3559 |
3560 | // @pragma Composition
3561 |
3562 | src_Set__Set.prototype.union = function() {var iters = SLICE$0.call(arguments, 0);
3563 | iters = iters.filter(function(x ) {return x.size !== 0});
3564 | if (iters.length === 0) {
3565 | return this;
3566 | }
3567 | if (this.size === 0 && !this.__ownerID && iters.length === 1) {
3568 | return this.constructor(iters[0]);
3569 | }
3570 | return this.withMutations(function(set ) {
3571 | for (var ii = 0; ii < iters.length; ii++) {
3572 | SetIterable(iters[ii]).forEach(function(value ) {return set.add(value)});
3573 | }
3574 | });
3575 | };
3576 |
3577 | src_Set__Set.prototype.intersect = function() {var iters = SLICE$0.call(arguments, 0);
3578 | if (iters.length === 0) {
3579 | return this;
3580 | }
3581 | iters = iters.map(function(iter ) {return SetIterable(iter)});
3582 | var originalSet = this;
3583 | return this.withMutations(function(set ) {
3584 | originalSet.forEach(function(value ) {
3585 | if (!iters.every(function(iter ) {return iter.includes(value)})) {
3586 | set.remove(value);
3587 | }
3588 | });
3589 | });
3590 | };
3591 |
3592 | src_Set__Set.prototype.subtract = function() {var iters = SLICE$0.call(arguments, 0);
3593 | if (iters.length === 0) {
3594 | return this;
3595 | }
3596 | iters = iters.map(function(iter ) {return SetIterable(iter)});
3597 | var originalSet = this;
3598 | return this.withMutations(function(set ) {
3599 | originalSet.forEach(function(value ) {
3600 | if (iters.some(function(iter ) {return iter.includes(value)})) {
3601 | set.remove(value);
3602 | }
3603 | });
3604 | });
3605 | };
3606 |
3607 | src_Set__Set.prototype.merge = function() {
3608 | return this.union.apply(this, arguments);
3609 | };
3610 |
3611 | src_Set__Set.prototype.mergeWith = function(merger) {var iters = SLICE$0.call(arguments, 1);
3612 | return this.union.apply(this, iters);
3613 | };
3614 |
3615 | src_Set__Set.prototype.sort = function(comparator) {
3616 | // Late binding
3617 | return OrderedSet(sortFactory(this, comparator));
3618 | };
3619 |
3620 | src_Set__Set.prototype.sortBy = function(mapper, comparator) {
3621 | // Late binding
3622 | return OrderedSet(sortFactory(this, comparator, mapper));
3623 | };
3624 |
3625 | src_Set__Set.prototype.wasAltered = function() {
3626 | return this._map.wasAltered();
3627 | };
3628 |
3629 | src_Set__Set.prototype.__iterate = function(fn, reverse) {var this$0 = this;
3630 | return this._map.__iterate(function(_, k) {return fn(k, k, this$0)}, reverse);
3631 | };
3632 |
3633 | src_Set__Set.prototype.__iterator = function(type, reverse) {
3634 | return this._map.map(function(_, k) {return k}).__iterator(type, reverse);
3635 | };
3636 |
3637 | src_Set__Set.prototype.__ensureOwner = function(ownerID) {
3638 | if (ownerID === this.__ownerID) {
3639 | return this;
3640 | }
3641 | var newMap = this._map.__ensureOwner(ownerID);
3642 | if (!ownerID) {
3643 | this.__ownerID = ownerID;
3644 | this._map = newMap;
3645 | return this;
3646 | }
3647 | return this.__make(newMap, ownerID);
3648 | };
3649 |
3650 |
3651 | function isSet(maybeSet) {
3652 | return !!(maybeSet && maybeSet[IS_SET_SENTINEL]);
3653 | }
3654 |
3655 | src_Set__Set.isSet = isSet;
3656 |
3657 | var IS_SET_SENTINEL = '@@__IMMUTABLE_SET__@@';
3658 |
3659 | var SetPrototype = src_Set__Set.prototype;
3660 | SetPrototype[IS_SET_SENTINEL] = true;
3661 | SetPrototype[DELETE] = SetPrototype.remove;
3662 | SetPrototype.mergeDeep = SetPrototype.merge;
3663 | SetPrototype.mergeDeepWith = SetPrototype.mergeWith;
3664 | SetPrototype.withMutations = MapPrototype.withMutations;
3665 | SetPrototype.asMutable = MapPrototype.asMutable;
3666 | SetPrototype.asImmutable = MapPrototype.asImmutable;
3667 |
3668 | SetPrototype.__empty = emptySet;
3669 | SetPrototype.__make = makeSet;
3670 |
3671 | function updateSet(set, newMap) {
3672 | if (set.__ownerID) {
3673 | set.size = newMap.size;
3674 | set._map = newMap;
3675 | return set;
3676 | }
3677 | return newMap === set._map ? set :
3678 | newMap.size === 0 ? set.__empty() :
3679 | set.__make(newMap);
3680 | }
3681 |
3682 | function makeSet(map, ownerID) {
3683 | var set = Object.create(SetPrototype);
3684 | set.size = map ? map.size : 0;
3685 | set._map = map;
3686 | set.__ownerID = ownerID;
3687 | return set;
3688 | }
3689 |
3690 | var EMPTY_SET;
3691 | function emptySet() {
3692 | return EMPTY_SET || (EMPTY_SET = makeSet(emptyMap()));
3693 | }
3694 |
3695 | createClass(OrderedSet, src_Set__Set);
3696 |
3697 | // @pragma Construction
3698 |
3699 | function OrderedSet(value) {
3700 | return value === null || value === undefined ? emptyOrderedSet() :
3701 | isOrderedSet(value) ? value :
3702 | emptyOrderedSet().withMutations(function(set ) {
3703 | var iter = SetIterable(value);
3704 | assertNotInfinite(iter.size);
3705 | iter.forEach(function(v ) {return set.add(v)});
3706 | });
3707 | }
3708 |
3709 | OrderedSet.of = function(/*...values*/) {
3710 | return this(arguments);
3711 | };
3712 |
3713 | OrderedSet.fromKeys = function(value) {
3714 | return this(KeyedIterable(value).keySeq());
3715 | };
3716 |
3717 | OrderedSet.prototype.toString = function() {
3718 | return this.__toString('OrderedSet {', '}');
3719 | };
3720 |
3721 |
3722 | function isOrderedSet(maybeOrderedSet) {
3723 | return isSet(maybeOrderedSet) && isOrdered(maybeOrderedSet);
3724 | }
3725 |
3726 | OrderedSet.isOrderedSet = isOrderedSet;
3727 |
3728 | var OrderedSetPrototype = OrderedSet.prototype;
3729 | OrderedSetPrototype[IS_ORDERED_SENTINEL] = true;
3730 |
3731 | OrderedSetPrototype.__empty = emptyOrderedSet;
3732 | OrderedSetPrototype.__make = makeOrderedSet;
3733 |
3734 | function makeOrderedSet(map, ownerID) {
3735 | var set = Object.create(OrderedSetPrototype);
3736 | set.size = map ? map.size : 0;
3737 | set._map = map;
3738 | set.__ownerID = ownerID;
3739 | return set;
3740 | }
3741 |
3742 | var EMPTY_ORDERED_SET;
3743 | function emptyOrderedSet() {
3744 | return EMPTY_ORDERED_SET || (EMPTY_ORDERED_SET = makeOrderedSet(emptyOrderedMap()));
3745 | }
3746 |
3747 | createClass(Record, KeyedCollection);
3748 |
3749 | function Record(defaultValues, name) {
3750 | var hasInitialized;
3751 |
3752 | var RecordType = function Record(values) {
3753 | if (values instanceof RecordType) {
3754 | return values;
3755 | }
3756 | if (!(this instanceof RecordType)) {
3757 | return new RecordType(values);
3758 | }
3759 | if (!hasInitialized) {
3760 | hasInitialized = true;
3761 | var keys = Object.keys(defaultValues);
3762 | setProps(RecordTypePrototype, keys);
3763 | RecordTypePrototype.size = keys.length;
3764 | RecordTypePrototype._name = name;
3765 | RecordTypePrototype._keys = keys;
3766 | RecordTypePrototype._defaultValues = defaultValues;
3767 | }
3768 | this._map = src_Map__Map(values);
3769 | };
3770 |
3771 | var RecordTypePrototype = RecordType.prototype = Object.create(RecordPrototype);
3772 | RecordTypePrototype.constructor = RecordType;
3773 |
3774 | return RecordType;
3775 | }
3776 |
3777 | Record.prototype.toString = function() {
3778 | return this.__toString(recordName(this) + ' {', '}');
3779 | };
3780 |
3781 | // @pragma Access
3782 |
3783 | Record.prototype.has = function(k) {
3784 | return this._defaultValues.hasOwnProperty(k);
3785 | };
3786 |
3787 | Record.prototype.get = function(k, notSetValue) {
3788 | if (!this.has(k)) {
3789 | return notSetValue;
3790 | }
3791 | var defaultVal = this._defaultValues[k];
3792 | return this._map ? this._map.get(k, defaultVal) : defaultVal;
3793 | };
3794 |
3795 | // @pragma Modification
3796 |
3797 | Record.prototype.clear = function() {
3798 | if (this.__ownerID) {
3799 | this._map && this._map.clear();
3800 | return this;
3801 | }
3802 | var RecordType = this.constructor;
3803 | return RecordType._empty || (RecordType._empty = makeRecord(this, emptyMap()));
3804 | };
3805 |
3806 | Record.prototype.set = function(k, v) {
3807 | if (!this.has(k)) {
3808 | throw new Error('Cannot set unknown key "' + k + '" on ' + recordName(this));
3809 | }
3810 | var newMap = this._map && this._map.set(k, v);
3811 | if (this.__ownerID || newMap === this._map) {
3812 | return this;
3813 | }
3814 | return makeRecord(this, newMap);
3815 | };
3816 |
3817 | Record.prototype.remove = function(k) {
3818 | if (!this.has(k)) {
3819 | return this;
3820 | }
3821 | var newMap = this._map && this._map.remove(k);
3822 | if (this.__ownerID || newMap === this._map) {
3823 | return this;
3824 | }
3825 | return makeRecord(this, newMap);
3826 | };
3827 |
3828 | Record.prototype.wasAltered = function() {
3829 | return this._map.wasAltered();
3830 | };
3831 |
3832 | Record.prototype.__iterator = function(type, reverse) {var this$0 = this;
3833 | return KeyedIterable(this._defaultValues).map(function(_, k) {return this$0.get(k)}).__iterator(type, reverse);
3834 | };
3835 |
3836 | Record.prototype.__iterate = function(fn, reverse) {var this$0 = this;
3837 | return KeyedIterable(this._defaultValues).map(function(_, k) {return this$0.get(k)}).__iterate(fn, reverse);
3838 | };
3839 |
3840 | Record.prototype.__ensureOwner = function(ownerID) {
3841 | if (ownerID === this.__ownerID) {
3842 | return this;
3843 | }
3844 | var newMap = this._map && this._map.__ensureOwner(ownerID);
3845 | if (!ownerID) {
3846 | this.__ownerID = ownerID;
3847 | this._map = newMap;
3848 | return this;
3849 | }
3850 | return makeRecord(this, newMap, ownerID);
3851 | };
3852 |
3853 |
3854 | var RecordPrototype = Record.prototype;
3855 | RecordPrototype[DELETE] = RecordPrototype.remove;
3856 | RecordPrototype.deleteIn =
3857 | RecordPrototype.removeIn = MapPrototype.removeIn;
3858 | RecordPrototype.merge = MapPrototype.merge;
3859 | RecordPrototype.mergeWith = MapPrototype.mergeWith;
3860 | RecordPrototype.mergeIn = MapPrototype.mergeIn;
3861 | RecordPrototype.mergeDeep = MapPrototype.mergeDeep;
3862 | RecordPrototype.mergeDeepWith = MapPrototype.mergeDeepWith;
3863 | RecordPrototype.mergeDeepIn = MapPrototype.mergeDeepIn;
3864 | RecordPrototype.setIn = MapPrototype.setIn;
3865 | RecordPrototype.update = MapPrototype.update;
3866 | RecordPrototype.updateIn = MapPrototype.updateIn;
3867 | RecordPrototype.withMutations = MapPrototype.withMutations;
3868 | RecordPrototype.asMutable = MapPrototype.asMutable;
3869 | RecordPrototype.asImmutable = MapPrototype.asImmutable;
3870 |
3871 |
3872 | function makeRecord(likeRecord, map, ownerID) {
3873 | var record = Object.create(Object.getPrototypeOf(likeRecord));
3874 | record._map = map;
3875 | record.__ownerID = ownerID;
3876 | return record;
3877 | }
3878 |
3879 | function recordName(record) {
3880 | return record._name || record.constructor.name || 'Record';
3881 | }
3882 |
3883 | function setProps(prototype, names) {
3884 | try {
3885 | names.forEach(setProp.bind(undefined, prototype));
3886 | } catch (error) {
3887 | // Object.defineProperty failed. Probably IE8.
3888 | }
3889 | }
3890 |
3891 | function setProp(prototype, name) {
3892 | Object.defineProperty(prototype, name, {
3893 | get: function() {
3894 | return this.get(name);
3895 | },
3896 | set: function(value) {
3897 | invariant(this.__ownerID, 'Cannot set on an immutable record.');
3898 | this.set(name, value);
3899 | }
3900 | });
3901 | }
3902 |
3903 | function deepEqual(a, b) {
3904 | if (a === b) {
3905 | return true;
3906 | }
3907 |
3908 | if (
3909 | !isIterable(b) ||
3910 | a.size !== undefined && b.size !== undefined && a.size !== b.size ||
3911 | a.__hash !== undefined && b.__hash !== undefined && a.__hash !== b.__hash ||
3912 | isKeyed(a) !== isKeyed(b) ||
3913 | isIndexed(a) !== isIndexed(b) ||
3914 | isOrdered(a) !== isOrdered(b)
3915 | ) {
3916 | return false;
3917 | }
3918 |
3919 | if (a.size === 0 && b.size === 0) {
3920 | return true;
3921 | }
3922 |
3923 | var notAssociative = !isAssociative(a);
3924 |
3925 | if (isOrdered(a)) {
3926 | var entries = a.entries();
3927 | return b.every(function(v, k) {
3928 | var entry = entries.next().value;
3929 | return entry && is(entry[1], v) && (notAssociative || is(entry[0], k));
3930 | }) && entries.next().done;
3931 | }
3932 |
3933 | var flipped = false;
3934 |
3935 | if (a.size === undefined) {
3936 | if (b.size === undefined) {
3937 | if (typeof a.cacheResult === 'function') {
3938 | a.cacheResult();
3939 | }
3940 | } else {
3941 | flipped = true;
3942 | var _ = a;
3943 | a = b;
3944 | b = _;
3945 | }
3946 | }
3947 |
3948 | var allEqual = true;
3949 | var bSize = b.__iterate(function(v, k) {
3950 | if (notAssociative ? !a.has(v) :
3951 | flipped ? !is(v, a.get(k, NOT_SET)) : !is(a.get(k, NOT_SET), v)) {
3952 | allEqual = false;
3953 | return false;
3954 | }
3955 | });
3956 |
3957 | return allEqual && a.size === bSize;
3958 | }
3959 |
3960 | createClass(Range, IndexedSeq);
3961 |
3962 | function Range(start, end, step) {
3963 | if (!(this instanceof Range)) {
3964 | return new Range(start, end, step);
3965 | }
3966 | invariant(step !== 0, 'Cannot step a Range by 0');
3967 | start = start || 0;
3968 | if (end === undefined) {
3969 | end = Infinity;
3970 | }
3971 | step = step === undefined ? 1 : Math.abs(step);
3972 | if (end < start) {
3973 | step = -step;
3974 | }
3975 | this._start = start;
3976 | this._end = end;
3977 | this._step = step;
3978 | this.size = Math.max(0, Math.ceil((end - start) / step - 1) + 1);
3979 | if (this.size === 0) {
3980 | if (EMPTY_RANGE) {
3981 | return EMPTY_RANGE;
3982 | }
3983 | EMPTY_RANGE = this;
3984 | }
3985 | }
3986 |
3987 | Range.prototype.toString = function() {
3988 | if (this.size === 0) {
3989 | return 'Range []';
3990 | }
3991 | return 'Range [ ' +
3992 | this._start + '...' + this._end +
3993 | (this._step > 1 ? ' by ' + this._step : '') +
3994 | ' ]';
3995 | };
3996 |
3997 | Range.prototype.get = function(index, notSetValue) {
3998 | return this.has(index) ?
3999 | this._start + wrapIndex(this, index) * this._step :
4000 | notSetValue;
4001 | };
4002 |
4003 | Range.prototype.includes = function(searchValue) {
4004 | var possibleIndex = (searchValue - this._start) / this._step;
4005 | return possibleIndex >= 0 &&
4006 | possibleIndex < this.size &&
4007 | possibleIndex === Math.floor(possibleIndex);
4008 | };
4009 |
4010 | Range.prototype.slice = function(begin, end) {
4011 | if (wholeSlice(begin, end, this.size)) {
4012 | return this;
4013 | }
4014 | begin = resolveBegin(begin, this.size);
4015 | end = resolveEnd(end, this.size);
4016 | if (end <= begin) {
4017 | return new Range(0, 0);
4018 | }
4019 | return new Range(this.get(begin, this._end), this.get(end, this._end), this._step);
4020 | };
4021 |
4022 | Range.prototype.indexOf = function(searchValue) {
4023 | var offsetValue = searchValue - this._start;
4024 | if (offsetValue % this._step === 0) {
4025 | var index = offsetValue / this._step;
4026 | if (index >= 0 && index < this.size) {
4027 | return index
4028 | }
4029 | }
4030 | return -1;
4031 | };
4032 |
4033 | Range.prototype.lastIndexOf = function(searchValue) {
4034 | return this.indexOf(searchValue);
4035 | };
4036 |
4037 | Range.prototype.__iterate = function(fn, reverse) {
4038 | var maxIndex = this.size - 1;
4039 | var step = this._step;
4040 | var value = reverse ? this._start + maxIndex * step : this._start;
4041 | for (var ii = 0; ii <= maxIndex; ii++) {
4042 | if (fn(value, ii, this) === false) {
4043 | return ii + 1;
4044 | }
4045 | value += reverse ? -step : step;
4046 | }
4047 | return ii;
4048 | };
4049 |
4050 | Range.prototype.__iterator = function(type, reverse) {
4051 | var maxIndex = this.size - 1;
4052 | var step = this._step;
4053 | var value = reverse ? this._start + maxIndex * step : this._start;
4054 | var ii = 0;
4055 | return new src_Iterator__Iterator(function() {
4056 | var v = value;
4057 | value += reverse ? -step : step;
4058 | return ii > maxIndex ? iteratorDone() : iteratorValue(type, ii++, v);
4059 | });
4060 | };
4061 |
4062 | Range.prototype.equals = function(other) {
4063 | return other instanceof Range ?
4064 | this._start === other._start &&
4065 | this._end === other._end &&
4066 | this._step === other._step :
4067 | deepEqual(this, other);
4068 | };
4069 |
4070 |
4071 | var EMPTY_RANGE;
4072 |
4073 | createClass(Repeat, IndexedSeq);
4074 |
4075 | function Repeat(value, times) {
4076 | if (!(this instanceof Repeat)) {
4077 | return new Repeat(value, times);
4078 | }
4079 | this._value = value;
4080 | this.size = times === undefined ? Infinity : Math.max(0, times);
4081 | if (this.size === 0) {
4082 | if (EMPTY_REPEAT) {
4083 | return EMPTY_REPEAT;
4084 | }
4085 | EMPTY_REPEAT = this;
4086 | }
4087 | }
4088 |
4089 | Repeat.prototype.toString = function() {
4090 | if (this.size === 0) {
4091 | return 'Repeat []';
4092 | }
4093 | return 'Repeat [ ' + this._value + ' ' + this.size + ' times ]';
4094 | };
4095 |
4096 | Repeat.prototype.get = function(index, notSetValue) {
4097 | return this.has(index) ? this._value : notSetValue;
4098 | };
4099 |
4100 | Repeat.prototype.includes = function(searchValue) {
4101 | return is(this._value, searchValue);
4102 | };
4103 |
4104 | Repeat.prototype.slice = function(begin, end) {
4105 | var size = this.size;
4106 | return wholeSlice(begin, end, size) ? this :
4107 | new Repeat(this._value, resolveEnd(end, size) - resolveBegin(begin, size));
4108 | };
4109 |
4110 | Repeat.prototype.reverse = function() {
4111 | return this;
4112 | };
4113 |
4114 | Repeat.prototype.indexOf = function(searchValue) {
4115 | if (is(this._value, searchValue)) {
4116 | return 0;
4117 | }
4118 | return -1;
4119 | };
4120 |
4121 | Repeat.prototype.lastIndexOf = function(searchValue) {
4122 | if (is(this._value, searchValue)) {
4123 | return this.size;
4124 | }
4125 | return -1;
4126 | };
4127 |
4128 | Repeat.prototype.__iterate = function(fn, reverse) {
4129 | for (var ii = 0; ii < this.size; ii++) {
4130 | if (fn(this._value, ii, this) === false) {
4131 | return ii + 1;
4132 | }
4133 | }
4134 | return ii;
4135 | };
4136 |
4137 | Repeat.prototype.__iterator = function(type, reverse) {var this$0 = this;
4138 | var ii = 0;
4139 | return new src_Iterator__Iterator(function()
4140 | {return ii < this$0.size ? iteratorValue(type, ii++, this$0._value) : iteratorDone()}
4141 | );
4142 | };
4143 |
4144 | Repeat.prototype.equals = function(other) {
4145 | return other instanceof Repeat ?
4146 | is(this._value, other._value) :
4147 | deepEqual(other);
4148 | };
4149 |
4150 |
4151 | var EMPTY_REPEAT;
4152 |
4153 | /**
4154 | * Contributes additional methods to a constructor
4155 | */
4156 | function mixin(ctor, methods) {
4157 | var keyCopier = function(key ) { ctor.prototype[key] = methods[key]; };
4158 | Object.keys(methods).forEach(keyCopier);
4159 | Object.getOwnPropertySymbols &&
4160 | Object.getOwnPropertySymbols(methods).forEach(keyCopier);
4161 | return ctor;
4162 | }
4163 |
4164 | Iterable.Iterator = src_Iterator__Iterator;
4165 |
4166 | mixin(Iterable, {
4167 |
4168 | // ### Conversion to other types
4169 |
4170 | toArray: function() {
4171 | assertNotInfinite(this.size);
4172 | var array = new Array(this.size || 0);
4173 | this.valueSeq().__iterate(function(v, i) { array[i] = v; });
4174 | return array;
4175 | },
4176 |
4177 | toIndexedSeq: function() {
4178 | return new ToIndexedSequence(this);
4179 | },
4180 |
4181 | toJS: function() {
4182 | return this.toSeq().map(
4183 | function(value ) {return value && typeof value.toJS === 'function' ? value.toJS() : value}
4184 | ).__toJS();
4185 | },
4186 |
4187 | toJSON: function() {
4188 | return this.toSeq().map(
4189 | function(value ) {return value && typeof value.toJSON === 'function' ? value.toJSON() : value}
4190 | ).__toJS();
4191 | },
4192 |
4193 | toKeyedSeq: function() {
4194 | return new ToKeyedSequence(this, true);
4195 | },
4196 |
4197 | toMap: function() {
4198 | // Use Late Binding here to solve the circular dependency.
4199 | return src_Map__Map(this.toKeyedSeq());
4200 | },
4201 |
4202 | toObject: function() {
4203 | assertNotInfinite(this.size);
4204 | var object = {};
4205 | this.__iterate(function(v, k) { object[k] = v; });
4206 | return object;
4207 | },
4208 |
4209 | toOrderedMap: function() {
4210 | // Use Late Binding here to solve the circular dependency.
4211 | return OrderedMap(this.toKeyedSeq());
4212 | },
4213 |
4214 | toOrderedSet: function() {
4215 | // Use Late Binding here to solve the circular dependency.
4216 | return OrderedSet(isKeyed(this) ? this.valueSeq() : this);
4217 | },
4218 |
4219 | toSet: function() {
4220 | // Use Late Binding here to solve the circular dependency.
4221 | return src_Set__Set(isKeyed(this) ? this.valueSeq() : this);
4222 | },
4223 |
4224 | toSetSeq: function() {
4225 | return new ToSetSequence(this);
4226 | },
4227 |
4228 | toSeq: function() {
4229 | return isIndexed(this) ? this.toIndexedSeq() :
4230 | isKeyed(this) ? this.toKeyedSeq() :
4231 | this.toSetSeq();
4232 | },
4233 |
4234 | toStack: function() {
4235 | // Use Late Binding here to solve the circular dependency.
4236 | return Stack(isKeyed(this) ? this.valueSeq() : this);
4237 | },
4238 |
4239 | toList: function() {
4240 | // Use Late Binding here to solve the circular dependency.
4241 | return List(isKeyed(this) ? this.valueSeq() : this);
4242 | },
4243 |
4244 |
4245 | // ### Common JavaScript methods and properties
4246 |
4247 | toString: function() {
4248 | return '[Iterable]';
4249 | },
4250 |
4251 | __toString: function(head, tail) {
4252 | if (this.size === 0) {
4253 | return head + tail;
4254 | }
4255 | return head + ' ' + this.toSeq().map(this.__toStringMapper).join(', ') + ' ' + tail;
4256 | },
4257 |
4258 |
4259 | // ### ES6 Collection methods (ES6 Array and Map)
4260 |
4261 | concat: function() {var values = SLICE$0.call(arguments, 0);
4262 | return reify(this, concatFactory(this, values));
4263 | },
4264 |
4265 | contains: function(searchValue) {
4266 | return this.includes(searchValue);
4267 | },
4268 |
4269 | includes: function(searchValue) {
4270 | return this.some(function(value ) {return is(value, searchValue)});
4271 | },
4272 |
4273 | entries: function() {
4274 | return this.__iterator(ITERATE_ENTRIES);
4275 | },
4276 |
4277 | every: function(predicate, context) {
4278 | assertNotInfinite(this.size);
4279 | var returnValue = true;
4280 | this.__iterate(function(v, k, c) {
4281 | if (!predicate.call(context, v, k, c)) {
4282 | returnValue = false;
4283 | return false;
4284 | }
4285 | });
4286 | return returnValue;
4287 | },
4288 |
4289 | filter: function(predicate, context) {
4290 | return reify(this, filterFactory(this, predicate, context, true));
4291 | },
4292 |
4293 | find: function(predicate, context, notSetValue) {
4294 | var entry = this.findEntry(predicate, context);
4295 | return entry ? entry[1] : notSetValue;
4296 | },
4297 |
4298 | findEntry: function(predicate, context) {
4299 | var found;
4300 | this.__iterate(function(v, k, c) {
4301 | if (predicate.call(context, v, k, c)) {
4302 | found = [k, v];
4303 | return false;
4304 | }
4305 | });
4306 | return found;
4307 | },
4308 |
4309 | findLastEntry: function(predicate, context) {
4310 | return this.toSeq().reverse().findEntry(predicate, context);
4311 | },
4312 |
4313 | forEach: function(sideEffect, context) {
4314 | assertNotInfinite(this.size);
4315 | return this.__iterate(context ? sideEffect.bind(context) : sideEffect);
4316 | },
4317 |
4318 | join: function(separator) {
4319 | assertNotInfinite(this.size);
4320 | separator = separator !== undefined ? '' + separator : ',';
4321 | var joined = '';
4322 | var isFirst = true;
4323 | this.__iterate(function(v ) {
4324 | isFirst ? (isFirst = false) : (joined += separator);
4325 | joined += v !== null && v !== undefined ? v.toString() : '';
4326 | });
4327 | return joined;
4328 | },
4329 |
4330 | keys: function() {
4331 | return this.__iterator(ITERATE_KEYS);
4332 | },
4333 |
4334 | map: function(mapper, context) {
4335 | return reify(this, mapFactory(this, mapper, context));
4336 | },
4337 |
4338 | reduce: function(reducer, initialReduction, context) {
4339 | assertNotInfinite(this.size);
4340 | var reduction;
4341 | var useFirst;
4342 | if (arguments.length < 2) {
4343 | useFirst = true;
4344 | } else {
4345 | reduction = initialReduction;
4346 | }
4347 | this.__iterate(function(v, k, c) {
4348 | if (useFirst) {
4349 | useFirst = false;
4350 | reduction = v;
4351 | } else {
4352 | reduction = reducer.call(context, reduction, v, k, c);
4353 | }
4354 | });
4355 | return reduction;
4356 | },
4357 |
4358 | reduceRight: function(reducer, initialReduction, context) {
4359 | var reversed = this.toKeyedSeq().reverse();
4360 | return reversed.reduce.apply(reversed, arguments);
4361 | },
4362 |
4363 | reverse: function() {
4364 | return reify(this, reverseFactory(this, true));
4365 | },
4366 |
4367 | slice: function(begin, end) {
4368 | return reify(this, sliceFactory(this, begin, end, true));
4369 | },
4370 |
4371 | some: function(predicate, context) {
4372 | return !this.every(not(predicate), context);
4373 | },
4374 |
4375 | sort: function(comparator) {
4376 | return reify(this, sortFactory(this, comparator));
4377 | },
4378 |
4379 | values: function() {
4380 | return this.__iterator(ITERATE_VALUES);
4381 | },
4382 |
4383 |
4384 | // ### More sequential methods
4385 |
4386 | butLast: function() {
4387 | return this.slice(0, -1);
4388 | },
4389 |
4390 | isEmpty: function() {
4391 | return this.size !== undefined ? this.size === 0 : !this.some(function() {return true});
4392 | },
4393 |
4394 | count: function(predicate, context) {
4395 | return ensureSize(
4396 | predicate ? this.toSeq().filter(predicate, context) : this
4397 | );
4398 | },
4399 |
4400 | countBy: function(grouper, context) {
4401 | return countByFactory(this, grouper, context);
4402 | },
4403 |
4404 | equals: function(other) {
4405 | return deepEqual(this, other);
4406 | },
4407 |
4408 | entrySeq: function() {
4409 | var iterable = this;
4410 | if (iterable._cache) {
4411 | // We cache as an entries array, so we can just return the cache!
4412 | return new ArraySeq(iterable._cache);
4413 | }
4414 | var entriesSequence = iterable.toSeq().map(entryMapper).toIndexedSeq();
4415 | entriesSequence.fromEntrySeq = function() {return iterable.toSeq()};
4416 | return entriesSequence;
4417 | },
4418 |
4419 | filterNot: function(predicate, context) {
4420 | return this.filter(not(predicate), context);
4421 | },
4422 |
4423 | findLast: function(predicate, context, notSetValue) {
4424 | return this.toKeyedSeq().reverse().find(predicate, context, notSetValue);
4425 | },
4426 |
4427 | first: function() {
4428 | return this.find(returnTrue);
4429 | },
4430 |
4431 | flatMap: function(mapper, context) {
4432 | return reify(this, flatMapFactory(this, mapper, context));
4433 | },
4434 |
4435 | flatten: function(depth) {
4436 | return reify(this, flattenFactory(this, depth, true));
4437 | },
4438 |
4439 | fromEntrySeq: function() {
4440 | return new FromEntriesSequence(this);
4441 | },
4442 |
4443 | get: function(searchKey, notSetValue) {
4444 | return this.find(function(_, key) {return is(key, searchKey)}, undefined, notSetValue);
4445 | },
4446 |
4447 | getIn: function(searchKeyPath, notSetValue) {
4448 | var nested = this;
4449 | // Note: in an ES6 environment, we would prefer:
4450 | // for (var key of searchKeyPath) {
4451 | var iter = forceIterator(searchKeyPath);
4452 | var step;
4453 | while (!(step = iter.next()).done) {
4454 | var key = step.value;
4455 | nested = nested && nested.get ? nested.get(key, NOT_SET) : NOT_SET;
4456 | if (nested === NOT_SET) {
4457 | return notSetValue;
4458 | }
4459 | }
4460 | return nested;
4461 | },
4462 |
4463 | groupBy: function(grouper, context) {
4464 | return groupByFactory(this, grouper, context);
4465 | },
4466 |
4467 | has: function(searchKey) {
4468 | return this.get(searchKey, NOT_SET) !== NOT_SET;
4469 | },
4470 |
4471 | hasIn: function(searchKeyPath) {
4472 | return this.getIn(searchKeyPath, NOT_SET) !== NOT_SET;
4473 | },
4474 |
4475 | isSubset: function(iter) {
4476 | iter = typeof iter.includes === 'function' ? iter : Iterable(iter);
4477 | return this.every(function(value ) {return iter.includes(value)});
4478 | },
4479 |
4480 | isSuperset: function(iter) {
4481 | return iter.isSubset(this);
4482 | },
4483 |
4484 | keySeq: function() {
4485 | return this.toSeq().map(keyMapper).toIndexedSeq();
4486 | },
4487 |
4488 | last: function() {
4489 | return this.toSeq().reverse().first();
4490 | },
4491 |
4492 | max: function(comparator) {
4493 | return maxFactory(this, comparator);
4494 | },
4495 |
4496 | maxBy: function(mapper, comparator) {
4497 | return maxFactory(this, comparator, mapper);
4498 | },
4499 |
4500 | min: function(comparator) {
4501 | return maxFactory(this, comparator ? neg(comparator) : defaultNegComparator);
4502 | },
4503 |
4504 | minBy: function(mapper, comparator) {
4505 | return maxFactory(this, comparator ? neg(comparator) : defaultNegComparator, mapper);
4506 | },
4507 |
4508 | rest: function() {
4509 | return this.slice(1);
4510 | },
4511 |
4512 | skip: function(amount) {
4513 | return this.slice(Math.max(0, amount));
4514 | },
4515 |
4516 | skipLast: function(amount) {
4517 | return reify(this, this.toSeq().reverse().skip(amount).reverse());
4518 | },
4519 |
4520 | skipWhile: function(predicate, context) {
4521 | return reify(this, skipWhileFactory(this, predicate, context, true));
4522 | },
4523 |
4524 | skipUntil: function(predicate, context) {
4525 | return this.skipWhile(not(predicate), context);
4526 | },
4527 |
4528 | sortBy: function(mapper, comparator) {
4529 | return reify(this, sortFactory(this, comparator, mapper));
4530 | },
4531 |
4532 | take: function(amount) {
4533 | return this.slice(0, Math.max(0, amount));
4534 | },
4535 |
4536 | takeLast: function(amount) {
4537 | return reify(this, this.toSeq().reverse().take(amount).reverse());
4538 | },
4539 |
4540 | takeWhile: function(predicate, context) {
4541 | return reify(this, takeWhileFactory(this, predicate, context));
4542 | },
4543 |
4544 | takeUntil: function(predicate, context) {
4545 | return this.takeWhile(not(predicate), context);
4546 | },
4547 |
4548 | valueSeq: function() {
4549 | return this.toIndexedSeq();
4550 | },
4551 |
4552 |
4553 | // ### Hashable Object
4554 |
4555 | hashCode: function() {
4556 | return this.__hash || (this.__hash = hashIterable(this));
4557 | },
4558 |
4559 |
4560 | // ### Internal
4561 |
4562 | // abstract __iterate(fn, reverse)
4563 |
4564 | // abstract __iterator(type, reverse)
4565 | });
4566 |
4567 | // var IS_ITERABLE_SENTINEL = '@@__IMMUTABLE_ITERABLE__@@';
4568 | // var IS_KEYED_SENTINEL = '@@__IMMUTABLE_KEYED__@@';
4569 | // var IS_INDEXED_SENTINEL = '@@__IMMUTABLE_INDEXED__@@';
4570 | // var IS_ORDERED_SENTINEL = '@@__IMMUTABLE_ORDERED__@@';
4571 |
4572 | var IterablePrototype = Iterable.prototype;
4573 | IterablePrototype[IS_ITERABLE_SENTINEL] = true;
4574 | IterablePrototype[ITERATOR_SYMBOL] = IterablePrototype.values;
4575 | IterablePrototype.__toJS = IterablePrototype.toArray;
4576 | IterablePrototype.__toStringMapper = quoteString;
4577 | IterablePrototype.inspect =
4578 | IterablePrototype.toSource = function() { return this.toString(); };
4579 | IterablePrototype.chain = IterablePrototype.flatMap;
4580 |
4581 | // Temporary warning about using length
4582 | (function () {
4583 | try {
4584 | Object.defineProperty(IterablePrototype, 'length', {
4585 | get: function () {
4586 | if (!Iterable.noLengthWarning) {
4587 | var stack;
4588 | try {
4589 | throw new Error();
4590 | } catch (error) {
4591 | stack = error.stack;
4592 | }
4593 | if (stack.indexOf('_wrapObject') === -1) {
4594 | console && console.warn && console.warn(
4595 | 'iterable.length has been deprecated, '+
4596 | 'use iterable.size or iterable.count(). '+
4597 | 'This warning will become a silent error in a future version. ' +
4598 | stack
4599 | );
4600 | return this.size;
4601 | }
4602 | }
4603 | }
4604 | });
4605 | } catch (e) {}
4606 | })();
4607 |
4608 |
4609 |
4610 | mixin(KeyedIterable, {
4611 |
4612 | // ### More sequential methods
4613 |
4614 | flip: function() {
4615 | return reify(this, flipFactory(this));
4616 | },
4617 |
4618 | findKey: function(predicate, context) {
4619 | var entry = this.findEntry(predicate, context);
4620 | return entry && entry[0];
4621 | },
4622 |
4623 | findLastKey: function(predicate, context) {
4624 | return this.toSeq().reverse().findKey(predicate, context);
4625 | },
4626 |
4627 | keyOf: function(searchValue) {
4628 | return this.findKey(function(value ) {return is(value, searchValue)});
4629 | },
4630 |
4631 | lastKeyOf: function(searchValue) {
4632 | return this.findLastKey(function(value ) {return is(value, searchValue)});
4633 | },
4634 |
4635 | mapEntries: function(mapper, context) {var this$0 = this;
4636 | var iterations = 0;
4637 | return reify(this,
4638 | this.toSeq().map(
4639 | function(v, k) {return mapper.call(context, [k, v], iterations++, this$0)}
4640 | ).fromEntrySeq()
4641 | );
4642 | },
4643 |
4644 | mapKeys: function(mapper, context) {var this$0 = this;
4645 | return reify(this,
4646 | this.toSeq().flip().map(
4647 | function(k, v) {return mapper.call(context, k, v, this$0)}
4648 | ).flip()
4649 | );
4650 | },
4651 |
4652 | });
4653 |
4654 | var KeyedIterablePrototype = KeyedIterable.prototype;
4655 | KeyedIterablePrototype[IS_KEYED_SENTINEL] = true;
4656 | KeyedIterablePrototype[ITERATOR_SYMBOL] = IterablePrototype.entries;
4657 | KeyedIterablePrototype.__toJS = IterablePrototype.toObject;
4658 | KeyedIterablePrototype.__toStringMapper = function(v, k) {return JSON.stringify(k) + ': ' + quoteString(v)};
4659 |
4660 |
4661 |
4662 | mixin(IndexedIterable, {
4663 |
4664 | // ### Conversion to other types
4665 |
4666 | toKeyedSeq: function() {
4667 | return new ToKeyedSequence(this, false);
4668 | },
4669 |
4670 |
4671 | // ### ES6 Collection methods (ES6 Array and Map)
4672 |
4673 | filter: function(predicate, context) {
4674 | return reify(this, filterFactory(this, predicate, context, false));
4675 | },
4676 |
4677 | findIndex: function(predicate, context) {
4678 | var entry = this.findEntry(predicate, context);
4679 | return entry ? entry[0] : -1;
4680 | },
4681 |
4682 | indexOf: function(searchValue) {
4683 | var key = this.toKeyedSeq().keyOf(searchValue);
4684 | return key === undefined ? -1 : key;
4685 | },
4686 |
4687 | lastIndexOf: function(searchValue) {
4688 | return this.toSeq().reverse().indexOf(searchValue);
4689 | },
4690 |
4691 | reverse: function() {
4692 | return reify(this, reverseFactory(this, false));
4693 | },
4694 |
4695 | slice: function(begin, end) {
4696 | return reify(this, sliceFactory(this, begin, end, false));
4697 | },
4698 |
4699 | splice: function(index, removeNum /*, ...values*/) {
4700 | var numArgs = arguments.length;
4701 | removeNum = Math.max(removeNum | 0, 0);
4702 | if (numArgs === 0 || (numArgs === 2 && !removeNum)) {
4703 | return this;
4704 | }
4705 | index = resolveBegin(index, this.size);
4706 | var spliced = this.slice(0, index);
4707 | return reify(
4708 | this,
4709 | numArgs === 1 ?
4710 | spliced :
4711 | spliced.concat(arrCopy(arguments, 2), this.slice(index + removeNum))
4712 | );
4713 | },
4714 |
4715 |
4716 | // ### More collection methods
4717 |
4718 | findLastIndex: function(predicate, context) {
4719 | var key = this.toKeyedSeq().findLastKey(predicate, context);
4720 | return key === undefined ? -1 : key;
4721 | },
4722 |
4723 | first: function() {
4724 | return this.get(0);
4725 | },
4726 |
4727 | flatten: function(depth) {
4728 | return reify(this, flattenFactory(this, depth, false));
4729 | },
4730 |
4731 | get: function(index, notSetValue) {
4732 | index = wrapIndex(this, index);
4733 | return (index < 0 || (this.size === Infinity ||
4734 | (this.size !== undefined && index > this.size))) ?
4735 | notSetValue :
4736 | this.find(function(_, key) {return key === index}, undefined, notSetValue);
4737 | },
4738 |
4739 | has: function(index) {
4740 | index = wrapIndex(this, index);
4741 | return index >= 0 && (this.size !== undefined ?
4742 | this.size === Infinity || index < this.size :
4743 | this.indexOf(index) !== -1
4744 | );
4745 | },
4746 |
4747 | interpose: function(separator) {
4748 | return reify(this, interposeFactory(this, separator));
4749 | },
4750 |
4751 | interleave: function(/*...iterables*/) {
4752 | var iterables = [this].concat(arrCopy(arguments));
4753 | var zipped = zipWithFactory(this.toSeq(), IndexedSeq.of, iterables);
4754 | var interleaved = zipped.flatten(true);
4755 | if (zipped.size) {
4756 | interleaved.size = zipped.size * iterables.length;
4757 | }
4758 | return reify(this, interleaved);
4759 | },
4760 |
4761 | last: function() {
4762 | return this.get(-1);
4763 | },
4764 |
4765 | skipWhile: function(predicate, context) {
4766 | return reify(this, skipWhileFactory(this, predicate, context, false));
4767 | },
4768 |
4769 | zip: function(/*, ...iterables */) {
4770 | var iterables = [this].concat(arrCopy(arguments));
4771 | return reify(this, zipWithFactory(this, defaultZipper, iterables));
4772 | },
4773 |
4774 | zipWith: function(zipper/*, ...iterables */) {
4775 | var iterables = arrCopy(arguments);
4776 | iterables[0] = this;
4777 | return reify(this, zipWithFactory(this, zipper, iterables));
4778 | },
4779 |
4780 | });
4781 |
4782 | IndexedIterable.prototype[IS_INDEXED_SENTINEL] = true;
4783 | IndexedIterable.prototype[IS_ORDERED_SENTINEL] = true;
4784 |
4785 |
4786 |
4787 | mixin(SetIterable, {
4788 |
4789 | // ### ES6 Collection methods (ES6 Array and Map)
4790 |
4791 | get: function(value, notSetValue) {
4792 | return this.has(value) ? value : notSetValue;
4793 | },
4794 |
4795 | includes: function(value) {
4796 | return this.has(value);
4797 | },
4798 |
4799 |
4800 | // ### More sequential methods
4801 |
4802 | keySeq: function() {
4803 | return this.valueSeq();
4804 | },
4805 |
4806 | });
4807 |
4808 | SetIterable.prototype.has = IterablePrototype.includes;
4809 |
4810 |
4811 | // Mixin subclasses
4812 |
4813 | mixin(KeyedSeq, KeyedIterable.prototype);
4814 | mixin(IndexedSeq, IndexedIterable.prototype);
4815 | mixin(SetSeq, SetIterable.prototype);
4816 |
4817 | mixin(KeyedCollection, KeyedIterable.prototype);
4818 | mixin(IndexedCollection, IndexedIterable.prototype);
4819 | mixin(SetCollection, SetIterable.prototype);
4820 |
4821 |
4822 | // #pragma Helper functions
4823 |
4824 | function keyMapper(v, k) {
4825 | return k;
4826 | }
4827 |
4828 | function entryMapper(v, k) {
4829 | return [k, v];
4830 | }
4831 |
4832 | function not(predicate) {
4833 | return function() {
4834 | return !predicate.apply(this, arguments);
4835 | }
4836 | }
4837 |
4838 | function neg(predicate) {
4839 | return function() {
4840 | return -predicate.apply(this, arguments);
4841 | }
4842 | }
4843 |
4844 | function quoteString(value) {
4845 | return typeof value === 'string' ? JSON.stringify(value) : value;
4846 | }
4847 |
4848 | function defaultZipper() {
4849 | return arrCopy(arguments);
4850 | }
4851 |
4852 | function defaultNegComparator(a, b) {
4853 | return a < b ? 1 : a > b ? -1 : 0;
4854 | }
4855 |
4856 | function hashIterable(iterable) {
4857 | if (iterable.size === Infinity) {
4858 | return 0;
4859 | }
4860 | var ordered = isOrdered(iterable);
4861 | var keyed = isKeyed(iterable);
4862 | var h = ordered ? 1 : 0;
4863 | var size = iterable.__iterate(
4864 | keyed ?
4865 | ordered ?
4866 | function(v, k) { h = 31 * h + hashMerge(hash(v), hash(k)) | 0; } :
4867 | function(v, k) { h = h + hashMerge(hash(v), hash(k)) | 0; } :
4868 | ordered ?
4869 | function(v ) { h = 31 * h + hash(v) | 0; } :
4870 | function(v ) { h = h + hash(v) | 0; }
4871 | );
4872 | return murmurHashOfSize(size, h);
4873 | }
4874 |
4875 | function murmurHashOfSize(size, h) {
4876 | h = src_Math__imul(h, 0xCC9E2D51);
4877 | h = src_Math__imul(h << 15 | h >>> -15, 0x1B873593);
4878 | h = src_Math__imul(h << 13 | h >>> -13, 5);
4879 | h = (h + 0xE6546B64 | 0) ^ size;
4880 | h = src_Math__imul(h ^ h >>> 16, 0x85EBCA6B);
4881 | h = src_Math__imul(h ^ h >>> 13, 0xC2B2AE35);
4882 | h = smi(h ^ h >>> 16);
4883 | return h;
4884 | }
4885 |
4886 | function hashMerge(a, b) {
4887 | return a ^ b + 0x9E3779B9 + (a << 6) + (a >> 2) | 0; // int
4888 | }
4889 |
4890 | var Immutable = {
4891 |
4892 | Iterable: Iterable,
4893 |
4894 | Seq: Seq,
4895 | Collection: Collection,
4896 | Map: src_Map__Map,
4897 | OrderedMap: OrderedMap,
4898 | List: List,
4899 | Stack: Stack,
4900 | Set: src_Set__Set,
4901 | OrderedSet: OrderedSet,
4902 |
4903 | Record: Record,
4904 | Range: Range,
4905 | Repeat: Repeat,
4906 |
4907 | is: is,
4908 | fromJS: fromJS,
4909 |
4910 | };
4911 |
4912 | return Immutable;
4913 |
4914 | }));
--------------------------------------------------------------------------------