From 6b4f2fca15a92ca1db59f5f963d22c0910e5c5f3 Mon Sep 17 00:00:00 2001 From: bluepnume Date: Fri, 9 Jan 2015 03:37:09 -0800 Subject: [PATCH 1/3] fix($q): correctly set constructor on prototypes This patch will correctly set `Promise.prototype.constructor` and `Deferred.prototype.constructor`. When prototype is set in the form `Foo.prototype = {x: y};`, the constructor will not be set correctly (as opposed to in the form `Foo.prototype.x = y;`. As such, it is necessary to manually add the constructor to the prototype in these cases. --- src/ng/q.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/ng/q.js b/src/ng/q.js index 7353be52e18d..be5911fbdbf0 100644 --- a/src/ng/q.js +++ b/src/ng/q.js @@ -271,6 +271,8 @@ function qFactory(nextTick, exceptionHandler) { } Promise.prototype = { + constructor: Promise, + then: function(onFulfilled, onRejected, progressBack) { var result = new Deferred(); @@ -340,6 +342,8 @@ function qFactory(nextTick, exceptionHandler) { } Deferred.prototype = { + constructor: Deferred, + resolve: function(val) { if (this.promise.$$state.status) return; if (val === this.promise) { From 8bc6e76af8e0f22765880ba87c845e4fd920921c Mon Sep 17 00:00:00 2001 From: bluepnume Date: Fri, 9 Jan 2015 05:03:41 -0800 Subject: [PATCH 2/3] fix(promises-aplus): Add setHashKey and extend Add `setHashKey` and `extend` methods, to allow `$q` to use `extend` to extend its prototype. --- .../promises-aplus-test-adapter.js | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/lib/promises-aplus/promises-aplus-test-adapter.js b/lib/promises-aplus/promises-aplus-test-adapter.js index ba1ad125902b..e65127e73090 100644 --- a/lib/promises-aplus/promises-aplus-test-adapter.js +++ b/lib/promises-aplus/promises-aplus-test-adapter.js @@ -10,6 +10,31 @@ var minErr = function minErr (module, constructor) { throw new ErrorConstructor(module + arguments[0] + arguments[1]); }; }; +var setHashKey = function setHashKey(obj, h) { + if (h) { + obj.$$hashKey = h; + } + else { + delete obj.$$hashKey; + } +} +var extend = function extend(dst) { + var h = dst.$$hashKey; + + for (var i = 1, ii = arguments.length; i < ii; i++) { + var obj = arguments[i]; + if (obj) { + var keys = Object.keys(obj); + for (var j = 0, jj = keys.length; j < jj; j++) { + var key = keys[j]; + dst[key] = obj[key]; + } + } + } + + setHashKey(dst, h); + return dst; +} var $q = qFactory(process.nextTick, function noopExceptionHandler() {}); From 3361db7833a5e24d49b82bc0982c03a6826df2e0 Mon Sep 17 00:00:00 2001 From: bluepnume Date: Fri, 9 Jan 2015 05:05:29 -0800 Subject: [PATCH 3/3] fix($q): Use extend to avoid overwriting prototype Use `extend` on `Promise.prototype` and `Deferred.prototype`, to avoid having to manually set `constructor` on the overwritten prototypes. --- src/ng/q.js | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/ng/q.js b/src/ng/q.js index be5911fbdbf0..7a8087c7f81a 100644 --- a/src/ng/q.js +++ b/src/ng/q.js @@ -270,7 +270,7 @@ function qFactory(nextTick, exceptionHandler) { this.$$state = { status: 0 }; } - Promise.prototype = { + extend(Promise.prototype, { constructor: Promise, then: function(onFulfilled, onRejected, progressBack) { @@ -294,7 +294,7 @@ function qFactory(nextTick, exceptionHandler) { return handleCallback(error, false, callback); }, progressBack); } - }; + }); //Faster, more basic than angular.bind http://jsperf.com/angular-bind-vs-custom-vs-native function simpleBind(context, fn) { @@ -341,9 +341,7 @@ function qFactory(nextTick, exceptionHandler) { this.notify = simpleBind(this, this.notify); } - Deferred.prototype = { - constructor: Deferred, - + extend(Deferred.prototype, { resolve: function(val) { if (this.promise.$$state.status) return; if (val === this.promise) { @@ -407,7 +405,7 @@ function qFactory(nextTick, exceptionHandler) { }); } } - }; + }); /** * @ngdoc method