Skip to content

Commit

Permalink
Describe how to use subclassing functionality of Map/Set/Promise.
Browse files Browse the repository at this point in the history
Also updated all our test cases to be consistent with the recommended
pattern. No change in functionality; we're just using appropriate ES6
methods (`Object.setPrototypeOf`) and making the `constructor` field
non-enumerable.
  • Loading branch information
cscott committed Feb 27, 2014
1 parent a04221b commit f7e8acb
Show file tree
Hide file tree
Showing 5 changed files with 35 additions and 15 deletions.
15 changes: 15 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,21 @@ For node.js:

Math functions accuracy is 1e-11.

## Subclassing
The `Map`, `Set`, and `Promise` implementations are subclassable.
You should use the following pattern to create a subclass in ES5 which
will continue to work in ES6:
```javascript
function MyPromise(exec) {
Promise.call(this, exec);
// ...
}
Object.setPrototypeOf(MyPromise, Promise);
MyPromise.prototype = Object.create(Promise.prototype, {
constructor: { value: MyPromise }
});
```

## String.prototype.normalize
Including a proper shim for `String.prototype.normalize` would
increase the size of this library by a factor of more than 4.
Expand Down
14 changes: 8 additions & 6 deletions test/collections.js
Original file line number Diff line number Diff line change
Expand Up @@ -86,9 +86,10 @@ describe('Collections', function() {
it('should be subclassable', function() {
var MyMap = function() { Map.call(this, [['a','b']]); }
if (!MyMap.__proto__) { return; } // skip test if on IE < 11
MyMap.__proto__ = Map;
MyMap.prototype = Object.create(Map.prototype);
MyMap.prototype.constructor = MyMap;
Object.setPrototypeOf(MyMap, Map);
MyMap.prototype = Object.create(Map.prototype, {
constructor: { value: MyMap }
});

map = new MyMap();
testMapping('c', 'd');
Expand Down Expand Up @@ -440,9 +441,10 @@ describe('Collections', function() {
it('should be subclassable', function() {
var MySet = function() { Set.call(this, ['a', 'b']); }
if (!MySet.__proto__) { return; } // skip test if on IE < 11
MySet.__proto__ = Set;
MySet.prototype = Object.create(Set.prototype);
MySet.prototype.constructor = MySet;
Object.setPrototypeOf(MySet, Set);
MySet.prototype = Object.create(Set.prototype, {
constructor: { value: MySet }
});

set = new MySet();
testSet('c'); testSet('d');
Expand Down
7 changes: 4 additions & 3 deletions test/promise/all.js
Original file line number Diff line number Diff line change
Expand Up @@ -176,9 +176,10 @@ describe("Promise.all", function () {
}
};
if (!P.__proto__) { return done(); } // skip test if on IE < 11
P.__proto__ = Promise;
P.prototype = Object.create(Promise.prototype);
P.prototype.constructor = P;
Object.setPrototypeOf(P, Promise);
P.prototype = Object.create(Promise.prototype, {
constructor: { value: P }
});
P.resolve = function(p) { return p; };

var g = [
Expand Down
7 changes: 4 additions & 3 deletions test/promise/evil-promises.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,10 @@ describe("Evil promises should not be able to break invariants", function () {
// Promise.resolve(evilPromise) is just the identity function.
var EvilPromise = function(executor) { Promise.call(this, executor); };
if (!EvilPromise.__proto__) { return; } // skip test if on IE < 11
EvilPromise.__proto__ = Promise; // mutable __proto__ is in es6.
EvilPromise.prototype = Object.create(Promise.prototype);
EvilPromise.prototype.constructor = EvilPromise;
Object.setPrototypeOf(EvilPromise, Promise);
EvilPromise.prototype = Object.create(Promise.prototype, {
constructor: { value: EvilPromise }
});

var evilPromise = EvilPromise.resolve();
evilPromise.then = function (f) {
Expand Down
7 changes: 4 additions & 3 deletions test/promise/subclass.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,10 @@ describe("Support user subclassing of Promise", function() {
this.mine = 'yeah';
};
if (!MyPromise.__proto__) { return; } // skip test if on IE < 11
MyPromise.__proto__ = Promise; // mutable __proto__ is in es6.
MyPromise.prototype = Object.create(Promise.prototype);
MyPromise.prototype.constructor = MyPromise;
Object.setPrototypeOf(MyPromise, Promise);
MyPromise.prototype = Object.create(Promise.prototype, {
constructor: { value: MyPromise }
});

// let's try it!
var p1 = MyPromise.resolve(5);
Expand Down

0 comments on commit f7e8acb

Please sign in to comment.