ember-source 2.6.1 → 2.6.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -6,7 +6,7 @@
6
6
  * Portions Copyright 2008-2011 Apple Inc. All rights reserved.
7
7
  * @license Licensed under MIT license
8
8
  * See https://raw.github.com/emberjs/ember.js/master/LICENSE
9
- * @version 2.6.1
9
+ * @version 2.6.2
10
10
  */
11
11
 
12
12
  var enifed, requireModule, require, Ember;
@@ -113,1045 +113,1045 @@ var mainContext = this;
113
113
  }
114
114
  })();
115
115
 
116
- enifed("backburner/binary-search", ["exports"], function (exports) {
117
- "use strict";
116
+ enifed('backburner', ['exports', 'backburner/utils', 'backburner/platform', 'backburner/binary-search', 'backburner/deferred-action-queues'], function (exports, _backburnerUtils, _backburnerPlatform, _backburnerBinarySearch, _backburnerDeferredActionQueues) {
117
+ 'use strict';
118
118
 
119
- exports.default = binarySearch;
119
+ exports.default = Backburner;
120
120
 
121
- function binarySearch(time, timers) {
122
- var start = 0;
123
- var end = timers.length - 2;
124
- var middle, l;
121
+ function Backburner(queueNames, options) {
122
+ this.queueNames = queueNames;
123
+ this.options = options || {};
124
+ if (!this.options.defaultQueue) {
125
+ this.options.defaultQueue = queueNames[0];
126
+ }
127
+ this.instanceStack = [];
128
+ this._debouncees = [];
129
+ this._throttlers = [];
130
+ this._eventCallbacks = {
131
+ end: [],
132
+ begin: []
133
+ };
125
134
 
126
- while (start < end) {
127
- // since timers is an array of pairs 'l' will always
128
- // be an integer
129
- l = (end - start) / 2;
135
+ var _this = this;
136
+ this._boundClearItems = function () {
137
+ clearItems();
138
+ };
130
139
 
131
- // compensate for the index in case even number
132
- // of pairs inside timers
133
- middle = start + l - l % 2;
140
+ this._timerTimeoutId = undefined;
141
+ this._timers = [];
134
142
 
135
- if (time >= timers[middle]) {
136
- start = middle + 2;
137
- } else {
138
- end = middle;
139
- }
140
- }
143
+ this._platform = this.options._platform || _backburnerPlatform.default;
141
144
 
142
- return time >= timers[start] ? start + 2 : start;
145
+ this._boundRunExpiredTimers = function () {
146
+ _this._runExpiredTimers();
147
+ };
143
148
  }
144
- });
145
- enifed('backburner/deferred-action-queues', ['exports', 'backburner/utils', 'backburner/queue'], function (exports, _backburnerUtils, _backburnerQueue) {
146
- 'use strict';
147
149
 
148
- exports.default = DeferredActionQueues;
149
-
150
- function DeferredActionQueues(queueNames, options) {
151
- var queues = this.queues = {};
152
- this.queueNames = queueNames = queueNames || [];
150
+ Backburner.prototype = {
151
+ begin: function () {
152
+ var options = this.options;
153
+ var onBegin = options && options.onBegin;
154
+ var previousInstance = this.currentInstance;
153
155
 
154
- this.options = options;
156
+ if (previousInstance) {
157
+ this.instanceStack.push(previousInstance);
158
+ }
155
159
 
156
- _backburnerUtils.each(queueNames, function (queueName) {
157
- queues[queueName] = new _backburnerQueue.default(queueName, options[queueName], options);
158
- });
159
- }
160
+ this.currentInstance = new _backburnerDeferredActionQueues.default(this.queueNames, options);
161
+ this._trigger('begin', this.currentInstance, previousInstance);
162
+ if (onBegin) {
163
+ onBegin(this.currentInstance, previousInstance);
164
+ }
165
+ },
160
166
 
161
- function noSuchQueue(name) {
162
- throw new Error('You attempted to schedule an action in a queue (' + name + ') that doesn\'t exist');
163
- }
167
+ end: function () {
168
+ var options = this.options;
169
+ var onEnd = options && options.onEnd;
170
+ var currentInstance = this.currentInstance;
171
+ var nextInstance = null;
164
172
 
165
- function noSuchMethod(name) {
166
- throw new Error('You attempted to schedule an action in a queue (' + name + ') for a method that doesn\'t exist');
167
- }
173
+ // Prevent double-finally bug in Safari 6.0.2 and iOS 6
174
+ // This bug appears to be resolved in Safari 6.0.5 and iOS 7
175
+ var finallyAlreadyCalled = false;
176
+ try {
177
+ currentInstance.flush();
178
+ } finally {
179
+ if (!finallyAlreadyCalled) {
180
+ finallyAlreadyCalled = true;
168
181
 
169
- DeferredActionQueues.prototype = {
170
- schedule: function (name, target, method, args, onceFlag, stack) {
171
- var queues = this.queues;
172
- var queue = queues[name];
182
+ this.currentInstance = null;
173
183
 
174
- if (!queue) {
175
- noSuchQueue(name);
184
+ if (this.instanceStack.length) {
185
+ nextInstance = this.instanceStack.pop();
186
+ this.currentInstance = nextInstance;
187
+ }
188
+ this._trigger('end', currentInstance, nextInstance);
189
+ if (onEnd) {
190
+ onEnd(currentInstance, nextInstance);
191
+ }
192
+ }
176
193
  }
194
+ },
177
195
 
178
- if (!method) {
179
- noSuchMethod(name);
196
+ /**
197
+ Trigger an event. Supports up to two arguments. Designed around
198
+ triggering transition events from one run loop instance to the
199
+ next, which requires an argument for the first instance and then
200
+ an argument for the next instance.
201
+ @private
202
+ @method _trigger
203
+ @param {String} eventName
204
+ @param {any} arg1
205
+ @param {any} arg2
206
+ */
207
+ _trigger: function (eventName, arg1, arg2) {
208
+ var callbacks = this._eventCallbacks[eventName];
209
+ if (callbacks) {
210
+ for (var i = 0; i < callbacks.length; i++) {
211
+ callbacks[i](arg1, arg2);
212
+ }
180
213
  }
214
+ },
181
215
 
182
- if (onceFlag) {
183
- return queue.pushUnique(target, method, args, stack);
216
+ on: function (eventName, callback) {
217
+ if (typeof callback !== 'function') {
218
+ throw new TypeError('Callback must be a function');
219
+ }
220
+ var callbacks = this._eventCallbacks[eventName];
221
+ if (callbacks) {
222
+ callbacks.push(callback);
184
223
  } else {
185
- return queue.push(target, method, args, stack);
224
+ throw new TypeError('Cannot on() event "' + eventName + '" because it does not exist');
186
225
  }
187
226
  },
188
227
 
189
- flush: function () {
190
- var queues = this.queues;
191
- var queueNames = this.queueNames;
192
- var queueName, queue;
193
- var queueNameIndex = 0;
194
- var numberOfQueues = queueNames.length;
195
-
196
- while (queueNameIndex < numberOfQueues) {
197
- queueName = queueNames[queueNameIndex];
198
- queue = queues[queueName];
199
-
200
- var numberOfQueueItems = queue._queue.length;
201
-
202
- if (numberOfQueueItems === 0) {
203
- queueNameIndex++;
204
- } else {
205
- queue.flush(false /* async */);
206
- queueNameIndex = 0;
228
+ off: function (eventName, callback) {
229
+ if (eventName) {
230
+ var callbacks = this._eventCallbacks[eventName];
231
+ var callbackFound = false;
232
+ if (!callbacks) return;
233
+ if (callback) {
234
+ for (var i = 0; i < callbacks.length; i++) {
235
+ if (callbacks[i] === callback) {
236
+ callbackFound = true;
237
+ callbacks.splice(i, 1);
238
+ i--;
239
+ }
240
+ }
207
241
  }
242
+ if (!callbackFound) {
243
+ throw new TypeError('Cannot off() callback that does not exist');
244
+ }
245
+ } else {
246
+ throw new TypeError('Cannot off() event "' + eventName + '" because it does not exist');
208
247
  }
209
- }
210
- };
211
- });
212
- enifed('backburner/platform', ['exports'], function (exports) {
213
- 'use strict';
248
+ },
214
249
 
215
- var GlobalContext;
250
+ run: function () /* target, method, args */{
251
+ var length = arguments.length;
252
+ var method, target, args;
216
253
 
217
- /* global self */
218
- if (typeof self === 'object') {
219
- GlobalContext = self;
254
+ if (length === 1) {
255
+ method = arguments[0];
256
+ target = null;
257
+ } else {
258
+ target = arguments[0];
259
+ method = arguments[1];
260
+ }
220
261
 
221
- /* global global */
222
- } else if (typeof global === 'object') {
223
- GlobalContext = global;
262
+ if (_backburnerUtils.isString(method)) {
263
+ method = target[method];
264
+ }
224
265
 
225
- /* global window */
226
- } else if (typeof window === 'object') {
227
- GlobalContext = window;
266
+ if (length > 2) {
267
+ args = new Array(length - 2);
268
+ for (var i = 0, l = length - 2; i < l; i++) {
269
+ args[i] = arguments[i + 2];
270
+ }
228
271
  } else {
229
- throw new Error('no global: `self`, `global` nor `window` was found');
272
+ args = [];
230
273
  }
231
274
 
232
- exports.default = GlobalContext;
233
- });
234
- enifed('backburner/queue', ['exports', 'backburner/utils'], function (exports, _backburnerUtils) {
235
- 'use strict';
236
-
237
- exports.default = Queue;
275
+ var onError = getOnError(this.options);
238
276
 
239
- function Queue(name, options, globalOptions) {
240
- this.name = name;
241
- this.globalOptions = globalOptions || {};
242
- this.options = options;
243
- this._queue = [];
244
- this.targetQueues = {};
245
- this._queueBeingFlushed = undefined;
246
- }
277
+ this.begin();
247
278
 
248
- Queue.prototype = {
249
- push: function (target, method, args, stack) {
250
- var queue = this._queue;
251
- queue.push(target, method, args, stack);
279
+ // guard against Safari 6's double-finally bug
280
+ var didFinally = false;
252
281
 
253
- return {
254
- queue: this,
255
- target: target,
256
- method: method
257
- };
282
+ if (onError) {
283
+ try {
284
+ return method.apply(target, args);
285
+ } catch (error) {
286
+ onError(error);
287
+ } finally {
288
+ if (!didFinally) {
289
+ didFinally = true;
290
+ this.end();
291
+ }
292
+ }
293
+ } else {
294
+ try {
295
+ return method.apply(target, args);
296
+ } finally {
297
+ if (!didFinally) {
298
+ didFinally = true;
299
+ this.end();
300
+ }
301
+ }
302
+ }
258
303
  },
259
304
 
260
- pushUniqueWithoutGuid: function (target, method, args, stack) {
261
- var queue = this._queue;
262
-
263
- for (var i = 0, l = queue.length; i < l; i += 4) {
264
- var currentTarget = queue[i];
265
- var currentMethod = queue[i + 1];
266
-
267
- if (currentTarget === target && currentMethod === method) {
268
- queue[i + 2] = args; // replace args
269
- queue[i + 3] = stack; // replace stack
270
- return;
271
- }
305
+ /*
306
+ Join the passed method with an existing queue and execute immediately,
307
+ if there isn't one use `Backburner#run`.
308
+ The join method is like the run method except that it will schedule into
309
+ an existing queue if one already exists. In either case, the join method will
310
+ immediately execute the passed in function and return its result.
311
+ @method join
312
+ @param {Object} target
313
+ @param {Function} method The method to be executed
314
+ @param {any} args The method arguments
315
+ @return method result
316
+ */
317
+ join: function () /* target, method, args */{
318
+ if (!this.currentInstance) {
319
+ return this.run.apply(this, arguments);
272
320
  }
273
321
 
274
- queue.push(target, method, args, stack);
275
- },
322
+ var length = arguments.length;
323
+ var method, target;
276
324
 
277
- targetQueue: function (targetQueue, target, method, args, stack) {
278
- var queue = this._queue;
325
+ if (length === 1) {
326
+ method = arguments[0];
327
+ target = null;
328
+ } else {
329
+ target = arguments[0];
330
+ method = arguments[1];
331
+ }
279
332
 
280
- for (var i = 0, l = targetQueue.length; i < l; i += 2) {
281
- var currentMethod = targetQueue[i];
282
- var currentIndex = targetQueue[i + 1];
333
+ if (_backburnerUtils.isString(method)) {
334
+ method = target[method];
335
+ }
283
336
 
284
- if (currentMethod === method) {
285
- queue[currentIndex + 2] = args; // replace args
286
- queue[currentIndex + 3] = stack; // replace stack
287
- return;
337
+ if (length === 1) {
338
+ return method();
339
+ } else if (length === 2) {
340
+ return method.call(target);
341
+ } else {
342
+ var args = new Array(length - 2);
343
+ for (var i = 0, l = length - 2; i < l; i++) {
344
+ args[i] = arguments[i + 2];
288
345
  }
346
+ return method.apply(target, args);
289
347
  }
290
-
291
- targetQueue.push(method, queue.push(target, method, args, stack) - 4);
292
348
  },
293
349
 
294
- pushUniqueWithGuid: function (guid, target, method, args, stack) {
295
- var hasLocalQueue = this.targetQueues[guid];
350
+ /*
351
+ Defer the passed function to run inside the specified queue.
352
+ @method defer
353
+ @param {String} queueName
354
+ @param {Object} target
355
+ @param {Function|String} method The method or method name to be executed
356
+ @param {any} args The method arguments
357
+ @return method result
358
+ */
359
+ defer: function (queueName /* , target, method, args */) {
360
+ var length = arguments.length;
361
+ var method, target, args;
296
362
 
297
- if (hasLocalQueue) {
298
- this.targetQueue(hasLocalQueue, target, method, args, stack);
363
+ if (length === 2) {
364
+ method = arguments[1];
365
+ target = null;
299
366
  } else {
300
- this.targetQueues[guid] = [method, this._queue.push(target, method, args, stack) - 4];
367
+ target = arguments[1];
368
+ method = arguments[2];
301
369
  }
302
370
 
303
- return {
304
- queue: this,
305
- target: target,
306
- method: method
307
- };
308
- },
371
+ if (_backburnerUtils.isString(method)) {
372
+ method = target[method];
373
+ }
309
374
 
310
- pushUnique: function (target, method, args, stack) {
311
- var KEY = this.globalOptions.GUID_KEY;
375
+ var stack = this.DEBUG ? new Error() : undefined;
312
376
 
313
- if (target && KEY) {
314
- var guid = target[KEY];
315
- if (guid) {
316
- return this.pushUniqueWithGuid(guid, target, method, args, stack);
377
+ if (length > 3) {
378
+ args = new Array(length - 3);
379
+ for (var i = 3; i < length; i++) {
380
+ args[i - 3] = arguments[i];
317
381
  }
382
+ } else {
383
+ args = undefined;
318
384
  }
319
385
 
320
- this.pushUniqueWithoutGuid(target, method, args, stack);
321
-
322
- return {
323
- queue: this,
324
- target: target,
325
- method: method
326
- };
386
+ if (!this.currentInstance) {
387
+ createAutorun(this);
388
+ }
389
+ return this.currentInstance.schedule(queueName, target, method, args, false, stack);
327
390
  },
328
391
 
329
- invoke: function (target, method, args, _, _errorRecordedForStack) {
330
- if (args && args.length > 0) {
331
- method.apply(target, args);
392
+ deferOnce: function (queueName /* , target, method, args */) {
393
+ var length = arguments.length;
394
+ var method, target, args;
395
+
396
+ if (length === 2) {
397
+ method = arguments[1];
398
+ target = null;
332
399
  } else {
333
- method.call(target);
400
+ target = arguments[1];
401
+ method = arguments[2];
334
402
  }
335
- },
336
403
 
337
- invokeWithOnError: function (target, method, args, onError, errorRecordedForStack) {
338
- try {
339
- if (args && args.length > 0) {
340
- method.apply(target, args);
341
- } else {
342
- method.call(target);
343
- }
344
- } catch (error) {
345
- onError(error, errorRecordedForStack);
404
+ if (_backburnerUtils.isString(method)) {
405
+ method = target[method];
346
406
  }
347
- },
348
407
 
349
- flush: function (sync) {
350
- var queue = this._queue;
351
- var length = queue.length;
408
+ var stack = this.DEBUG ? new Error() : undefined;
352
409
 
353
- if (length === 0) {
354
- return;
410
+ if (length > 3) {
411
+ args = new Array(length - 3);
412
+ for (var i = 3; i < length; i++) {
413
+ args[i - 3] = arguments[i];
414
+ }
415
+ } else {
416
+ args = undefined;
355
417
  }
356
418
 
357
- var globalOptions = this.globalOptions;
358
- var options = this.options;
359
- var before = options && options.before;
360
- var after = options && options.after;
361
- var onError = globalOptions.onError || globalOptions.onErrorTarget && globalOptions.onErrorTarget[globalOptions.onErrorMethod];
362
- var target, method, args, errorRecordedForStack;
363
- var invoke = onError ? this.invokeWithOnError : this.invoke;
419
+ if (!this.currentInstance) {
420
+ createAutorun(this);
421
+ }
422
+ return this.currentInstance.schedule(queueName, target, method, args, true, stack);
423
+ },
364
424
 
365
- this.targetQueues = Object.create(null);
366
- var queueItems = this._queueBeingFlushed = this._queue.slice();
367
- this._queue = [];
425
+ setTimeout: function () {
426
+ var l = arguments.length;
427
+ var args = new Array(l);
368
428
 
369
- if (before) {
370
- before();
429
+ for (var x = 0; x < l; x++) {
430
+ args[x] = arguments[x];
371
431
  }
372
432
 
373
- for (var i = 0; i < length; i += 4) {
374
- target = queueItems[i];
375
- method = queueItems[i + 1];
376
- args = queueItems[i + 2];
377
- errorRecordedForStack = queueItems[i + 3]; // Debugging assistance
433
+ var length = args.length,
434
+ method,
435
+ wait,
436
+ target,
437
+ methodOrTarget,
438
+ methodOrWait,
439
+ methodOrArgs;
378
440
 
379
- if (_backburnerUtils.isString(method)) {
380
- method = target[method];
381
- }
441
+ if (length === 0) {
442
+ return;
443
+ } else if (length === 1) {
444
+ method = args.shift();
445
+ wait = 0;
446
+ } else if (length === 2) {
447
+ methodOrTarget = args[0];
448
+ methodOrWait = args[1];
382
449
 
383
- // method could have been nullified / canceled during flush
384
- if (method) {
385
- //
386
- // ** Attention intrepid developer **
387
- //
388
- // To find out the stack of this task when it was scheduled onto
389
- // the run loop, add the following to your app.js:
390
- //
391
- // Ember.run.backburner.DEBUG = true; // NOTE: This slows your app, don't leave it on in production.
392
- //
393
- // Once that is in place, when you are at a breakpoint and navigate
394
- // here in the stack explorer, you can look at `errorRecordedForStack.stack`,
395
- // which will be the captured stack when this job was scheduled.
396
- //
397
- invoke(target, method, args, onError, errorRecordedForStack);
450
+ if (_backburnerUtils.isFunction(methodOrWait) || _backburnerUtils.isFunction(methodOrTarget[methodOrWait])) {
451
+ target = args.shift();
452
+ method = args.shift();
453
+ wait = 0;
454
+ } else if (_backburnerUtils.isCoercableNumber(methodOrWait)) {
455
+ method = args.shift();
456
+ wait = args.shift();
457
+ } else {
458
+ method = args.shift();
459
+ wait = 0;
398
460
  }
399
- }
461
+ } else {
462
+ var last = args[args.length - 1];
400
463
 
401
- if (after) {
402
- after();
403
- }
464
+ if (_backburnerUtils.isCoercableNumber(last)) {
465
+ wait = args.pop();
466
+ } else {
467
+ wait = 0;
468
+ }
404
469
 
405
- this._queueBeingFlushed = undefined;
470
+ methodOrTarget = args[0];
471
+ methodOrArgs = args[1];
406
472
 
407
- if (sync !== false && this._queue.length > 0) {
408
- // check if new items have been added
409
- this.flush(true);
473
+ if (_backburnerUtils.isFunction(methodOrArgs) || _backburnerUtils.isString(methodOrArgs) && methodOrTarget !== null && methodOrArgs in methodOrTarget) {
474
+ target = args.shift();
475
+ method = args.shift();
476
+ } else {
477
+ method = args.shift();
478
+ }
410
479
  }
411
- },
412
-
413
- cancel: function (actionToCancel) {
414
- var queue = this._queue,
415
- currentTarget,
416
- currentMethod,
417
- i,
418
- l;
419
- var target = actionToCancel.target;
420
- var method = actionToCancel.method;
421
- var GUID_KEY = this.globalOptions.GUID_KEY;
422
480
 
423
- if (GUID_KEY && this.targetQueues && target) {
424
- var targetQueue = this.targetQueues[target[GUID_KEY]];
481
+ var executeAt = Date.now() + parseInt(wait !== wait ? 0 : wait, 10);
425
482
 
426
- if (targetQueue) {
427
- for (i = 0, l = targetQueue.length; i < l; i++) {
428
- if (targetQueue[i] === method) {
429
- targetQueue.splice(i, 1);
430
- }
431
- }
432
- }
483
+ if (_backburnerUtils.isString(method)) {
484
+ method = target[method];
433
485
  }
434
486
 
435
- for (i = 0, l = queue.length; i < l; i += 4) {
436
- currentTarget = queue[i];
437
- currentMethod = queue[i + 1];
487
+ var onError = getOnError(this.options);
438
488
 
439
- if (currentTarget === target && currentMethod === method) {
440
- queue.splice(i, 4);
441
- return true;
489
+ function fn() {
490
+ if (onError) {
491
+ try {
492
+ method.apply(target, args);
493
+ } catch (e) {
494
+ onError(e);
495
+ }
496
+ } else {
497
+ method.apply(target, args);
442
498
  }
443
499
  }
444
500
 
445
- // if not found in current queue
446
- // could be in the queue that is being flushed
447
- queue = this._queueBeingFlushed;
501
+ return this._setTimeout(fn, executeAt);
502
+ },
448
503
 
449
- if (!queue) {
450
- return;
504
+ _setTimeout: function (fn, executeAt) {
505
+ if (this._timers.length === 0) {
506
+ this._timers.push(executeAt, fn);
507
+ this._installTimerTimeout();
508
+ return fn;
451
509
  }
452
510
 
453
- for (i = 0, l = queue.length; i < l; i += 4) {
454
- currentTarget = queue[i];
455
- currentMethod = queue[i + 1];
511
+ // find position to insert
512
+ var i = _backburnerBinarySearch.default(executeAt, this._timers);
456
513
 
457
- if (currentTarget === target && currentMethod === method) {
458
- // don't mess with array during flush
459
- // just nullify the method
460
- queue[i + 1] = null;
461
- return true;
462
- }
514
+ this._timers.splice(i, 0, executeAt, fn);
515
+
516
+ // we should be the new earliest timer if i == 0
517
+ if (i === 0) {
518
+ this._reinstallTimerTimeout();
463
519
  }
464
- }
465
- };
466
- });
467
- enifed('backburner/utils', ['exports'], function (exports) {
468
- 'use strict';
469
520
 
470
- exports.each = each;
471
- exports.isString = isString;
472
- exports.isFunction = isFunction;
473
- exports.isNumber = isNumber;
474
- exports.isCoercableNumber = isCoercableNumber;
475
- var NUMBER = /\d+/;
521
+ return fn;
522
+ },
476
523
 
477
- function each(collection, callback) {
478
- for (var i = 0; i < collection.length; i++) {
479
- callback(collection[i]);
480
- }
481
- }
524
+ throttle: function (target, method /* , args, wait, [immediate] */) {
525
+ var backburner = this;
526
+ var args = new Array(arguments.length);
527
+ for (var i = 0; i < arguments.length; i++) {
528
+ args[i] = arguments[i];
529
+ }
530
+ var immediate = args.pop();
531
+ var wait, throttler, index, timer;
482
532
 
483
- function isString(suspect) {
484
- return typeof suspect === 'string';
485
- }
533
+ if (_backburnerUtils.isNumber(immediate) || _backburnerUtils.isString(immediate)) {
534
+ wait = immediate;
535
+ immediate = true;
536
+ } else {
537
+ wait = args.pop();
538
+ }
486
539
 
487
- function isFunction(suspect) {
488
- return typeof suspect === 'function';
489
- }
540
+ wait = parseInt(wait, 10);
490
541
 
491
- function isNumber(suspect) {
492
- return typeof suspect === 'number';
493
- }
542
+ index = findThrottler(target, method, this._throttlers);
543
+ if (index > -1) {
544
+ return this._throttlers[index];
545
+ } // throttled
494
546
 
495
- function isCoercableNumber(number) {
496
- return isNumber(number) || NUMBER.test(number);
497
- }
498
- });
499
- enifed('backburner', ['exports', 'backburner/utils', 'backburner/platform', 'backburner/binary-search', 'backburner/deferred-action-queues'], function (exports, _backburnerUtils, _backburnerPlatform, _backburnerBinarySearch, _backburnerDeferredActionQueues) {
500
- 'use strict';
547
+ timer = this._platform.setTimeout(function () {
548
+ if (!immediate) {
549
+ backburner.run.apply(backburner, args);
550
+ }
551
+ var index = findThrottler(target, method, backburner._throttlers);
552
+ if (index > -1) {
553
+ backburner._throttlers.splice(index, 1);
554
+ }
555
+ }, wait);
501
556
 
502
- exports.default = Backburner;
557
+ if (immediate) {
558
+ this.run.apply(this, args);
559
+ }
503
560
 
504
- function Backburner(queueNames, options) {
505
- this.queueNames = queueNames;
506
- this.options = options || {};
507
- if (!this.options.defaultQueue) {
508
- this.options.defaultQueue = queueNames[0];
509
- }
510
- this.instanceStack = [];
511
- this._debouncees = [];
512
- this._throttlers = [];
513
- this._eventCallbacks = {
514
- end: [],
515
- begin: []
516
- };
561
+ throttler = [target, method, timer];
517
562
 
518
- var _this = this;
519
- this._boundClearItems = function () {
520
- clearItems();
521
- };
563
+ this._throttlers.push(throttler);
522
564
 
523
- this._timerTimeoutId = undefined;
524
- this._timers = [];
565
+ return throttler;
566
+ },
525
567
 
526
- this._platform = this.options._platform || _backburnerPlatform.default;
568
+ debounce: function (target, method /* , args, wait, [immediate] */) {
569
+ var backburner = this;
570
+ var args = new Array(arguments.length);
571
+ for (var i = 0; i < arguments.length; i++) {
572
+ args[i] = arguments[i];
573
+ }
527
574
 
528
- this._boundRunExpiredTimers = function () {
529
- _this._runExpiredTimers();
530
- };
531
- }
575
+ var immediate = args.pop();
576
+ var wait, index, debouncee, timer;
532
577
 
533
- Backburner.prototype = {
534
- begin: function () {
535
- var options = this.options;
536
- var onBegin = options && options.onBegin;
537
- var previousInstance = this.currentInstance;
578
+ if (_backburnerUtils.isNumber(immediate) || _backburnerUtils.isString(immediate)) {
579
+ wait = immediate;
580
+ immediate = false;
581
+ } else {
582
+ wait = args.pop();
583
+ }
538
584
 
539
- if (previousInstance) {
540
- this.instanceStack.push(previousInstance);
585
+ wait = parseInt(wait, 10);
586
+ // Remove debouncee
587
+ index = findDebouncee(target, method, this._debouncees);
588
+
589
+ if (index > -1) {
590
+ debouncee = this._debouncees[index];
591
+ this._debouncees.splice(index, 1);
592
+ this._platform.clearTimeout(debouncee[2]);
541
593
  }
542
594
 
543
- this.currentInstance = new _backburnerDeferredActionQueues.default(this.queueNames, options);
544
- this._trigger('begin', this.currentInstance, previousInstance);
545
- if (onBegin) {
546
- onBegin(this.currentInstance, previousInstance);
595
+ timer = this._platform.setTimeout(function () {
596
+ if (!immediate) {
597
+ backburner.run.apply(backburner, args);
598
+ }
599
+ var index = findDebouncee(target, method, backburner._debouncees);
600
+ if (index > -1) {
601
+ backburner._debouncees.splice(index, 1);
602
+ }
603
+ }, wait);
604
+
605
+ if (immediate && index === -1) {
606
+ backburner.run.apply(backburner, args);
547
607
  }
608
+
609
+ debouncee = [target, method, timer];
610
+
611
+ backburner._debouncees.push(debouncee);
612
+
613
+ return debouncee;
548
614
  },
549
615
 
550
- end: function () {
551
- var options = this.options;
552
- var onEnd = options && options.onEnd;
553
- var currentInstance = this.currentInstance;
554
- var nextInstance = null;
616
+ cancelTimers: function () {
617
+ _backburnerUtils.each(this._throttlers, this._boundClearItems);
618
+ this._throttlers = [];
555
619
 
556
- // Prevent double-finally bug in Safari 6.0.2 and iOS 6
557
- // This bug appears to be resolved in Safari 6.0.5 and iOS 7
558
- var finallyAlreadyCalled = false;
559
- try {
560
- currentInstance.flush();
561
- } finally {
562
- if (!finallyAlreadyCalled) {
563
- finallyAlreadyCalled = true;
620
+ _backburnerUtils.each(this._debouncees, this._boundClearItems);
621
+ this._debouncees = [];
564
622
 
565
- this.currentInstance = null;
623
+ this._clearTimerTimeout();
624
+ this._timers = [];
566
625
 
567
- if (this.instanceStack.length) {
568
- nextInstance = this.instanceStack.pop();
569
- this.currentInstance = nextInstance;
570
- }
571
- this._trigger('end', currentInstance, nextInstance);
572
- if (onEnd) {
573
- onEnd(currentInstance, nextInstance);
574
- }
575
- }
626
+ if (this._autorun) {
627
+ this._platform.clearTimeout(this._autorun);
628
+ this._autorun = null;
576
629
  }
577
630
  },
578
631
 
579
- /**
580
- Trigger an event. Supports up to two arguments. Designed around
581
- triggering transition events from one run loop instance to the
582
- next, which requires an argument for the first instance and then
583
- an argument for the next instance.
584
- @private
585
- @method _trigger
586
- @param {String} eventName
587
- @param {any} arg1
588
- @param {any} arg2
589
- */
590
- _trigger: function (eventName, arg1, arg2) {
591
- var callbacks = this._eventCallbacks[eventName];
592
- if (callbacks) {
593
- for (var i = 0; i < callbacks.length; i++) {
594
- callbacks[i](arg1, arg2);
595
- }
596
- }
632
+ hasTimers: function () {
633
+ return !!this._timers.length || !!this._debouncees.length || !!this._throttlers.length || this._autorun;
597
634
  },
598
635
 
599
- on: function (eventName, callback) {
600
- if (typeof callback !== 'function') {
601
- throw new TypeError('Callback must be a function');
602
- }
603
- var callbacks = this._eventCallbacks[eventName];
604
- if (callbacks) {
605
- callbacks.push(callback);
606
- } else {
607
- throw new TypeError('Cannot on() event "' + eventName + '" because it does not exist');
608
- }
609
- },
636
+ cancel: function (timer) {
637
+ var timerType = typeof timer;
610
638
 
611
- off: function (eventName, callback) {
612
- if (eventName) {
613
- var callbacks = this._eventCallbacks[eventName];
614
- var callbackFound = false;
615
- if (!callbacks) return;
616
- if (callback) {
617
- for (var i = 0; i < callbacks.length; i++) {
618
- if (callbacks[i] === callback) {
619
- callbackFound = true;
620
- callbacks.splice(i, 1);
621
- i--;
639
+ if (timer && timerType === 'object' && timer.queue && timer.method) {
640
+ // we're cancelling a deferOnce
641
+ return timer.queue.cancel(timer);
642
+ } else if (timerType === 'function') {
643
+ // we're cancelling a setTimeout
644
+ for (var i = 0, l = this._timers.length; i < l; i += 2) {
645
+ if (this._timers[i + 1] === timer) {
646
+ this._timers.splice(i, 2); // remove the two elements
647
+ if (i === 0) {
648
+ this._reinstallTimerTimeout();
622
649
  }
650
+ return true;
623
651
  }
624
652
  }
625
- if (!callbackFound) {
626
- throw new TypeError('Cannot off() callback that does not exist');
627
- }
653
+ } else if (Object.prototype.toString.call(timer) === '[object Array]') {
654
+ // we're cancelling a throttle or debounce
655
+ return this._cancelItem(findThrottler, this._throttlers, timer) || this._cancelItem(findDebouncee, this._debouncees, timer);
628
656
  } else {
629
- throw new TypeError('Cannot off() event "' + eventName + '" because it does not exist');
657
+ return; // timer was null or not a timer
630
658
  }
631
659
  },
632
660
 
633
- run: function () /* target, method, args */{
634
- var length = arguments.length;
635
- var method, target, args;
661
+ _cancelItem: function (findMethod, array, timer) {
662
+ var item, index;
636
663
 
637
- if (length === 1) {
638
- method = arguments[0];
639
- target = null;
640
- } else {
641
- target = arguments[0];
642
- method = arguments[1];
664
+ if (timer.length < 3) {
665
+ return false;
643
666
  }
644
667
 
645
- if (_backburnerUtils.isString(method)) {
646
- method = target[method];
647
- }
668
+ index = findMethod(timer[0], timer[1], array);
648
669
 
649
- if (length > 2) {
650
- args = new Array(length - 2);
651
- for (var i = 0, l = length - 2; i < l; i++) {
652
- args[i] = arguments[i + 2];
670
+ if (index > -1) {
671
+
672
+ item = array[index];
673
+
674
+ if (item[2] === timer[2]) {
675
+ array.splice(index, 1);
676
+ this._platform.clearTimeout(timer[2]);
677
+ return true;
653
678
  }
654
- } else {
655
- args = [];
656
679
  }
657
680
 
658
- var onError = getOnError(this.options);
659
-
660
- this.begin();
681
+ return false;
682
+ },
661
683
 
662
- // guard against Safari 6's double-finally bug
663
- var didFinally = false;
684
+ _runExpiredTimers: function () {
685
+ this._timerTimeoutId = undefined;
686
+ this.run(this, this._scheduleExpiredTimers);
687
+ },
664
688
 
665
- if (onError) {
666
- try {
667
- return method.apply(target, args);
668
- } catch (error) {
669
- onError(error);
670
- } finally {
671
- if (!didFinally) {
672
- didFinally = true;
673
- this.end();
674
- }
675
- }
676
- } else {
677
- try {
678
- return method.apply(target, args);
679
- } finally {
680
- if (!didFinally) {
681
- didFinally = true;
682
- this.end();
683
- }
689
+ _scheduleExpiredTimers: function () {
690
+ var n = Date.now();
691
+ var timers = this._timers;
692
+ var i = 0;
693
+ var l = timers.length;
694
+ for (; i < l; i += 2) {
695
+ var executeAt = timers[i];
696
+ var fn = timers[i + 1];
697
+ if (executeAt <= n) {
698
+ this.schedule(this.options.defaultQueue, null, fn);
699
+ } else {
700
+ break;
684
701
  }
685
702
  }
703
+ timers.splice(0, i);
704
+ this._installTimerTimeout();
686
705
  },
687
706
 
688
- /*
689
- Join the passed method with an existing queue and execute immediately,
690
- if there isn't one use `Backburner#run`.
691
- The join method is like the run method except that it will schedule into
692
- an existing queue if one already exists. In either case, the join method will
693
- immediately execute the passed in function and return its result.
694
- @method join
695
- @param {Object} target
696
- @param {Function} method The method to be executed
697
- @param {any} args The method arguments
698
- @return method result
699
- */
700
- join: function () /* target, method, args */{
701
- if (!this.currentInstance) {
702
- return this.run.apply(this, arguments);
703
- }
704
-
705
- var length = arguments.length;
706
- var method, target;
707
+ _reinstallTimerTimeout: function () {
708
+ this._clearTimerTimeout();
709
+ this._installTimerTimeout();
710
+ },
707
711
 
708
- if (length === 1) {
709
- method = arguments[0];
710
- target = null;
711
- } else {
712
- target = arguments[0];
713
- method = arguments[1];
712
+ _clearTimerTimeout: function () {
713
+ if (!this._timerTimeoutId) {
714
+ return;
714
715
  }
716
+ this._platform.clearTimeout(this._timerTimeoutId);
717
+ this._timerTimeoutId = undefined;
718
+ },
715
719
 
716
- if (_backburnerUtils.isString(method)) {
717
- method = target[method];
720
+ _installTimerTimeout: function () {
721
+ if (!this._timers.length) {
722
+ return;
718
723
  }
724
+ var minExpiresAt = this._timers[0];
725
+ var n = Date.now();
726
+ var wait = Math.max(0, minExpiresAt - n);
727
+ this._timerTimeoutId = this._platform.setTimeout(this._boundRunExpiredTimers, wait);
728
+ }
729
+ };
719
730
 
720
- if (length === 1) {
721
- return method();
722
- } else if (length === 2) {
723
- return method.call(target);
724
- } else {
725
- var args = new Array(length - 2);
726
- for (var i = 0, l = length - 2; i < l; i++) {
727
- args[i] = arguments[i + 2];
728
- }
729
- return method.apply(target, args);
730
- }
731
- },
731
+ Backburner.prototype.schedule = Backburner.prototype.defer;
732
+ Backburner.prototype.scheduleOnce = Backburner.prototype.deferOnce;
733
+ Backburner.prototype.later = Backburner.prototype.setTimeout;
732
734
 
733
- /*
734
- Defer the passed function to run inside the specified queue.
735
- @method defer
736
- @param {String} queueName
737
- @param {Object} target
738
- @param {Function|String} method The method or method name to be executed
739
- @param {any} args The method arguments
740
- @return method result
741
- */
742
- defer: function (queueName /* , target, method, args */) {
743
- var length = arguments.length;
744
- var method, target, args;
735
+ function getOnError(options) {
736
+ return options.onError || options.onErrorTarget && options.onErrorTarget[options.onErrorMethod];
737
+ }
745
738
 
746
- if (length === 2) {
747
- method = arguments[1];
748
- target = null;
749
- } else {
750
- target = arguments[1];
751
- method = arguments[2];
752
- }
739
+ function createAutorun(backburner) {
740
+ backburner.begin();
741
+ backburner._autorun = backburner._platform.setTimeout(function () {
742
+ backburner._autorun = null;
743
+ backburner.end();
744
+ });
745
+ }
753
746
 
754
- if (_backburnerUtils.isString(method)) {
755
- method = target[method];
756
- }
747
+ function findDebouncee(target, method, debouncees) {
748
+ return findItem(target, method, debouncees);
749
+ }
757
750
 
758
- var stack = this.DEBUG ? new Error() : undefined;
751
+ function findThrottler(target, method, throttlers) {
752
+ return findItem(target, method, throttlers);
753
+ }
759
754
 
760
- if (length > 3) {
761
- args = new Array(length - 3);
762
- for (var i = 3; i < length; i++) {
763
- args[i - 3] = arguments[i];
764
- }
765
- } else {
766
- args = undefined;
767
- }
755
+ function findItem(target, method, collection) {
756
+ var item;
757
+ var index = -1;
768
758
 
769
- if (!this.currentInstance) {
770
- createAutorun(this);
759
+ for (var i = 0, l = collection.length; i < l; i++) {
760
+ item = collection[i];
761
+ if (item[0] === target && item[1] === method) {
762
+ index = i;
763
+ break;
771
764
  }
772
- return this.currentInstance.schedule(queueName, target, method, args, false, stack);
773
- },
765
+ }
774
766
 
775
- deferOnce: function (queueName /* , target, method, args */) {
776
- var length = arguments.length;
777
- var method, target, args;
767
+ return index;
768
+ }
778
769
 
779
- if (length === 2) {
780
- method = arguments[1];
781
- target = null;
782
- } else {
783
- target = arguments[1];
784
- method = arguments[2];
785
- }
770
+ function clearItems(item) {
771
+ this._platform.clearTimeout(item[2]);
772
+ }
773
+ });
774
+ enifed("backburner/binary-search", ["exports"], function (exports) {
775
+ "use strict";
786
776
 
787
- if (_backburnerUtils.isString(method)) {
788
- method = target[method];
789
- }
777
+ exports.default = binarySearch;
790
778
 
791
- var stack = this.DEBUG ? new Error() : undefined;
779
+ function binarySearch(time, timers) {
780
+ var start = 0;
781
+ var end = timers.length - 2;
782
+ var middle, l;
792
783
 
793
- if (length > 3) {
794
- args = new Array(length - 3);
795
- for (var i = 3; i < length; i++) {
796
- args[i - 3] = arguments[i];
797
- }
784
+ while (start < end) {
785
+ // since timers is an array of pairs 'l' will always
786
+ // be an integer
787
+ l = (end - start) / 2;
788
+
789
+ // compensate for the index in case even number
790
+ // of pairs inside timers
791
+ middle = start + l - l % 2;
792
+
793
+ if (time >= timers[middle]) {
794
+ start = middle + 2;
798
795
  } else {
799
- args = undefined;
796
+ end = middle;
800
797
  }
798
+ }
801
799
 
802
- if (!this.currentInstance) {
803
- createAutorun(this);
804
- }
805
- return this.currentInstance.schedule(queueName, target, method, args, true, stack);
806
- },
800
+ return time >= timers[start] ? start + 2 : start;
801
+ }
802
+ });
803
+ enifed('backburner/deferred-action-queues', ['exports', 'backburner/utils', 'backburner/queue'], function (exports, _backburnerUtils, _backburnerQueue) {
804
+ 'use strict';
807
805
 
808
- setTimeout: function () {
809
- var l = arguments.length;
810
- var args = new Array(l);
806
+ exports.default = DeferredActionQueues;
811
807
 
812
- for (var x = 0; x < l; x++) {
813
- args[x] = arguments[x];
814
- }
808
+ function DeferredActionQueues(queueNames, options) {
809
+ var queues = this.queues = {};
810
+ this.queueNames = queueNames = queueNames || [];
815
811
 
816
- var length = args.length,
817
- method,
818
- wait,
819
- target,
820
- methodOrTarget,
821
- methodOrWait,
822
- methodOrArgs;
812
+ this.options = options;
823
813
 
824
- if (length === 0) {
825
- return;
826
- } else if (length === 1) {
827
- method = args.shift();
828
- wait = 0;
829
- } else if (length === 2) {
830
- methodOrTarget = args[0];
831
- methodOrWait = args[1];
814
+ _backburnerUtils.each(queueNames, function (queueName) {
815
+ queues[queueName] = new _backburnerQueue.default(queueName, options[queueName], options);
816
+ });
817
+ }
832
818
 
833
- if (_backburnerUtils.isFunction(methodOrWait) || _backburnerUtils.isFunction(methodOrTarget[methodOrWait])) {
834
- target = args.shift();
835
- method = args.shift();
836
- wait = 0;
837
- } else if (_backburnerUtils.isCoercableNumber(methodOrWait)) {
838
- method = args.shift();
839
- wait = args.shift();
840
- } else {
841
- method = args.shift();
842
- wait = 0;
843
- }
844
- } else {
845
- var last = args[args.length - 1];
819
+ function noSuchQueue(name) {
820
+ throw new Error('You attempted to schedule an action in a queue (' + name + ') that doesn\'t exist');
821
+ }
846
822
 
847
- if (_backburnerUtils.isCoercableNumber(last)) {
848
- wait = args.pop();
849
- } else {
850
- wait = 0;
851
- }
823
+ function noSuchMethod(name) {
824
+ throw new Error('You attempted to schedule an action in a queue (' + name + ') for a method that doesn\'t exist');
825
+ }
852
826
 
853
- methodOrTarget = args[0];
854
- methodOrArgs = args[1];
827
+ DeferredActionQueues.prototype = {
828
+ schedule: function (name, target, method, args, onceFlag, stack) {
829
+ var queues = this.queues;
830
+ var queue = queues[name];
855
831
 
856
- if (_backburnerUtils.isFunction(methodOrArgs) || _backburnerUtils.isString(methodOrArgs) && methodOrTarget !== null && methodOrArgs in methodOrTarget) {
857
- target = args.shift();
858
- method = args.shift();
859
- } else {
860
- method = args.shift();
861
- }
832
+ if (!queue) {
833
+ noSuchQueue(name);
862
834
  }
863
835
 
864
- var executeAt = Date.now() + parseInt(wait !== wait ? 0 : wait, 10);
865
-
866
- if (_backburnerUtils.isString(method)) {
867
- method = target[method];
836
+ if (!method) {
837
+ noSuchMethod(name);
868
838
  }
869
839
 
870
- var onError = getOnError(this.options);
871
-
872
- function fn() {
873
- if (onError) {
874
- try {
875
- method.apply(target, args);
876
- } catch (e) {
877
- onError(e);
878
- }
879
- } else {
880
- method.apply(target, args);
881
- }
840
+ if (onceFlag) {
841
+ return queue.pushUnique(target, method, args, stack);
842
+ } else {
843
+ return queue.push(target, method, args, stack);
882
844
  }
883
-
884
- return this._setTimeout(fn, executeAt);
885
845
  },
886
846
 
887
- _setTimeout: function (fn, executeAt) {
888
- if (this._timers.length === 0) {
889
- this._timers.push(executeAt, fn);
890
- this._installTimerTimeout();
891
- return fn;
892
- }
847
+ flush: function () {
848
+ var queues = this.queues;
849
+ var queueNames = this.queueNames;
850
+ var queueName, queue;
851
+ var queueNameIndex = 0;
852
+ var numberOfQueues = queueNames.length;
893
853
 
894
- // find position to insert
895
- var i = _backburnerBinarySearch.default(executeAt, this._timers);
854
+ while (queueNameIndex < numberOfQueues) {
855
+ queueName = queueNames[queueNameIndex];
856
+ queue = queues[queueName];
896
857
 
897
- this._timers.splice(i, 0, executeAt, fn);
858
+ var numberOfQueueItems = queue._queue.length;
898
859
 
899
- // we should be the new earliest timer if i == 0
900
- if (i === 0) {
901
- this._reinstallTimerTimeout();
860
+ if (numberOfQueueItems === 0) {
861
+ queueNameIndex++;
862
+ } else {
863
+ queue.flush(false /* async */);
864
+ queueNameIndex = 0;
865
+ }
902
866
  }
867
+ }
868
+ };
869
+ });
870
+ enifed('backburner/platform', ['exports'], function (exports) {
871
+ 'use strict';
903
872
 
904
- return fn;
905
- },
873
+ var GlobalContext;
906
874
 
907
- throttle: function (target, method /* , args, wait, [immediate] */) {
908
- var backburner = this;
909
- var args = new Array(arguments.length);
910
- for (var i = 0; i < arguments.length; i++) {
911
- args[i] = arguments[i];
912
- }
913
- var immediate = args.pop();
914
- var wait, throttler, index, timer;
875
+ /* global self */
876
+ if (typeof self === 'object') {
877
+ GlobalContext = self;
915
878
 
916
- if (_backburnerUtils.isNumber(immediate) || _backburnerUtils.isString(immediate)) {
917
- wait = immediate;
918
- immediate = true;
879
+ /* global global */
880
+ } else if (typeof global === 'object') {
881
+ GlobalContext = global;
882
+
883
+ /* global window */
884
+ } else if (typeof window === 'object') {
885
+ GlobalContext = window;
919
886
  } else {
920
- wait = args.pop();
887
+ throw new Error('no global: `self`, `global` nor `window` was found');
921
888
  }
922
889
 
923
- wait = parseInt(wait, 10);
924
-
925
- index = findThrottler(target, method, this._throttlers);
926
- if (index > -1) {
927
- return this._throttlers[index];
928
- } // throttled
929
-
930
- timer = this._platform.setTimeout(function () {
931
- if (!immediate) {
932
- backburner.run.apply(backburner, args);
933
- }
934
- var index = findThrottler(target, method, backburner._throttlers);
935
- if (index > -1) {
936
- backburner._throttlers.splice(index, 1);
937
- }
938
- }, wait);
890
+ exports.default = GlobalContext;
891
+ });
892
+ enifed('backburner/queue', ['exports', 'backburner/utils'], function (exports, _backburnerUtils) {
893
+ 'use strict';
939
894
 
940
- if (immediate) {
941
- this.run.apply(this, args);
942
- }
895
+ exports.default = Queue;
943
896
 
944
- throttler = [target, method, timer];
897
+ function Queue(name, options, globalOptions) {
898
+ this.name = name;
899
+ this.globalOptions = globalOptions || {};
900
+ this.options = options;
901
+ this._queue = [];
902
+ this.targetQueues = {};
903
+ this._queueBeingFlushed = undefined;
904
+ }
945
905
 
946
- this._throttlers.push(throttler);
906
+ Queue.prototype = {
907
+ push: function (target, method, args, stack) {
908
+ var queue = this._queue;
909
+ queue.push(target, method, args, stack);
947
910
 
948
- return throttler;
911
+ return {
912
+ queue: this,
913
+ target: target,
914
+ method: method
915
+ };
949
916
  },
950
917
 
951
- debounce: function (target, method /* , args, wait, [immediate] */) {
952
- var backburner = this;
953
- var args = new Array(arguments.length);
954
- for (var i = 0; i < arguments.length; i++) {
955
- args[i] = arguments[i];
956
- }
918
+ pushUniqueWithoutGuid: function (target, method, args, stack) {
919
+ var queue = this._queue;
957
920
 
958
- var immediate = args.pop();
959
- var wait, index, debouncee, timer;
921
+ for (var i = 0, l = queue.length; i < l; i += 4) {
922
+ var currentTarget = queue[i];
923
+ var currentMethod = queue[i + 1];
960
924
 
961
- if (_backburnerUtils.isNumber(immediate) || _backburnerUtils.isString(immediate)) {
962
- wait = immediate;
963
- immediate = false;
964
- } else {
965
- wait = args.pop();
925
+ if (currentTarget === target && currentMethod === method) {
926
+ queue[i + 2] = args; // replace args
927
+ queue[i + 3] = stack; // replace stack
928
+ return;
929
+ }
966
930
  }
967
931
 
968
- wait = parseInt(wait, 10);
969
- // Remove debouncee
970
- index = findDebouncee(target, method, this._debouncees);
932
+ queue.push(target, method, args, stack);
933
+ },
971
934
 
972
- if (index > -1) {
973
- debouncee = this._debouncees[index];
974
- this._debouncees.splice(index, 1);
975
- this._platform.clearTimeout(debouncee[2]);
976
- }
935
+ targetQueue: function (targetQueue, target, method, args, stack) {
936
+ var queue = this._queue;
977
937
 
978
- timer = this._platform.setTimeout(function () {
979
- if (!immediate) {
980
- backburner.run.apply(backburner, args);
981
- }
982
- var index = findDebouncee(target, method, backburner._debouncees);
983
- if (index > -1) {
984
- backburner._debouncees.splice(index, 1);
938
+ for (var i = 0, l = targetQueue.length; i < l; i += 2) {
939
+ var currentMethod = targetQueue[i];
940
+ var currentIndex = targetQueue[i + 1];
941
+
942
+ if (currentMethod === method) {
943
+ queue[currentIndex + 2] = args; // replace args
944
+ queue[currentIndex + 3] = stack; // replace stack
945
+ return;
985
946
  }
986
- }, wait);
987
-
988
- if (immediate && index === -1) {
989
- backburner.run.apply(backburner, args);
990
947
  }
991
948
 
992
- debouncee = [target, method, timer];
949
+ targetQueue.push(method, queue.push(target, method, args, stack) - 4);
950
+ },
993
951
 
994
- backburner._debouncees.push(debouncee);
952
+ pushUniqueWithGuid: function (guid, target, method, args, stack) {
953
+ var hasLocalQueue = this.targetQueues[guid];
995
954
 
996
- return debouncee;
955
+ if (hasLocalQueue) {
956
+ this.targetQueue(hasLocalQueue, target, method, args, stack);
957
+ } else {
958
+ this.targetQueues[guid] = [method, this._queue.push(target, method, args, stack) - 4];
959
+ }
960
+
961
+ return {
962
+ queue: this,
963
+ target: target,
964
+ method: method
965
+ };
997
966
  },
998
967
 
999
- cancelTimers: function () {
1000
- _backburnerUtils.each(this._throttlers, this._boundClearItems);
1001
- this._throttlers = [];
968
+ pushUnique: function (target, method, args, stack) {
969
+ var KEY = this.globalOptions.GUID_KEY;
1002
970
 
1003
- _backburnerUtils.each(this._debouncees, this._boundClearItems);
1004
- this._debouncees = [];
971
+ if (target && KEY) {
972
+ var guid = target[KEY];
973
+ if (guid) {
974
+ return this.pushUniqueWithGuid(guid, target, method, args, stack);
975
+ }
976
+ }
1005
977
 
1006
- this._clearTimerTimeout();
1007
- this._timers = [];
978
+ this.pushUniqueWithoutGuid(target, method, args, stack);
1008
979
 
1009
- if (this._autorun) {
1010
- this._platform.clearTimeout(this._autorun);
1011
- this._autorun = null;
1012
- }
980
+ return {
981
+ queue: this,
982
+ target: target,
983
+ method: method
984
+ };
1013
985
  },
1014
986
 
1015
- hasTimers: function () {
1016
- return !!this._timers.length || !!this._debouncees.length || !!this._throttlers.length || this._autorun;
987
+ invoke: function (target, method, args, _, _errorRecordedForStack) {
988
+ if (args && args.length > 0) {
989
+ method.apply(target, args);
990
+ } else {
991
+ method.call(target);
992
+ }
1017
993
  },
1018
994
 
1019
- cancel: function (timer) {
1020
- var timerType = typeof timer;
1021
-
1022
- if (timer && timerType === 'object' && timer.queue && timer.method) {
1023
- // we're cancelling a deferOnce
1024
- return timer.queue.cancel(timer);
1025
- } else if (timerType === 'function') {
1026
- // we're cancelling a setTimeout
1027
- for (var i = 0, l = this._timers.length; i < l; i += 2) {
1028
- if (this._timers[i + 1] === timer) {
1029
- this._timers.splice(i, 2); // remove the two elements
1030
- if (i === 0) {
1031
- this._reinstallTimerTimeout();
1032
- }
1033
- return true;
1034
- }
995
+ invokeWithOnError: function (target, method, args, onError, errorRecordedForStack) {
996
+ try {
997
+ if (args && args.length > 0) {
998
+ method.apply(target, args);
999
+ } else {
1000
+ method.call(target);
1035
1001
  }
1036
- } else if (Object.prototype.toString.call(timer) === '[object Array]') {
1037
- // we're cancelling a throttle or debounce
1038
- return this._cancelItem(findThrottler, this._throttlers, timer) || this._cancelItem(findDebouncee, this._debouncees, timer);
1039
- } else {
1040
- return; // timer was null or not a timer
1002
+ } catch (error) {
1003
+ onError(error, errorRecordedForStack);
1041
1004
  }
1042
1005
  },
1043
1006
 
1044
- _cancelItem: function (findMethod, array, timer) {
1045
- var item, index;
1007
+ flush: function (sync) {
1008
+ var queue = this._queue;
1009
+ var length = queue.length;
1046
1010
 
1047
- if (timer.length < 3) {
1048
- return false;
1011
+ if (length === 0) {
1012
+ return;
1049
1013
  }
1050
1014
 
1051
- index = findMethod(timer[0], timer[1], array);
1015
+ var globalOptions = this.globalOptions;
1016
+ var options = this.options;
1017
+ var before = options && options.before;
1018
+ var after = options && options.after;
1019
+ var onError = globalOptions.onError || globalOptions.onErrorTarget && globalOptions.onErrorTarget[globalOptions.onErrorMethod];
1020
+ var target, method, args, errorRecordedForStack;
1021
+ var invoke = onError ? this.invokeWithOnError : this.invoke;
1052
1022
 
1053
- if (index > -1) {
1023
+ this.targetQueues = Object.create(null);
1024
+ var queueItems = this._queueBeingFlushed = this._queue.slice();
1025
+ this._queue = [];
1054
1026
 
1055
- item = array[index];
1027
+ if (before) {
1028
+ before();
1029
+ }
1056
1030
 
1057
- if (item[2] === timer[2]) {
1058
- array.splice(index, 1);
1059
- this._platform.clearTimeout(timer[2]);
1060
- return true;
1031
+ for (var i = 0; i < length; i += 4) {
1032
+ target = queueItems[i];
1033
+ method = queueItems[i + 1];
1034
+ args = queueItems[i + 2];
1035
+ errorRecordedForStack = queueItems[i + 3]; // Debugging assistance
1036
+
1037
+ if (_backburnerUtils.isString(method)) {
1038
+ method = target[method];
1039
+ }
1040
+
1041
+ // method could have been nullified / canceled during flush
1042
+ if (method) {
1043
+ //
1044
+ // ** Attention intrepid developer **
1045
+ //
1046
+ // To find out the stack of this task when it was scheduled onto
1047
+ // the run loop, add the following to your app.js:
1048
+ //
1049
+ // Ember.run.backburner.DEBUG = true; // NOTE: This slows your app, don't leave it on in production.
1050
+ //
1051
+ // Once that is in place, when you are at a breakpoint and navigate
1052
+ // here in the stack explorer, you can look at `errorRecordedForStack.stack`,
1053
+ // which will be the captured stack when this job was scheduled.
1054
+ //
1055
+ invoke(target, method, args, onError, errorRecordedForStack);
1061
1056
  }
1062
1057
  }
1063
1058
 
1064
- return false;
1065
- },
1059
+ if (after) {
1060
+ after();
1061
+ }
1066
1062
 
1067
- _runExpiredTimers: function () {
1068
- this._timerTimeoutId = undefined;
1069
- this.run(this, this._scheduleExpiredTimers);
1063
+ this._queueBeingFlushed = undefined;
1064
+
1065
+ if (sync !== false && this._queue.length > 0) {
1066
+ // check if new items have been added
1067
+ this.flush(true);
1068
+ }
1070
1069
  },
1071
1070
 
1072
- _scheduleExpiredTimers: function () {
1073
- var n = Date.now();
1074
- var timers = this._timers;
1075
- var i = 0;
1076
- var l = timers.length;
1077
- for (; i < l; i += 2) {
1078
- var executeAt = timers[i];
1079
- var fn = timers[i + 1];
1080
- if (executeAt <= n) {
1081
- this.schedule(this.options.defaultQueue, null, fn);
1082
- } else {
1083
- break;
1071
+ cancel: function (actionToCancel) {
1072
+ var queue = this._queue,
1073
+ currentTarget,
1074
+ currentMethod,
1075
+ i,
1076
+ l;
1077
+ var target = actionToCancel.target;
1078
+ var method = actionToCancel.method;
1079
+ var GUID_KEY = this.globalOptions.GUID_KEY;
1080
+
1081
+ if (GUID_KEY && this.targetQueues && target) {
1082
+ var targetQueue = this.targetQueues[target[GUID_KEY]];
1083
+
1084
+ if (targetQueue) {
1085
+ for (i = 0, l = targetQueue.length; i < l; i++) {
1086
+ if (targetQueue[i] === method) {
1087
+ targetQueue.splice(i, 1);
1088
+ }
1089
+ }
1084
1090
  }
1085
1091
  }
1086
- timers.splice(0, i);
1087
- this._installTimerTimeout();
1088
- },
1089
1092
 
1090
- _reinstallTimerTimeout: function () {
1091
- this._clearTimerTimeout();
1092
- this._installTimerTimeout();
1093
- },
1093
+ for (i = 0, l = queue.length; i < l; i += 4) {
1094
+ currentTarget = queue[i];
1095
+ currentMethod = queue[i + 1];
1094
1096
 
1095
- _clearTimerTimeout: function () {
1096
- if (!this._timerTimeoutId) {
1097
- return;
1097
+ if (currentTarget === target && currentMethod === method) {
1098
+ queue.splice(i, 4);
1099
+ return true;
1100
+ }
1098
1101
  }
1099
- this._platform.clearTimeout(this._timerTimeoutId);
1100
- this._timerTimeoutId = undefined;
1101
- },
1102
1102
 
1103
- _installTimerTimeout: function () {
1104
- if (!this._timers.length) {
1103
+ // if not found in current queue
1104
+ // could be in the queue that is being flushed
1105
+ queue = this._queueBeingFlushed;
1106
+
1107
+ if (!queue) {
1105
1108
  return;
1106
1109
  }
1107
- var minExpiresAt = this._timers[0];
1108
- var n = Date.now();
1109
- var wait = Math.max(0, minExpiresAt - n);
1110
- this._timerTimeoutId = this._platform.setTimeout(this._boundRunExpiredTimers, wait);
1111
- }
1112
- };
1113
1110
 
1114
- Backburner.prototype.schedule = Backburner.prototype.defer;
1115
- Backburner.prototype.scheduleOnce = Backburner.prototype.deferOnce;
1116
- Backburner.prototype.later = Backburner.prototype.setTimeout;
1111
+ for (i = 0, l = queue.length; i < l; i += 4) {
1112
+ currentTarget = queue[i];
1113
+ currentMethod = queue[i + 1];
1117
1114
 
1118
- function getOnError(options) {
1119
- return options.onError || options.onErrorTarget && options.onErrorTarget[options.onErrorMethod];
1120
- }
1115
+ if (currentTarget === target && currentMethod === method) {
1116
+ // don't mess with array during flush
1117
+ // just nullify the method
1118
+ queue[i + 1] = null;
1119
+ return true;
1120
+ }
1121
+ }
1122
+ }
1123
+ };
1124
+ });
1125
+ enifed('backburner/utils', ['exports'], function (exports) {
1126
+ 'use strict';
1121
1127
 
1122
- function createAutorun(backburner) {
1123
- backburner.begin();
1124
- backburner._autorun = backburner._platform.setTimeout(function () {
1125
- backburner._autorun = null;
1126
- backburner.end();
1127
- });
1128
- }
1128
+ exports.each = each;
1129
+ exports.isString = isString;
1130
+ exports.isFunction = isFunction;
1131
+ exports.isNumber = isNumber;
1132
+ exports.isCoercableNumber = isCoercableNumber;
1133
+ var NUMBER = /\d+/;
1129
1134
 
1130
- function findDebouncee(target, method, debouncees) {
1131
- return findItem(target, method, debouncees);
1135
+ function each(collection, callback) {
1136
+ for (var i = 0; i < collection.length; i++) {
1137
+ callback(collection[i]);
1138
+ }
1132
1139
  }
1133
1140
 
1134
- function findThrottler(target, method, throttlers) {
1135
- return findItem(target, method, throttlers);
1141
+ function isString(suspect) {
1142
+ return typeof suspect === 'string';
1136
1143
  }
1137
1144
 
1138
- function findItem(target, method, collection) {
1139
- var item;
1140
- var index = -1;
1141
-
1142
- for (var i = 0, l = collection.length; i < l; i++) {
1143
- item = collection[i];
1144
- if (item[0] === target && item[1] === method) {
1145
- index = i;
1146
- break;
1147
- }
1148
- }
1145
+ function isFunction(suspect) {
1146
+ return typeof suspect === 'function';
1147
+ }
1149
1148
 
1150
- return index;
1149
+ function isNumber(suspect) {
1150
+ return typeof suspect === 'number';
1151
1151
  }
1152
1152
 
1153
- function clearItems(item) {
1154
- this._platform.clearTimeout(item[2]);
1153
+ function isCoercableNumber(number) {
1154
+ return isNumber(number) || NUMBER.test(number);
1155
1155
  }
1156
1156
  });
1157
1157
  enifed('ember-debug/deprecate', ['exports', 'ember-metal/core', 'ember-metal/error', 'ember-metal/logger', 'ember-debug/handlers'], function (exports, _emberMetalCore, _emberMetalError, _emberMetalLogger, _emberDebugHandlers) {
@@ -3988,7 +3988,7 @@ enifed('ember-metal/core', ['exports', 'require'], function (exports, _require)
3988
3988
 
3989
3989
  @class Ember
3990
3990
  @static
3991
- @version 2.6.1
3991
+ @version 2.6.2
3992
3992
  @public
3993
3993
  */
3994
3994
 
@@ -4030,11 +4030,11 @@ enifed('ember-metal/core', ['exports', 'require'], function (exports, _require)
4030
4030
 
4031
4031
  @property VERSION
4032
4032
  @type String
4033
- @default '2.6.1'
4033
+ @default '2.6.2'
4034
4034
  @static
4035
4035
  @public
4036
4036
  */
4037
- Ember.VERSION = '2.6.1';
4037
+ Ember.VERSION = '2.6.2';
4038
4038
 
4039
4039
  /**
4040
4040
  The hash of environment variables used to control various configuration
@@ -4522,13 +4522,11 @@ enifed('ember-metal/events', ['exports', 'ember-metal/debug', 'ember-metal/utils
4522
4522
  function addListener(obj, eventName, target, method, once) {
4523
4523
  _emberMetalDebug.assert('You must pass at least an object and event name to Ember.addListener', !!obj && !!eventName);
4524
4524
 
4525
- if (eventName === 'didInitAttrs' && obj.isComponent) {
4526
- _emberMetalDebug.deprecate('[DEPRECATED] didInitAttrs called in ' + obj.toString() + '.', false, {
4527
- id: 'ember-views.did-init-attrs',
4528
- until: '3.0.0',
4529
- url: 'http://emberjs.com/deprecations/v2.x#toc_ember-component-didinitattrs'
4530
- });
4531
- }
4525
+ _emberMetalDebug.deprecate('didInitAttrs called in ' + (obj && obj.toString && obj.toString()) + '.', eventName !== 'didInitAttrs', {
4526
+ id: 'ember-views.did-init-attrs',
4527
+ until: '3.0.0',
4528
+ url: 'http://emberjs.com/deprecations/v2.x#toc_ember-component-didinitattrs'
4529
+ });
4532
4530
 
4533
4531
  if (!method && 'function' === typeof target) {
4534
4532
  method = target;
@@ -11610,6 +11608,15 @@ enifed('ember-metal/weak_map', ['exports', 'ember-metal/debug', 'ember-metal/uti
11610
11608
  }
11611
11609
  };
11612
11610
  });
11611
+ enifed('ember-template-compiler/compat', ['exports', 'ember-metal/core', 'ember-template-compiler/compat/precompile', 'ember-template-compiler/system/compile', 'ember-template-compiler/system/template'], function (exports, _emberMetalCore, _emberTemplateCompilerCompatPrecompile, _emberTemplateCompilerSystemCompile, _emberTemplateCompilerSystemTemplate) {
11612
+ 'use strict';
11613
+
11614
+ var EmberHandlebars = _emberMetalCore.default.Handlebars = _emberMetalCore.default.Handlebars || {};
11615
+
11616
+ EmberHandlebars.precompile = _emberTemplateCompilerCompatPrecompile.default;
11617
+ EmberHandlebars.compile = _emberTemplateCompilerSystemCompile.default;
11618
+ EmberHandlebars.template = _emberTemplateCompilerSystemTemplate.default;
11619
+ });
11613
11620
  enifed('ember-template-compiler/compat/precompile', ['exports', 'require', 'ember-template-compiler/system/compile_options'], function (exports, _require, _emberTemplateCompilerSystemCompile_options) {
11614
11621
  /**
11615
11622
  @module ember
@@ -11637,15 +11644,6 @@ enifed('ember-template-compiler/compat/precompile', ['exports', 'require', 'embe
11637
11644
  return compileFunc(string, _emberTemplateCompilerSystemCompile_options.default());
11638
11645
  };
11639
11646
  });
11640
- enifed('ember-template-compiler/compat', ['exports', 'ember-metal/core', 'ember-template-compiler/compat/precompile', 'ember-template-compiler/system/compile', 'ember-template-compiler/system/template'], function (exports, _emberMetalCore, _emberTemplateCompilerCompatPrecompile, _emberTemplateCompilerSystemCompile, _emberTemplateCompilerSystemTemplate) {
11641
- 'use strict';
11642
-
11643
- var EmberHandlebars = _emberMetalCore.default.Handlebars = _emberMetalCore.default.Handlebars || {};
11644
-
11645
- EmberHandlebars.precompile = _emberTemplateCompilerCompatPrecompile.default;
11646
- EmberHandlebars.compile = _emberTemplateCompilerSystemCompile.default;
11647
- EmberHandlebars.template = _emberTemplateCompilerSystemTemplate.default;
11648
- });
11649
11647
  enifed('ember-template-compiler/index', ['exports', 'ember-metal', 'ember-template-compiler/system/precompile', 'ember-template-compiler/system/compile', 'ember-template-compiler/system/template', 'ember-template-compiler/plugins', 'ember-template-compiler/plugins/transform-old-binding-syntax', 'ember-template-compiler/plugins/transform-old-class-binding-syntax', 'ember-template-compiler/plugins/transform-item-class', 'ember-template-compiler/plugins/transform-closure-component-attrs-into-mut', 'ember-template-compiler/plugins/transform-component-attrs-into-mut', 'ember-template-compiler/plugins/transform-component-curly-to-readonly', 'ember-template-compiler/plugins/transform-angle-bracket-components', 'ember-template-compiler/plugins/transform-input-on-to-onEvent', 'ember-template-compiler/plugins/transform-top-level-components', 'ember-template-compiler/plugins/deprecate-render-model', 'ember-template-compiler/plugins/prevent-render-block', 'ember-template-compiler/plugins/transform-inline-link-to', 'ember-template-compiler/plugins/assert-no-view-and-controller-paths', 'ember-template-compiler/plugins/assert-no-view-helper', 'ember-template-compiler/plugins/assert-no-each-in', 'ember-template-compiler/compat'], function (exports, _emberMetal, _emberTemplateCompilerSystemPrecompile, _emberTemplateCompilerSystemCompile, _emberTemplateCompilerSystemTemplate, _emberTemplateCompilerPlugins, _emberTemplateCompilerPluginsTransformOldBindingSyntax, _emberTemplateCompilerPluginsTransformOldClassBindingSyntax, _emberTemplateCompilerPluginsTransformItemClass, _emberTemplateCompilerPluginsTransformClosureComponentAttrsIntoMut, _emberTemplateCompilerPluginsTransformComponentAttrsIntoMut, _emberTemplateCompilerPluginsTransformComponentCurlyToReadonly, _emberTemplateCompilerPluginsTransformAngleBracketComponents, _emberTemplateCompilerPluginsTransformInputOnToOnEvent, _emberTemplateCompilerPluginsTransformTopLevelComponents, _emberTemplateCompilerPluginsDeprecateRenderModel, _emberTemplateCompilerPluginsPreventRenderBlock, _emberTemplateCompilerPluginsTransformInlineLinkTo, _emberTemplateCompilerPluginsAssertNoViewAndControllerPaths, _emberTemplateCompilerPluginsAssertNoViewHelper, _emberTemplateCompilerPluginsAssertNoEachIn, _emberTemplateCompilerCompat) {
11650
11648
  'use strict';
11651
11649
 
@@ -11676,6 +11674,40 @@ enifed('ember-template-compiler/index', ['exports', 'ember-metal', 'ember-templa
11676
11674
  });
11677
11675
 
11678
11676
  // used for adding Ember.Handlebars.compile for backwards compat
11677
+ enifed('ember-template-compiler/plugins', ['exports'], function (exports) {
11678
+ /**
11679
+ @module ember
11680
+ @submodule ember-template-compiler
11681
+ */
11682
+
11683
+ /**
11684
+ @private
11685
+ @property helpers
11686
+ */
11687
+ 'use strict';
11688
+
11689
+ exports.registerPlugin = registerPlugin;
11690
+ var plugins = {
11691
+ ast: []
11692
+ };
11693
+
11694
+ /**
11695
+ Adds an AST plugin to be used by Ember.HTMLBars.compile.
11696
+
11697
+ @private
11698
+ @method registerASTPlugin
11699
+ */
11700
+
11701
+ function registerPlugin(type, Plugin) {
11702
+ if (!plugins[type]) {
11703
+ throw new Error('Attempting to register "' + Plugin + '" as "' + type + '" which is not a valid HTMLBars plugin type.');
11704
+ }
11705
+
11706
+ plugins[type].push(Plugin);
11707
+ }
11708
+
11709
+ exports.default = plugins;
11710
+ });
11679
11711
  enifed('ember-template-compiler/plugins/assert-no-each-in', ['exports', 'ember-metal/core', 'ember-metal/debug', 'ember-template-compiler/system/calculate-location-display'], function (exports, _emberMetalCore, _emberMetalDebug, _emberTemplateCompilerSystemCalculateLocationDisplay) {
11680
11712
  'use strict';
11681
11713
 
@@ -12630,40 +12662,6 @@ enifed('ember-template-compiler/plugins/transform-top-level-components', ['expor
12630
12662
 
12631
12663
  exports.default = TransformTopLevelComponents;
12632
12664
  });
12633
- enifed('ember-template-compiler/plugins', ['exports'], function (exports) {
12634
- /**
12635
- @module ember
12636
- @submodule ember-template-compiler
12637
- */
12638
-
12639
- /**
12640
- @private
12641
- @property helpers
12642
- */
12643
- 'use strict';
12644
-
12645
- exports.registerPlugin = registerPlugin;
12646
- var plugins = {
12647
- ast: []
12648
- };
12649
-
12650
- /**
12651
- Adds an AST plugin to be used by Ember.HTMLBars.compile.
12652
-
12653
- @private
12654
- @method registerASTPlugin
12655
- */
12656
-
12657
- function registerPlugin(type, Plugin) {
12658
- if (!plugins[type]) {
12659
- throw new Error('Attempting to register "' + Plugin + '" as "' + type + '" which is not a valid HTMLBars plugin type.');
12660
- }
12661
-
12662
- plugins[type].push(Plugin);
12663
- }
12664
-
12665
- exports.default = plugins;
12666
- });
12667
12665
  enifed('ember-template-compiler/system/calculate-location-display', ['exports'], function (exports) {
12668
12666
  'use strict';
12669
12667
 
@@ -12774,7 +12772,7 @@ enifed('ember-template-compiler/system/compile_options', ['exports', 'ember-meta
12774
12772
  options.buildMeta = function buildMeta(program) {
12775
12773
  return {
12776
12774
  fragmentReason: fragmentReason(program),
12777
- revision: 'Ember@2.6.1',
12775
+ revision: 'Ember@2.6.2',
12778
12776
  loc: program.loc,
12779
12777
  moduleName: options.moduleName
12780
12778
  };
@@ -12910,6 +12908,13 @@ enifed('ember-template-compiler/system/template', ['exports', 'ember-metal/featu
12910
12908
  };
12911
12909
  exports.default = template;
12912
12910
  });
12911
+ enifed("htmlbars-compiler", ["exports", "htmlbars-compiler/compiler"], function (exports, _htmlbarsCompilerCompiler) {
12912
+ "use strict";
12913
+
12914
+ exports.compile = _htmlbarsCompilerCompiler.compile;
12915
+ exports.compileSpec = _htmlbarsCompilerCompiler.compileSpec;
12916
+ exports.template = _htmlbarsCompilerCompiler.template;
12917
+ });
12913
12918
  enifed("htmlbars-compiler/compiler", ["exports", "htmlbars-syntax/parser", "htmlbars-compiler/template-compiler", "htmlbars-runtime/hooks", "htmlbars-runtime/render"], function (exports, _htmlbarsSyntaxParser, _htmlbarsCompilerTemplateCompiler, _htmlbarsRuntimeHooks, _htmlbarsRuntimeRender) {
12914
12919
  /*jshint evil:true*/
12915
12920
  "use strict";
@@ -14166,12 +14171,23 @@ enifed("htmlbars-compiler/utils", ["exports"], function (exports) {
14166
14171
  }
14167
14172
  }
14168
14173
  });
14169
- enifed("htmlbars-compiler", ["exports", "htmlbars-compiler/compiler"], function (exports, _htmlbarsCompilerCompiler) {
14170
- "use strict";
14174
+ enifed('htmlbars-runtime', ['exports', 'htmlbars-runtime/hooks', 'htmlbars-runtime/render', 'htmlbars-util/morph-utils', 'htmlbars-util/template-utils'], function (exports, _htmlbarsRuntimeHooks, _htmlbarsRuntimeRender, _htmlbarsUtilMorphUtils, _htmlbarsUtilTemplateUtils) {
14175
+ 'use strict';
14171
14176
 
14172
- exports.compile = _htmlbarsCompilerCompiler.compile;
14173
- exports.compileSpec = _htmlbarsCompilerCompiler.compileSpec;
14174
- exports.template = _htmlbarsCompilerCompiler.template;
14177
+ var internal = {
14178
+ blockFor: _htmlbarsUtilTemplateUtils.blockFor,
14179
+ manualElement: _htmlbarsRuntimeRender.manualElement,
14180
+ hostBlock: _htmlbarsRuntimeHooks.hostBlock,
14181
+ continueBlock: _htmlbarsRuntimeHooks.continueBlock,
14182
+ hostYieldWithShadowTemplate: _htmlbarsRuntimeHooks.hostYieldWithShadowTemplate,
14183
+ visitChildren: _htmlbarsUtilMorphUtils.visitChildren,
14184
+ validateChildMorphs: _htmlbarsUtilMorphUtils.validateChildMorphs,
14185
+ clearMorph: _htmlbarsUtilTemplateUtils.clearMorph
14186
+ };
14187
+
14188
+ exports.hooks = _htmlbarsRuntimeHooks.default;
14189
+ exports.render = _htmlbarsRuntimeRender.default;
14190
+ exports.internal = internal;
14175
14191
  });
14176
14192
  enifed('htmlbars-runtime/expression-visitor', ['exports'], function (exports) {
14177
14193
  /**
@@ -16038,23 +16054,14 @@ enifed("htmlbars-runtime/render", ["exports", "htmlbars-util/morph-utils", "html
16038
16054
  return fragment;
16039
16055
  }
16040
16056
  });
16041
- enifed('htmlbars-runtime', ['exports', 'htmlbars-runtime/hooks', 'htmlbars-runtime/render', 'htmlbars-util/morph-utils', 'htmlbars-util/template-utils'], function (exports, _htmlbarsRuntimeHooks, _htmlbarsRuntimeRender, _htmlbarsUtilMorphUtils, _htmlbarsUtilTemplateUtils) {
16042
- 'use strict';
16043
-
16044
- var internal = {
16045
- blockFor: _htmlbarsUtilTemplateUtils.blockFor,
16046
- manualElement: _htmlbarsRuntimeRender.manualElement,
16047
- hostBlock: _htmlbarsRuntimeHooks.hostBlock,
16048
- continueBlock: _htmlbarsRuntimeHooks.continueBlock,
16049
- hostYieldWithShadowTemplate: _htmlbarsRuntimeHooks.hostYieldWithShadowTemplate,
16050
- visitChildren: _htmlbarsUtilMorphUtils.visitChildren,
16051
- validateChildMorphs: _htmlbarsUtilMorphUtils.validateChildMorphs,
16052
- clearMorph: _htmlbarsUtilTemplateUtils.clearMorph
16053
- };
16057
+ enifed("htmlbars-syntax", ["exports", "htmlbars-syntax/builders", "htmlbars-syntax/parser", "htmlbars-syntax/generation/print", "htmlbars-syntax/traversal/traverse", "htmlbars-syntax/traversal/walker"], function (exports, _htmlbarsSyntaxBuilders, _htmlbarsSyntaxParser, _htmlbarsSyntaxGenerationPrint, _htmlbarsSyntaxTraversalTraverse, _htmlbarsSyntaxTraversalWalker) {
16058
+ "use strict";
16054
16059
 
16055
- exports.hooks = _htmlbarsRuntimeHooks.default;
16056
- exports.render = _htmlbarsRuntimeRender.default;
16057
- exports.internal = internal;
16060
+ exports.builders = _htmlbarsSyntaxBuilders.default;
16061
+ exports.parse = _htmlbarsSyntaxParser.default;
16062
+ exports.print = _htmlbarsSyntaxGenerationPrint.default;
16063
+ exports.traverse = _htmlbarsSyntaxTraversalTraverse.default;
16064
+ exports.Walker = _htmlbarsSyntaxTraversalWalker.default;
16058
16065
  });
16059
16066
  enifed("htmlbars-syntax/builders", ["exports"], function (exports) {
16060
16067
  // Statements
@@ -17987,16 +17994,105 @@ enifed('htmlbars-syntax/handlebars/utils', ['exports'], function (exports) {
17987
17994
  } else {
17988
17995
  return false;
17989
17996
  }
17990
- }
17997
+ }
17998
+
17999
+ function blockParams(params, ids) {
18000
+ params.path = ids;
18001
+ return params;
18002
+ }
18003
+
18004
+ function appendContextPath(contextPath, id) {
18005
+ return (contextPath ? contextPath + '.' : '') + id;
18006
+ }
18007
+ });
18008
+ enifed("htmlbars-syntax/parser", ["exports", "htmlbars-syntax/handlebars/compiler/base", "htmlbars-syntax", "simple-html-tokenizer/evented-tokenizer", "simple-html-tokenizer/entity-parser", "simple-html-tokenizer/html5-named-char-refs", "htmlbars-syntax/parser/handlebars-node-visitors", "htmlbars-syntax/parser/tokenizer-event-handlers"], function (exports, _htmlbarsSyntaxHandlebarsCompilerBase, _htmlbarsSyntax, _simpleHtmlTokenizerEventedTokenizer, _simpleHtmlTokenizerEntityParser, _simpleHtmlTokenizerHtml5NamedCharRefs, _htmlbarsSyntaxParserHandlebarsNodeVisitors, _htmlbarsSyntaxParserTokenizerEventHandlers) {
18009
+ "use strict";
18010
+
18011
+ exports.preprocess = preprocess;
18012
+ exports.Parser = Parser;
18013
+
18014
+ function preprocess(html, options) {
18015
+ var ast = typeof html === 'object' ? html : _htmlbarsSyntaxHandlebarsCompilerBase.parse(html);
18016
+ var combined = new Parser(html, options).acceptNode(ast);
18017
+
18018
+ if (options && options.plugins && options.plugins.ast) {
18019
+ for (var i = 0, l = options.plugins.ast.length; i < l; i++) {
18020
+ var plugin = new options.plugins.ast[i](options);
18021
+
18022
+ plugin.syntax = _htmlbarsSyntax;
18023
+
18024
+ combined = plugin.transform(combined);
18025
+ }
18026
+ }
18027
+
18028
+ return combined;
18029
+ }
18030
+
18031
+ exports.default = preprocess;
18032
+
18033
+ var entityParser = new _simpleHtmlTokenizerEntityParser.default(_simpleHtmlTokenizerHtml5NamedCharRefs.default);
18034
+
18035
+ function Parser(source, options) {
18036
+ this.options = options || {};
18037
+ this.elementStack = [];
18038
+ this.tokenizer = new _simpleHtmlTokenizerEventedTokenizer.default(this, entityParser);
18039
+
18040
+ this.currentNode = null;
18041
+ this.currentAttribute = null;
18042
+
18043
+ if (typeof source === 'string') {
18044
+ this.source = source.split(/(?:\r\n?|\n)/g);
18045
+ }
18046
+ }
18047
+
18048
+ for (var key in _htmlbarsSyntaxParserHandlebarsNodeVisitors.default) {
18049
+ Parser.prototype[key] = _htmlbarsSyntaxParserHandlebarsNodeVisitors.default[key];
18050
+ }
18051
+
18052
+ for (var key in _htmlbarsSyntaxParserTokenizerEventHandlers.default) {
18053
+ Parser.prototype[key] = _htmlbarsSyntaxParserTokenizerEventHandlers.default[key];
18054
+ }
18055
+
18056
+ Parser.prototype.acceptNode = function (node) {
18057
+ return this[node.type](node);
18058
+ };
18059
+
18060
+ Parser.prototype.currentElement = function () {
18061
+ return this.elementStack[this.elementStack.length - 1];
18062
+ };
18063
+
18064
+ Parser.prototype.sourceForMustache = function (mustache) {
18065
+ var firstLine = mustache.loc.start.line - 1;
18066
+ var lastLine = mustache.loc.end.line - 1;
18067
+ var currentLine = firstLine - 1;
18068
+ var firstColumn = mustache.loc.start.column + 2;
18069
+ var lastColumn = mustache.loc.end.column - 2;
18070
+ var string = [];
18071
+ var line;
18072
+
18073
+ if (!this.source) {
18074
+ return '{{' + mustache.path.id.original + '}}';
18075
+ }
18076
+
18077
+ while (currentLine < lastLine) {
18078
+ currentLine++;
18079
+ line = this.source[currentLine];
18080
+
18081
+ if (currentLine === firstLine) {
18082
+ if (firstLine === lastLine) {
18083
+ string.push(line.slice(firstColumn, lastColumn));
18084
+ } else {
18085
+ string.push(line.slice(firstColumn));
18086
+ }
18087
+ } else if (currentLine === lastLine) {
18088
+ string.push(line.slice(0, lastColumn));
18089
+ } else {
18090
+ string.push(line);
18091
+ }
18092
+ }
17991
18093
 
17992
- function blockParams(params, ids) {
17993
- params.path = ids;
17994
- return params;
17995
- }
17996
-
17997
- function appendContextPath(contextPath, id) {
17998
- return (contextPath ? contextPath + '.' : '') + id;
17999
- }
18094
+ return string.join('\n');
18095
+ };
18000
18096
  });
18001
18097
  enifed("htmlbars-syntax/parser/handlebars-node-visitors", ["exports", "htmlbars-syntax/builders", "htmlbars-syntax/utils"], function (exports, _htmlbarsSyntaxBuilders, _htmlbarsSyntaxUtils) {
18002
18098
  "use strict";
@@ -18442,95 +18538,6 @@ enifed("htmlbars-syntax/parser/tokenizer-event-handlers", ["exports", "htmlbars-
18442
18538
  return "`" + tag.name + "` (on line " + tag.loc.end.line + ")";
18443
18539
  }
18444
18540
  });
18445
- enifed("htmlbars-syntax/parser", ["exports", "htmlbars-syntax/handlebars/compiler/base", "htmlbars-syntax", "simple-html-tokenizer/evented-tokenizer", "simple-html-tokenizer/entity-parser", "simple-html-tokenizer/html5-named-char-refs", "htmlbars-syntax/parser/handlebars-node-visitors", "htmlbars-syntax/parser/tokenizer-event-handlers"], function (exports, _htmlbarsSyntaxHandlebarsCompilerBase, _htmlbarsSyntax, _simpleHtmlTokenizerEventedTokenizer, _simpleHtmlTokenizerEntityParser, _simpleHtmlTokenizerHtml5NamedCharRefs, _htmlbarsSyntaxParserHandlebarsNodeVisitors, _htmlbarsSyntaxParserTokenizerEventHandlers) {
18446
- "use strict";
18447
-
18448
- exports.preprocess = preprocess;
18449
- exports.Parser = Parser;
18450
-
18451
- function preprocess(html, options) {
18452
- var ast = typeof html === 'object' ? html : _htmlbarsSyntaxHandlebarsCompilerBase.parse(html);
18453
- var combined = new Parser(html, options).acceptNode(ast);
18454
-
18455
- if (options && options.plugins && options.plugins.ast) {
18456
- for (var i = 0, l = options.plugins.ast.length; i < l; i++) {
18457
- var plugin = new options.plugins.ast[i](options);
18458
-
18459
- plugin.syntax = _htmlbarsSyntax;
18460
-
18461
- combined = plugin.transform(combined);
18462
- }
18463
- }
18464
-
18465
- return combined;
18466
- }
18467
-
18468
- exports.default = preprocess;
18469
-
18470
- var entityParser = new _simpleHtmlTokenizerEntityParser.default(_simpleHtmlTokenizerHtml5NamedCharRefs.default);
18471
-
18472
- function Parser(source, options) {
18473
- this.options = options || {};
18474
- this.elementStack = [];
18475
- this.tokenizer = new _simpleHtmlTokenizerEventedTokenizer.default(this, entityParser);
18476
-
18477
- this.currentNode = null;
18478
- this.currentAttribute = null;
18479
-
18480
- if (typeof source === 'string') {
18481
- this.source = source.split(/(?:\r\n?|\n)/g);
18482
- }
18483
- }
18484
-
18485
- for (var key in _htmlbarsSyntaxParserHandlebarsNodeVisitors.default) {
18486
- Parser.prototype[key] = _htmlbarsSyntaxParserHandlebarsNodeVisitors.default[key];
18487
- }
18488
-
18489
- for (var key in _htmlbarsSyntaxParserTokenizerEventHandlers.default) {
18490
- Parser.prototype[key] = _htmlbarsSyntaxParserTokenizerEventHandlers.default[key];
18491
- }
18492
-
18493
- Parser.prototype.acceptNode = function (node) {
18494
- return this[node.type](node);
18495
- };
18496
-
18497
- Parser.prototype.currentElement = function () {
18498
- return this.elementStack[this.elementStack.length - 1];
18499
- };
18500
-
18501
- Parser.prototype.sourceForMustache = function (mustache) {
18502
- var firstLine = mustache.loc.start.line - 1;
18503
- var lastLine = mustache.loc.end.line - 1;
18504
- var currentLine = firstLine - 1;
18505
- var firstColumn = mustache.loc.start.column + 2;
18506
- var lastColumn = mustache.loc.end.column - 2;
18507
- var string = [];
18508
- var line;
18509
-
18510
- if (!this.source) {
18511
- return '{{' + mustache.path.id.original + '}}';
18512
- }
18513
-
18514
- while (currentLine < lastLine) {
18515
- currentLine++;
18516
- line = this.source[currentLine];
18517
-
18518
- if (currentLine === firstLine) {
18519
- if (firstLine === lastLine) {
18520
- string.push(line.slice(firstColumn, lastColumn));
18521
- } else {
18522
- string.push(line.slice(firstColumn));
18523
- }
18524
- } else if (currentLine === lastLine) {
18525
- string.push(line.slice(0, lastColumn));
18526
- } else {
18527
- string.push(line);
18528
- }
18529
- }
18530
-
18531
- return string.join('\n');
18532
- };
18533
- });
18534
18541
  enifed("htmlbars-syntax/traversal/errors", ["exports"], function (exports) {
18535
18542
  "use strict";
18536
18543
 
@@ -18879,15 +18886,6 @@ enifed('htmlbars-syntax/utils', ['exports', 'htmlbars-util/array-utils'], functi
18879
18886
  }
18880
18887
  }
18881
18888
  });
18882
- enifed("htmlbars-syntax", ["exports", "htmlbars-syntax/builders", "htmlbars-syntax/parser", "htmlbars-syntax/generation/print", "htmlbars-syntax/traversal/traverse", "htmlbars-syntax/traversal/walker"], function (exports, _htmlbarsSyntaxBuilders, _htmlbarsSyntaxParser, _htmlbarsSyntaxGenerationPrint, _htmlbarsSyntaxTraversalTraverse, _htmlbarsSyntaxTraversalWalker) {
18883
- "use strict";
18884
-
18885
- exports.builders = _htmlbarsSyntaxBuilders.default;
18886
- exports.parse = _htmlbarsSyntaxParser.default;
18887
- exports.print = _htmlbarsSyntaxGenerationPrint.default;
18888
- exports.traverse = _htmlbarsSyntaxTraversalTraverse.default;
18889
- exports.Walker = _htmlbarsSyntaxTraversalWalker.default;
18890
- });
18891
18889
  enifed("htmlbars-test-helpers", ["exports", "simple-html-tokenizer/index", "htmlbars-util/array-utils"], function (exports, _simpleHtmlTokenizerIndex, _htmlbarsUtilArrayUtils) {
18892
18890
  "use strict";
18893
18891
 
@@ -19015,6 +19013,16 @@ enifed("htmlbars-test-helpers", ["exports", "simple-html-tokenizer/index", "html
19015
19013
  }
19016
19014
  }
19017
19015
  });
19016
+ enifed('htmlbars-util', ['exports', 'htmlbars-util/safe-string', 'htmlbars-util/handlebars/utils', 'htmlbars-util/namespaces', 'htmlbars-util/morph-utils'], function (exports, _htmlbarsUtilSafeString, _htmlbarsUtilHandlebarsUtils, _htmlbarsUtilNamespaces, _htmlbarsUtilMorphUtils) {
19017
+ 'use strict';
19018
+
19019
+ exports.SafeString = _htmlbarsUtilSafeString.default;
19020
+ exports.escapeExpression = _htmlbarsUtilHandlebarsUtils.escapeExpression;
19021
+ exports.getAttrNamespace = _htmlbarsUtilNamespaces.getAttrNamespace;
19022
+ exports.validateChildMorphs = _htmlbarsUtilMorphUtils.validateChildMorphs;
19023
+ exports.linkParams = _htmlbarsUtilMorphUtils.linkParams;
19024
+ exports.dump = _htmlbarsUtilMorphUtils.dump;
19025
+ });
19018
19026
  enifed('htmlbars-util/array-utils', ['exports'], function (exports) {
19019
19027
  'use strict';
19020
19028
 
@@ -19569,221 +19577,72 @@ enifed("htmlbars-util/template-utils", ["exports", "htmlbars-util/morph-utils",
19569
19577
  var cleanup = env.hooks.cleanupRenderNode;
19570
19578
  var destroy = env.hooks.destroyRenderNode;
19571
19579
  var willCleanup = env.hooks.willCleanupTree;
19572
- var didCleanup = env.hooks.didCleanupTree;
19573
-
19574
- function destroyNode(node) {
19575
- if (cleanup) {
19576
- cleanup(node);
19577
- }
19578
- if (destroy) {
19579
- destroy(node);
19580
- }
19581
- }
19582
-
19583
- if (willCleanup) {
19584
- willCleanup(env, morph, destroySelf);
19585
- }
19586
- if (cleanup) {
19587
- cleanup(morph);
19588
- }
19589
- if (destroySelf && destroy) {
19590
- destroy(morph);
19591
- }
19592
-
19593
- _htmlbarsUtilMorphUtils.visitChildren(morph.childNodes, destroyNode);
19594
-
19595
- // TODO: Deal with logical children that are not in the DOM tree
19596
- morph.clear();
19597
- if (didCleanup) {
19598
- didCleanup(env, morph, destroySelf);
19599
- }
19600
-
19601
- morph.lastResult = null;
19602
- morph.lastYielded = null;
19603
- morph.childNodes = null;
19604
- }
19605
-
19606
- function clearMorphList(morphList, morph, env) {
19607
- var item = morphList.firstChildMorph;
19608
-
19609
- while (item) {
19610
- var next = item.nextMorph;
19611
- morph.morphMap[item.key] = undefined;
19612
- clearMorph(item, env, true);
19613
- item.destroy();
19614
-
19615
- item = next;
19616
- }
19617
-
19618
- // Remove the MorphList from the morph.
19619
- morphList.clear();
19620
- morph.morphList = null;
19621
- }
19622
- });
19623
- enifed("htmlbars-util/void-tag-names", ["exports", "htmlbars-util/array-utils"], function (exports, _htmlbarsUtilArrayUtils) {
19624
- "use strict";
19625
-
19626
- // The HTML elements in this list are speced by
19627
- // http://www.w3.org/TR/html-markup/syntax.html#syntax-elements,
19628
- // and will be forced to close regardless of if they have a
19629
- // self-closing /> at the end.
19630
- var voidTagNames = "area base br col command embed hr img input keygen link meta param source track wbr";
19631
- var voidMap = {};
19632
-
19633
- _htmlbarsUtilArrayUtils.forEach(voidTagNames.split(" "), function (tagName) {
19634
- voidMap[tagName] = true;
19635
- });
19636
-
19637
- exports.default = voidMap;
19638
- });
19639
- enifed('htmlbars-util', ['exports', 'htmlbars-util/safe-string', 'htmlbars-util/handlebars/utils', 'htmlbars-util/namespaces', 'htmlbars-util/morph-utils'], function (exports, _htmlbarsUtilSafeString, _htmlbarsUtilHandlebarsUtils, _htmlbarsUtilNamespaces, _htmlbarsUtilMorphUtils) {
19640
- 'use strict';
19641
-
19642
- exports.SafeString = _htmlbarsUtilSafeString.default;
19643
- exports.escapeExpression = _htmlbarsUtilHandlebarsUtils.escapeExpression;
19644
- exports.getAttrNamespace = _htmlbarsUtilNamespaces.getAttrNamespace;
19645
- exports.validateChildMorphs = _htmlbarsUtilMorphUtils.validateChildMorphs;
19646
- exports.linkParams = _htmlbarsUtilMorphUtils.linkParams;
19647
- exports.dump = _htmlbarsUtilMorphUtils.dump;
19648
- });
19649
- enifed('morph-range/morph-list', ['exports', 'morph-range/utils'], function (exports, _morphRangeUtils) {
19650
- 'use strict';
19651
-
19652
- function MorphList() {
19653
- // morph graph
19654
- this.firstChildMorph = null;
19655
- this.lastChildMorph = null;
19656
-
19657
- this.mountedMorph = null;
19658
- }
19659
-
19660
- var prototype = MorphList.prototype;
19661
-
19662
- prototype.clear = function MorphList$clear() {
19663
- var current = this.firstChildMorph;
19664
-
19665
- while (current) {
19666
- var next = current.nextMorph;
19667
- current.previousMorph = null;
19668
- current.nextMorph = null;
19669
- current.parentMorphList = null;
19670
- current = next;
19671
- }
19672
-
19673
- this.firstChildMorph = this.lastChildMorph = null;
19674
- };
19675
-
19676
- prototype.destroy = function MorphList$destroy() {};
19677
-
19678
- prototype.appendMorph = function MorphList$appendMorph(morph) {
19679
- this.insertBeforeMorph(morph, null);
19680
- };
19681
-
19682
- prototype.insertBeforeMorph = function MorphList$insertBeforeMorph(morph, referenceMorph) {
19683
- if (morph.parentMorphList !== null) {
19684
- morph.unlink();
19685
- }
19686
- if (referenceMorph && referenceMorph.parentMorphList !== this) {
19687
- throw new Error('The morph before which the new morph is to be inserted is not a child of this morph.');
19688
- }
19689
-
19690
- var mountedMorph = this.mountedMorph;
19691
-
19692
- if (mountedMorph) {
19693
-
19694
- var parentNode = mountedMorph.firstNode.parentNode;
19695
- var referenceNode = referenceMorph ? referenceMorph.firstNode : mountedMorph.lastNode.nextSibling;
19696
-
19697
- _morphRangeUtils.insertBefore(parentNode, morph.firstNode, morph.lastNode, referenceNode);
19698
-
19699
- // was not in list mode replace current content
19700
- if (!this.firstChildMorph) {
19701
- _morphRangeUtils.clear(this.mountedMorph.firstNode.parentNode, this.mountedMorph.firstNode, this.mountedMorph.lastNode);
19580
+ var didCleanup = env.hooks.didCleanupTree;
19581
+
19582
+ function destroyNode(node) {
19583
+ if (cleanup) {
19584
+ cleanup(node);
19585
+ }
19586
+ if (destroy) {
19587
+ destroy(node);
19702
19588
  }
19703
19589
  }
19704
19590
 
19705
- morph.parentMorphList = this;
19706
-
19707
- var previousMorph = referenceMorph ? referenceMorph.previousMorph : this.lastChildMorph;
19708
- if (previousMorph) {
19709
- previousMorph.nextMorph = morph;
19710
- morph.previousMorph = previousMorph;
19711
- } else {
19712
- this.firstChildMorph = morph;
19591
+ if (willCleanup) {
19592
+ willCleanup(env, morph, destroySelf);
19713
19593
  }
19714
-
19715
- if (referenceMorph) {
19716
- referenceMorph.previousMorph = morph;
19717
- morph.nextMorph = referenceMorph;
19718
- } else {
19719
- this.lastChildMorph = morph;
19594
+ if (cleanup) {
19595
+ cleanup(morph);
19596
+ }
19597
+ if (destroySelf && destroy) {
19598
+ destroy(morph);
19720
19599
  }
19721
19600
 
19722
- this.firstChildMorph._syncFirstNode();
19723
- this.lastChildMorph._syncLastNode();
19724
- };
19601
+ _htmlbarsUtilMorphUtils.visitChildren(morph.childNodes, destroyNode);
19725
19602
 
19726
- prototype.removeChildMorph = function MorphList$removeChildMorph(morph) {
19727
- if (morph.parentMorphList !== this) {
19728
- throw new Error("Cannot remove a morph from a parent it is not inside of");
19603
+ // TODO: Deal with logical children that are not in the DOM tree
19604
+ morph.clear();
19605
+ if (didCleanup) {
19606
+ didCleanup(env, morph, destroySelf);
19729
19607
  }
19730
19608
 
19731
- morph.destroy();
19732
- };
19609
+ morph.lastResult = null;
19610
+ morph.lastYielded = null;
19611
+ morph.childNodes = null;
19612
+ }
19733
19613
 
19734
- exports.default = MorphList;
19735
- });
19736
- enifed('morph-range/morph-list.umd', ['exports', 'morph-range/morph-list'], function (exports, _morphRangeMorphList) {
19737
- 'use strict';
19614
+ function clearMorphList(morphList, morph, env) {
19615
+ var item = morphList.firstChildMorph;
19738
19616
 
19739
- (function (root, factory) {
19740
- if (typeof define === 'function' && define.amd) {
19741
- define([], factory);
19742
- } else if (typeof exports === 'object') {
19743
- module.exports = factory();
19744
- } else {
19745
- root.MorphList = factory();
19617
+ while (item) {
19618
+ var next = item.nextMorph;
19619
+ morph.morphMap[item.key] = undefined;
19620
+ clearMorph(item, env, true);
19621
+ item.destroy();
19622
+
19623
+ item = next;
19746
19624
  }
19747
- })(undefined, function () {
19748
- return _morphRangeMorphList.default;
19749
- });
19625
+
19626
+ // Remove the MorphList from the morph.
19627
+ morphList.clear();
19628
+ morph.morphList = null;
19629
+ }
19750
19630
  });
19751
- enifed("morph-range/utils", ["exports"], function (exports) {
19752
- // inclusive of both nodes
19631
+ enifed("htmlbars-util/void-tag-names", ["exports", "htmlbars-util/array-utils"], function (exports, _htmlbarsUtilArrayUtils) {
19753
19632
  "use strict";
19754
19633
 
19755
- exports.clear = clear;
19756
- exports.insertBefore = insertBefore;
19757
-
19758
- function clear(parentNode, firstNode, lastNode) {
19759
- if (!parentNode) {
19760
- return;
19761
- }
19634
+ // The HTML elements in this list are speced by
19635
+ // http://www.w3.org/TR/html-markup/syntax.html#syntax-elements,
19636
+ // and will be forced to close regardless of if they have a
19637
+ // self-closing /> at the end.
19638
+ var voidTagNames = "area base br col command embed hr img input keygen link meta param source track wbr";
19639
+ var voidMap = {};
19762
19640
 
19763
- var node = firstNode;
19764
- var nextNode;
19765
- do {
19766
- nextNode = node.nextSibling;
19767
- parentNode.removeChild(node);
19768
- if (node === lastNode) {
19769
- break;
19770
- }
19771
- node = nextNode;
19772
- } while (node);
19773
- }
19641
+ _htmlbarsUtilArrayUtils.forEach(voidTagNames.split(" "), function (tagName) {
19642
+ voidMap[tagName] = true;
19643
+ });
19774
19644
 
19775
- function insertBefore(parentNode, firstNode, lastNode, refNode) {
19776
- var node = firstNode;
19777
- var nextNode;
19778
- do {
19779
- nextNode = node.nextSibling;
19780
- parentNode.insertBefore(node, refNode);
19781
- if (node === lastNode) {
19782
- break;
19783
- }
19784
- node = nextNode;
19785
- } while (node);
19786
- }
19645
+ exports.default = voidMap;
19787
19646
  });
19788
19647
  enifed('morph-range', ['exports', 'morph-range/utils'], function (exports, _morphRangeUtils) {
19789
19648
  'use strict';
@@ -20064,6 +19923,145 @@ enifed('morph-range', ['exports', 'morph-range/utils'], function (exports, _morp
20064
19923
 
20065
19924
  exports.default = Morph;
20066
19925
  });
19926
+ enifed('morph-range/morph-list', ['exports', 'morph-range/utils'], function (exports, _morphRangeUtils) {
19927
+ 'use strict';
19928
+
19929
+ function MorphList() {
19930
+ // morph graph
19931
+ this.firstChildMorph = null;
19932
+ this.lastChildMorph = null;
19933
+
19934
+ this.mountedMorph = null;
19935
+ }
19936
+
19937
+ var prototype = MorphList.prototype;
19938
+
19939
+ prototype.clear = function MorphList$clear() {
19940
+ var current = this.firstChildMorph;
19941
+
19942
+ while (current) {
19943
+ var next = current.nextMorph;
19944
+ current.previousMorph = null;
19945
+ current.nextMorph = null;
19946
+ current.parentMorphList = null;
19947
+ current = next;
19948
+ }
19949
+
19950
+ this.firstChildMorph = this.lastChildMorph = null;
19951
+ };
19952
+
19953
+ prototype.destroy = function MorphList$destroy() {};
19954
+
19955
+ prototype.appendMorph = function MorphList$appendMorph(morph) {
19956
+ this.insertBeforeMorph(morph, null);
19957
+ };
19958
+
19959
+ prototype.insertBeforeMorph = function MorphList$insertBeforeMorph(morph, referenceMorph) {
19960
+ if (morph.parentMorphList !== null) {
19961
+ morph.unlink();
19962
+ }
19963
+ if (referenceMorph && referenceMorph.parentMorphList !== this) {
19964
+ throw new Error('The morph before which the new morph is to be inserted is not a child of this morph.');
19965
+ }
19966
+
19967
+ var mountedMorph = this.mountedMorph;
19968
+
19969
+ if (mountedMorph) {
19970
+
19971
+ var parentNode = mountedMorph.firstNode.parentNode;
19972
+ var referenceNode = referenceMorph ? referenceMorph.firstNode : mountedMorph.lastNode.nextSibling;
19973
+
19974
+ _morphRangeUtils.insertBefore(parentNode, morph.firstNode, morph.lastNode, referenceNode);
19975
+
19976
+ // was not in list mode replace current content
19977
+ if (!this.firstChildMorph) {
19978
+ _morphRangeUtils.clear(this.mountedMorph.firstNode.parentNode, this.mountedMorph.firstNode, this.mountedMorph.lastNode);
19979
+ }
19980
+ }
19981
+
19982
+ morph.parentMorphList = this;
19983
+
19984
+ var previousMorph = referenceMorph ? referenceMorph.previousMorph : this.lastChildMorph;
19985
+ if (previousMorph) {
19986
+ previousMorph.nextMorph = morph;
19987
+ morph.previousMorph = previousMorph;
19988
+ } else {
19989
+ this.firstChildMorph = morph;
19990
+ }
19991
+
19992
+ if (referenceMorph) {
19993
+ referenceMorph.previousMorph = morph;
19994
+ morph.nextMorph = referenceMorph;
19995
+ } else {
19996
+ this.lastChildMorph = morph;
19997
+ }
19998
+
19999
+ this.firstChildMorph._syncFirstNode();
20000
+ this.lastChildMorph._syncLastNode();
20001
+ };
20002
+
20003
+ prototype.removeChildMorph = function MorphList$removeChildMorph(morph) {
20004
+ if (morph.parentMorphList !== this) {
20005
+ throw new Error("Cannot remove a morph from a parent it is not inside of");
20006
+ }
20007
+
20008
+ morph.destroy();
20009
+ };
20010
+
20011
+ exports.default = MorphList;
20012
+ });
20013
+ enifed('morph-range/morph-list.umd', ['exports', 'morph-range/morph-list'], function (exports, _morphRangeMorphList) {
20014
+ 'use strict';
20015
+
20016
+ (function (root, factory) {
20017
+ if (typeof define === 'function' && define.amd) {
20018
+ define([], factory);
20019
+ } else if (typeof exports === 'object') {
20020
+ module.exports = factory();
20021
+ } else {
20022
+ root.MorphList = factory();
20023
+ }
20024
+ })(undefined, function () {
20025
+ return _morphRangeMorphList.default;
20026
+ });
20027
+ });
20028
+ enifed("morph-range/utils", ["exports"], function (exports) {
20029
+ // inclusive of both nodes
20030
+ "use strict";
20031
+
20032
+ exports.clear = clear;
20033
+ exports.insertBefore = insertBefore;
20034
+
20035
+ function clear(parentNode, firstNode, lastNode) {
20036
+ if (!parentNode) {
20037
+ return;
20038
+ }
20039
+
20040
+ var node = firstNode;
20041
+ var nextNode;
20042
+ do {
20043
+ nextNode = node.nextSibling;
20044
+ parentNode.removeChild(node);
20045
+ if (node === lastNode) {
20046
+ break;
20047
+ }
20048
+ node = nextNode;
20049
+ } while (node);
20050
+ }
20051
+
20052
+ function insertBefore(parentNode, firstNode, lastNode, refNode) {
20053
+ var node = firstNode;
20054
+ var nextNode;
20055
+ do {
20056
+ nextNode = node.nextSibling;
20057
+ parentNode.insertBefore(node, refNode);
20058
+ if (node === lastNode) {
20059
+ break;
20060
+ }
20061
+ node = nextNode;
20062
+ } while (node);
20063
+ }
20064
+ });
20067
20065
  enifed("simple-html-tokenizer/entity-parser", ["exports"], function (exports) {
20068
20066
  "use strict";
20069
20067