Skip to content

Commit

Permalink
Merge pull request #402 from EB-Forks/fix/use-define-for-tostringtag
Browse files Browse the repository at this point in the history
runtime: Use `[[Define]]` for the `Symbol.toStringTag` property
  • Loading branch information
benjamn authored Jul 22, 2020
2 parents 81042af + d4868b6 commit f48768c
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 14 deletions.
36 changes: 24 additions & 12 deletions packages/regenerator-runtime/runtime.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,24 @@ var runtime = (function (exports) {
var asyncIteratorSymbol = $Symbol.asyncIterator || "@@asyncIterator";
var toStringTagSymbol = $Symbol.toStringTag || "@@toStringTag";

function define(obj, key, value) {
Object.defineProperty(obj, key, {
value: value,
enumerable: true,
configurable: true,
writable: true
});
return obj[key];
}
try {
// IE 8 has a broken Object.defineProperty that only works on DOM objects.
define({}, "");
} catch (err) {
define = function(obj, key, value) {
return obj[key] = value;
};
}

function wrap(innerFn, outerFn, self, tryLocsList) {
// If outerFn provided and outerFn.prototype is a Generator, then outerFn.prototype instanceof Generator.
var protoGenerator = outerFn && outerFn.prototype instanceof Generator ? outerFn : Generator;
Expand Down Expand Up @@ -82,29 +100,23 @@ var runtime = (function (exports) {
IteratorPrototype = NativeIteratorPrototype;
}

function ensureDefaultToStringTag(object, defaultValue) {
// https://bugzilla.mozilla.org/show_bug.cgi?id=1644581#c6
return toStringTagSymbol in object
? object[toStringTagSymbol]
: object[toStringTagSymbol] = defaultValue;
}

var Gp = GeneratorFunctionPrototype.prototype =
Generator.prototype = Object.create(IteratorPrototype);
GeneratorFunction.prototype = Gp.constructor = GeneratorFunctionPrototype;
GeneratorFunctionPrototype.constructor = GeneratorFunction;
GeneratorFunction.displayName = ensureDefaultToStringTag(
GeneratorFunction.displayName = define(
GeneratorFunctionPrototype,
toStringTagSymbol,
"GeneratorFunction"
);

// Helper for defining the .next, .throw, and .return methods of the
// Iterator interface in terms of a single ._invoke method.
function defineIteratorMethods(prototype) {
["next", "throw", "return"].forEach(function(method) {
prototype[method] = function(arg) {
define(prototype, method, function(arg) {
return this._invoke(method, arg);
};
});
});
}

Expand All @@ -123,7 +135,7 @@ var runtime = (function (exports) {
Object.setPrototypeOf(genFun, GeneratorFunctionPrototype);
} else {
genFun.__proto__ = GeneratorFunctionPrototype;
ensureDefaultToStringTag(genFun, "GeneratorFunction");
define(genFun, toStringTagSymbol, "GeneratorFunction");
}
genFun.prototype = Object.create(Gp);
return genFun;
Expand Down Expand Up @@ -393,7 +405,7 @@ var runtime = (function (exports) {
// unified ._invoke helper method.
defineIteratorMethods(Gp);

ensureDefaultToStringTag(Gp, "Generator");
define(Gp, toStringTagSymbol, "Generator");

// A Generator should always return itself as the iterator object when the
// @@iterator function is called on it. Some browsers' implementations of the
Expand Down
13 changes: 11 additions & 2 deletions test/non-writable-tostringtag-property.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
* LICENSE file in the root directory of this source tree.
*/

var hasOwn = Object.prototype.hasOwnProperty;
var assert = require("assert");

var getProto = Object.getPrototypeOf;
var NativeIteratorPrototype =
typeof Symbol === "function" &&
Expand All @@ -20,8 +21,16 @@ Object.defineProperty(NativeIteratorPrototype, Symbol.toStringTag, {
value: "Iterator",
});

describe("Symbol.toStringTag safety (#399, #400)", function () {
(NativeIteratorPrototype ? describe : describe.skip)("Symbol.toStringTag safety (#399, #400)", function () {
it("regenerator-runtime doesn't fail to initialize when native iterator prototype has a non-writable @@toStringTag property", function() {
require("./runtime.js");
});

it("regenerator-runtime's polyfilled generator prototype has the correct @@toStringTag value", function() {
require("./runtime.js");
function foo() {}
regeneratorRuntime.mark(foo);

assert.strictEqual(foo.prototype[Symbol.toStringTag], "Generator");
});
});

0 comments on commit f48768c

Please sign in to comment.