Skip to content

Commit

Permalink
fix(compiler): add heritage clauses earlier in native transform (#4769)
Browse files Browse the repository at this point in the history
This fixes an issue that surface in the stencil / ionic-framework
nightly tests, where a `super()` call was mistakenly omitted from native
components.

This was occurring after changing to use the `updateConstructor` helper
function in #4741 in the native transform. When that function updates
the constructor on a class it inspects the class declaration's heritage
clauses to determine if a `super()` call needs to be present in the
constructor, and adds one if needed.

In the native component transform, however, the transformer to add an
`extends HTMLElement` heritage clause and transform the constructor were
called separately and then combined into a single updated class
declaration using `updateComponentClass`. This meant that when the
`updateConstructor` function was called the class declaration node
didn't yet have a heritage function, so a `super()` call was not added.

This was addressed by a small refactor to the heritage clause insertion
function. Instead of creating and returning an updated heritage clause
it uses `ts.factory.updateClassDeclaration` to return an updated class
declaration node with an appropriate heritage clause added to it. This
updated class declaration is then passed to `updateConstructor` and a
`super()` call is correctly inserted.
  • Loading branch information
alicewriteswrongs committed Sep 11, 2023
1 parent 9ee02c5 commit 9a92ad1
Showing 1 changed file with 14 additions and 7 deletions.
21 changes: 14 additions & 7 deletions src/compiler/transformers/component-native/native-component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,9 @@ export const updateNativeComponentClass = (
moduleFile: d.Module,
cmp: d.ComponentCompilerMeta,
): ts.ClassDeclaration | ts.VariableStatement => {
const heritageClauses = updateNativeHostComponentHeritageClauses(classNode, moduleFile);
const members = updateNativeHostComponentMembers(transformOpts, classNode, moduleFile, cmp);
return updateComponentClass(transformOpts, classNode, heritageClauses, members);
const withHeritageClauses = updateNativeHostComponentHeritageClauses(classNode, moduleFile);
const members = updateNativeHostComponentMembers(transformOpts, withHeritageClauses, moduleFile, cmp);
return updateComponentClass(transformOpts, withHeritageClauses, withHeritageClauses.heritageClauses, members);
};

/**
Expand All @@ -46,15 +46,15 @@ export const updateNativeComponentClass = (
*
* @param classNode the syntax tree of the Stencil component class to update
* @param moduleFile the Stencil Module associated with the provided class node
* @returns the generated heritage clause
* @returns an updated class declaration with the generated heritage clause
*/
const updateNativeHostComponentHeritageClauses = (
classNode: ts.ClassDeclaration,
moduleFile: d.Module,
): ts.NodeArray<ts.HeritageClause> | [ts.HeritageClause] => {
): ts.ClassDeclaration => {
if (classNode.heritageClauses != null && classNode.heritageClauses.length > 0) {
// the syntax tree has a heritage clause already, don't generate a new one
return classNode.heritageClauses;
return classNode;
}

if (moduleFile.cmps.length >= 1) {
Expand All @@ -66,7 +66,14 @@ const updateNativeHostComponentHeritageClauses = (
ts.factory.createExpressionWithTypeArguments(ts.factory.createIdentifier(HTML_ELEMENT), []),
]);

return [heritageClause];
return ts.factory.updateClassDeclaration(
classNode,
classNode.modifiers,
classNode.name,
classNode.typeParameters,
[heritageClause],
classNode.members,
);
};

/**
Expand Down

0 comments on commit 9a92ad1

Please sign in to comment.