mirror of
https://github.com/vuejs/babel-plugin-jsx.git
synced 2025-05-14 12:14:37 +08:00
fix: throw state.get(...)
when using object slots (#494)
This commit is contained in:
parent
e0d0162d6b
commit
55035e3f1d
@ -13,7 +13,8 @@ export { VueJSXPluginOptions };
|
|||||||
const hasJSX = (parentPath: NodePath<t.Program>) => {
|
const hasJSX = (parentPath: NodePath<t.Program>) => {
|
||||||
let fileHasJSX = false;
|
let fileHasJSX = false;
|
||||||
parentPath.traverse({
|
parentPath.traverse({
|
||||||
JSXElement(path) { // skip ts error
|
JSXElement(path) {
|
||||||
|
// skip ts error
|
||||||
fileHasJSX = true;
|
fileHasJSX = true;
|
||||||
path.stop();
|
path.stop();
|
||||||
},
|
},
|
||||||
@ -62,14 +63,9 @@ export default ({ types }: typeof BabelCore) => ({
|
|||||||
if (importMap[name]) {
|
if (importMap[name]) {
|
||||||
return types.cloneNode(importMap[name]);
|
return types.cloneNode(importMap[name]);
|
||||||
}
|
}
|
||||||
const identifier = addNamed(
|
const identifier = addNamed(path, name, 'vue', {
|
||||||
path,
|
ensureLiveReference: true,
|
||||||
name,
|
});
|
||||||
'vue',
|
|
||||||
{
|
|
||||||
ensureLiveReference: true,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
importMap[name] = identifier;
|
importMap[name] = identifier;
|
||||||
return identifier;
|
return identifier;
|
||||||
});
|
});
|
||||||
@ -80,14 +76,18 @@ export default ({ types }: typeof BabelCore) => ({
|
|||||||
if (importMap.runtimeIsSlot) {
|
if (importMap.runtimeIsSlot) {
|
||||||
return importMap.runtimeIsSlot;
|
return importMap.runtimeIsSlot;
|
||||||
}
|
}
|
||||||
const { name: isVNodeName } = state.get('isVNode')();
|
const { name: isVNodeName } = state.get(
|
||||||
|
'isVNode',
|
||||||
|
)() as t.Identifier;
|
||||||
const isSlot = path.scope.generateUidIdentifier('isSlot');
|
const isSlot = path.scope.generateUidIdentifier('isSlot');
|
||||||
const ast = template.ast`
|
const ast = template.ast`
|
||||||
function ${isSlot.name}(s) {
|
function ${isSlot.name}(s) {
|
||||||
return typeof s === 'function' || (Object.prototype.toString.call(s) === '[object Object]' && !${isVNodeName}(s));
|
return typeof s === 'function' || (Object.prototype.toString.call(s) === '[object Object]' && !${isVNodeName}(s));
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
const lastImport = (path.get('body') as NodePath[]).filter((p) => p.isImportDeclaration()).pop();
|
const lastImport = (path.get('body') as NodePath[])
|
||||||
|
.filter((p) => p.isImportDeclaration())
|
||||||
|
.pop();
|
||||||
if (lastImport) {
|
if (lastImport) {
|
||||||
lastImport.insertAfter(ast);
|
lastImport.insertAfter(ast);
|
||||||
}
|
}
|
||||||
@ -97,24 +97,57 @@ export default ({ types }: typeof BabelCore) => ({
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// var _vue = require('vue');
|
// var _vue = require('vue');
|
||||||
let sourceName = '';
|
let sourceName: t.Identifier;
|
||||||
importNames.forEach((name) => {
|
importNames.forEach((name) => {
|
||||||
state.set(name, () => {
|
state.set(name, () => {
|
||||||
if (!sourceName) {
|
if (!sourceName) {
|
||||||
sourceName = addNamespace(
|
sourceName = addNamespace(path, 'vue', {
|
||||||
path,
|
ensureLiveReference: true,
|
||||||
'vue',
|
});
|
||||||
{
|
|
||||||
ensureLiveReference: true,
|
|
||||||
},
|
|
||||||
).name;
|
|
||||||
}
|
}
|
||||||
return t.memberExpression(t.identifier(sourceName), t.identifier(name));
|
return t.memberExpression(sourceName, t.identifier(name));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const helpers: Record<string, t.Identifier> = {};
|
||||||
|
|
||||||
|
const { enableObjectSlots = true } = state.opts;
|
||||||
|
if (enableObjectSlots) {
|
||||||
|
state.set('@vue/babel-plugin-jsx/runtimeIsSlot', () => {
|
||||||
|
if (helpers.runtimeIsSlot) {
|
||||||
|
return helpers.runtimeIsSlot;
|
||||||
|
}
|
||||||
|
const isSlot = path.scope.generateUidIdentifier('isSlot');
|
||||||
|
const { object: objectName } = state.get(
|
||||||
|
'isVNode',
|
||||||
|
)() as t.MemberExpression;
|
||||||
|
const ast = template.ast`
|
||||||
|
function ${isSlot.name}(s) {
|
||||||
|
return typeof s === 'function' || (Object.prototype.toString.call(s) === '[object Object]' && !${(objectName as t.Identifier).name}.isVNode(s));
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
const nodePaths = path.get('body') as NodePath[];
|
||||||
|
const lastImport = nodePaths
|
||||||
|
.filter(
|
||||||
|
(p) => p.isVariableDeclaration()
|
||||||
|
&& p.node.declarations.some(
|
||||||
|
(d) => (d.id as t.Identifier)?.name === sourceName.name,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.pop();
|
||||||
|
if (lastImport) {
|
||||||
|
lastImport.insertAfter(ast);
|
||||||
|
}
|
||||||
|
return isSlot;
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const { opts: { pragma = '' }, file } = state;
|
const {
|
||||||
|
opts: { pragma = '' },
|
||||||
|
file,
|
||||||
|
} = state;
|
||||||
|
|
||||||
if (pragma) {
|
if (pragma) {
|
||||||
state.set('createVNode', () => t.identifier(pragma));
|
state.set('createVNode', () => t.identifier(pragma));
|
||||||
@ -134,13 +167,20 @@ export default ({ types }: typeof BabelCore) => ({
|
|||||||
const body = path.get('body') as NodePath[];
|
const body = path.get('body') as NodePath[];
|
||||||
const specifiersMap = new Map<string, t.ImportSpecifier>();
|
const specifiersMap = new Map<string, t.ImportSpecifier>();
|
||||||
|
|
||||||
body.filter((nodePath) => t.isImportDeclaration(nodePath.node)
|
body
|
||||||
&& nodePath.node.source.value === 'vue')
|
.filter(
|
||||||
|
(nodePath) => t.isImportDeclaration(nodePath.node)
|
||||||
|
&& nodePath.node.source.value === 'vue',
|
||||||
|
)
|
||||||
.forEach((nodePath) => {
|
.forEach((nodePath) => {
|
||||||
const { specifiers } = nodePath.node as t.ImportDeclaration;
|
const { specifiers } = nodePath.node as t.ImportDeclaration;
|
||||||
let shouldRemove = false;
|
let shouldRemove = false;
|
||||||
specifiers.forEach((specifier) => {
|
specifiers.forEach((specifier) => {
|
||||||
if (!specifier.loc && t.isImportSpecifier(specifier) && t.isIdentifier(specifier.imported)) {
|
if (
|
||||||
|
!specifier.loc
|
||||||
|
&& t.isImportSpecifier(specifier)
|
||||||
|
&& t.isIdentifier(specifier.imported)
|
||||||
|
) {
|
||||||
specifiersMap.set(specifier.imported.name, specifier);
|
specifiersMap.set(specifier.imported.name, specifier);
|
||||||
shouldRemove = true;
|
shouldRemove = true;
|
||||||
}
|
}
|
||||||
@ -154,7 +194,10 @@ export default ({ types }: typeof BabelCore) => ({
|
|||||||
(imported) => specifiersMap.get(imported)!,
|
(imported) => specifiersMap.get(imported)!,
|
||||||
);
|
);
|
||||||
if (specifiers.length) {
|
if (specifiers.length) {
|
||||||
path.unshiftContainer('body', t.importDeclaration(specifiers, t.stringLiteral('vue')));
|
path.unshiftContainer(
|
||||||
|
'body',
|
||||||
|
t.importDeclaration(specifiers, t.stringLiteral('vue')),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -24,5 +24,3 @@ export interface VueJSXPluginOptions {
|
|||||||
/** Replace the function used when compiling JSX expressions */
|
/** Replace the function used when compiling JSX expressions */
|
||||||
pragma?: string;
|
pragma?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type ExcludesBoolean = <T>(x: T | false | true) => x is T;
|
|
||||||
|
@ -20,10 +20,12 @@ import {
|
|||||||
import SlotFlags from './slotFlags';
|
import SlotFlags from './slotFlags';
|
||||||
import { PatchFlags } from './patchFlags';
|
import { PatchFlags } from './patchFlags';
|
||||||
import parseDirectives from './parseDirectives';
|
import parseDirectives from './parseDirectives';
|
||||||
import type { State, ExcludesBoolean, Slots } from './interface';
|
import type { State, Slots } from './interface';
|
||||||
|
|
||||||
const xlinkRE = /^xlink([A-Z])/;
|
const xlinkRE = /^xlink([A-Z])/;
|
||||||
|
|
||||||
|
type ExcludesBoolean = <T>(x: T | false | true) => x is T;
|
||||||
|
|
||||||
const getJSXAttributeValue = (
|
const getJSXAttributeValue = (
|
||||||
path: NodePath<t.JSXAttribute>,
|
path: NodePath<t.JSXAttribute>,
|
||||||
state: State,
|
state: State,
|
||||||
|
@ -4,7 +4,8 @@
|
|||||||
"rootDirs": ["./src"],
|
"rootDirs": ["./src"],
|
||||||
"outDir": "dist",
|
"outDir": "dist",
|
||||||
"downlevelIteration": true,
|
"downlevelIteration": true,
|
||||||
"declaration": true
|
"declaration": true,
|
||||||
|
"jsx": "preserve",
|
||||||
},
|
},
|
||||||
"include": ["src/**/*", "global.d.ts"],
|
"include": ["src/**/*", "global.d.ts"],
|
||||||
"exclude": ["node_modules"]
|
"exclude": ["node_modules"]
|
||||||
|
@ -11,7 +11,6 @@
|
|||||||
"resolveJsonModule": true,
|
"resolveJsonModule": true,
|
||||||
"esModuleInterop": true,
|
"esModuleInterop": true,
|
||||||
"removeComments": false,
|
"removeComments": false,
|
||||||
"jsx": "preserve",
|
|
||||||
"lib": [
|
"lib": [
|
||||||
"esnext",
|
"esnext",
|
||||||
"dom"
|
"dom"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user