dist/ember-runtime.js in ember-source-1.6.0.beta.4 vs dist/ember-runtime.js in ember-source-1.6.0.beta.5
- old
+ new
@@ -3,11 +3,11 @@
* @copyright Copyright 2011-2014 Tilde Inc. and contributors
* Portions Copyright 2006-2011 Strobe Inc.
* Portions Copyright 2008-2011 Apple Inc. All rights reserved.
* @license Licensed under MIT license
* See https://raw.github.com/emberjs/ember.js/master/LICENSE
- * @version 1.6.0-beta.4
+ * @version 1.6.0-beta.5
*/
(function() {
var define, requireModule, require, requirejs, Ember;
@@ -1679,10 +1679,11 @@
todoList.get('done'); // false
todoList.get('todos').clear();
todoList.get('done'); // true
```
+ @since 1.6.0
@method computed.empty
@for Ember
@param {String} dependentKey
@return {Ember.ComputedProperty} computed property which negate
the original value for property
@@ -2170,11 +2171,11 @@
*/
computed.alias = function(dependentKey) {
return computed(dependentKey, function(key, value) {
if (arguments.length > 1) {
set(this, dependentKey, value);
- return value;
+ return get(this, dependentKey);
} else {
return get(this, dependentKey);
}
});
};
@@ -2323,11 +2324,11 @@
The core Runtime framework is based on the jQuery API with a number of
performance optimizations.
@class Ember
@static
- @version 1.6.0-beta.4
+ @version 1.6.0-beta.5
*/
if ('undefined' === typeof Ember) {
// Create core object. Make it act like an instance of Ember.Namespace so that
// objects assigned to it are given a sane string representation.
@@ -2350,14 +2351,14 @@
/**
@property VERSION
@type String
- @default '1.6.0-beta.4'
+ @default '1.6.0-beta.5'
@static
*/
- Ember.VERSION = '1.6.0-beta.4';
+ Ember.VERSION = '1.6.0-beta.5';
/**
Standard environmental variables. You can define these in a global `EmberENV`
variable before loading Ember to control various configuration settings.
@@ -2438,11 +2439,11 @@
// ..........................................................
// BOOTSTRAP
//
/**
- Determines whether Ember should enhances some built-in object prototypes to
+ Determines whether Ember should enhance some built-in object prototypes to
provide a more friendly API. If enabled, a few methods will be added to
`Function`, `String`, and `Array`. `Object.prototype` will not be enhanced,
which is the one that causes most trouble for people.
In general we recommend leaving this option set to true since it rarely
@@ -3214,28 +3215,29 @@
__exports__.listenersFor = listenersFor;
__exports__.listenersDiff = listenersDiff;
__exports__.listenersUnion = listenersUnion;
});
define("ember-metal/expand_properties",
- ["ember-metal/enumerable_utils","exports"],
- function(__dependency1__, __exports__) {
+ ["ember-metal/error","ember-metal/enumerable_utils","exports"],
+ function(__dependency1__, __dependency2__, __exports__) {
"use strict";
- var EnumerableUtils = __dependency1__["default"];
+ var EmberError = __dependency1__["default"];
+ var EnumerableUtils = __dependency2__["default"];
/**
@module ember-metal
*/
var forEach = EnumerableUtils.forEach,
- BRACE_EXPANSION = /^((?:[^\.]*\.)*)\{(.*)\}$/;
+ BRACE_EXPANSION = /^((?:[^\.]*\.)*)\{(.*)\}$/;
/**
Expands `pattern`, invoking `callback` for each expansion.
The only pattern supported is brace-expansion, anything else will be passed
once to `callback` directly. Brace expansion can only appear at the end of a
- pattern, for example as the last item in a chain.
+ pattern, for an example see the last call below.
Example
```js
function echo(arg){ console.log(arg); }
@@ -3252,16 +3254,21 @@
expansion, and is passed the expansion.
*/
function expandProperties(pattern, callback) {
var match, prefix, list;
+ if (pattern.indexOf(' ') > -1) {
+ throw new EmberError('Brace expanded properties cannot contain spaces, ' +
+ 'e.g. `user.{firstName, lastName}` should be `user.{firstName,lastName}`');
+ }
+
if (match = BRACE_EXPANSION.exec(pattern)) {
prefix = match[1];
list = match[2];
forEach(list.split(','), function (suffix) {
- callback(prefix + suffix);
+ callback(prefix + suffix);
});
} else {
callback(pattern);
}
};
@@ -6920,38 +6927,41 @@
return apply(backburner, backburner.debounce, arguments);
};
/**
Ensure that the target method is never called more frequently than
- the specified spacing period.
+ the specified spacing period. The target method is called immediately.
```javascript
var myFunc = function() { console.log(this.name + ' ran.'); };
var myContext = {name: 'throttle'};
run.throttle(myContext, myFunc, 150);
// myFunc is invoked with context myContext
+ // console logs 'throttle ran.'
// 50ms passes
run.throttle(myContext, myFunc, 150);
// 50ms passes
run.throttle(myContext, myFunc, 150);
// 150ms passes
run.throttle(myContext, myFunc, 150);
// myFunc is invoked with context myContext
- // console logs 'throttle ran.' twice, 250ms apart.
+ // console logs 'throttle ran.'
```
@method throttle
@param {Object} [target] target of method to invoke
@param {Function|String} method The method to invoke.
May be a function or a string. If you pass a string
then it will be looked up on the passed target.
@param {Object} [args*] Optional arguments to pass to the timeout.
@param {Number} spacing Number of milliseconds to space out requests.
+ @param {Boolean} immediate Trigger the function on the leading instead
+ of the trailing edge of the wait interval. Defaults to true.
@return {Array} Timer information for use in cancelling, see `run.cancel`.
*/
run.throttle = function() {
return apply(backburner, backburner.throttle, arguments);
};
@@ -7398,11 +7408,11 @@
@param {Object} obj The object to test
@return {Boolean} true if the passed object is an array or Array-like
*/
// ES6TODO: Move up to runtime? This is only use in ember-metal by concatenatedProperties
function isArray(obj) {
- var modulePath;
+ var modulePath, type;
if (typeof EmberArray === "undefined") {
modulePath = 'ember-runtime/mixins/array';
if (requirejs._eak_seen[modulePath]) {
EmberArray = requireModule(modulePath)['default'];
@@ -7410,11 +7420,14 @@
}
if (!obj || obj.setInterval) { return false; }
if (Array.isArray && Array.isArray(obj)) { return true; }
if (EmberArray && EmberArray.detect(obj)) { return true; }
- if ((obj.length !== undefined) && 'object'=== typeOf(obj)) { return true; }
+
+ type = typeOf(obj);
+ if ('array' === type) { return true; }
+ if ((obj.length !== undefined) && 'object' === type) { return true; }
return false;
};
/**
Forces the passed object to be part of an array. If the object is already
@@ -7815,22 +7828,24 @@
__exports__.tryFinally = tryFinally;
__exports__.wrap = wrap;
__exports__.applyStr = applyStr;
__exports__.apply = apply;
});
-define("backburner",
- ["backburner/deferred_action_queues","exports"],
- function(__dependency1__, __exports__) {
+define("backburner",
+ ["backburner/utils","backburner/deferred_action_queues","exports"],
+ function(__dependency1__, __dependency2__, __exports__) {
"use strict";
- var DeferredActionQueues = __dependency1__.DeferredActionQueues;
+ var Utils = __dependency1__["default"];
+ var DeferredActionQueues = __dependency2__.DeferredActionQueues;
var slice = [].slice,
pop = [].pop,
- throttlers = [],
- debouncees = [],
+ each = Utils.each,
+ isString = Utils.isString,
+ isFunction = Utils.isFunction,
+ isNumber = Utils.isNumber,
timers = [],
- autorun, laterTimer, laterTimerExpiresAt,
global = this,
NUMBER = /\d+/;
// In IE 6-8, try/finally doesn't work without a catch.
// Unfortunately, this is impossible to test for since wrapping it in a parent try/catch doesn't trigger the bug.
@@ -7840,20 +7855,22 @@
catch(e) { } // jshint ignore:line
return !!e;
})();
function isCoercableNumber(number) {
- return typeof number === 'number' || NUMBER.test(number);
+ return isNumber(number) || NUMBER.test(number);
}
function Backburner(queueNames, options) {
this.queueNames = queueNames;
this.options = options || {};
if (!this.options.defaultQueue) {
this.options.defaultQueue = queueNames[0];
}
this.instanceStack = [];
+ this._debouncees = [];
+ this._throttlers = [];
}
Backburner.prototype = {
queueNames: null,
options: null,
@@ -7903,25 +7920,23 @@
}
}
},
run: function(target, method /*, args */) {
- var options = this.options,
- ret, length = arguments.length;
+ var onError = getOnError(this.options);
this.begin();
if (!method) {
method = target;
target = null;
}
- if (typeof method === 'string') {
+ if (isString(method)) {
method = target[method];
}
- var onError = options.onError || (options.onErrorTarget && options.onErrorTarget[options.onErrorMethod]);
var args = slice.call(arguments, 2);
// guard against Safari 6's double-finally bug
var didFinally = false;
@@ -7952,11 +7967,11 @@
if (!method) {
method = target;
target = null;
}
- if (typeof method === 'string') {
+ if (isString(method)) {
method = target[method];
}
var stack = this.DEBUG ? new Error() : undefined,
args = arguments.length > 3 ? slice.call(arguments, 3) : undefined;
@@ -7968,38 +7983,36 @@
if (!method) {
method = target;
target = null;
}
- if (typeof method === 'string') {
+ if (isString(method)) {
method = target[method];
}
var stack = this.DEBUG ? new Error() : undefined,
args = arguments.length > 3 ? slice.call(arguments, 3) : undefined;
if (!this.currentInstance) { createAutorun(this); }
return this.currentInstance.schedule(queueName, target, method, args, true, stack);
},
setTimeout: function() {
- var args = slice.call(arguments);
- var length = args.length;
- var method, wait, target;
- var self = this;
- var methodOrTarget, methodOrWait, methodOrArgs;
- var options = this.options;
+ var args = slice.call(arguments),
+ length = args.length,
+ method, wait, target,
+ methodOrTarget, methodOrWait, methodOrArgs;
if (length === 0) {
return;
} else if (length === 1) {
method = args.shift();
wait = 0;
} else if (length === 2) {
methodOrTarget = args[0];
methodOrWait = args[1];
- if (typeof methodOrWait === 'function' || typeof methodOrTarget[methodOrWait] === 'function') {
+ if (isFunction(methodOrWait) || isFunction(methodOrTarget[methodOrWait])) {
target = args.shift();
method = args.shift();
wait = 0;
} else if (isCoercableNumber(methodOrWait)) {
method = args.shift();
@@ -8018,27 +8031,27 @@
}
methodOrTarget = args[0];
methodOrArgs = args[1];
- if (typeof methodOrArgs === 'function' || (typeof methodOrArgs === 'string' &&
- methodOrTarget !== null &&
- methodOrArgs in methodOrTarget)) {
+ if (isFunction(methodOrArgs) || (isString(methodOrArgs) &&
+ methodOrTarget !== null &&
+ methodOrArgs in methodOrTarget)) {
target = args.shift();
method = args.shift();
} else {
method = args.shift();
}
}
var executeAt = (+new Date()) + parseInt(wait, 10);
- if (typeof method === 'string') {
+ if (isString(method)) {
method = target[method];
}
- var onError = options.onError || (options.onErrorTarget && options.onErrorTarget[options.onErrorMethod]);
+ var onError = getOnError(this.options);
function fn() {
if (onError) {
try {
method.apply(target, args);
@@ -8053,11 +8066,11 @@
// find position to insert
var i = searchTimer(executeAt, timers);
timers.splice(i, 0, executeAt, fn);
- updateLaterTimer(self, executeAt, wait);
+ updateLaterTimer(this, executeAt, wait);
return fn;
},
throttle: function(target, method /* , args, wait, [immediate] */) {
@@ -8067,37 +8080,39 @@
wait,
throttler,
index,
timer;
- if (typeof immediate === "number" || typeof immediate === "string") {
+ if (isNumber(immediate) || isString(immediate)) {
wait = immediate;
immediate = true;
} else {
wait = pop.call(args);
}
wait = parseInt(wait, 10);
- index = findThrottler(target, method);
- if (index > -1) { return throttlers[index]; } // throttled
+ index = findThrottler(target, method, this._throttlers);
+ if (index > -1) { return this._throttlers[index]; } // throttled
timer = global.setTimeout(function() {
if (!immediate) {
self.run.apply(self, args);
}
- var index = findThrottler(target, method);
- if (index > -1) { throttlers.splice(index, 1); }
+ var index = findThrottler(target, method, self._throttlers);
+ if (index > -1) {
+ self._throttlers.splice(index, 1);
+ }
}, wait);
if (immediate) {
self.run.apply(self, args);
}
throttler = [target, method, timer];
- throttlers.push(throttler);
+ this._throttlers.push(throttler);
return throttler;
},
debounce: function(target, method /* , args, wait, [immediate] */) {
@@ -8107,75 +8122,73 @@
wait,
index,
debouncee,
timer;
- if (typeof immediate === "number" || typeof immediate === "string") {
+ if (isNumber(immediate) || isString(immediate)) {
wait = immediate;
immediate = false;
} else {
wait = pop.call(args);
}
wait = parseInt(wait, 10);
// Remove debouncee
- index = findDebouncee(target, method);
+ index = findDebouncee(target, method, this._debouncees);
if (index > -1) {
- debouncee = debouncees[index];
- debouncees.splice(index, 1);
+ debouncee = this._debouncees[index];
+ this._debouncees.splice(index, 1);
clearTimeout(debouncee[2]);
}
timer = global.setTimeout(function() {
if (!immediate) {
self.run.apply(self, args);
}
- var index = findDebouncee(target, method);
+ var index = findDebouncee(target, method, self._debouncees);
if (index > -1) {
- debouncees.splice(index, 1);
+ self._debouncees.splice(index, 1);
}
}, wait);
if (immediate && index === -1) {
self.run.apply(self, args);
}
debouncee = [target, method, timer];
- debouncees.push(debouncee);
+ self._debouncees.push(debouncee);
return debouncee;
},
cancelTimers: function() {
- var i, len;
+ var clearItems = function(item) {
+ clearTimeout(item[2]);
+ };
- for (i = 0, len = throttlers.length; i < len; i++) {
- clearTimeout(throttlers[i][2]);
- }
- throttlers = [];
+ each(this._throttlers, clearItems);
+ this._throttlers = [];
- for (i = 0, len = debouncees.length; i < len; i++) {
- clearTimeout(debouncees[i][2]);
- }
- debouncees = [];
+ each(this._debouncees, clearItems);
+ this._debouncees = [];
- if (laterTimer) {
- clearTimeout(laterTimer);
- laterTimer = null;
+ if (this._laterTimer) {
+ clearTimeout(this._laterTimer);
+ this._laterTimer = null;
}
timers = [];
- if (autorun) {
- clearTimeout(autorun);
- autorun = null;
+ if (this._autorun) {
+ clearTimeout(this._autorun);
+ this._autorun = null;
}
},
hasTimers: function() {
- return !!timers.length || !!debouncees.length || !!throttlers.length || autorun;
+ return !!timers.length || !!this._debouncees.length || !!this._throttlers.length || this._autorun;
},
cancel: function(timer) {
var timerType = typeof timer;
@@ -8187,12 +8200,12 @@
timers.splice(i, 2); // remove the two elements
return true;
}
}
} else if (Object.prototype.toString.call(timer) === "[object Array]"){ // we're cancelling a throttle or debounce
- return this._cancelItem(findThrottler, throttlers, timer) ||
- this._cancelItem(findDebouncee, debouncees, timer);
+ return this._cancelItem(findThrottler, this._throttlers, timer) ||
+ this._cancelItem(findDebouncee, this._debouncees, timer);
} else {
return; // timer was null or not a timer
}
},
@@ -8200,11 +8213,11 @@
var item,
index;
if (timer.length < 3) { return false; }
- index = findMethod(timer[0], timer[1]);
+ index = findMethod(timer[0], timer[1], array);
if(index > -1) {
item = array[index];
@@ -8223,48 +8236,47 @@
Backburner.prototype.scheduleOnce = Backburner.prototype.deferOnce;
Backburner.prototype.later = Backburner.prototype.setTimeout;
if (needsIETryCatchFix) {
var originalRun = Backburner.prototype.run;
- Backburner.prototype.run = function() {
- try {
- originalRun.apply(this, arguments);
- } catch (e) {
- throw e;
- }
- };
+ Backburner.prototype.run = wrapInTryCatch(originalRun);
var originalEnd = Backburner.prototype.end;
- Backburner.prototype.end = function() {
+ Backburner.prototype.end = wrapInTryCatch(originalEnd);
+ }
+
+ function wrapInTryCatch(func) {
+ return function () {
try {
- originalEnd.apply(this, arguments);
+ return func.apply(this, arguments);
} catch (e) {
throw e;
}
};
}
+ function getOnError(options) {
+ return options.onError || (options.onErrorTarget && options.onErrorTarget[options.onErrorMethod]);
+ }
+
function createAutorun(backburner) {
backburner.begin();
- autorun = global.setTimeout(function() {
- autorun = null;
+ backburner._autorun = global.setTimeout(function() {
+ backburner._autorun = null;
backburner.end();
});
}
function updateLaterTimer(self, executeAt, wait) {
- if (!laterTimer || executeAt < laterTimerExpiresAt) {
- if (laterTimer) {
- clearTimeout(laterTimer);
- }
- laterTimer = global.setTimeout(function() {
- laterTimer = null;
- laterTimerExpiresAt = null;
+ if (!self._laterTimer || executeAt < self._laterTimerExpiresAt) {
+ self._laterTimer = global.setTimeout(function() {
+ self._laterTimer = null;
+ self._laterTimerExpiresAt = null;
executeTimers(self);
}, wait);
- laterTimerExpiresAt = executeAt;
+ self._laterTimerExpiresAt = executeAt;
}
}
function executeTimers(self) {
var now = +new Date(),
@@ -8283,32 +8295,25 @@
if (timers.length) {
updateLaterTimer(self, timers[0], timers[0] - now);
}
}
- function findDebouncee(target, method) {
- var debouncee,
- index = -1;
+ function findDebouncee(target, method, debouncees) {
+ return findItem(target, method, debouncees);
+ }
- for (var i = 0, l = debouncees.length; i < l; i++) {
- debouncee = debouncees[i];
- if (debouncee[0] === target && debouncee[1] === method) {
- index = i;
- break;
- }
- }
-
- return index;
+ function findThrottler(target, method, throttlers) {
+ return findItem(target, method, throttlers);
}
- function findThrottler(target, method) {
- var throttler,
+ function findItem(target, method, collection) {
+ var item,
index = -1;
- for (var i = 0, l = throttlers.length; i < l; i++) {
- throttler = throttlers[i];
- if (throttler[0] === target && throttler[1] === method) {
+ for (var i = 0, l = collection.length; i < l; i++) {
+ item = collection[i];
+ if (item[0] === target && item[1] === method) {
index = i;
break;
}
}
@@ -8339,27 +8344,29 @@
return (time >= timers[start]) ? start + 2 : start;
}
__exports__.Backburner = Backburner;
});
-define("backburner/deferred_action_queues",
- ["backburner/queue","exports"],
- function(__dependency1__, __exports__) {
+define("backburner/deferred_action_queues",
+ ["backburner/utils","backburner/queue","exports"],
+ function(__dependency1__, __dependency2__, __exports__) {
"use strict";
- var Queue = __dependency1__.Queue;
+ var Utils = __dependency1__["default"];
+ var Queue = __dependency2__.Queue;
+ var each = Utils.each,
+ isString = Utils.isString;
+
function DeferredActionQueues(queueNames, options) {
var queues = this.queues = {};
this.queueNames = queueNames = queueNames || [];
this.options = options;
- var queueName;
- for (var i = 0, l = queueNames.length; i < l; i++) {
- queueName = queueNames[i];
- queues[queueName] = new Queue(this, queueName, this.options);
- }
+ each(queueNames, function(queueName) {
+ queues[queueName] = new Queue(this, queueName, options);
+ });
}
DeferredActionQueues.prototype = {
queueNames: null,
queues: null,
@@ -8426,11 +8433,11 @@
target = queueItems[queueIndex];
method = queueItems[queueIndex+1];
args = queueItems[queueIndex+2];
stack = queueItems[queueIndex+3]; // Debugging assistance
- if (typeof method === 'string') { method = target[method]; }
+ if (isString(method)) { method = target[method]; }
// method could have been nullified / canceled during flush
if (method) {
invoke(target, method, args, onError);
}
@@ -8463,11 +8470,11 @@
return -1;
}
__exports__.DeferredActionQueues = DeferredActionQueues;
});
-define("backburner/queue",
+define("backburner/queue",
["exports"],
function(__exports__) {
"use strict";
function Queue(daq, name, options) {
this.daq = daq;
@@ -8502,11 +8509,11 @@
queue[i+3] = stack; // replace stack
return {queue: this, target: target, method: method};
}
}
- this._queue.push(target, method, args, stack);
+ queue.push(target, method, args, stack);
return {queue: this, target: target, method: method};
},
// TODO: remove me, only being used for Ember.run.sync
flush: function() {
@@ -8592,10 +8599,35 @@
}
};
__exports__.Queue = Queue;
});
+define("backburner/utils",
+ ["exports"],
+ function(__exports__) {
+ "use strict";
+ __exports__["default"] = {
+ each: function(collection, callback) {
+ for (var i = 0; i < collection.length; i++) {
+ callback(collection[i]);
+ }
+ },
+
+ isString: function(suspect) {
+ return typeof suspect === 'string';
+ },
+
+ isFunction: function(suspect) {
+ return typeof suspect === 'function';
+ },
+
+ isNumber: function(suspect) {
+ return typeof suspect === 'number';
+ }
+ };
+ });
+
define("ember-metal/watch_key",
["ember-metal/core","ember-metal/utils","ember-metal/platform","exports"],
function(__dependency1__, __dependency2__, __dependency3__, __exports__) {
"use strict";
var Ember = __dependency1__["default"];
@@ -14131,11 +14163,11 @@
},
init: function() {
this._super();
- this.set('_subControllers', Ember.A());
+ this.set('_subControllers', [ ]);
},
content: computed(function () {
return Ember.A();
}),
@@ -14181,17 +14213,27 @@
_subControllers: null,
_resetSubControllers: function() {
var subControllers = get(this, '_subControllers');
- if (subControllers) {
- forEach(subControllers, function(subController) {
- if (subController) { subController.destroy(); }
- });
+ var controller;
+
+ if (subControllers.length) {
+ for (var i = 0, length = subControllers.length; length > i; i++) {
+ controller = subControllers[i];
+ if (controller) {
+ controller.destroy();
+ }
+ }
+
+ subControllers.length = 0;
}
+ },
- this.set('_subControllers', Ember.A());
+ willDestroy: function() {
+ this._resetSubControllers();
+ this._super();
}
});
__exports__["default"] = ArrayController;
});
@@ -17647,10 +17689,12 @@
@param {Ember.Enumerable} objects the objects to remove
@return {Object} receiver
*/
removeObjects: function(objects) {
beginPropertyChanges(this);
- forEach(objects, function(obj) { this.removeObject(obj); }, this);
+ for (var i = objects.length - 1; i >= 0; i--) {
+ this.removeObject(objects[i]);
+ }
endPropertyChanges(this);
return this;
}
});