Describe the bug
With jsc.transform.tsEnumIsMutable: true, reads of non-const enum members are deliberately kept as runtime reads. But an enum member initializer that reads another enum is still folded to the compile-time value by the collection pass, so within one file the option is honored for expression reads and ignored inside enum initializers.
Input code
enum D { A = 1 }
(D as any).A = 5;
enum F { P = D.A, Q }
console.log(D.A, F.P);
with { "jsc": { "transform": { "tsEnumIsMutable": true } } }.
Actual behavior (@swc/core 1.16.1)
var D = /*#__PURE__*/ function(D) {
D[D["A"] = 1] = "A";
return D;
}(D || {});
D.A = 5;
var F = /*#__PURE__*/ function(F) {
F[F["P"] = 1] = "P";
F[F["Q"] = 2] = "Q";
return F;
}(F || {});
console.log(D.A, F.P);
console.log(D.A, ...) correctly stays a runtime read and prints 5 — but F.P was folded to 1, even though D.A is 5 by the time F initializes. The emitted file contradicts itself about whether D is mutable.
Expected behavior
Under this option, F.P = D.A should stay a runtime read (F[F["P"] = D.A] = "P"), consistent with how every other read of a non-const enum is treated. (tsc has no equivalent option, so the reference here is the option's own contract, not tsc emit.)
Mechanism: enter_expr_for_inline_enum checks ts_enum_is_mutable && !const_enum.contains(&enum_id) before inlining, but member evaluation in the collection pass resolves through enum_record without consulting the option. The const-initializer path was given the same guard in #12101 (ts_enum_is_mutable_true covers it); the direct member-initializer path predates that PR and is unchanged.
Noted in the #12101 review, reporting separately as promised there.
Version: @swc/core 1.16.1
Describe the bug
With
jsc.transform.tsEnumIsMutable: true, reads of non-const enum members are deliberately kept as runtime reads. But an enum member initializer that reads another enum is still folded to the compile-time value by the collection pass, so within one file the option is honored for expression reads and ignored inside enum initializers.Input code
with
{ "jsc": { "transform": { "tsEnumIsMutable": true } } }.Actual behavior (
@swc/core1.16.1)console.log(D.A, ...)correctly stays a runtime read and prints5— butF.Pwas folded to1, even thoughD.Ais5by the timeFinitializes. The emitted file contradicts itself about whetherDis mutable.Expected behavior
Under this option,
F.P = D.Ashould stay a runtime read (F[F["P"] = D.A] = "P"), consistent with how every other read of a non-const enum is treated. (tschas no equivalent option, so the reference here is the option's own contract, nottscemit.)Mechanism:
enter_expr_for_inline_enumchecksts_enum_is_mutable && !const_enum.contains(&enum_id)before inlining, but member evaluation in the collection pass resolves throughenum_recordwithout consulting the option. The const-initializer path was given the same guard in #12101 (ts_enum_is_mutable_truecovers it); the direct member-initializer path predates that PR and is unchanged.Noted in the #12101 review, reporting separately as promised there.
Version:
@swc/core1.16.1