Skip to content

Commit

Permalink
fix: identifiers are not incorrectly scoped to state (#1630)
Browse files Browse the repository at this point in the history
* add failing test

* update tests

* fails

* fix: only map state variables used in useState

* base tests

* update tests

* account for other state values and functions

* update snapshots

* changeset

* make sure state is actually used

* rename

* fix angular

* snapshots

* Update late-papayas-eat.md

* Update .changeset/late-papayas-eat.md

---------

Co-authored-by: Sami Jaber <[email protected]>
  • Loading branch information
liamdebeasi and samijaber authored Nov 8, 2024
1 parent b1386ef commit e9cfef0
Show file tree
Hide file tree
Showing 37 changed files with 3,731 additions and 157 deletions.
6 changes: 6 additions & 0 deletions .changeset/late-papayas-eat.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'@builder.io/mitosis': patch
---

[All] Fix: scope renaming of state methods to not include shadow variables
[Angular]: Update `state.*` -> `this.*` transform to new AST transform approach
64 changes: 64 additions & 0 deletions packages/core/src/__tests__/__snapshots__/alpine.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -1395,6 +1395,38 @@ exports[`Alpine.js > jsx > Javascript Test > StoreComment 1`] = `
"
`;
exports[`Alpine.js > jsx > Javascript Test > StoreShadowVars 1`] = `
"<div x-data=\\"myComponent()\\"><span x-html=\\"foo(errors)\\"></span></div>
<script>
document.addEventListener(\\"alpine:init\\", () => {
Alpine.data(\\"myComponent\\", () => ({
errors: {},
foo(errors) {
return errors;
},
}));
});
</script>
"
`;
exports[`Alpine.js > jsx > Javascript Test > StoreWithState 1`] = `
"<div x-data=\\"myComponent()\\"><span x-html=\\"bar()\\"></span></div>
<script>
document.addEventListener(\\"alpine:init\\", () => {
Alpine.data(\\"myComponent\\", () => ({
foo: false,
bar() {
return this.foo;
},
}));
});
</script>
"
`;
exports[`Alpine.js > jsx > Javascript Test > Submit 1`] = `
"<button type=\\"submit\\" x-data=\\"submitButton()\\" x-bind=\\"attributes\\">
<span x-html=\\"text\\"></span>
Expand Down Expand Up @@ -4416,6 +4448,38 @@ exports[`Alpine.js > jsx > Typescript Test > StoreComment 1`] = `
"
`;
exports[`Alpine.js > jsx > Typescript Test > StoreShadowVars 1`] = `
"<div x-data=\\"myComponent()\\"><span x-html=\\"foo(errors)\\"></span></div>
<script>
document.addEventListener(\\"alpine:init\\", () => {
Alpine.data(\\"myComponent\\", () => ({
errors: {},
foo(errors) {
return errors;
},
}));
});
</script>
"
`;
exports[`Alpine.js > jsx > Typescript Test > StoreWithState 1`] = `
"<div x-data=\\"myComponent()\\"><span x-html=\\"bar()\\"></span></div>
<script>
document.addEventListener(\\"alpine:init\\", () => {
Alpine.data(\\"myComponent\\", () => ({
foo: false,
bar() {
return this.foo;
},
}));
});
</script>
"
`;
exports[`Alpine.js > jsx > Typescript Test > Submit 1`] = `
"<button type=\\"submit\\" x-data=\\"submitButton()\\" x-bind=\\"attributes\\">
<span x-html=\\"text\\"></span>
Expand Down
178 changes: 154 additions & 24 deletions packages/core/src/__tests__/__snapshots__/angular.import.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -2750,6 +2750,76 @@ export class StringLiteralStoreModule {}
"
`;

exports[`Angular with Preserve Imports and File Extensions > jsx > Javascript Test > StoreShadowVars 1`] = `
"import { NgModule } from \\"@angular/core\\";
import { CommonModule } from \\"@angular/common\\";

import { Component } from \\"@angular/core\\";

@Component({
selector: \\"my-component\\",
template: \`
<ng-container>{{foo(errors)}}</ng-container>
\`,
styles: [
\`
:host {
display: contents;
}
\`,
],
})
export default class MyComponent {
errors = {};
foo(errors) {
return errors;
}
}

@NgModule({
declarations: [MyComponent],
imports: [CommonModule],
exports: [MyComponent],
})
export class MyComponentModule {}
"
`;

exports[`Angular with Preserve Imports and File Extensions > jsx > Javascript Test > StoreWithState 1`] = `
"import { NgModule } from \\"@angular/core\\";
import { CommonModule } from \\"@angular/common\\";

import { Component } from \\"@angular/core\\";

@Component({
selector: \\"my-component\\",
template: \`
<ng-container>{{bar()}}</ng-container>
\`,
styles: [
\`
:host {
display: contents;
}
\`,
],
})
export default class MyComponent {
foo = false;
bar() {
return this.foo;
}
}

@NgModule({
declarations: [MyComponent],
imports: [CommonModule],
exports: [MyComponent],
})
export class MyComponentModule {}
"
`;

exports[`Angular with Preserve Imports and File Extensions > jsx > Javascript Test > Submit 1`] = `
"import { NgModule } from \\"@angular/core\\";
import { CommonModule } from \\"@angular/common\\";
Expand Down Expand Up @@ -4574,12 +4644,12 @@ export default class MultipleOnUpdateWithDeps {

ngOnChanges(changes) {
if (typeof window !== \\"undefined\\") {
console.log(\\"Runs when this.a or this.b changes\\", this.a, this.b);
console.log(\\"Runs when a or b changes\\", this.a, this.b);

if (this.a === \\"a\\") {
this.a = \\"b\\";
}
console.log(\\"Runs when this.c or this.d changes\\", this.c, this.d);
console.log(\\"Runs when c or d changes\\", this.c, this.d);

if (this.a === \\"a\\") {
this.a = \\"b\\";
Expand Down Expand Up @@ -5124,12 +5194,7 @@ export default class OnUpdateWithDeps {

ngOnChanges(changes) {
if (typeof window !== \\"undefined\\") {
console.log(
\\"Runs when this.a, this.b or size changes\\",
this.a,
this.b,
this.size
);
console.log(\\"Runs when a, b or size changes\\", this.a, this.b, this.size);
}
}
}
Expand Down Expand Up @@ -5507,7 +5572,7 @@ export default class RenderBlock {
if (!ref) {
// TODO: Public doc page with more info about this message
console.warn(\`
Could not find a registered this.component named \\"\${componentName}\\".
Could not find a registered component named \\"\${componentName}\\".
If you registered it, is the file that registered it imported by the file that needs to render it?\`);
return undefined;
} else {
Expand Down Expand Up @@ -5560,8 +5625,8 @@ export default class RenderBlock {
...getBlockComponentOptions(this.useBlock),

/**
* These this.attributes are passed to the wrapper element when there is one. If \`noWrap\` is set to true, then
* they are provided to the this.component itself directly.
* These attributes are passed to the wrapper element when there is one. If \`noWrap\` is set to true, then
* they are provided to the component itself directly.
*/
...(this.shouldWrap
? {}
Expand Down Expand Up @@ -5656,7 +5721,7 @@ export default class RenderBlock {
if (TARGET === \\"reactNative\\") {
return RenderComponentWithContext;
} else if (TARGET === \\"vue3\\") {
// vue3 expects a string for the this.component tag
// vue3 expects a string for the component tag
return \\"RenderComponent\\";
} else {
return RenderComponent;
Expand Down Expand Up @@ -10292,6 +10357,76 @@ export class StringLiteralStoreModule {}
"
`;

exports[`Angular with Preserve Imports and File Extensions > jsx > Typescript Test > StoreShadowVars 1`] = `
"import { NgModule } from \\"@angular/core\\";
import { CommonModule } from \\"@angular/common\\";

import { Component } from \\"@angular/core\\";

@Component({
selector: \\"my-component\\",
template: \`
<ng-container>{{foo(errors)}}</ng-container>
\`,
styles: [
\`
:host {
display: contents;
}
\`,
],
})
export default class MyComponent {
errors = {};
foo(errors) {
return errors;
}
}

@NgModule({
declarations: [MyComponent],
imports: [CommonModule],
exports: [MyComponent],
})
export class MyComponentModule {}
"
`;

exports[`Angular with Preserve Imports and File Extensions > jsx > Typescript Test > StoreWithState 1`] = `
"import { NgModule } from \\"@angular/core\\";
import { CommonModule } from \\"@angular/common\\";

import { Component } from \\"@angular/core\\";

@Component({
selector: \\"my-component\\",
template: \`
<ng-container>{{bar()}}</ng-container>
\`,
styles: [
\`
:host {
display: contents;
}
\`,
],
})
export default class MyComponent {
foo = false;
bar() {
return this.foo;
}
}

@NgModule({
declarations: [MyComponent],
imports: [CommonModule],
exports: [MyComponent],
})
export class MyComponentModule {}
"
`;

exports[`Angular with Preserve Imports and File Extensions > jsx > Typescript Test > Submit 1`] = `
"import { NgModule } from \\"@angular/core\\";
import { CommonModule } from \\"@angular/common\\";
Expand Down Expand Up @@ -12239,12 +12374,12 @@ export default class MultipleOnUpdateWithDeps {

ngOnChanges(changes: SimpleChanges) {
if (typeof window !== \\"undefined\\") {
console.log(\\"Runs when this.a or this.b changes\\", this.a, this.b);
console.log(\\"Runs when a or b changes\\", this.a, this.b);

if (this.a === \\"a\\") {
this.a = \\"b\\";
}
console.log(\\"Runs when this.c or this.d changes\\", this.c, this.d);
console.log(\\"Runs when c or d changes\\", this.c, this.d);

if (this.a === \\"a\\") {
this.a = \\"b\\";
Expand Down Expand Up @@ -12808,12 +12943,7 @@ export default class OnUpdateWithDeps {

ngOnChanges(changes: SimpleChanges) {
if (typeof window !== \\"undefined\\") {
console.log(
\\"Runs when this.a, this.b or size changes\\",
this.a,
this.b,
this.size
);
console.log(\\"Runs when a, b or size changes\\", this.a, this.b, this.size);
}
}
}
Expand Down Expand Up @@ -13242,7 +13372,7 @@ export default class RenderBlock {
if (!ref) {
// TODO: Public doc page with more info about this message
console.warn(\`
Could not find a registered this.component named \\"\${componentName}\\".
Could not find a registered component named \\"\${componentName}\\".
If you registered it, is the file that registered it imported by the file that needs to render it?\`);
return undefined;
} else {
Expand Down Expand Up @@ -13295,8 +13425,8 @@ export default class RenderBlock {
...getBlockComponentOptions(this.useBlock),

/**
* These this.attributes are passed to the wrapper element when there is one. If \`noWrap\` is set to true, then
* they are provided to the this.component itself directly.
* These attributes are passed to the wrapper element when there is one. If \`noWrap\` is set to true, then
* they are provided to the component itself directly.
*/
...(this.shouldWrap
? {}
Expand Down Expand Up @@ -13391,7 +13521,7 @@ export default class RenderBlock {
if (TARGET === \\"reactNative\\") {
return RenderComponentWithContext;
} else if (TARGET === \\"vue3\\") {
// vue3 expects a string for the this.component tag
// vue3 expects a string for the component tag
return \\"RenderComponent\\";
} else {
return RenderComponent;
Expand Down
Loading

0 comments on commit e9cfef0

Please sign in to comment.