Skip to content

Commit e79fc03

Browse files
committed
fix: issue with stencil local exports
1 parent 37d430e commit e79fc03

File tree

7 files changed

+70
-83
lines changed

7 files changed

+70
-83
lines changed

packages/core/src/__tests__/__snapshots__/stencil.test.ts.snap

+30-76
Original file line numberDiff line numberDiff line change
@@ -131,11 +131,7 @@ export class MyBasicRefComponent {
131131
`;
132132

133133
exports[`Stencil > jsx > Javascript Test > Basic 1`] = `
134-
"export const DEFAULT_VALUES = {
135-
name: \\"Steve\\",
136-
};
137-
138-
import { Component, h, Fragment, State } from \\"@stencil/core\\";
134+
"import { Component, h, Fragment, State } from \\"@stencil/core\\";
139135

140136
@Component({
141137
tag: \\"my-basic-component\\",
@@ -155,11 +151,15 @@ export class MyBasicComponent {
155151
return \\"bar\\";
156152
}
157153

154+
DEFAULT_VALUES = {
155+
name: \\"Steve\\",
156+
};
157+
158158
render() {
159159
return (
160160
<div class=\\"test div\\">
161161
<input
162-
value={DEFAULT_VALUES.name || this.name}
162+
value={this.DEFAULT_VALUES.name || this.name}
163163
onChange={(myEvent) => (this.name = myEvent.target.value)}
164164
/>
165165
Hello! I can run in React, Vue, Solid, or Liquid! &gt;
@@ -524,20 +524,7 @@ export class MyBasicRefAssignmentComponent {
524524
`;
525525

526526
exports[`Stencil > jsx > Javascript Test > BasicRefPrevious 1`] = `
527-
"export function usePrevious(value) {
528-
// The ref object is a generic container whose current property is mutable ...
529-
// ... and can hold any value, similar to an instance property on a class
530-
let ref = useRef(null); // Store current value in ref
531-
532-
onUpdate(() => {
533-
ref = value;
534-
}, [value]); // Only re-run if value changes
535-
// Return previous value (happens before update in useEffect above)
536-
537-
return ref;
538-
}
539-
540-
import { Component, h, Fragment, State } from \\"@stencil/core\\";
527+
"import { Component, h, Fragment, State } from \\"@stencil/core\\";
541528

542529
@Component({
543530
tag: \\"my-previous-component\\",
@@ -2490,24 +2477,24 @@ export class Button {
24902477
`;
24912478

24922479
exports[`Stencil > jsx > Javascript Test > defaultValsWithTypes 1`] = `
2493-
"const DEFAULT_VALUES = {
2494-
name: \\"Sami\\",
2495-
};
2496-
2497-
import { Component, h, Fragment, Prop } from \\"@stencil/core\\";
2480+
"import { Component, h, Fragment, Prop } from \\"@stencil/core\\";
24982481

24992482
@Component({
25002483
tag: \\"component-with-types\\",
25012484
})
25022485
export class ComponentWithTypes {
25032486
@Prop() name: any;
25042487

2488+
DEFAULT_VALUES = {
2489+
name: \\"Sami\\",
2490+
};
2491+
25052492
render() {
25062493
return (
25072494
<div>
25082495
{\\" \\"}
25092496
Hello
2510-
{this.name || DEFAULT_VALUES.name}
2497+
{this.name || this.DEFAULT_VALUES.name}
25112498
</div>
25122499
);
25132500
}
@@ -2819,11 +2806,7 @@ export class OnInit {
28192806
`;
28202807

28212808
exports[`Stencil > jsx > Javascript Test > onInit 1`] = `
2822-
"export const defaultValues = {
2823-
name: \\"PatrickJS\\",
2824-
};
2825-
2826-
import { Component, h, Fragment, Prop, State } from \\"@stencil/core\\";
2809+
"import { Component, h, Fragment, Prop, State } from \\"@stencil/core\\";
28272810

28282811
@Component({
28292812
tag: \\"on-init\\",
@@ -2949,13 +2932,7 @@ export class OnUpdateWithDeps {
29492932
`;
29502933

29512934
exports[`Stencil > jsx > Javascript Test > preserveExportOrLocalStatement 1`] = `
2952-
"const b = 3;
2953-
const foo = () => {};
2954-
export const a = 3;
2955-
export const bar = () => {};
2956-
export function run(value) {}
2957-
2958-
import { Component, h, Fragment } from \\"@stencil/core\\";
2935+
"import { Component, h, Fragment } from \\"@stencil/core\\";
29592936

29602937
@Component({
29612938
tag: \\"my-basic-component\\",
@@ -4081,11 +4058,7 @@ export class MyBasicRefComponent {
40814058
`;
40824059

40834060
exports[`Stencil > jsx > Typescript Test > Basic 1`] = `
4084-
"export const DEFAULT_VALUES = {
4085-
name: \\"Steve\\",
4086-
};
4087-
4088-
import { Component, h, Fragment, State } from \\"@stencil/core\\";
4061+
"import { Component, h, Fragment, State } from \\"@stencil/core\\";
40894062

40904063
@Component({
40914064
tag: \\"my-basic-component\\",
@@ -4105,11 +4078,15 @@ export class MyBasicComponent {
41054078
return \\"bar\\";
41064079
}
41074080

4081+
DEFAULT_VALUES = {
4082+
name: \\"Steve\\",
4083+
};
4084+
41084085
render() {
41094086
return (
41104087
<div class=\\"test div\\">
41114088
<input
4112-
value={DEFAULT_VALUES.name || this.name}
4089+
value={this.DEFAULT_VALUES.name || this.name}
41134090
onChange={(myEvent) => (this.name = myEvent.target.value)}
41144091
/>
41154092
Hello! I can run in React, Vue, Solid, or Liquid! &gt;
@@ -4474,20 +4451,7 @@ export class MyBasicRefAssignmentComponent {
44744451
`;
44754452

44764453
exports[`Stencil > jsx > Typescript Test > BasicRefPrevious 1`] = `
4477-
"export function usePrevious<T>(value: T) {
4478-
// The ref object is a generic container whose current property is mutable ...
4479-
// ... and can hold any value, similar to an instance property on a class
4480-
let ref = useRef<T>(null); // Store current value in ref
4481-
4482-
onUpdate(() => {
4483-
ref = value;
4484-
}, [value]); // Only re-run if value changes
4485-
// Return previous value (happens before update in useEffect above)
4486-
4487-
return ref;
4488-
}
4489-
4490-
import { Component, h, Fragment, State } from \\"@stencil/core\\";
4454+
"import { Component, h, Fragment, State } from \\"@stencil/core\\";
44914455

44924456
@Component({
44934457
tag: \\"my-previous-component\\",
@@ -6453,24 +6417,24 @@ export class Button {
64536417
`;
64546418

64556419
exports[`Stencil > jsx > Typescript Test > defaultValsWithTypes 1`] = `
6456-
"const DEFAULT_VALUES: Props = {
6457-
name: \\"Sami\\",
6458-
};
6459-
6460-
import { Component, h, Fragment, Prop } from \\"@stencil/core\\";
6420+
"import { Component, h, Fragment, Prop } from \\"@stencil/core\\";
64616421

64626422
@Component({
64636423
tag: \\"component-with-types\\",
64646424
})
64656425
export class ComponentWithTypes {
64666426
@Prop() name: any;
64676427

6428+
DEFAULT_VALUES = {
6429+
name: \\"Sami\\",
6430+
};
6431+
64686432
render() {
64696433
return (
64706434
<div>
64716435
{\\" \\"}
64726436
Hello
6473-
{this.name || DEFAULT_VALUES.name}
6437+
{this.name || this.DEFAULT_VALUES.name}
64746438
</div>
64756439
);
64766440
}
@@ -6783,11 +6747,7 @@ export class OnInit {
67836747
`;
67846748

67856749
exports[`Stencil > jsx > Typescript Test > onInit 1`] = `
6786-
"export const defaultValues = {
6787-
name: \\"PatrickJS\\",
6788-
};
6789-
6790-
import { Component, h, Fragment, Prop, State } from \\"@stencil/core\\";
6750+
"import { Component, h, Fragment, Prop, State } from \\"@stencil/core\\";
67916751

67926752
@Component({
67936753
tag: \\"on-init\\",
@@ -6913,13 +6873,7 @@ export class OnUpdateWithDeps {
69136873
`;
69146874

69156875
exports[`Stencil > jsx > Typescript Test > preserveExportOrLocalStatement 1`] = `
6916-
"const b = 3;
6917-
const foo = () => {};
6918-
export const a = 3;
6919-
export const bar = () => {};
6920-
export function run<T>(value: T) {}
6921-
6922-
import { Component, h, Fragment } from \\"@stencil/core\\";
6876+
"import { Component, h, Fragment } from \\"@stencil/core\\";
69236877

69246878
@Component({
69256879
tag: \\"my-basic-component\\",

packages/core/src/__tests__/stencil.test.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,6 @@ describe('Stencil', () => {
1414
generator: componentToStencil,
1515
options: {},
1616
logOutput: true,
17-
only: ['typeDependency'],
17+
only: ['defaultValsWithTypes'],
1818
});
1919
});*/

packages/core/src/__tests__/test-generator.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,7 @@ const BASIC_TESTS: Tests = {
218218
propsInterface: propsInterface,
219219
defaultProps: defaultProps,
220220
defaultPropsOutsideComponent,
221-
preserveTyping: preserveTyping,
221+
preserveTyping,
222222
typeDependency,
223223
typeExternalStore,
224224
typeExternalProps,

packages/core/src/generators/stencil/component.ts

+4-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { stringifySingleScopeOnMount } from '@/generators/helpers/on-mount';
22
import { blockToStencil } from '@/generators/stencil/blocks';
33
import {
4+
getExportsAndLocal,
45
getImports,
56
getPropsAsCode,
67
getStencilCoreImportsAsString,
@@ -57,7 +58,7 @@ export const componentToStencil: TranspilerGenerator<ToStencilOptions> =
5758
const childComponents: string[] = getChildComponents(json);
5859
const processBindingOptions: ProcessBindingOptions = { events };
5960

60-
options.plugins = getCodeProcessorPlugins(options, processBindingOptions);
61+
options.plugins = getCodeProcessorPlugins(json, options, processBindingOptions);
6162

6263
if (options.plugins) {
6364
json = runPostJsonPlugins({ json, plugins: options.plugins });
@@ -128,6 +129,8 @@ export const componentToStencil: TranspilerGenerator<ToStencilOptions> =
128129
${getPropsAsCode(props, json, defaultProps)}
129130
${dataString}
130131
${methodsString}
132+
133+
${getExportsAndLocal(json)}
131134
132135
${
133136
!json.hooks.onMount.length

packages/core/src/generators/stencil/helpers/index.ts

+28-2
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,21 @@ const appendEmits = (str: string, events: string[]): string => {
2323

2424
export type ProcessBindingOptions = { events: string[] };
2525

26-
export const processBinding = (code: string, { events }: ProcessBindingOptions) => {
27-
return stripStateAndPropsRefs(appendEmits(code, events), { replaceWith: 'this.' });
26+
export const processBinding = (
27+
json: MitosisComponent,
28+
code: string,
29+
{ events }: ProcessBindingOptions,
30+
) => {
31+
let resolvedCode = stripStateAndPropsRefs(appendEmits(code, events), { replaceWith: 'this.' });
32+
if (json.exports) {
33+
// We need to use local exports with `this.` in stencil
34+
Object.entries(json.exports)
35+
.filter(([, value]) => value.usedInLocal)
36+
.forEach(([key]) => {
37+
resolvedCode = resolvedCode.replaceAll(key, `this.${key}`);
38+
});
39+
}
40+
return resolvedCode;
2841
};
2942

3043
export const getTagName = (name: string, { prefix }: ToStencilOptions): string => {
@@ -126,6 +139,7 @@ export const getImports = (
126139
explicitImportFileExtension: options.explicitImportFileExtension,
127140
component: json,
128141
target: 'stencil',
142+
excludeExportAndLocal: true,
129143
importMapper: (_: any, theImport: any, importedValues: any) => {
130144
const childImport = importedValues.defaultImport;
131145
if (childImport && childComponents.includes(childImport)) {
@@ -136,3 +150,15 @@ export const getImports = (
136150
},
137151
});
138152
};
153+
154+
export const getExportsAndLocal = (json: MitosisComponent) => {
155+
return Object.entries(json.exports || {})
156+
.map(([key, { usedInLocal, code }]) => {
157+
if (usedInLocal) {
158+
return `${key} = ${code.substring(code.indexOf('=') + 1)}`;
159+
}
160+
161+
return '';
162+
})
163+
.join('\n');
164+
};

packages/core/src/generators/stencil/plugins/get-code-processor-plugins.ts

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
import { processBinding, ProcessBindingOptions } from '@/generators/stencil/helpers/index';
22
import { ToStencilOptions } from '@/generators/stencil/types';
33
import { CODE_PROCESSOR_PLUGIN } from '@/helpers/plugins/process-code';
4+
import { MitosisComponent } from '@/types/mitosis-component';
45

56
export const getCodeProcessorPlugins = (
7+
json: MitosisComponent,
68
options: ToStencilOptions,
79
processBindingOptions: ProcessBindingOptions,
810
) => {
@@ -18,7 +20,7 @@ export const getCodeProcessorPlugins = (
1820
case 'context-set':
1921
case 'dynamic-jsx-elements':
2022
case 'types':
21-
return (code) => processBinding(code, processBindingOptions);
23+
return (code) => processBinding(json, code, processBindingOptions);
2224
}
2325
}),
2426
];

packages/core/src/helpers/render-imports.ts

+3-1
Original file line numberDiff line numberDiff line change
@@ -237,11 +237,13 @@ export const renderPreComponent = ({
237237
componentsUsed = [],
238238
importMapper,
239239
explicitImportFileExtension = false,
240+
excludeExportAndLocal = false,
240241
}: Omit<ImportArgs, 'explicitImportFileExtension' | 'asyncComponentImports'> &
241242
Partial<Pick<ImportArgs, 'explicitImportFileExtension' | 'asyncComponentImports'>> & {
242243
component: MitosisComponent;
243244
target: Target;
244245
excludeMitosisComponents?: boolean;
246+
excludeExportAndLocal?: boolean;
245247
}): string => `
246248
${renderImports({
247249
imports: component.imports,
@@ -254,7 +256,7 @@ export const renderPreComponent = ({
254256
importMapper,
255257
explicitImportFileExtension,
256258
})}
257-
${renderExportAndLocal(component)}
259+
${excludeExportAndLocal ? '' : renderExportAndLocal(component)}
258260
${component.hooks.preComponent?.code || ''}
259261
`;
260262

0 commit comments

Comments
 (0)