question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

ES5 class rewriting incompatible with frozen intrinsics

See original GitHub issue

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 the Function.prototype, are frozen. This affects programs that are freezing their intrinsics to protect against supply chain attacks, particularly using SES.

🔎 Search Terms

  • constructor
  • frozen

🕗 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.json

In 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

Object.freeze(Function);
Object.freeze(Function.prototype);
class Foo {
    constructor() {
    }
}
class Bar extends Foo {
    constructor() {
    }
}

🙁 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 of prototype.constructor = constructor. This is a symptom of the so-called property override mistake, in the design of ES5.

Issue Analytics

  • State:open
  • Created 2 years ago
  • Comments:11 (4 by maintainers)

github_iconTop GitHub Comments

4reactions
kriskowalcommented, Mar 31, 2021

Would it work if the ES3 and ES5 helpers were identical:

function __extends(x, y) {
  if (Object.defineProperty) {
    Object.defineProperty(x, 'constructor', {value: y});
  } else {
    x.constructor = y;
  }
}
1reaction
kumaviscommented, Apr 12, 2021

@rbuckton should this

setConstructor = Object.create ?

be

setConstructor = Object.defineProperty ?
Read more comments on GitHub >

github_iconTop Results From Across the Web

classes and enumerability - ES Discuss
Just wondering, is es6 class frozen? ... but the ES5 MOP is painful enough (both its intrinsic complexity and ES5's indirect costs, e.g.,...
Read more >
Drafting Frozen Realm proposal for ES7 - GitHub
This document specifies "compartments", a concept focused on making lightweight realms designed to be used with a shared immutable realm. The proposal here...
Read more >
Javascript Class: Difference between ES5 and ES6 Classes
Short answer — using functions . Though javascript functions were the only saviors those days, we had to struggle a lot with one...
Read more >
Strengthening JavaScript | Hacker News
Specifically, "accessing missing properties throws" will undermine how developers use the language. Options objects require this as a feature. Immutable classes ...
Read more >
ChangeLog - v8/v8 - Git at Google
involve instance rewriting (issue 5009, Chromium issue 617524). Performance and stability improvements on all platforms. 2016-06-07: Version 5.3.159.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found