Skip to content

Commit c206f87

Browse files
author
Forbes Lindesay
committed
Avoid attaching unnecessary methods to the prototype
This doesn't seem to affect the benchmark significantly either way, and it helps make all those functions properly private.
1 parent dc5a7f6 commit c206f87

File tree

1 file changed

+55
-58
lines changed

1 file changed

+55
-58
lines changed

src/core.js

Lines changed: 55 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ function tryCallTwo(fn, a, b) {
5050
}
5151

5252
module.exports = Promise;
53+
5354
function Promise(fn) {
5455
if (typeof this !== 'object') {
5556
throw new TypeError('Promises must be constructed via new');
@@ -63,55 +64,54 @@ function Promise(fn) {
6364
if (fn === noop) return;
6465
doResolve(fn, this);
6566
}
66-
Promise.prototype._safeThen = function (onFulfilled, onRejected) {
67-
var self = this;
68-
return new this.constructor(function (resolve, reject) {
69-
var res = new Promise(noop);
70-
res.then(resolve, reject);
71-
self._handle(new Handler(onFulfilled, onRejected, res));
72-
});
73-
};
67+
7468
Promise.prototype.then = function(onFulfilled, onRejected) {
7569
if (this.constructor !== Promise) {
76-
return this._safeThen(onFulfilled, onRejected);
70+
return safeThen(this, onFulfilled, onRejected);
7771
}
7872
var res = new Promise(noop);
79-
this._handle(new Handler(onFulfilled, onRejected, res));
73+
handle(this, new Handler(onFulfilled, onRejected, res));
8074
return res;
8175
};
82-
Promise.prototype._handle = function(deferred) {
83-
if (this._state === 3) {
84-
this._value._handle(deferred);
85-
return;
76+
77+
function safeThen(self, onFulfilled, onRejected) {
78+
return new self.constructor(function (resolve, reject) {
79+
var res = new Promise(noop);
80+
res.then(resolve, reject);
81+
handle(self, new Handler(onFulfilled, onRejected, res));
82+
});
83+
};
84+
function handle(self, deferred) {
85+
while (self._state === 3) {
86+
self = self._value;
8687
}
87-
if (this._state === 0) {
88-
this._deferreds.push(deferred);
88+
if (self._state === 0) {
89+
self._deferreds.push(deferred);
8990
return;
9091
}
91-
var state = this._state;
92-
var value = this._value;
9392
asap(function() {
94-
var cb = state === 1 ? deferred.onFulfilled : deferred.onRejected;
93+
var cb = self._state === 1 ? deferred.onFulfilled : deferred.onRejected;
9594
if (cb === null) {
96-
if (state === 1) {
97-
deferred.promise._resolve(value);
95+
if (self._state === 1) {
96+
resolve(deferred.promise, self._value);
9897
} else {
99-
deferred.promise._reject(value);
98+
reject(deferred.promise, self._value);
10099
}
101100
return;
102101
}
103-
var ret = tryCallOne(cb, value);
102+
var ret = tryCallOne(cb, self._value);
104103
if (ret === IS_ERROR) {
105-
deferred.promise._reject(LAST_ERROR);
104+
reject(deferred.promise, LAST_ERROR);
106105
} else {
107-
deferred.promise._resolve(ret);
106+
resolve(deferred.promise, ret);
108107
}
109108
});
110-
};
111-
Promise.prototype._resolve = function(newValue) {
109+
}
110+
function resolve(self, newValue) {
112111
// Promise Resolution Procedure: https://github.com/promises-aplus/promises-spec#the-promise-resolution-procedure
113-
if (newValue === this) {
114-
return this._reject(
112+
if (newValue === self) {
113+
return reject(
114+
self,
115115
new TypeError('A promise cannot be resolved with itself.')
116116
);
117117
}
@@ -121,40 +121,37 @@ Promise.prototype._resolve = function(newValue) {
121121
) {
122122
var then = getThen(newValue);
123123
if (then === IS_ERROR) {
124-
return this._reject(LAST_ERROR);
124+
return reject(self, LAST_ERROR);
125125
}
126126
if (
127-
then === this.then &&
128-
newValue instanceof Promise &&
129-
newValue._handle === this._handle
127+
then === self.then &&
128+
newValue instanceof Promise
130129
) {
131-
this._state = 3;
132-
this._value = newValue;
133-
for (var i = 0; i < this._deferreds.length; i++) {
134-
newValue._handle(this._deferreds[i]);
135-
}
130+
self._state = 3;
131+
self._value = newValue;
132+
finale(self);
136133
return;
137134
} else if (typeof then === 'function') {
138-
doResolve(then.bind(newValue), this);
135+
doResolve(then.bind(newValue), self);
139136
return;
140137
}
141138
}
142-
this._state = 1;
143-
this._value = newValue;
144-
this._finale();
145-
};
146-
147-
Promise.prototype._reject = function (newValue) {
148-
this._state = 2;
149-
this._value = newValue;
150-
this._finale();
151-
};
152-
Promise.prototype._finale = function () {
153-
for (var i = 0; i < this._deferreds.length; i++)
154-
this._handle(this._deferreds[i]);
155-
this._deferreds = null;
156-
};
139+
self._state = 1;
140+
self._value = newValue;
141+
finale(self);
142+
}
157143

144+
function reject(self, newValue) {
145+
self._state = 2;
146+
self._value = newValue;
147+
finale(self);
148+
}
149+
function finale(self) {
150+
for (var i = 0; i < self._deferreds.length; i++) {
151+
handle(self, self._deferreds[i]);
152+
}
153+
self._deferreds = null;
154+
}
158155

159156
function Handler(onFulfilled, onRejected, promise){
160157
this.onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : null;
@@ -173,14 +170,14 @@ function doResolve(fn, promise) {
173170
var res = tryCallTwo(fn, function (value) {
174171
if (done) return;
175172
done = true;
176-
promise._resolve(value);
173+
resolve(promise, value);
177174
}, function (reason) {
178175
if (done) return;
179176
done = true;
180-
promise._reject(reason);
181-
});
177+
reject(promise, reason);
178+
})
182179
if (!done && res === IS_ERROR) {
183180
done = true;
184-
promise._reject(LAST_ERROR);
181+
reject(promise, LAST_ERROR);
185182
}
186183
}

0 commit comments

Comments
 (0)