ef4 / decorator-transforms

Better babel transforms for decorators

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Installing version 1.0.2 causes a runtime error (The @action decorator must be applied to methods when used in native classes)

ijlee2 opened this issue · comments

I have several v2 addons that use decorator-transforms. Some of the v1 addons in a monorepo, which consume these v2 addons, resulted in test failures with error messages such as,

Uncaught Error: Assertion Failed: The @action decorator must be applied to methods when used in native classes
    at assert (index.js:145:1)
    at action (index.js:322:1)
    at m (chunk-E5TPHQ3P.js:11:1117)
    at eval (container-query.js:15:4156)
    at ../../../node_modules/ember-container-query/dist/modifiers/container-query.js (chunk.vendors-node_modules_ember-container-query_dist_components_container-query_js-node_modules_em-f578d1.9d22dd9550bb959ad4b0.js:68:1)
    at __webpack_require__ (chunk.app.2b5a474e7320f4c07d13.js:218:42)
    at Module.eval [as callback] (app.cjs:22:195)
    at Module.exports (loader.js:106:1)
    at Module._reify (loader.js:143:1)
    at Module.reify (loader.js:130:1)
Corresponding dist file for the {{container-query}} modifier
import { registerDestructor } from '@ember/destroyable';
import { action } from '@ember/object';
import { debounce } from '@ember/runloop';
import { inject } from '@ember/service';
import Modifier from 'ember-modifier';
import { f, i, m } from 'decorator-transforms/runtime';

class ContainerQueryModifier extends Modifier {
  static {
    f(this, "resizeObserver", [inject]);
  }
  #resizeObserver = (i(this, "resizeObserver"), void 0);
  dimensions;
  queryResults;
  _dataAttributes = [];
  _element;
  _named;
  get dataAttributePrefix() {
    return this._named.dataAttributePrefix ?? 'container-query';
  }
  get debounce() {
    return this._named.debounce ?? 0;
  }
  get features() {
    return this._named.features ?? {};
  }
  constructor(owner, args) {
    super(owner, args);
    registerDestructor(this, () => {
      this.resizeObserver.unobserve(this._element, this.onResize);
    });
  }
  modify(element, _positional, named) {
    this._named = named;
    this.registerResizeObserver(element);
    this.queryContainer(element);
  }
  onResize(resizeObserverEntry) {
    const element = resizeObserverEntry.target;
    if (this.debounce > 0) {
      debounce(this, this.queryContainer, element, this.debounce);
      return;
    }
    this.queryContainer(element);
  }
  static {
    m(this, "onResize", [action]);
  }
  registerResizeObserver(element) {
    this.resizeObserver.unobserve(this._element, this.onResize);
    this._element = element;
    this.resizeObserver.observe(this._element, this.onResize);
  }
  queryContainer(element) {
    this.measureDimensions(element);
    this.evaluateQueries();
    this.resetDataAttributes(element);
    this.setDataAttributes(element);
    this._named.onQuery?.({
      dimensions: this.dimensions,
      queryResults: this.queryResults
    });
  }
  measureDimensions(element) {
    const height = element.clientHeight;
    const width = element.clientWidth;
    this.dimensions = {
      aspectRatio: width / height,
      height,
      width
    };
  }
  evaluateQueries() {
    const queryResults = {};
    for (const [featureName, metadata] of Object.entries(this.features)) {
      const {
        dimension,
        min,
        max
      } = metadata;
      const value = this.dimensions[dimension];
      queryResults[featureName] = min <= value && value < max;
    }
    this.queryResults = queryResults;
  }
  resetDataAttributes(element) {
    this._dataAttributes.forEach(dataAttribute => {
      element.removeAttribute(dataAttribute);
    });
    this._dataAttributes = [];
  }
  setDataAttributes(element) {
    const prefix = this.dataAttributePrefix;
    for (const [featureName, meetsFeature] of Object.entries(this.queryResults)) {
      if (!meetsFeature) {
        continue;
      }
      const dataAttribute = prefix ? `data-${prefix}-${String(featureName)}` : `data-${String(featureName)}`;
      element.setAttribute(dataAttribute, '');
      this._dataAttributes.push(dataAttribute);
    }
  }
}

export { ContainerQueryModifier as default };
//# sourceMappingURL=container-query.js.map

The problem didn't seem to be limited to the addon ember-container-query (my initial guess), but to all v2 addons that use transform-decorators (and have @action?). It seemed like, downgrading transform-decorators from 1.0.2 to 1.0.1 (I pinned the version to 1.0.1) fixed the issue, in the sense that the tests are passing again.

Here's an example of how I had configured transform-decorators in babel.config.json in all v2 addons (based on that from @embroider/addon-blueprint):

https://github.com/ijlee2/ember-container-query/blob/5.0.4/ember-container-query/babel.config.json#L19-L26

Thanks for the bug report, this is the problem line:

    m(this, "onResize", [action]);

It should say this.prototype instead of this. The release changed the runtime to expect this.prototype and changed the transform to emit it. But you're only getting the runtime change without the transform change.

Are you seeing this locally or in CI? Because if you have a babel cache that could be the source of trouble.

if it's not caching then there must be some combination of babel version and options that cause us to misidentify this case as static.

I think I ran into a similar problem. In my case it was failing CI only (example log), and that for all ember-try scenarios. Was not able to reproduce locally though (even when ignoring the lockfile).

Updating the version specifier to force 1.0.2 everywhere (PR) was fixing the problem.

