Skip to content

Commit 1da750c

Browse files
committed
WIP: TODO notes
1 parent 0c3b65a commit 1da750c

File tree

10 files changed

+29
-0
lines changed

10 files changed

+29
-0
lines changed

src/Angular.js

+2
Original file line numberDiff line numberDiff line change
@@ -440,6 +440,7 @@ function isDefined(value){return typeof value !== 'undefined';}
440440
* @param {*} value Reference to check.
441441
* @returns {boolean} True if `value` is an `Object` but not `null`.
442442
*/
443+
// TODO(perf): use !== null to avoid conversion???
443444
function isObject(value){return value != null && typeof value === 'object';}
444445

445446

@@ -832,6 +833,7 @@ function shallowCopy(src, dst) {
832833
if (isArray(src)) {
833834
dst = dst || [];
834835

836+
// TODO(perf): how about slice?
835837
for (l = src.length; i < l; i++) {
836838
dst[i] = src[i];
837839
}

src/jqLite.js

+3
Original file line numberDiff line numberDiff line change
@@ -253,8 +253,10 @@ function jqLiteClone(element) {
253253
function jqLiteDealoc(element, onlyDescendants){
254254
if (!onlyDescendants) jqLiteRemoveData(element);
255255

256+
// TODO(perf): do we need to check length here? if so, cache childNodes
256257
if (element.childNodes && element.childNodes.length) {
257258
// we use querySelectorAll because documentFragments don't have getElementsByTagName
259+
// TODO(perf): since we need to slice the live list, shoudn't we just use querySelectorAll all the time?
258260
var descendants = element.getElementsByTagName ? sliceArgs(element.getElementsByTagName('*')) :
259261
element.querySelectorAll ? element.querySelectorAll('*') : [];
260262
for (var i = 0, l = descendants.length; i < l; i++) {
@@ -307,6 +309,7 @@ function jqLiteRemoveData(element, name) {
307309
}
308310
jqLiteOff(element);
309311
}
312+
// TODO(perf): delete vs set to undefined?
310313
delete jqCache[expandoId];
311314
element.ng339 = undefined; // don't delete DOM expandos. IE and Chrome don't like it
312315
}

src/ng/compile.js

+7
Original file line numberDiff line numberDiff line change
@@ -911,6 +911,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
911911
: $compileNodes;
912912

913913
if (transcludeControllers) {
914+
// TODO(perf): use Object.create(null) for transcludeControllers and then `for in`
914915
var names = Object.keys(transcludeControllers);
915916
var i = names.length;
916917
var name;
@@ -1061,6 +1062,8 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
10611062

10621063
var clone = transcludeFn(transcludedScope, cloneFn, controllers, previousBoundTranscludeFn);
10631064
if (scopeCreated) {
1065+
// TODO(perf): do we really need this? looks bogus + tries to registers listeners on
1066+
// boundary comment needs in repeater
10641067
clone.on('$destroy', function() { transcludedScope.$destroy(); });
10651068
}
10661069
return clone;
@@ -1670,6 +1673,8 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
16701673
var transcludeControllers;
16711674

16721675
// no scope passed
1676+
// TODO(perf): arguments.length is slow, check if cloneAttachFn is truthy instead
1677+
// http://jsperf.com/isundefined-vs-arguments-length
16731678
if (arguments.length < 2) {
16741679
cloneAttachFn = scope;
16751680
scope = undefined;
@@ -2075,6 +2080,8 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
20752080
if (parent) {
20762081
parent.replaceChild(newNode, firstElementToRemove);
20772082
}
2083+
2084+
// TODO(perf): what are we doing with this document fragment? could we return it for cloning?
20782085
var fragment = document.createDocumentFragment();
20792086
fragment.appendChild(firstElementToRemove);
20802087
newNode[jqLite.expando] = firstElementToRemove[jqLite.expando];

src/ng/directive/input.js

+2
Original file line numberDiff line numberDiff line change
@@ -1188,6 +1188,7 @@ function radioInputType(scope, element, attr, ctrl) {
11881188

11891189
ctrl.$render = function() {
11901190
var value = attr.value;
1191+
// TODO(perf): update checked only when match since only one radio button can be checked at a time?
11911192
element[0].checked = (value == ctrl.$viewValue);
11921193
};
11931194

@@ -1966,6 +1967,7 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
19661967
modelValue = modelValue();
19671968
}
19681969

1970+
// TODO(perf): why not move this to the action fn?
19691971
// if scope model value and ngModel value are out of sync
19701972
if (ctrl.$modelValue !== modelValue &&
19711973
(isUndefined(ctrl.$$invalidModelValue) || ctrl.$$invalidModelValue != modelValue)) {

src/ng/directive/ngBind.js

+1
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ var ngBindDirective = ['$compile', function($compile) {
5959
// We are purposefully using == here rather than === because we want to
6060
// catch when value is "null or undefined"
6161
// jshint -W041
62+
// TODO(perf): consider setting textContent directly
6263
element.text(value == undefined ? '' : value);
6364
});
6465
}

src/ng/directive/ngRepeat.js

+4
Original file line numberDiff line numberDiff line change
@@ -341,6 +341,7 @@ var ngRepeatDirective = ['$parse', '$animate', function($parse, $animate) {
341341
arrayLength = collectionKeys.length;
342342

343343
// locate existing items
344+
// TODO(perf): don't reset nextBlockOrder.length ???
344345
length = nextBlockOrder.length = collectionKeys.length;
345346
for (index = 0; index < length; index++) {
346347
key = (collection === collectionKeys) ? index : collectionKeys[index];
@@ -386,6 +387,7 @@ var ngRepeatDirective = ['$parse', '$animate', function($parse, $animate) {
386387
key = (collection === collectionKeys) ? index : collectionKeys[index];
387388
value = collection[key];
388389
block = nextBlockOrder[index];
390+
// TODO(perf): simplify previousBlockBoundaryNode calculation
389391
if (nextBlockOrder[index - 1]) previousNode = getBlockEnd(nextBlockOrder[index - 1]);
390392

391393
if (block.scope) {
@@ -406,8 +408,10 @@ var ngRepeatDirective = ['$parse', '$animate', function($parse, $animate) {
406408
// new item which we don't know about
407409
$transclude(function ngRepeatTransclude(clone, scope) {
408410
block.scope = scope;
411+
// TODO(perf): could we move this into the template element and have it cloned with it?
409412
// http://jsperf.com/clone-vs-createcomment
410413
clone[clone.length++] = ngRepeatEndComment.cloneNode();
414+
// TODO(perf): support naked previousNode in `enter`?
411415
$animate.enter(clone, null, jqLite(previousNode));
412416
previousNode = clone;
413417
// Note: We only need the first/last node of the cloned nodes.

src/ng/directive/ngSwitch.js

+1
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,7 @@ var ngSwitchDirective = ['$animate', function($animate) {
156156
selectedScopes[i].$destroy();
157157
previousElements[i] = selected;
158158
$animate.leave(selected, function() {
159+
// TODO(perf): this schedules rAF even without animations which dealocs the elements again via previousElements[i].remove() above;
159160
previousElements.splice(i, 1);
160161
});
161162
}

src/ng/httpBackend.js

+1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
'use strict';
22

33
function createXhr(method) {
4+
// TODO(ie): remove
45
//if IE and the method is not RFC2616 compliant, or if XMLHttpRequest
56
//is not available, try getting an ActiveXObject. Otherwise, use XMLHttpRequest
67
//if it is available

src/ng/parse.js

+1
Original file line numberDiff line numberDiff line change
@@ -308,6 +308,7 @@ Lexer.prototype = {
308308
token.constant = true;
309309
} else {
310310
var getter = getterFn(ident, this.options, this.text);
311+
// TODO(perf): consider exposing the getter reference
311312
token.fn = extend(function(self, locals) {
312313
return (getter(self, locals));
313314
}, {

src/ng/rootScope.js

+7
Original file line numberDiff line numberDiff line change
@@ -529,6 +529,7 @@ function $RootScopeProvider(){
529529
oldValue.length = oldLength = newLength;
530530
}
531531
// copy the items to oldValue and look for changes.
532+
// TODO(perf): consider caching oldValue[i] and newValue[i]
532533
for (var i = 0; i < newLength; i++) {
533534
bothNaN = (oldValue[i] !== oldValue[i]) &&
534535
(newValue[i] !== newValue[i]);
@@ -540,6 +541,7 @@ function $RootScopeProvider(){
540541
} else {
541542
if (oldValue !== internalObject) {
542543
// we are transitioning from something which was not an object into object.
544+
// TODO(perf): Object.create(null) + don't use hasOwnProperty for oldValue
543545
oldValue = internalObject = {};
544546
oldLength = 0;
545547
changeDetected++;
@@ -700,7 +702,10 @@ function $RootScopeProvider(){
700702
watch = watchers[length];
701703
// Most common watches are on primitives, in which case we can short
702704
// circuit it with === operator, only when === fails do we use .equals
705+
// TODO(perf): is this if needed?
703706
if (watch) {
707+
// TODO(perf): the last typeof number + NaN checks are executed for all counter watches
708+
// can we skip it or at least remember if the lastValue is NaN
704709
if ((value = watch.get(current)) !== (last = watch.last) &&
705710
!(watch.eq
706711
? equals(value, last)
@@ -709,6 +714,7 @@ function $RootScopeProvider(){
709714
dirty = true;
710715
lastDirtyWatch = watch;
711716
watch.last = watch.eq ? copy(value, null) : value;
717+
// TODO(perf): initialize all watches via async queue?
712718
watch.fn(value, ((last === initWatchVal) ? value : last), current);
713719
if (ttl < 5) {
714720
logIdx = 4 - ttl;
@@ -811,6 +817,7 @@ function $RootScopeProvider(){
811817
this.$$destroyed = true;
812818
if (this === $rootScope) return;
813819

820+
// TODO(perf): $$listenerCount should be Object.create(null), then use `for in`
814821
forEach(this.$$listenerCount, bind(null, decrementListenerCount, this));
815822

816823
// sever all the references to parent scopes (after this cleanup, the current scope should

0 commit comments

Comments
 (0)