qooxdoo / qooxdoo

qooxdoo - Universal JavaScript Framework
http://qooxdoo.org
Other
769 stars 262 forks source link

[BUG][ES6+] Compiler Fails on Rest Param in Destructured object #10623

Open WillsterJohnsonAtZenesis opened 1 year ago

WillsterJohnsonAtZenesis commented 1 year ago

Describe the bug

The following is valid ES6+ syntax;

function name({ destruct1, destruct2, ...restDestruct }) {/* ... */}

For example;

$ node
Welcome to Node.js v18.17.1.
Type ".help" for more information.
> function name({ destruct1, destruct2, ...restDestruct }) {
...   console.log(destruct1, destruct2, restDestruct);
... }
undefined
> name({ destruct1: "destruct1", destruct2: "destruct2", a: "a", b: "b" })
destruct1 destruct2 { a: 'a', b: 'b' }
undefined
> 

However when using this paramater notation inside of a method on a Qooxdoo class, the compiler outputs a somewhat cryptic error.

Note that this occurs for all rest destructuring of objects, for example the following fails also;

const { destruct1, destruct2, ...restDestruct } = arg0;

To Reproduce

  1. Add the following class to a Qooxdoo project;
qx.Class.define("<an appropriate name>", {
  extend: qx.core.Object,

  members: {
    myMethod({ destruct1, destruct2, ...restDestruct }) {}
  }
});
  1. Run qx compile
  2. Observe the error;
TypeError: /path/to/class.js: Cannot read properties of undefined (reading 'type')
<class name>: error: FATAL Syntax error: /path/to/class.js: Cannot read properties of undefined (reading 'type')

Expected behavior

The compiler should compile the class, transpiling to older syntax if necessary.

Desktop (please complete the following information):

Additional Context

This does not occur if a destructured array paramater is used. The following class compiles without any issues;

qx.Class.define("<an appropriate name>", {
  extend: qx.core.Object,

  members: {
    myMethod([ destruct1, destruct2, ...restDestruct ]) {}
  }
});
goldim commented 1 year ago

Adding @babel/plugin-transform-destructuring in config argument babelCore.transform(src, config) fixes the case: const { destruct1, destruct2, ...restDestruct } = arg0. And @babel/plugin-transform-parameters solves the function name({ destruct1, destruct2, ...restDestruct }) {/* ... */} case. I am not sure that we need to add these plugins so it could increase somehow compilation time.

WillsterJohnsonAtZenesis commented 6 months ago

Seems that it may generally fail to collect any variable declarations from nested assignment destructuring. For example, the following seems to fail only on the nested identifier prop but has no problem with the first-level identifier name.

const objects = [["name", { prop: 1 }]];
for (const [name, { prop }] of objects) {
  console.log(prop);
}

Discovered the above example while manipulating some json with a similar shape. Using @ignore(prop) silences the compiler warning.