Ah, this must be a version skew problem! I shouldn’t have made a breaking change to the runtime without accounting for that.

Are you seeing this locally or in CI? Because if you have a babel cache that could be the source of trouble.

if it's not caching then there must be some combination of babel version and options that cause us to misidentify this case as static.

@ef4 I saw the error message when I ran the test app locally for one package (let's call it Package A), and when tests ran in CI for another package (Package B). I also saw the error when running the tests for Package B locally (by visiting http://localhost:4200/tests).

Here is a diff of yarn.lock, in case the change in Babel dependencies might help you with debugging. We use yarn-deduplicate to ensure that a single version is installed whenever possible.

Lockfile diff
-"@babel/plugin-syntax-decorators@^7.16.7", "@babel/plugin-syntax-decorators@^7.22.10":
-  version "7.22.10"
+"@babel/plugin-syntax-decorators@^7.16.7", "@babel/plugin-syntax-decorators@^7.22.10", "@babel/plugin-syntax-decorators@^7.23.3":
+  version "7.23.3"
   dependencies:
     "@babel/helper-plugin-utils" "^7.22.5"

-"@embroider/macros@^0.50.0 || ^1.0.0", "@embroider/macros@^1.0.0", "@embroider/macros@^1.10.0", "@embroider/macros@^1.12.0", "@embroider/macros@^1.12.2", "@embroider/macros@^1.12.3", "@embroider/macros@^1.13.0", "@embroider/macros@^1.13.1", "@embroider/macros@^1.13.2", "@embroider/macros@^1.13.3", "@embroider/macros@^1.8.3", "@embroider/macros@^1.9.0":
-  version "1.13.3"
+"@embroider/macros@^0.50.0 || ^1.0.0", "@embroider/macros@^1.0.0", "@embroider/macros@^1.10.0", "@embroider/macros@^1.12.0", "@embroider/macros@^1.12.2", "@embroider/macros@^1.12.3", "@embroider/macros@^1.13.0", "@embroider/macros@^1.13.1", "@embroider/macros@^1.13.2", "@embroider/macros@^1.13.3", "@embroider/macros@^1.13.4", "@embroider/macros@^1.8.3", "@embroider/macros@^1.9.0":
+  version "1.13.4"
   dependencies:
     "@embroider/shared-internals" "2.5.1"
     assert-never "^1.2.1"

-babel-import-util@^2.0.0:
-  version "2.0.0"
+babel-import-util@^2.0.0, babel-import-util@^2.0.1:
+  version "2.0.1"

+decorator-transforms@^1.0.1, decorator-transforms@^1.0.2:
+  version "1.0.2"
+  dependencies:
+    "@babel/plugin-syntax-decorators" "^7.23.3"
+    babel-import-util "^2.0.1"
+

-"ember-auto-import@^1.12.1 || ^2.4.3", ember-auto-import@^2.0.0, ember-auto-import@^2.2.3, ember-auto-import@^2.2.4, ember-auto-import@^2.4.0, ember-auto-import@^2.5.0, ember-auto-import@^2.6.0, ember-auto-import@^2.6.1, ember-auto-import@^2.6.3, ember-auto-import@^2.7.0:
-  version "2.7.0"
+"ember-auto-import@^1.12.1 || ^2.4.3", ember-auto-import@^2.0.0, ember-auto-import@^2.2.3, ember-auto-import@^2.2.4, ember-auto-import@^2.4.0, ember-auto-import@^2.5.0, ember-auto-import@^2.6.0, ember-auto-import@^2.6.1, ember-auto-import@^2.6.3, ember-auto-import@^2.7.0, ember-auto-import@^2.7.2:
+  version "2.7.2"

-ember-container-query@^5.0.2:
-  version "5.0.2"
+ember-container-query@^5.0.2, ember-container-query@^5.0.4:
+  version "5.0.5"
   dependencies:
-    "@embroider/addon-shim" "^1.8.6"
+    "@embroider/addon-shim" "^1.8.7"
+    decorator-transforms "^1.0.2"
     ember-element-helper "^0.8.5"
     ember-modifier "^3.2.7 || ^4.1.0"
     ember-resize-observer-service "^1.1.0"

-embroider-css-modules@^2.0.0:
-  version "2.0.0"
+embroider-css-modules@^2.0.0, embroider-css-modules@^2.0.2:
+  version "2.0.2"
   dependencies:
-    "@embroider/addon-shim" "^1.8.6"
+    "@embroider/addon-shim" "^1.8.7"
+    decorator-transforms "^1.0.1"

When I filed the issue earlier, the project depended on v2 addons whose dist had been created with decorator-transforms@1.0.1.

Now, with ember-container-query@5.0.5, whose dist was created with decorator-transforms@1.0.2 today, I seem to be encountering a new issue in Packages A and B when I pin decorator-transforms to 1.0.1

TypeError: Object.defineProperty called on non-object
    at Function.defineProperty (<anonymous>)
    at f (chunk-DOLZLHFH.js:11:879)
    at eval (container-query.js:15:4014)
    at ../../../node_modules/ember-container-query/dist/modifiers/container-query.js

I wonder if the original issue might have occurred because the addons had been built with 1.0.1, while the monorepo tried to install 1.0.2. Tomorrow, I can check what will happen if all v2 addons are built with 1.0.2.

Should be fixed in 1.0.3.

@ef4 @simonihmig Thanks for your help with fixing the issue quickly. I updated all v2 addons to use decorator-transforms@1.0.3 and the CI for the consuming app passed.