Skip to content

fix: restore legacy-app module type via loose SWC lowering - #65

Merged
Jan Eliáš (jeliasmake) merged 3 commits into
masterfrom
jeliasmake-proto-loose-legacy-inheritance
Aug 14, 2026
Merged

Jan Eliáš (jeliasmake) merged 3 commits into
masterfrom
jeliasmake-proto-loose-legacy-inheritance

Conversation

@jeliasmake

@jeliasmake Jan Eliáš (jeliasmake) commented Aug 14, 2026 •

Copy link
Copy Markdown
Contributor

The toolchain migration (2.18.0) switched the ES5 build from tsc to SWC. SWC's default (spec-faithful) lowering compiles super-constructor calls to Reflect.construct(Parent, args, newTarget) and class fields to _defineProperty(...). This breaks the CoffeeScript-style inheritance that built-in gateway apps (e.g. gateway:CustomWebHook) rely on: those apps invoke the parent constructor as a plain function on an existing this (Super.apply(this) / __super__.constructor.call(this)). Under Reflect.construct the base field initializer (type = ModuleType.TRIGGER) runs on a detached throwaway object instead of that this, so the module the engine uses ends up with type === undefined. Every switch (moduleType) in the engine then falls through to its default branch, producing errors such as "UNKNOWN TYPE of a MODULE" at operation-end logging.

Enable jsc.loose in .swcrc so super calls compile to Super.apply(this, args) || this and fields to this.x = ... assignments — matching the pre-migration tsc ES5 output and preserving the contract the .inherits() compat shim promises. The narrower useDefineForClassFields: false is not sufficient: it fixes the field emit but leaves Reflect.construct in the super helper, so the instance is still detached.

Test infra:

  • vitest.config.ts: mirror .swcrc with loose: true so tests exercise the same lowering the lib ships (the inline transform previously diverged from the build, which is why this shipped undetected).
  • legacy-compatibility.test.ts: the existing CoffeeScript/.inherits tests only asserted instanceof — which passes even under the detaching fork. Assert instance.type against a native-new instance so the regression is caught.

Bump version to 2.18.1 (never reship a fixed artifact under 2.18.0).

https://make.atlassian.net/browse/BARI-12

The toolchain migration (2.18.0) switched the ES5 build from tsc to SWC.
SWC's default (spec-faithful) lowering compiles super-constructor calls to
`Reflect.construct(Parent, args, newTarget)` and class fields to
`_defineProperty(...)`. This breaks the CoffeeScript-style inheritance that
built-in gateway apps (e.g. gateway:CustomWebHook) rely on: those apps invoke
the parent constructor as a plain function on an existing `this`
(`Super.apply(this)` / `__super__.constructor.call(this)`). Under
`Reflect.construct` the base field initializer (`type = ModuleType.TRIGGER`)
runs on a detached throwaway object instead of that `this`, so the module the
engine uses ends up with `type === undefined`. Every `switch (moduleType)` in
the engine then falls through to its default branch, producing errors such as
"UNKNOWN TYPE of a MODULE" at operation-end logging.

Enable `jsc.loose` in .swcrc so super calls compile to
`Super.apply(this, args) || this` and fields to `this.x = ...` assignments —
matching the pre-migration tsc ES5 output and preserving the contract the
.inherits() compat shim promises. The narrower `useDefineForClassFields: false`
is not sufficient: it fixes the field emit but leaves `Reflect.construct` in
the super helper, so the instance is still detached.

Test infra:
- vitest.config.ts: mirror `.swcrc` with `loose: true` so tests exercise the
  same lowering the lib ships (the inline transform previously diverged from
  the build, which is why this shipped undetected).
- legacy-compatibility.test.ts: the existing CoffeeScript/.inherits tests only
  asserted `instanceof` — which passes even under the detaching fork. Assert
  `instance.type` against a native-`new` instance so the regression is caught.

Bump version to 2.18.1 (never reship a fixed artifact under 2.18.0).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@github-actions

github-actions Bot commented Aug 14, 2026 •

Copy link
Copy Markdown
Messages
✅Your PR title & description are valid

Generated 14. 8. 2026 15:08:32 GMT+2 for b3316a2

@jeliasmake
Jan Eliáš (jeliasmake) marked this pull request as ready for review August 14, 2026 12:43
@jeliasmake
Jan Eliáš (jeliasmake) requested a review from a team as a code owner August 14, 2026 12:43
Copilot AI lite review requested due to automatic review settings August 14, 2026 12:43

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR restores legacy CoffeeScript-style inheritance compatibility for ES5 builds by switching SWC to jsc.loose lowering (avoiding Reflect.construct + _defineProperty helpers that can detach instance field initialization from the legacy this). It also aligns the Vitest SWC transform with the library’s build lowering and adds regression assertions to catch the type === undefined failure mode, then bumps the package version for release.

Changes:

  • Enable SWC jsc.loose: true in the build (.swcrc) to match the pre-migration ES5 semantics for super calls and class fields.
  • Mirror the same lowering in vitest.config.ts so tests exercise the shipped compilation behavior.
  • Strengthen legacy compatibility tests by asserting that type is initialized consistently vs a native new instance, and bump version to 2.18.1.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated no comments.

File Description
vitest.config.ts Mirrors .swcrc by enabling jsc.loose in the Vitest SWC transform so tests match the shipped ES5 lowering.
test/legacy-compatibility.test.ts Adds regression assertions ensuring base instance fields (e.g. type) land on the legacy this, not a detached object.
package.json Bumps package version to 2.18.1 for the fix release.
.swcrc Enables jsc.loose: true for the library build to restore legacy-compatible ES5 output.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

@make-sonarqube

Copy link
Copy Markdown

@jeliasmake
Jan Eliáš (jeliasmake) merged commit 16a4e71 into master Aug 14, 2026
3 checks passed
@jeliasmake
Jan Eliáš (jeliasmake) deleted the jeliasmake-proto-loose-legacy-inheritance branch August 14, 2026 13:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants