-
Notifications
You must be signed in to change notification settings - Fork 12.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
ES5 class rewriting incompatible with frozen intrinsics #43450
Comments
Our helper emit is designed to work in ES3 as well, where |
There’s no way to discriminate the output based on ES5 vs ES3? |
Would it be an option to feature-test Object.defineProperty to discriminate at runtime? |
This just confuses the situation, because this is a global helper with "first in wins" semantics (to enable you to provide your own, as mentioned) - so if an ES3-targeted library loads before an ES5-targeted library, which is a totally legal situation, then the ES3 version of the helper is going to win and you're back where you started. |
Would it work if the ES3 and ES5 helpers were identical:
|
We do that in |
I took a look and we do that wrong in So, we need to fix var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
var setConstructor = function (f, d) {
setConstructor = Object.create ?
function (f, d) { Object.defineProperty(f, "constructor", { value: d, writable: true, configurable: true }); } :
function (f, d) { f.constructor = d; };
setConstructor(f, d);
};
return function (d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { setConstructor(this, d); }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})(); |
@rbuckton should this setConstructor = Object.create ? be setConstructor = Object.defineProperty ? |
oh i see you explained exactly why you did this 🤦 I suppose adding a comment would help clarify its intentional. 😸 |
Hi @rbuckton any progress on #43450 (comment) ? |
Bug Report
When TSC targets ES5, classes that extend other classes generate JS that throws a
Cannot assign to read only property 'constructor' of object
TypeError when the intrinsics, particularly theFunction.prototype
, are frozen. This affects programs that are freezing their intrinsics to protect against supply chain attacks, particularly using SES.🔎 Search Terms
🕗 Version & Regression Information
I identified this issue in the published code of
external-editor
3.1.0, which is using TypeScript 3.5.2 https://github.com/mrkmg/node-external-editor/blob/e1070a8295b8ebbafa7b29802ae0e2da0fad47c0/tsconfig.jsonIn the playground, the output is consistent for the very oldest and very newest versions of TypeScript when targeting ES5.
⏯ Playground Link
Playground link with relevant code
💻 Code
🙁 Actual behavior
This code throws an exception like:
TypeError: Cannot assign to read only property 'constructor' of object ''
🙂 Expected behavior
This should not throw an exception. This can be achieved by using
Object.defineProperty(prototype, 'constructor', {value: constructor})
instead ofprototype.constructor = constructor
. This is a symptom of the so-called property override mistake, in the design of ES5.The text was updated successfully, but these errors were encountered: