Skip to content

Commit

Permalink
Fix: Vue this access in provide() (BuilderIO#964)
Browse files Browse the repository at this point in the history
* dedupe @babel/types

* augment babel types

* update yarn

* comment

* update yarn lock

* add missing path for jsx-runtime

* remove redundant type workaround

* improve replace-identifiers

* tweak

* refactor, pass hook key

* improve logging

* debug

* remove patch

* fix fiddle

* revert tsconfig changes

* revert to yarn 3.2

* run yarn

* add some missing deps for fiddle

* undo @babel/types dedupe

* remove

* always add React.Fragment

* bring back _this context workaround in vue

* undo react change

* use keys for Vue contexts

* improve context check

* fix for composition api too
  • Loading branch information
samijaber authored Dec 22, 2022
1 parent 5456136 commit 53e6619
Show file tree
Hide file tree
Showing 9 changed files with 153 additions and 110 deletions.
7 changes: 5 additions & 2 deletions packages/cli/src/build/helpers/context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ export const generateContextFile = async ({
case 'vue':
case 'vue2':
case 'vue3':
return contextToVue(context);
return contextToVue(options.options[target])({ context });
case 'solid':
return contextToSolid()({ context });
case 'react':
Expand All @@ -46,7 +46,10 @@ export const generateContextFile = async ({
return contextToQwik()({ context });
default:
console.warn('Context files are not supported for this target. Outputting no-op');
return contextToVue(context);
return `
// Noop file
export default {};
`;
}
}
};
Original file line number Diff line number Diff line change
Expand Up @@ -134,9 +134,9 @@ import { Injector, createInjector, MyService } from \\"@dummy/injection-js\\";

const name = ref(\\"PatrickJS\\");

const myService = inject(MyService);
const myService = inject(MyService.key);

provide(Injector, createInjector());
provide(Injector.key, createInjector());

const hi = myService.method(\\"hi\\");
console.log(hi);
Expand Down Expand Up @@ -1746,15 +1746,15 @@ import Context2 from \\"@dummy/2\\";

const props = defineProps([\\"content\\"]);

const foo = inject(Context1);
const foo = inject(Context1.key);

provide(Context1, {
provide(Context1.key, {
foo: \\"bar\\",
content() {
return props.content;
},
});
provide(Context2, { bar: \\"baz\\" });
provide(Context2.key, { bar: \\"baz\\" });
</script>"
`;

Expand All @@ -1770,7 +1770,7 @@ import BuilderContext from \\"@dummy/context.vue\\";

const props = defineProps([\\"content\\", \\"customComponents\\"]);

provide(BuilderContext, {
provide(BuilderContext.key, {
content: props.content,
registeredComponents: props.customComponents,
});
Expand Down Expand Up @@ -2196,7 +2196,7 @@ import RenderBlocks from \\"@dummy/RenderBlocks.lite.tsx\\";

const props = defineProps([\\"content\\", \\"customComponents\\"]);

provide(BuilderContext, {
provide(BuilderContext.key, {
get content() {
return 3;
},
Expand Down Expand Up @@ -2594,9 +2594,9 @@ import { Injector, createInjector, MyService } from \\"@dummy/injection-js\\";

const name = ref(\\"PatrickJS\\");

const myService = inject(MyService);
const myService = inject(MyService.key);

provide(Injector, createInjector());
provide(Injector.key, createInjector());

const hi = myService.method(\\"hi\\");
console.log(hi);
Expand Down Expand Up @@ -4383,15 +4383,15 @@ import Context2 from \\"@dummy/2\\";

const props = defineProps<ComponentWithContextProps>();

const foo = inject(Context1);
const foo = inject(Context1.key);

provide(Context1, {
provide(Context1.key, {
foo: \\"bar\\",
content() {
return props.content;
},
});
provide(Context2, { bar: \\"baz\\" });
provide(Context2.key, { bar: \\"baz\\" });
</script>"
`;

Expand All @@ -4407,7 +4407,7 @@ import BuilderContext from \\"@dummy/context.vue\\";

const props = defineProps([\\"content\\", \\"customComponents\\"]);

provide(BuilderContext, {
provide(BuilderContext.key, {
content: props.content,
registeredComponents: props.customComponents,
});
Expand Down Expand Up @@ -4914,7 +4914,7 @@ import RenderBlocks from \\"@dummy/RenderBlocks.lite.tsx\\";

const props = defineProps<Props>();

provide(BuilderContext, {
provide(BuilderContext.key, {
get content() {
return 3;
},
Expand Down
36 changes: 22 additions & 14 deletions packages/core/src/__tests__/__snapshots__/vue.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -150,12 +150,13 @@ export default {
data: () => ({ name: \\"PatrickJS\\" }),

provide() {
const _this = this;
return {
Injector: createInjector(),
[Injector.key]: createInjector(),
};
},
inject: {
myService: MyService,
myService: MyService.key,
},
created() {
const hi = this.myService.method(\\"hi\\");
Expand Down Expand Up @@ -1936,10 +1937,11 @@ export default {
props: [\\"content\\", \\"customComponents\\"],

provide() {
const _this = this;
return {
BuilderContext: {
content: this.content,
registeredComponents: this.customComponents,
[BuilderContext.key]: {
content: _this.content,
registeredComponents: _this.customComponents,
},
};
},
Expand Down Expand Up @@ -2476,8 +2478,9 @@ export default {
data: () => ({ trackClick }),

provide() {
const _this = this;
return {
BuilderContext: {
[BuilderContext.key]: {
get content() {
return 3;
},
Expand Down Expand Up @@ -2934,12 +2937,13 @@ export default {
data: () => ({ name: \\"PatrickJS\\" }),

provide() {
const _this = this;
return {
Injector: createInjector(),
[Injector.key]: createInjector(),
};
},
inject: {
myService: MyService,
myService: MyService.key,
},
created() {
const hi = this.myService.method(\\"hi\\");
Expand Down Expand Up @@ -4964,10 +4968,11 @@ export default {
props: [\\"content\\", \\"customComponents\\"],

provide() {
const _this = this;
return {
BuilderContext: {
content: this.content,
registeredComponents: this.customComponents,
[BuilderContext.key]: {
content: _this.content,
registeredComponents: _this.customComponents,
},
};
},
Expand Down Expand Up @@ -5589,8 +5594,9 @@ export default {
data: () => ({ trackClick }),

provide() {
const _this = this;
return {
BuilderContext: {
[BuilderContext.key]: {
get content() {
return 3;
},
Expand Down Expand Up @@ -6023,8 +6029,9 @@ export default {
data: () => ({ activeTab: 0 }),

provide() {
const _this = this;
return {
activeTab: this.activeTab,
[\\"activeTab\\"]: _this.activeTab,
};
},
inject: {
Expand Down Expand Up @@ -6402,8 +6409,9 @@ export default {
data: () => ({ activeTab: 0 }),

provide() {
const _this = this;
return {
activeTab: this.activeTab,
[\\"activeTab\\"]: _this.activeTab,
};
},
inject: {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { format } from 'prettier/standalone';
import { stringifyContextValue } from '../../../helpers/get-state-object-string';
import { MitosisContext } from '../../../types/mitosis-context';
import { BaseTranspilerOptions } from '../../../types/transpiler';

export const getContextWithSymbolKey =
(options: Pick<BaseTranspilerOptions, 'prettier'>) =>
({ context }: { context: MitosisContext }): string => {
let str = `
const key = Symbol();
export default {
${context.name}: ${stringifyContextValue(context.value)},
key
}
`;

if (options.prettier !== false) {
try {
str = format(str, {
parser: 'typescript',
plugins: [
require('prettier/parser-typescript'), // To support running in browsers
],
});
} catch (err) {
console.error('Format error for file:', str);
throw err;
}
}

return str;
};
33 changes: 2 additions & 31 deletions packages/core/src/generators/context/svelte.ts
Original file line number Diff line number Diff line change
@@ -1,38 +1,9 @@
import { format } from 'prettier/standalone';
import { stringifyContextValue } from '../../helpers/get-state-object-string';
import { MitosisContext } from '../../types/mitosis-context';
import { BaseTranspilerOptions } from '../../types/transpiler';
import { getContextWithSymbolKey } from './helpers/context-with-symbol-key';

interface ContextToSvelteOptions extends Pick<BaseTranspilerOptions, 'prettier'> {}

/**
* TO-DO: support types
*/
export const contextToSvelte =
(options: ContextToSvelteOptions = {}) =>
({ context }: { context: MitosisContext }): string => {
let str = `
const key = Symbol();
export default {
${context.name}: ${stringifyContextValue(context.value)},
key
}
`;

if (options.prettier !== false) {
try {
str = format(str, {
parser: 'typescript',
plugins: [
require('prettier/parser-typescript'), // To support running in browsers
],
});
} catch (err) {
console.error('Format error for file:', str);
throw err;
}
}

return str;
};
export const contextToSvelte = getContextWithSymbolKey;
15 changes: 2 additions & 13 deletions packages/core/src/generators/context/vue.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,3 @@
import { MitosisContext } from '../../types/mitosis-context';
import { getContextWithSymbolKey } from './helpers/context-with-symbol-key';

type ContextToVueOptions = {
format?: boolean;
};

export function contextToVue(context: MitosisContext, options: ContextToVueOptions = {}): string {
let str = `
// Noop file
export default {};
`;

return str;
}
export const contextToVue = getContextWithSymbolKey;
21 changes: 11 additions & 10 deletions packages/core/src/generators/vue/compositionApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import json5 from 'json5';
import { pickBy } from 'lodash';
import { getStateObjectStringFromComponent } from '../../helpers/get-state-object-string';
import { MitosisComponent, extendedHook } from '../../types/mitosis-component';
import { getContextValue } from './helpers';
import { getContextKey, getContextValue } from './helpers';
import { ToVueOptions } from './types';
import { stripStateAndPropsRefs } from '../../helpers/strip-state-and-props-refs';
import { processBinding } from './helpers';
Expand Down Expand Up @@ -81,18 +81,19 @@ export function generateCompositionApiScript(
${props.length ? getCompositionPropDefinition({ component, props, options }) : ''}
${refs}
${Object.keys(component.context.get)
?.map((key) => `const ${key} = inject(${component.context.get[key].name})`)
${Object.entries(component.context.get)
?.map(([key, context]) => {
return `const ${key} = inject(${getContextKey(context)})`;
})
.join('\n')}
${Object.values(component.context.set)
?.map(
(contextSet) =>
`provide(${contextSet.name}, ${getContextValue({
json: component,
options,
})(contextSet)})`,
)
?.map((contextSet) => {
const contextValue = getContextValue({ json: component, options })(contextSet);
const key = getContextKey(contextSet);
return `provide(${key}, ${contextValue})`;
})
.join('\n')}
${Object.keys(component.refs)
Expand Down
Loading

0 comments on commit 53e6619

Please sign in to comment.