-
-
Notifications
You must be signed in to change notification settings - Fork 553
fix(transformer/class-properties): align setPublicClassFields
with TypeScript's useDefineForClassFields: false
#10491
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
base: 04-22-test_transformer_class-properties_overrides_a_few_tests_that_contain_class_properties_without_initializer_usages
Are you sure you want to change the base?
Conversation
Warning This pull request is not mergeable via GitHub because a downstack PR is open. Once all requirements are satisfied, merge this PR as a stack on Graphite.
How to use the Graphite Merge QueueAdd either label to this PR to merge it via the merge queue:
You must have a Graphite account in order to use the merge queue. Sign up using this link. An organization admin has enabled the Graphite Merge Queue in this repository. Please do not merge from GitHub as this will restart CI on PRs being processed by the merge queue. This stack of pull requests is managed by Graphite. Learn more about stacking. |
setPublicClassFields
with TypeScript's useDefineForClassFields
setPublicClassFields
with TypeScript's useDefineForClassFields: false
CodSpeed Instrumentation Performance ReportMerging #10491 will create unknown performance changesComparing Summary
Benchmarks breakdown
|
d91fa32
to
988ef7a
Compare
…instance property initializer (#10492) Move the `instance_inits_scope_id` and `instance_inits_constructor_scope_id` fields from the `ClassProperties` struct to local variables. Using struct-level fields as temporary variables is unnecessary within three function depths, and you also need to consider when to reset the states, otherwise, you may cause a bug due to using previous temporary information. Moreover, I think it also improves a bit readability. NOTE: This is not only a refactor, but also along with #10495 and #10493 to prepare #10491.
This is tricky. Here's the example from #9192 as vanilla JS: class CountableSet extends Set {
_map;
constructor(values) {
super(values);
}
add(key) {
this._map ??= new Map();
this._map.set(key, (this._map.get(key) ?? 0) + 1);
return super.add(key);
}
}
const c = new CountableSet(['x']);
assert(c._map === undefined); Run in NodeJS, the assertion passes. And, before this PR, in the Oxc-transformed version it passes (regardless of whether So this PR fixes TypeScript, but breaks JS! Should we maybe:
|
The specific issue which motivated #9192 is now fixed upstream: unocss/unocss#4436. Does that make this a bit less urgent, so we have time to discuss what we want to do? Or also I don't object to merging this now, and fixing JS transform in a follow-on. |
Your example missed The correct example is: class CountableSet extends Set {
_map;
constructor(values) {
super(values);
this._map ??= new Map();
}
add(key) {
this._map ??= new Map();
this._map.set(key, (this._map.get(key) ?? 0) + 1);
return super.add(key);
}
}
const c = new CountableSet(['x']);
assert(c._map === undefined); Also, you shouldn't run code by
I prefer 2, because this is exactly what the @hi-ogawa @sapphi-red @sxzz, any thoughts here. It seems that all of you are paying attention to this |
It seems TypeScript (
|
For this input class CountableSet extends Set {
_map = null;
constructor(values) {
super(values);
this._map ??= new Map();
}
add(key) {
this._map ??= new Map();
this._map.set(key, (this._map.get(key) ?? 0) + 1);
return super.add(key);
}
}
const c = new CountableSet(['x']);
assert(c._map === undefined); The output for function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
class CountableSet extends Set {
constructor(values) {
super(values);
_defineProperty(this, "_map", null);
this._map ??= new Map();
}
add(key) {
this._map ??= new Map();
this._map.set(key, (this._map.get(key) ?? 0) + 1);
return super.add(key);
}
}
const c = new CountableSet(['x']);
assert(c._map === undefined); and the output for class CountableSet extends Set {
constructor(values) {
super(values);
this._map = null;
this._map ??= new Map();
}
add(key) {
this._map ??= new Map();
this._map.set(key, (this._map.get(key) ?? 0) + 1);
return super.add(key);
}
}
const c = new CountableSet(['x']);
assert(c._map === undefined); I guess |
988ef7a
to
7bf5a9b
Compare
401943c
to
c9299a1
Compare
edb1aa9
to
e77b382
Compare
…peScript's useDefineForClassFields
e7f88e6
to
b9f2d63
Compare
Thank you for taking the time to review this! Yes, you are right! It's the same as your thought, see Babel implementation, but I haven't seen any documentation mention this. It's pretty weird that Babel completes alignment with But anyway, we need to consider how to align it. How do we provide the |
I think Oxc can have two options to control the behavior:
Then, document that if a user wants to align with
For Vite's usecase, the minimal requirements is that there's a way to behave like |
Sounds good! Also, I'm going to deprecate |
Makes sense to me 👍 |
assumptions.setPublicClassFields
doesn't fully simulate tsconfiguseDefineForClassFields
#9192Do not need to convert the property without an initializer when
setPublicClassFields
is true.Input:
Before output:
After output:
The behaviour is the same as TypeScript now.
I am not sure whether we should align this behavior with
TypeScript
because this will break cases like'prop1' in (new Cls())
. But if not, we will break #9192 the issue, though it is not used correctly. ConsideringsetPublicClassFields
is equivalent touseDefineForClassFields: false
and people always regard both are the same, so personally I think align is correct.