Skip to content

Commit

Permalink
Use Symbol.species when available, else fall back to "@@species" (ren…
Browse files Browse the repository at this point in the history
…amed from @@create)

Relates to paulmillr#303.
  • Loading branch information
ljharb committed Jan 5, 2015
1 parent e949caa commit 54ed0b7
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 41 deletions.
76 changes: 36 additions & 40 deletions es6-shim.js
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@
var noop = function () {};

var Symbol = globals.Symbol || {};
var symbolSpecies = Symbol.species || '@@species';
var Type = {
string: function (x) { return _toString(x) === '[object String]'; },
regex: function (x) { return _toString(x) === '[object RegExp]'; },
Expand Down Expand Up @@ -304,8 +305,8 @@
Construct: function (C, args) {
// CreateFromConstructor
var obj;
if (ES.IsCallable(C['@@create'])) {
obj = C['@@create']();
if (ES.IsCallable(C[symbolSpecies])) {
obj = C[symbolSpecies]();
} else {
// OrdinaryCreateFromConstructor
obj = create(C.prototype || null);
Expand All @@ -322,12 +323,12 @@
var emulateES6construct = function (o) {
if (!ES.TypeIsObject(o)) { throw new TypeError('bad object'); }
// es5 approximation to es6 subclass semantics: in es6, 'new Foo'
// would invoke Foo.@@create to allocation/initialize the new object.
// would invoke Foo.@@species to allocation/initialize the new object.
// In es5 we just get the plain object. So if we detect an
// uninitialized object, invoke o.constructor.@@create
// uninitialized object, invoke o.constructor.@@species
if (!o._es6construct) {
if (o.constructor && ES.IsCallable(o.constructor['@@create'])) {
o = o.constructor['@@create'](o);
if (o.constructor && ES.IsCallable(o.constructor[symbolSpecies])) {
o = o.constructor[symbolSpecies](o);
}
defineProperties(o, { _es6construct: true });
}
Expand Down Expand Up @@ -1469,25 +1470,24 @@
};
};

defineProperty(Promise, symbolSpecies, function (obj) {
var constructor = this;
// AllocatePromise
// The `obj` parameter is a hack we use for es5
// compatibility.
var prototype = constructor.prototype || Promise$prototype;
obj = obj || create(prototype);
defineProperties(obj, {
_status: void 0,
_result: void 0,
_resolveReactions: void 0,
_rejectReactions: void 0,
_promiseConstructor: void 0
});
obj._promiseConstructor = constructor;
return obj;
});
defineProperties(Promise, {
'@@create': function (obj) {
var constructor = this;
// AllocatePromise
// The `obj` parameter is a hack we use for es5
// compatibility.
var prototype = constructor.prototype || Promise$prototype;
obj = obj || create(prototype);
defineProperties(obj, {
_status: void 0,
_result: void 0,
_resolveReactions: void 0,
_rejectReactions: void 0,
_promiseConstructor: void 0
});
obj._promiseConstructor = constructor;
return obj;
},

all: function all(iterable) {
var C = this;
var capability = new PromiseCapability(C);
Expand Down Expand Up @@ -1776,14 +1776,12 @@
return map;
}
var Map$prototype = Map.prototype;
defineProperties(Map, {
'@@create': function (obj) {
var constructor = this;
var prototype = constructor.prototype || Map$prototype;
obj = obj || create(prototype);
defineProperties(obj, { _es6map: true });
return obj;
}
defineProperty(Map, symbolSpecies, function (obj) {
var constructor = this;
var prototype = constructor.prototype || Map$prototype;
obj = obj || create(prototype);
defineProperties(obj, { _es6map: true });
return obj;
});

Value.getter(Map.prototype, 'size', function () {
Expand Down Expand Up @@ -1960,14 +1958,12 @@
return set;
};
var Set$prototype = SetShim.prototype;
defineProperties(SetShim, {
'@@create': function (obj) {
var constructor = this;
var prototype = constructor.prototype || Set$prototype;
obj = obj || create(prototype);
defineProperties(obj, { _es6set: true });
return obj;
}
defineProperty(SetShim, symbolSpecies, function (obj) {
var constructor = this;
var prototype = constructor.prototype || Set$prototype;
obj = obj || create(prototype);
defineProperties(obj, { _es6set: true });
return obj;
});

// Switch from the object backing storage to a full Map.
Expand Down
2 changes: 1 addition & 1 deletion test/promise/subclass.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ describe('Support user subclassing of Promise', function () {
this.mine = 'yeah';
};
// If the constructor doesn't inherit from Promise then
// in an es6 engine we won't pick up the internal @@create
// in an es6 engine we won't pick up the internal @@species
// method, even if we do everything else 'correctly'
MyPromise.prototype = Object.create(Promise.prototype, {
constructor: { value: MyPromise }
Expand Down

0 comments on commit 54ed0b7

Please sign in to comment.