ember-source 2.6.1 → 2.6.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -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