更新
This commit is contained in:
+3
@@ -0,0 +1,3 @@
|
||||
import type { Plugin } from 'vite';
|
||||
export declare function uniAppCssPrePlugin(): Plugin;
|
||||
export declare function uniAppCssPlugin(): Plugin;
|
||||
+144
@@ -0,0 +1,144 @@
|
||||
"use strict";
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.uniAppCssPlugin = exports.uniAppCssPrePlugin = void 0;
|
||||
const path_1 = __importDefault(require("path"));
|
||||
const picocolors_1 = __importDefault(require("picocolors"));
|
||||
const uni_cli_shared_1 = require("@dcloudio/uni-cli-shared");
|
||||
const uni_nvue_styler_1 = require("@dcloudio/uni-nvue-styler");
|
||||
const descriptorCache_1 = require("./uvue/descriptorCache");
|
||||
const utils_1 = require("./utils");
|
||||
function uniAppCssPrePlugin() {
|
||||
const name = 'uni:app-uvue-css-pre';
|
||||
const descriptorOptions = {
|
||||
...(0, descriptorCache_1.getResolvedOptions)(),
|
||||
sourceMap: false,
|
||||
};
|
||||
const mainPath = (0, uni_cli_shared_1.resolveMainPathOnce)(process.env.UNI_INPUT_DIR);
|
||||
return {
|
||||
name,
|
||||
// 需要提前,因为unocss会在configResolved读取vite:css-post插件
|
||||
// 所以需要在它之前做替换
|
||||
enforce: 'pre',
|
||||
apply: 'build',
|
||||
configResolved(config) {
|
||||
(0, uni_cli_shared_1.removePlugins)(['vite:css', 'vite:css-post'], config);
|
||||
const uvueCssPostPlugin = (0, uni_cli_shared_1.cssPostPlugin)(config, {
|
||||
isJsCode: true,
|
||||
platform: process.env.UNI_PLATFORM,
|
||||
includeComponentCss: false,
|
||||
chunkCssFilename(id) {
|
||||
const { filename } = (0, uni_cli_shared_1.parseVueRequest)(id);
|
||||
if (filename === mainPath) {
|
||||
// 合并到App
|
||||
return `App.uvue.style.uts`;
|
||||
}
|
||||
if ((0, utils_1.isVue)(filename)) {
|
||||
return (0, uni_cli_shared_1.normalizeNodeModules)((path_1.default.isAbsolute(filename)
|
||||
? path_1.default.relative(process.env.UNI_INPUT_DIR, filename)
|
||||
: filename) + '.style.uts');
|
||||
}
|
||||
},
|
||||
async chunkCssCode(filename, cssCode) {
|
||||
cssCode = (0, uni_cli_shared_1.parseAssets)(config, cssCode);
|
||||
const { code, messages } = await (0, uni_nvue_styler_1.parse)(cssCode, {
|
||||
filename,
|
||||
logLevel: 'ERROR',
|
||||
mapOf: 'utsMapOf',
|
||||
chunk: 100,
|
||||
type: 'uvue',
|
||||
platform: process.env.UNI_UTS_PLATFORM,
|
||||
trim: true,
|
||||
});
|
||||
messages.forEach((message) => {
|
||||
if (message.type === 'error') {
|
||||
let msg = `[plugin:uni:app-uvue-css] ${message.text}`;
|
||||
if (message.line && message.column) {
|
||||
msg += `\n${(0, uni_cli_shared_1.generateCodeFrame)(cssCode, {
|
||||
line: message.line,
|
||||
column: message.column,
|
||||
}).replace(/\t/g, ' ')}`;
|
||||
}
|
||||
msg += `\n${(0, uni_cli_shared_1.formatAtFilename)(filename)}`;
|
||||
config.logger.error(picocolors_1.default.red(msg));
|
||||
}
|
||||
});
|
||||
const fileName = filename.replace('.style.uts', '');
|
||||
const className = process.env.UNI_COMPILE_TARGET === 'ext-api'
|
||||
? // components/map/map.vue => UniMap
|
||||
(0, uni_cli_shared_1.genUTSClassName)(path_1.default.basename(fileName), descriptorOptions.classNamePrefix)
|
||||
: (0, uni_cli_shared_1.genUTSClassName)(fileName, descriptorOptions.classNamePrefix);
|
||||
return `export const ${className}Styles = ${code}`;
|
||||
},
|
||||
});
|
||||
// 增加 css plugins
|
||||
// TODO 加密插件
|
||||
(0, uni_cli_shared_1.insertBeforePlugin)((0, uni_cli_shared_1.cssPlugin)(config, {
|
||||
isAndroidX: true,
|
||||
getDescriptor: (filename) => {
|
||||
return (0, descriptorCache_1.getDescriptor)(filename, descriptorOptions, false);
|
||||
},
|
||||
}), name, config);
|
||||
const plugins = config.plugins;
|
||||
const index = plugins.findIndex((p) => p.name === 'uni:app-uvue');
|
||||
plugins.splice(index, 0, uvueCssPostPlugin);
|
||||
},
|
||||
};
|
||||
}
|
||||
exports.uniAppCssPrePlugin = uniAppCssPrePlugin;
|
||||
function uniAppCssPlugin() {
|
||||
let resolvedConfig;
|
||||
return {
|
||||
name: 'uni:app-uvue-css',
|
||||
apply: 'build',
|
||||
configResolved(config) {
|
||||
resolvedConfig = config;
|
||||
},
|
||||
async transform(source, filename) {
|
||||
if (!uni_cli_shared_1.cssLangRE.test(filename) || uni_cli_shared_1.commonjsProxyRE.test(filename)) {
|
||||
return;
|
||||
}
|
||||
if (filename.endsWith('__uno.css')) {
|
||||
return;
|
||||
}
|
||||
if (source.includes('#endif')) {
|
||||
source = (0, uni_cli_shared_1.preUVueCss)(source, filename);
|
||||
}
|
||||
source = (0, uni_cli_shared_1.parseAssets)(resolvedConfig, source);
|
||||
// 仅做校验使用
|
||||
const { messages } = await (0, uni_nvue_styler_1.parse)(source, {
|
||||
filename,
|
||||
logLevel: 'WARNING',
|
||||
map: true,
|
||||
ts: true,
|
||||
noCode: true,
|
||||
type: 'uvue',
|
||||
platform: process.env.UNI_UTS_PLATFORM,
|
||||
});
|
||||
messages.forEach((message) => {
|
||||
if (message.type === 'warning') {
|
||||
// 拆分成多行,第一行输出信息(有颜色),后续输出错误代码+文件行号
|
||||
resolvedConfig.logger.warn(picocolors_1.default.yellow(`[plugin:uni:app-uvue-css] ${message.text}`));
|
||||
let msg = '';
|
||||
if (message.line && message.column) {
|
||||
msg += `\n${(0, uni_cli_shared_1.generateCodeFrame)(source, {
|
||||
line: message.line,
|
||||
column: message.column,
|
||||
}).replace(/\t/g, ' ')}\n`;
|
||||
}
|
||||
msg += `${(0, uni_cli_shared_1.formatAtFilename)(filename)}`;
|
||||
resolvedConfig.logger.warn(msg);
|
||||
}
|
||||
});
|
||||
return {
|
||||
code: source,
|
||||
map: {
|
||||
mappings: '',
|
||||
},
|
||||
};
|
||||
},
|
||||
};
|
||||
}
|
||||
exports.uniAppCssPlugin = uniAppCssPlugin;
|
||||
+1
@@ -0,0 +1 @@
|
||||
export declare function init(): any[];
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.init = void 0;
|
||||
const uni_cli_shared_1 = require("@dcloudio/uni-cli-shared");
|
||||
const pre_1 = require("./pre");
|
||||
const plugin_1 = require("./plugin");
|
||||
const css_1 = require("./css");
|
||||
const mainUTS_1 = require("./mainUTS");
|
||||
const manifestJson_1 = require("./manifestJson");
|
||||
const pagesJson_1 = require("./pagesJson");
|
||||
const uvue_1 = require("./uvue");
|
||||
const unicloud_1 = require("./unicloud");
|
||||
function init() {
|
||||
return [
|
||||
(0, css_1.uniAppCssPrePlugin)(),
|
||||
...((0, uni_cli_shared_1.isNormalCompileTarget)()
|
||||
? [
|
||||
require('@dcloudio/uni-console/lib/uni.plugin.js')(),
|
||||
(0, uni_cli_shared_1.uniDecryptUniModulesPlugin)(),
|
||||
]
|
||||
: []),
|
||||
(0, pre_1.uniPrePlugin)(),
|
||||
...((0, uni_cli_shared_1.isNormalCompileTarget)()
|
||||
? [
|
||||
(0, uni_cli_shared_1.uniUTSAppUniModulesPlugin)({
|
||||
x: true,
|
||||
isSingleThread: process.env.UNI_APP_X_SINGLE_THREAD !== 'false',
|
||||
extApis: (0, uni_cli_shared_1.parseUniExtApiNamespacesOnce)(process.env.UNI_UTS_PLATFORM, process.env.UNI_UTS_TARGET_LANGUAGE),
|
||||
}),
|
||||
]
|
||||
: []),
|
||||
(0, plugin_1.uniAppPlugin)(),
|
||||
...(process.env.UNI_COMPILE_TARGET === 'ext-api'
|
||||
? [(0, uni_cli_shared_1.uniUniModulesExtApiPlugin)()]
|
||||
: process.env.UNI_COMPILE_TARGET === 'uni_modules'
|
||||
? [(0, uni_cli_shared_1.uniEncryptUniModulesPlugin)()]
|
||||
: [
|
||||
// 需要放到 uniAppPlugin 之后(TSC模式无需),让 uniAppPlugin 先 emit 出真实的 main.uts,然后 MainPlugin 再返回仅包含 import 的 js code
|
||||
(0, mainUTS_1.uniAppMainPlugin)(),
|
||||
(0, manifestJson_1.uniAppManifestPlugin)(),
|
||||
(0, pagesJson_1.uniAppPagesPlugin)(),
|
||||
]),
|
||||
(0, css_1.uniAppCssPlugin)(),
|
||||
// 解决所有的src引入
|
||||
(0, uni_cli_shared_1.uniViteSfcSrcImportPlugin)({ onlyVue: false }),
|
||||
(0, uvue_1.uniAppUVuePlugin)(),
|
||||
(0, unicloud_1.uniCloudPlugin)(),
|
||||
];
|
||||
}
|
||||
exports.init = init;
|
||||
Generated
Vendored
+2
@@ -0,0 +1,2 @@
|
||||
import type { Plugin } from 'vite';
|
||||
export declare function uniAppMainPlugin(): Plugin;
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.uniAppMainPlugin = void 0;
|
||||
const uni_cli_shared_1 = require("@dcloudio/uni-cli-shared");
|
||||
const utils_1 = require("./utils");
|
||||
function uniAppMainPlugin() {
|
||||
const mainUTS = (0, uni_cli_shared_1.resolveMainPathOnce)(process.env.UNI_INPUT_DIR);
|
||||
return {
|
||||
name: 'uni:app-main',
|
||||
apply: 'build',
|
||||
async transform(code, id) {
|
||||
if ((0, uni_cli_shared_1.normalizePath)(id) === mainUTS) {
|
||||
code = await (0, utils_1.parseImports)(code, (0, utils_1.createTryResolve)(id, this.resolve.bind(this)));
|
||||
return {
|
||||
code: `import './${uni_cli_shared_1.MANIFEST_JSON_UTS}';import './${uni_cli_shared_1.PAGES_JSON_UTS}';${code}`,
|
||||
map: {
|
||||
mappings: '',
|
||||
},
|
||||
};
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
exports.uniAppMainPlugin = uniAppMainPlugin;
|
||||
Generated
Vendored
+3
@@ -0,0 +1,3 @@
|
||||
import type { Plugin } from 'vite';
|
||||
export declare function getOutputManifestJson(): Record<string, any> | undefined;
|
||||
export declare function uniAppManifestPlugin(): Plugin;
|
||||
Generated
Vendored
+102
@@ -0,0 +1,102 @@
|
||||
"use strict";
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.uniAppManifestPlugin = exports.getOutputManifestJson = void 0;
|
||||
const path_1 = __importDefault(require("path"));
|
||||
const fs_extra_1 = __importDefault(require("fs-extra"));
|
||||
const uni_cli_shared_1 = require("@dcloudio/uni-cli-shared");
|
||||
const utils_1 = require("./utils");
|
||||
const utils_2 = require("../utils");
|
||||
let outputManifestJson = undefined;
|
||||
function getOutputManifestJson() {
|
||||
return outputManifestJson;
|
||||
}
|
||||
exports.getOutputManifestJson = getOutputManifestJson;
|
||||
function uniAppManifestPlugin() {
|
||||
const manifestJsonPath = path_1.default.resolve(process.env.UNI_INPUT_DIR, 'manifest.json');
|
||||
const manifestJsonUTSPath = path_1.default.resolve(process.env.UNI_INPUT_DIR, uni_cli_shared_1.MANIFEST_JSON_UTS);
|
||||
let manifestJson = {};
|
||||
return {
|
||||
name: 'uni:app-manifest',
|
||||
apply: 'build',
|
||||
resolveId(id) {
|
||||
if ((0, utils_2.isManifest)(id)) {
|
||||
return manifestJsonUTSPath;
|
||||
}
|
||||
},
|
||||
load(id) {
|
||||
if ((0, utils_2.isManifest)(id)) {
|
||||
return fs_extra_1.default.readFileSync(manifestJsonPath, 'utf8');
|
||||
}
|
||||
},
|
||||
transform(code, id) {
|
||||
if ((0, utils_2.isManifest)(id)) {
|
||||
this.addWatchFile(path_1.default.resolve(process.env.UNI_INPUT_DIR, 'manifest.json'));
|
||||
manifestJson = (0, uni_cli_shared_1.parseJson)(code, false, id);
|
||||
return {
|
||||
code: `export default 'manifest.json'`,
|
||||
map: {
|
||||
mappings: '',
|
||||
},
|
||||
};
|
||||
}
|
||||
},
|
||||
generateBundle(_, bundle) {
|
||||
if (bundle[(0, utils_1.ENTRY_FILENAME)()]) {
|
||||
const asset = bundle[(0, utils_1.ENTRY_FILENAME)()];
|
||||
const singleThreadCode = manifestJson?.['uni-app-x']?.['singleThread'] === false
|
||||
? `override singleThread = false`
|
||||
: '';
|
||||
const flexDir = (0, uni_cli_shared_1.parseUniXFlexDirection)(manifestJson);
|
||||
const flexDirCode = flexDir !== 'column' ? `override flexDirection = "${flexDir}"` : '';
|
||||
const splashScreen = (0, uni_cli_shared_1.parseUniXSplashScreen)(manifestJson);
|
||||
const splashScreenCode = splashScreen && Object.keys(splashScreen).length > 0
|
||||
? `override splashScreen: Map<string, any> | null = ${(0, utils_1.stringifyMap)(splashScreen)}`
|
||||
: '';
|
||||
const uniStatistics = (0, uni_cli_shared_1.parseUniXUniStatistics)(manifestJson);
|
||||
const uniStatisticsCode = uniStatistics && Object.keys(uniStatistics).length > 0
|
||||
? `override uniStatistics: UTSJSONObject | null = ${JSON.stringify(uniStatistics)}`
|
||||
: '';
|
||||
const hasAppDefaultAppTheme = (0, uni_cli_shared_1.validateThemeValue)(manifestJson.app?.defaultAppTheme);
|
||||
const hasDefaultAppTheme = (0, uni_cli_shared_1.validateThemeValue)(manifestJson.defaultAppTheme);
|
||||
const defaultAppThemeCode = hasAppDefaultAppTheme
|
||||
? `override defaultAppTheme: string = "${manifestJson.app.defaultAppTheme}"`
|
||||
: hasDefaultAppTheme
|
||||
? `override defaultAppTheme: string = "${manifestJson.defaultAppTheme}"`
|
||||
: '';
|
||||
const codes = [
|
||||
singleThreadCode,
|
||||
flexDirCode,
|
||||
splashScreenCode,
|
||||
defaultAppThemeCode,
|
||||
uniStatisticsCode,
|
||||
]
|
||||
.filter(Boolean)
|
||||
.join('\n');
|
||||
asset.source =
|
||||
asset.source +
|
||||
`
|
||||
export class UniAppConfig extends io.dcloud.uniapp.appframe.AppConfig {
|
||||
override name: string = "${manifestJson.name || ''}"
|
||||
override appid: string = "${manifestJson.appid || ''}"
|
||||
override versionName: string = "${manifestJson.versionName || ''}"
|
||||
override versionCode: string = "${manifestJson.versionCode || ''}"
|
||||
override uniCompilerVersion: string = "${process.env.UNI_COMPILER_VERSION || ''}"
|
||||
${codes}
|
||||
constructor() { super() }
|
||||
}
|
||||
`;
|
||||
}
|
||||
},
|
||||
writeBundle() {
|
||||
outputManifestJson = (0, utils_2.normalizeManifestJson)(manifestJson);
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
// 发行模式下,需要等解析ext-api模块
|
||||
fs_extra_1.default.outputFileSync(path_1.default.resolve(process.env.UNI_OUTPUT_DIR, 'manifest.json'), JSON.stringify(outputManifestJson, null, 2));
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
exports.uniAppManifestPlugin = uniAppManifestPlugin;
|
||||
Generated
Vendored
+2
@@ -0,0 +1,2 @@
|
||||
import type { Plugin } from 'vite';
|
||||
export declare function uniAppPagesPlugin(): Plugin;
|
||||
Generated
Vendored
+165
@@ -0,0 +1,165 @@
|
||||
"use strict";
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.uniAppPagesPlugin = void 0;
|
||||
const path_1 = __importDefault(require("path"));
|
||||
const fs_extra_1 = __importDefault(require("fs-extra"));
|
||||
const uni_cli_shared_1 = require("@dcloudio/uni-cli-shared");
|
||||
const utils_1 = require("./utils");
|
||||
const utils_2 = require("../utils");
|
||||
function uniAppPagesPlugin() {
|
||||
const pagesJsonPath = path_1.default.resolve(process.env.UNI_INPUT_DIR, 'pages.json');
|
||||
const pagesJsonUTSPath = path_1.default.resolve(process.env.UNI_INPUT_DIR, uni_cli_shared_1.PAGES_JSON_UTS);
|
||||
let imports = [];
|
||||
let routes = [];
|
||||
let globalStyle = 'new Map()';
|
||||
let tabBar = 'null';
|
||||
let launchPage = 'null';
|
||||
let conditionUrl = '';
|
||||
let uniIdRouter = 'new Map()';
|
||||
let themeConfig = '';
|
||||
const codes = [];
|
||||
return {
|
||||
name: 'uni:app-pages',
|
||||
apply: 'build',
|
||||
resolveId(id) {
|
||||
if ((0, utils_2.isPages)(id)) {
|
||||
return pagesJsonUTSPath;
|
||||
}
|
||||
},
|
||||
load(id) {
|
||||
if ((0, utils_2.isPages)(id)) {
|
||||
return fs_extra_1.default.readFileSync(pagesJsonPath, 'utf8');
|
||||
}
|
||||
},
|
||||
transform(code, id) {
|
||||
if ((0, utils_2.isPages)(id)) {
|
||||
this.addWatchFile(path_1.default.resolve(process.env.UNI_INPUT_DIR, 'pages.json'));
|
||||
this.addWatchFile(path_1.default.resolve(process.env.UNI_INPUT_DIR, 'theme.json'));
|
||||
let pagesJson = {
|
||||
pages: [],
|
||||
globalStyle: {
|
||||
navigationBar: {},
|
||||
},
|
||||
};
|
||||
// 调整换行符,确保 parseTree 的loc正确
|
||||
code = code.replace(/\r\n/g, '\n');
|
||||
try {
|
||||
pagesJson = (0, uni_cli_shared_1.normalizeUniAppXAppPagesJson)(code);
|
||||
}
|
||||
catch (err) {
|
||||
if (err.loc) {
|
||||
const error = (0, uni_cli_shared_1.createRollupError)('uni:app-pages', pagesJsonPath, err, code);
|
||||
this.error(error);
|
||||
}
|
||||
else {
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
imports = [];
|
||||
routes = [];
|
||||
process.env.UNI_APP_X_PAGE_COUNT = pagesJson.pages.length + '';
|
||||
(0, utils_2.setGlobalPageOrientation)(pagesJson.globalStyle?.pageOrientation || '');
|
||||
pagesJson.pages.forEach((page, index) => {
|
||||
const className = (0, uni_cli_shared_1.genUTSClassName)(page.path);
|
||||
let isQuit = index === 0;
|
||||
imports.push(page.path);
|
||||
routes.push(`{ path: "${page.path}", component: ${className}Class, meta: { isQuit: ${isQuit} } as UniPageMeta, style: ${stringifyPageStyle(page.style)}${page.needLogin === undefined
|
||||
? ''
|
||||
: ', needLogin: ' + page.needLogin} } as UniPageRoute`);
|
||||
});
|
||||
if (pagesJson.globalStyle) {
|
||||
globalStyle = stringifyPageStyle(pagesJson.globalStyle);
|
||||
}
|
||||
if (pagesJson.tabBar) {
|
||||
tabBar = (0, utils_1.stringifyMap)(pagesJson.tabBar);
|
||||
}
|
||||
if (pagesJson.condition) {
|
||||
const conditionInfo = (0, uni_cli_shared_1.parseArguments)(pagesJson);
|
||||
if (conditionInfo) {
|
||||
const { path, query } = JSON.parse(conditionInfo);
|
||||
conditionUrl = `${path}${query ? '?' + query : ''}`;
|
||||
}
|
||||
}
|
||||
if (pagesJson.uniIdRouter) {
|
||||
uniIdRouter = (0, utils_1.stringifyMap)(pagesJson.uniIdRouter);
|
||||
}
|
||||
launchPage = stringifyLaunchPage(pagesJson.pages[0]);
|
||||
codes.length = 0;
|
||||
// theme.json
|
||||
themeConfig = readThemeJSONFileAsStringifyMap();
|
||||
if (themeConfig) {
|
||||
codes.push(`__uniConfig.themeConfig = ${themeConfig}`);
|
||||
}
|
||||
return {
|
||||
code: `${imports
|
||||
.map((p) => `import './${p}.uvue?type=page'`)
|
||||
.join('\n')}
|
||||
export default 'pages.json'`,
|
||||
map: {
|
||||
mappings: '',
|
||||
},
|
||||
};
|
||||
}
|
||||
},
|
||||
generateBundle(_, bundle) {
|
||||
if (bundle[(0, utils_1.ENTRY_FILENAME)()]) {
|
||||
const asset = bundle[(0, utils_1.ENTRY_FILENAME)()];
|
||||
asset.source =
|
||||
asset.source +
|
||||
`
|
||||
${imports
|
||||
.map((p) => {
|
||||
const className = (0, uni_cli_shared_1.genUTSClassName)(p);
|
||||
return `import ${className}Class from './${p}.uvue?type=page'`;
|
||||
})
|
||||
.join('\n')}
|
||||
function definePageRoutes() {
|
||||
${routes.map((route) => `__uniRoutes.push(${route})`).join('\n')}
|
||||
}
|
||||
const __uniTabBar: Map<string, any | null> | null = ${tabBar}
|
||||
const __uniLaunchPage: Map<string, any | null> = ${launchPage}
|
||||
function defineAppConfig(){
|
||||
__uniConfig.entryPagePath = '/${imports[0]}'
|
||||
__uniConfig.globalStyle = ${globalStyle}
|
||||
__uniConfig.getTabBarConfig = ():Map<string, any> | null => ${tabBar}
|
||||
__uniConfig.tabBar = __uniConfig.getTabBarConfig()
|
||||
__uniConfig.conditionUrl = '${conditionUrl}'
|
||||
__uniConfig.uniIdRouter = ${uniIdRouter}
|
||||
${codes.join('\n ')}
|
||||
__uniConfig.ready = true
|
||||
}
|
||||
`;
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
exports.uniAppPagesPlugin = uniAppPagesPlugin;
|
||||
function stringifyLaunchPage(launchPage) {
|
||||
return (0, utils_1.stringifyMap)({
|
||||
url: launchPage.path,
|
||||
style: launchPage.style,
|
||||
}, true);
|
||||
}
|
||||
function stringifyPageStyle(pageStyle) {
|
||||
return (0, utils_1.stringifyMap)(pageStyle);
|
||||
}
|
||||
// function readUniSassAsStringifyMap() {
|
||||
// const uniScssPath = path.resolve(process.env.UNI_INPUT_DIR, 'uni.scss')
|
||||
// let result = {}
|
||||
// if (fs.existsSync(uniScssPath)) {
|
||||
// const content = fs.readFileSync(uniScssPath, 'utf8')
|
||||
// const parser = new ThemeSassParser()
|
||||
// result = parser.parse(content)
|
||||
// }
|
||||
// return stringifyMap(result)
|
||||
// }
|
||||
function readThemeJSONFileAsStringifyMap() {
|
||||
const themeJsonPath = path_1.default.resolve(process.env.UNI_INPUT_DIR, 'theme.json');
|
||||
if (fs_extra_1.default.existsSync(themeJsonPath)) {
|
||||
return (0, utils_1.stringifyMap)(JSON.parse(fs_extra_1.default.readFileSync(themeJsonPath, 'utf8')));
|
||||
}
|
||||
return '';
|
||||
}
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
import { type UniVitePlugin } from '@dcloudio/uni-cli-shared';
|
||||
export declare function uniAppPlugin(): UniVitePlugin;
|
||||
+374
@@ -0,0 +1,374 @@
|
||||
"use strict";
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.uniAppPlugin = void 0;
|
||||
const path_1 = __importDefault(require("path"));
|
||||
const fs_extra_1 = __importDefault(require("fs-extra"));
|
||||
const shared_1 = require("@vue/shared");
|
||||
const uni_cli_shared_1 = require("@dcloudio/uni-cli-shared");
|
||||
const utils_1 = require("./utils");
|
||||
const manifestJson_1 = require("./manifestJson");
|
||||
const utils_2 = require("../utils");
|
||||
const uniCloudSpaceList = (0, utils_1.getUniCloudSpaceList)();
|
||||
let isFirst = true;
|
||||
let isFirstBundleSuccess = false;
|
||||
function uniAppPlugin() {
|
||||
const inputDir = process.env.UNI_INPUT_DIR;
|
||||
const outputDir = process.env.UNI_OUTPUT_DIR;
|
||||
// const uniModulesDir = normalizePath(path.resolve(inputDir, 'uni_modules'))
|
||||
const mainUTS = (0, uni_cli_shared_1.resolveMainPathOnce)(inputDir);
|
||||
const pagesJsonPath = (0, uni_cli_shared_1.normalizePath)(path_1.default.resolve(inputDir, 'pages.json'));
|
||||
const uvueOutputDir = (0, uni_cli_shared_1.uvueOutDir)('app-android');
|
||||
const tscOutputDir = (0, uni_cli_shared_1.tscOutDir)('app-android');
|
||||
const manifestJson = (0, uni_cli_shared_1.parseManifestJsonOnce)(inputDir);
|
||||
// 预留一个口子,方便切换测试
|
||||
const split = manifestJson['uni-app-x']?.split;
|
||||
// 开始编译时,清空输出目录
|
||||
function emptyOutDir() {
|
||||
// ext-api 编译时,需要同时编译多个平台,并保留多个平台的输出目录
|
||||
if (process.env.UNI_COMPILE_TARGET === 'ext-api') {
|
||||
return;
|
||||
}
|
||||
if (fs_extra_1.default.existsSync(outputDir)) {
|
||||
(0, uni_cli_shared_1.emptyDir)(outputDir);
|
||||
}
|
||||
}
|
||||
emptyOutDir();
|
||||
function emptyUVueDir() {
|
||||
if (fs_extra_1.default.existsSync(uvueOutputDir)) {
|
||||
(0, uni_cli_shared_1.emptyDir)(uvueOutputDir);
|
||||
}
|
||||
}
|
||||
emptyUVueDir();
|
||||
function emptyTscDir() {
|
||||
if (fs_extra_1.default.existsSync(tscOutputDir)) {
|
||||
(0, uni_cli_shared_1.emptyDir)(tscOutputDir);
|
||||
}
|
||||
}
|
||||
emptyTscDir();
|
||||
let resolvedConfig;
|
||||
const uniXKotlinCompiler = process.env.UNI_APP_X_TSC === 'true'
|
||||
? (0, uni_cli_shared_1.resolveUTSCompiler)().createUniXKotlinCompilerOnce()
|
||||
: null;
|
||||
const changedFiles = [];
|
||||
return {
|
||||
name: 'uni:app-uts',
|
||||
apply: 'build',
|
||||
uni: (0, utils_2.createUniOptions)('app-android'),
|
||||
config() {
|
||||
return {
|
||||
base: '/', // 强制 base
|
||||
build: {
|
||||
// 手动清理
|
||||
emptyOutDir: false,
|
||||
outDir: process.env.UNI_APP_X_TSC === 'true' ? tscOutputDir : uvueOutputDir,
|
||||
lib: {
|
||||
// 必须使用 lib 模式
|
||||
fileName: 'output',
|
||||
entry: (0, uni_cli_shared_1.resolveMainPathOnce)(inputDir),
|
||||
formats: ['cjs'],
|
||||
},
|
||||
rollupOptions: {
|
||||
external(source) {
|
||||
if (['vue', 'vuex', 'pinia', '@dcloudio/uni-app'].includes(source)) {
|
||||
return true;
|
||||
}
|
||||
// 相对目录
|
||||
if (source.startsWith('@/') || source.startsWith('.')) {
|
||||
return false;
|
||||
}
|
||||
if (path_1.default.isAbsolute(source)) {
|
||||
return false;
|
||||
}
|
||||
// 'virtual:uno.css'
|
||||
if (source.includes(':')) {
|
||||
return false;
|
||||
}
|
||||
// android 系统库,三方库,iOS 的库呢?一般不包含.
|
||||
if (source.includes('.')) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
output: {
|
||||
chunkFileNames(chunk) {
|
||||
// if (chunk.isDynamicEntry && chunk.facadeModuleId) {
|
||||
// const { filename } = parseVueRequest(chunk.facadeModuleId)
|
||||
// if (filename.endsWith('.nvue')) {
|
||||
// return (
|
||||
// removeExt(
|
||||
// normalizePath(path.relative(inputDir, filename))
|
||||
// ) + '.js'
|
||||
// )
|
||||
// }
|
||||
// }
|
||||
return '[name].js';
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
},
|
||||
async configResolved(config) {
|
||||
(0, utils_2.configResolved)(config, true);
|
||||
resolvedConfig = config;
|
||||
if (uniXKotlinCompiler) {
|
||||
await uniXKotlinCompiler.init();
|
||||
}
|
||||
},
|
||||
async transform(code, id) {
|
||||
const { filename } = (0, uni_cli_shared_1.parseVueRequest)(id);
|
||||
if (!filename.endsWith('.uts') && !filename.endsWith('.ts')) {
|
||||
if (filename.endsWith('.json')) {
|
||||
this.emitFile({
|
||||
type: 'asset',
|
||||
fileName: (0, uni_cli_shared_1.normalizeEmitAssetFileName)(normalizeFilename(id, false)),
|
||||
source: code,
|
||||
});
|
||||
}
|
||||
return;
|
||||
}
|
||||
// 仅处理 uts 文件
|
||||
// 忽略 uni-app-uts/lib/automator/index.uts
|
||||
if (!filename.includes('uni-app-uts')) {
|
||||
code = (await (0, utils_1.transformAutoImport)((0, utils_1.transformUniCloudMixinDataCom)((0, uni_cli_shared_1.rewriteUniModulesConsoleExpr)(id, code)), id)).code;
|
||||
const isMainUTS = (0, uni_cli_shared_1.normalizePath)(id) === mainUTS;
|
||||
this.emitFile({
|
||||
type: 'asset',
|
||||
fileName: (0, uni_cli_shared_1.normalizeEmitAssetFileName)(normalizeFilename(id, isMainUTS)),
|
||||
source: normalizeCode(code, isMainUTS),
|
||||
});
|
||||
}
|
||||
code = await (0, utils_1.parseImports)(code, (0, utils_1.createTryResolve)(id, this.resolve.bind(this)));
|
||||
return {
|
||||
code,
|
||||
map: {
|
||||
mappings: '',
|
||||
},
|
||||
};
|
||||
},
|
||||
generateBundle(_, bundle) {
|
||||
if (!(0, uni_cli_shared_1.isNormalCompileTarget)()) {
|
||||
return;
|
||||
}
|
||||
// 开发者仅在 script 中引入了 easyCom 类型,但模板里边没用到,此时额外生成一个辅助的.uvue文件
|
||||
// checkUTSEasyComAutoImports(inputDir, bundle, this)
|
||||
},
|
||||
watchChange(fileName, change) {
|
||||
if (uniXKotlinCompiler) {
|
||||
// watcher && watcher.watch(3000)
|
||||
fileName = (0, uni_cli_shared_1.normalizePath)(fileName);
|
||||
if (fileName === pagesJsonPath) {
|
||||
// pages.json 被注入了main.uts,需要触发main.uts的重新编译
|
||||
changedFiles.push({
|
||||
fileName: (0, uni_cli_shared_1.normalizePath)(mainUTS),
|
||||
event: change.event,
|
||||
});
|
||||
}
|
||||
else {
|
||||
// 主工程可能引入uni_modules中的文件
|
||||
// if (fileName.startsWith(uniModulesDir)) {
|
||||
// // 忽略uni_modules uts原生插件中的文件
|
||||
// const plugin = fileName
|
||||
// .slice(uniModulesDir.length + 1)
|
||||
// .split('/')[0]
|
||||
// if (getCurrentCompiledUTSPlugins().has(plugin)) {
|
||||
// return
|
||||
// }
|
||||
// }
|
||||
const depMap = (0, uni_cli_shared_1.getCssDepMap)();
|
||||
if (depMap.has(fileName)) {
|
||||
for (const id of depMap.get(fileName)) {
|
||||
changedFiles.push({ fileName: id, event: change.event });
|
||||
}
|
||||
}
|
||||
}
|
||||
changedFiles.push({ fileName, event: change.event });
|
||||
}
|
||||
},
|
||||
async writeBundle() {
|
||||
const { compileApp } = (0, uni_cli_shared_1.resolveUTSCompiler)();
|
||||
if (!(0, uni_cli_shared_1.isNormalCompileTarget)()) {
|
||||
if (process.env.UNI_COMPILE_TARGET === 'ext-api') {
|
||||
if (uniXKotlinCompiler) {
|
||||
await uniXKotlinCompiler.addRootFile(path_1.default.join(tscOutputDir, 'main.uts.ts'));
|
||||
await uniXKotlinCompiler.close();
|
||||
const res = await compileApp(path_1.default.join(uvueOutputDir, 'main.uts'), {
|
||||
pageCount: 0,
|
||||
split: false,
|
||||
disableSplitManifest: process.env.NODE_ENV !== 'development',
|
||||
inputDir: uvueOutputDir,
|
||||
outputDir: outputDir,
|
||||
outFilename: `${process.env.UNI_COMPILE_EXT_API_OUT_FILE_NAME || 'components'}.kt`,
|
||||
package: (0, uni_cli_shared_1.parseKotlinPackageWithPluginId)(process.env.UNI_COMPILE_EXT_API_PLUGIN_ID, true),
|
||||
sourceMap: false,
|
||||
uni_modules: [process.env.UNI_COMPILE_EXT_API_PLUGIN_ID],
|
||||
extApiComponents: [],
|
||||
uvueClassNamePrefix: utils_1.UVUE_CLASS_NAME_PREFIX,
|
||||
transform: {
|
||||
uvueClassNamePrefix: 'Uni',
|
||||
uvueClassNameOnlyBasename: true,
|
||||
},
|
||||
});
|
||||
if (res?.error) {
|
||||
throw res.error;
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (uniXKotlinCompiler) {
|
||||
// 如果 main.uts.ts 没有被添加到 uniXKotlinCompiler 中,则添加
|
||||
// 有可能首次编译失败,并没有走到这里,二次编译导致了changedFiles有内容
|
||||
const mainFile = path_1.default.join(tscOutputDir, 'main.uts.ts');
|
||||
if (!uniXKotlinCompiler.hasRootFile(mainFile)) {
|
||||
await uniXKotlinCompiler.addRootFile(mainFile);
|
||||
}
|
||||
if (changedFiles.length) {
|
||||
const files = changedFiles.splice(0);
|
||||
await uniXKotlinCompiler.invalidate(files);
|
||||
}
|
||||
}
|
||||
let pageCount = 0;
|
||||
if (isFirst) {
|
||||
isFirst = false;
|
||||
}
|
||||
// 首次编译成功后,不再显示页面数量进度条
|
||||
if (!isFirstBundleSuccess) {
|
||||
// 自动化测试时,不显示页面数量进度条
|
||||
// if (!process.env.UNI_AUTOMATOR_WS_ENDPOINT) {
|
||||
pageCount = parseInt(process.env.UNI_APP_X_PAGE_COUNT) || 0;
|
||||
// }
|
||||
}
|
||||
// x 上暂时编译所有uni ext api,不管代码里是否调用了
|
||||
await (0, uni_cli_shared_1.buildUniExtApis)();
|
||||
const uniCloudObjectInfo = (0, utils_1.getUniCloudObjectInfo)(uniCloudSpaceList);
|
||||
if (uniCloudObjectInfo.length > 0) {
|
||||
process.env.UNI_APP_X_UNICLOUD_OBJECT = 'true';
|
||||
}
|
||||
else {
|
||||
process.env.UNI_APP_X_UNICLOUD_OBJECT = 'false';
|
||||
}
|
||||
const res = await compileApp(path_1.default.join(uvueOutputDir, 'main.uts'), {
|
||||
pageCount,
|
||||
uniCloudObjectInfo,
|
||||
split: split !== false,
|
||||
disableSplitManifest: process.env.NODE_ENV !== 'development',
|
||||
inputDir: uvueOutputDir,
|
||||
outputDir: outputDir,
|
||||
package: 'uni.' + (manifestJson.appid || utils_1.DEFAULT_APPID).replace(/_/g, ''),
|
||||
sourceMap: (0, uni_cli_shared_1.enableSourceMap)(),
|
||||
uni_modules: [...(0, uni_cli_shared_1.getCurrentCompiledUTSPlugins)()],
|
||||
extApis: (0, uni_cli_shared_1.parseUniExtApiNamespacesOnce)(process.env.UNI_UTS_PLATFORM, process.env.UNI_UTS_TARGET_LANGUAGE),
|
||||
extApiComponents: [...(0, utils_2.getExtApiComponents)()],
|
||||
uvueClassNamePrefix: utils_1.UVUE_CLASS_NAME_PREFIX,
|
||||
autoImports: await (0, uni_cli_shared_1.initUTSKotlinAutoImportsOnce)(),
|
||||
extApiProviders: parseUniExtApiProviders(),
|
||||
uniModulesArtifacts: (0, uni_cli_shared_1.parseUniModulesArtifacts)(),
|
||||
env: parseProcessEnv(resolvedConfig),
|
||||
});
|
||||
if (uniXKotlinCompiler && process.env.NODE_ENV !== 'development') {
|
||||
await uniXKotlinCompiler.close();
|
||||
}
|
||||
if (res) {
|
||||
if (process.env.NODE_ENV === 'development') {
|
||||
const files = [];
|
||||
if (process.env.UNI_APP_UTS_CHANGED_FILES) {
|
||||
try {
|
||||
files.push(...JSON.parse(process.env.UNI_APP_UTS_CHANGED_FILES));
|
||||
}
|
||||
catch (e) { }
|
||||
}
|
||||
if (res.changed) {
|
||||
// 触发了kotlinc编译,且没有编译成功
|
||||
if (!res.changed.length && res.kotlinc) {
|
||||
throw new Error('编译失败');
|
||||
}
|
||||
files.push(...res.changed);
|
||||
}
|
||||
process.env.UNI_APP_UTS_CHANGED_FILES = JSON.stringify([
|
||||
...new Set(files),
|
||||
]);
|
||||
}
|
||||
else {
|
||||
// 生产环境,记录使用到的modules
|
||||
const modules = res.inject_modules;
|
||||
const manifest = (0, manifestJson_1.getOutputManifestJson)();
|
||||
if (manifest) {
|
||||
// 执行了摇树逻辑,就需要设置 modules 节点
|
||||
(0, utils_2.updateManifestModules)(manifest, modules);
|
||||
fs_extra_1.default.outputFileSync(path_1.default.resolve(process.env.UNI_OUTPUT_DIR, 'manifest.json'), JSON.stringify(manifest, null, 2));
|
||||
}
|
||||
}
|
||||
}
|
||||
isFirstBundleSuccess = true;
|
||||
},
|
||||
};
|
||||
}
|
||||
exports.uniAppPlugin = uniAppPlugin;
|
||||
function normalizeFilename(filename, isMain = false) {
|
||||
if (isMain) {
|
||||
return 'main.uts';
|
||||
}
|
||||
return (0, utils_1.parseUTSRelativeFilename)(filename, process.env.UNI_INPUT_DIR);
|
||||
}
|
||||
function commentUnoCssImport(code) {
|
||||
// 使用正则表达式匹配 'import 'virtual:uno.css'' 语句
|
||||
const regex = /^import\s+['"]virtual:uno\.css['"];?/gm;
|
||||
return code.replace(regex, '// $&');
|
||||
}
|
||||
function normalizeCode(code, isMain = false) {
|
||||
code = commentUnoCssImport(code);
|
||||
if (!(0, uni_cli_shared_1.isNormalCompileTarget)()) {
|
||||
return code;
|
||||
}
|
||||
if (!isMain) {
|
||||
return code;
|
||||
}
|
||||
const automatorCode = process.env.UNI_AUTOMATOR_WS_ENDPOINT &&
|
||||
process.env.UNI_AUTOMATOR_APP_WEBVIEW !== 'true'
|
||||
? 'initAutomator();\n'
|
||||
: '';
|
||||
return `${code}
|
||||
export function main(app: IApp) {
|
||||
definePageRoutes();
|
||||
defineAppConfig();
|
||||
${automatorCode}(createApp()['app'] as VueApp).mount(app, ${utils_1.UVUE_CLASS_NAME_PREFIX}UniApp());
|
||||
}
|
||||
`;
|
||||
}
|
||||
function parseUniExtApiProviders() {
|
||||
const providers = [];
|
||||
const customProviders = (0, uni_cli_shared_1.getUniExtApiProviderRegisters)();
|
||||
customProviders.forEach((provider) => {
|
||||
providers.push([provider.service, provider.name, provider.class]);
|
||||
});
|
||||
return providers;
|
||||
}
|
||||
function parseProcessEnv(resolvedConfig) {
|
||||
const env = {};
|
||||
const defines = {};
|
||||
const userDefines = resolvedConfig.define;
|
||||
Object.keys(userDefines).forEach((key) => {
|
||||
if (key.startsWith('process.env.')) {
|
||||
defines[key.replace('process.env.', '')] = userDefines[key];
|
||||
}
|
||||
});
|
||||
(0, shared_1.extend)(defines, resolvedConfig.env);
|
||||
Object.keys(defines).forEach((key) => {
|
||||
let value = defines[key];
|
||||
if ((0, shared_1.isString)(value)) {
|
||||
try {
|
||||
value = JSON.parse(value);
|
||||
}
|
||||
catch (e) { }
|
||||
}
|
||||
if (!(0, shared_1.isString)(value)) {
|
||||
value = JSON.stringify(value);
|
||||
}
|
||||
env[key] = value;
|
||||
});
|
||||
return env;
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
import type { Plugin } from 'vite';
|
||||
import { type FilterPattern } from '@rollup/pluginutils';
|
||||
export interface UniPrePluginOptions {
|
||||
include?: FilterPattern;
|
||||
exclude?: FilterPattern;
|
||||
}
|
||||
export declare function uniPrePlugin(options?: UniPrePluginOptions): Plugin;
|
||||
+56
@@ -0,0 +1,56 @@
|
||||
"use strict";
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.uniPrePlugin = void 0;
|
||||
const path_1 = __importDefault(require("path"));
|
||||
const debug_1 = __importDefault(require("debug"));
|
||||
const pluginutils_1 = require("@rollup/pluginutils");
|
||||
const uni_cli_shared_1 = require("@dcloudio/uni-cli-shared");
|
||||
const debugPreJs = (0, debug_1.default)('uni:pre-js');
|
||||
const debugPreHtml = (0, debug_1.default)('uni:pre-html');
|
||||
// const debugPreJsTry = debug('uni:pre-js-try')
|
||||
const PRE_HTML_EXTNAME = ['.vue', '.uvue'];
|
||||
const PRE_JS_EXTNAME = ['.json', '.css', '.uts', '.ts'].concat(PRE_HTML_EXTNAME);
|
||||
function uniPrePlugin(options = {}) {
|
||||
const filter = (0, pluginutils_1.createFilter)(options.include, options.exclude);
|
||||
const preJsFile = uni_cli_shared_1.preUVueJs;
|
||||
const preHtmlFile = uni_cli_shared_1.preUVueHtml;
|
||||
return {
|
||||
name: 'uni:pre-android',
|
||||
enforce: 'pre',
|
||||
transform(code, id) {
|
||||
if (!filter(id)) {
|
||||
return;
|
||||
}
|
||||
const { filename } = (0, uni_cli_shared_1.parseVueRequest)(id);
|
||||
const extname = path_1.default.extname(filename);
|
||||
const isHtml = PRE_HTML_EXTNAME.includes(extname);
|
||||
const isJs = PRE_JS_EXTNAME.includes(extname);
|
||||
const isPre = isHtml || isJs;
|
||||
if (isPre) {
|
||||
// debugPreJsTry(id)
|
||||
}
|
||||
const hasEndif = isPre && code.includes('#endif');
|
||||
if (!hasEndif) {
|
||||
return;
|
||||
}
|
||||
if (isHtml) {
|
||||
code = preHtmlFile(code, id);
|
||||
debugPreHtml(id);
|
||||
}
|
||||
if (isJs) {
|
||||
code = preJsFile(code, id);
|
||||
debugPreJs(id);
|
||||
}
|
||||
return {
|
||||
code,
|
||||
map: {
|
||||
mappings: '',
|
||||
},
|
||||
};
|
||||
},
|
||||
};
|
||||
}
|
||||
exports.uniPrePlugin = uniPrePlugin;
|
||||
Generated
Vendored
+2
@@ -0,0 +1,2 @@
|
||||
import type { Plugin } from 'vite';
|
||||
export declare function uniCloudPlugin(): Plugin;
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
"use strict";
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.uniCloudPlugin = void 0;
|
||||
const path_1 = __importDefault(require("path"));
|
||||
const uni_cli_shared_1 = require("@dcloudio/uni-cli-shared");
|
||||
const utils_1 = require("./utils");
|
||||
const uniCloudSpaceList = (0, utils_1.getUniCloudSpaceList)();
|
||||
function uniCloudPlugin() {
|
||||
if (!(process.env.UNI_COMPILE_TARGET === 'ext-api' &&
|
||||
process.env.UNI_APP_NEXT_WORKSPACE)) {
|
||||
(0, uni_cli_shared_1.addUTSEasyComAutoImports)((0, uni_cli_shared_1.normalizePath)(path_1.default.resolve((0, uni_cli_shared_1.resolveComponentsLibPath)(), 'unicloud-db', 'index.uts')), ['mixinDatacom', 'uniCloudMixinDatacom']);
|
||||
}
|
||||
return {
|
||||
name: 'uni:app-unicloud',
|
||||
apply: 'build',
|
||||
generateBundle(_, bundle) {
|
||||
if (uniCloudSpaceList.length === 0) {
|
||||
return;
|
||||
}
|
||||
if (bundle[(0, utils_1.ENTRY_FILENAME)()]) {
|
||||
const asset = bundle[(0, utils_1.ENTRY_FILENAME)()];
|
||||
asset.source =
|
||||
asset.source +
|
||||
`
|
||||
export class UniCloudConfig extends io.dcloud.unicloud.InternalUniCloudConfig {
|
||||
override isDev : boolean = ${process.env.NODE_ENV === 'development' ? 'true' : 'false'}
|
||||
override spaceList : string = ${JSON.stringify(JSON.stringify(uniCloudSpaceList.map((item) => {
|
||||
const itemCopy = { ...item };
|
||||
delete itemCopy.workspaceFolder;
|
||||
return itemCopy;
|
||||
})))}
|
||||
override debuggerInfo ?: string = ${JSON.stringify(process.env.UNICLOUD_DEBUG || null)}
|
||||
override secureNetworkEnable : boolean = false
|
||||
override secureNetworkConfig ?: string = ""
|
||||
constructor() { super() }
|
||||
}
|
||||
`;
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
exports.uniCloudPlugin = uniCloudPlugin;
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
import { type ImportSpecifier } from 'es-module-lexer';
|
||||
import { type Import } from 'unimport';
|
||||
import type { /*SourceMapInput, */ PluginContext } from 'rollup';
|
||||
import type { Position } from '@vue/compiler-core';
|
||||
export declare const UVUE_CLASS_NAME_PREFIX = "Gen";
|
||||
export declare const DEFAULT_APPID = "__UNI__uniappx";
|
||||
export declare const ENTRY_FILENAME: () => "main.uts.ts" | "main.uts";
|
||||
export declare function wrapResolve(resolve: PluginContext['resolve']): PluginContext['resolve'];
|
||||
export declare function createTryResolve(importer: string, resolve: PluginContext['resolve'], offsetStart?: Position, origCode?: string): (source: string, code: string, { ss, se }: ImportSpecifier) => Promise<boolean | void>;
|
||||
export declare function parseImports(code: string, tryResolve?: ReturnType<typeof createTryResolve>): Promise<string>;
|
||||
export declare function createResolveError(code: string, msg: string, start: Position, end: Position): import("rollup").RollupError;
|
||||
export declare function kotlinOutDir(): string;
|
||||
export declare function isVue(filename: string): boolean;
|
||||
export declare function stringifyMap(obj: unknown, ts?: boolean): string;
|
||||
export declare function parseUTSRelativeFilename(filename: string, root?: string): string;
|
||||
export declare function parseUTSImportFilename(filename: string): string;
|
||||
type UniCloudSpace = {
|
||||
provider: string;
|
||||
spaceName: string;
|
||||
spaceId: string;
|
||||
clientSecret?: string;
|
||||
endpoint?: string;
|
||||
workspaceFolder?: string;
|
||||
};
|
||||
export declare function getUniCloudSpaceList(): Array<UniCloudSpace>;
|
||||
type UniCloudObjectInfo = {
|
||||
name: string;
|
||||
methodList: string[];
|
||||
};
|
||||
export declare function getUniCloudObjectInfo(uniCloudSpaceList: Array<UniCloudSpace>): Array<UniCloudObjectInfo>;
|
||||
export declare function transformAutoImport(code: string, id: string, ignore?: string[]): Promise<{
|
||||
code: string;
|
||||
}>;
|
||||
export declare function genAutoImportsCode(imports: Import[]): string;
|
||||
export declare function transformUniCloudMixinDataCom(code: string): string;
|
||||
export declare function detectAutoImports(code: string, id: string, ignore?: string[]): Promise<{
|
||||
matchedImports: Import[];
|
||||
}> | {
|
||||
matchedImports: never[];
|
||||
};
|
||||
export {};
|
||||
+368
@@ -0,0 +1,368 @@
|
||||
"use strict";
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.detectAutoImports = exports.transformUniCloudMixinDataCom = exports.genAutoImportsCode = exports.transformAutoImport = exports.getUniCloudObjectInfo = exports.getUniCloudSpaceList = exports.parseUTSImportFilename = exports.parseUTSRelativeFilename = exports.stringifyMap = exports.isVue = exports.kotlinOutDir = exports.createResolveError = exports.parseImports = exports.createTryResolve = exports.wrapResolve = exports.ENTRY_FILENAME = exports.DEFAULT_APPID = exports.UVUE_CLASS_NAME_PREFIX = void 0;
|
||||
const fs_1 = __importDefault(require("fs"));
|
||||
const path_1 = __importDefault(require("path"));
|
||||
const es_module_lexer_1 = require("es-module-lexer");
|
||||
const uni_cli_shared_1 = require("@dcloudio/uni-cli-shared");
|
||||
const shared_1 = require("@vue/shared");
|
||||
const unimport_1 = require("unimport");
|
||||
const errors_1 = require("./uvue/compiler/errors");
|
||||
exports.UVUE_CLASS_NAME_PREFIX = 'Gen';
|
||||
exports.DEFAULT_APPID = '__UNI__uniappx';
|
||||
const ENTRY_FILENAME = () => process.env.UNI_APP_X_TSC === 'true' ? 'main.uts.ts' : 'main.uts';
|
||||
exports.ENTRY_FILENAME = ENTRY_FILENAME;
|
||||
function wrapResolve(resolve) {
|
||||
return async (source, importer, options) => {
|
||||
try {
|
||||
return await resolve(source, importer, options);
|
||||
}
|
||||
catch (e) {
|
||||
// import "@/pages/logo.png" 可能会报 Cannot find module 错误
|
||||
}
|
||||
return null;
|
||||
};
|
||||
}
|
||||
exports.wrapResolve = wrapResolve;
|
||||
function createTryResolve(importer, resolve, offsetStart, origCode = '') {
|
||||
return async (source, code, { ss, se }) => {
|
||||
const resolved = await wrapResolve(resolve)(source, importer);
|
||||
if (!resolved) {
|
||||
const { start, end } = (0, uni_cli_shared_1.offsetToStartAndEnd)(code, ss, se);
|
||||
if (offsetStart) {
|
||||
if (start.line === 1) {
|
||||
start.column = start.column + offsetStart.column;
|
||||
if (end.line === 1) {
|
||||
end.column = end.column + offsetStart.column;
|
||||
}
|
||||
}
|
||||
const offsetLine = offsetStart.line - 1;
|
||||
start.line = start.line + offsetLine;
|
||||
end.line = end.line + offsetLine;
|
||||
}
|
||||
throw createResolveError(origCode || code, (0, uni_cli_shared_1.createResolveErrorMsg)(source, importer), start, end);
|
||||
}
|
||||
};
|
||||
}
|
||||
exports.createTryResolve = createTryResolve;
|
||||
async function parseImports(code, tryResolve) {
|
||||
await es_module_lexer_1.init;
|
||||
let res = [[], [], false, false];
|
||||
try {
|
||||
res = (0, es_module_lexer_1.parse)(code);
|
||||
}
|
||||
catch (err) {
|
||||
const message = err.message;
|
||||
if (message) {
|
||||
const matches = message.match(/@:(\d+):(\d+)/);
|
||||
if (matches) {
|
||||
throw (0, uni_cli_shared_1.createRollupError)('', '', (0, errors_1.createCompilerError)(0, {
|
||||
start: {
|
||||
offset: 0,
|
||||
line: parseInt(matches[1]),
|
||||
column: parseInt(matches[2]),
|
||||
},
|
||||
}, { 0: `Parse error` }, ''), code);
|
||||
}
|
||||
}
|
||||
throw err;
|
||||
}
|
||||
const imports = res[0];
|
||||
const importsCode = [];
|
||||
for (const specifier of imports) {
|
||||
const source = code.slice(specifier.s, specifier.e);
|
||||
if (tryResolve) {
|
||||
const res = await tryResolve(source, code, specifier);
|
||||
if (res === false) {
|
||||
// 忽略该import
|
||||
continue;
|
||||
}
|
||||
}
|
||||
importsCode.push(`import "${source}"`);
|
||||
}
|
||||
return importsCode.concat(parseUniExtApiImports(code)).join('\n');
|
||||
}
|
||||
exports.parseImports = parseImports;
|
||||
function createResolveError(code, msg, start, end) {
|
||||
return (0, uni_cli_shared_1.createRollupError)('', '', (0, errors_1.createCompilerError)(0, {
|
||||
start,
|
||||
end,
|
||||
}, { 0: msg }, ''), code);
|
||||
}
|
||||
exports.createResolveError = createResolveError;
|
||||
// @ts-expect-error 暂时不用
|
||||
function genImportsCode(code, imports) {
|
||||
const chars = code.split('');
|
||||
const keepChars = [];
|
||||
imports.forEach(({ ss, se }) => {
|
||||
for (let i = ss; i <= se; i++) {
|
||||
keepChars.push(i);
|
||||
}
|
||||
});
|
||||
for (let i = 0; i < chars.length; i++) {
|
||||
if (!keepChars.includes(i)) {
|
||||
const char = chars[i];
|
||||
if (char !== '\r' && char !== '\n') {
|
||||
chars[i] = ' ';
|
||||
}
|
||||
}
|
||||
}
|
||||
return chars.join('');
|
||||
}
|
||||
function parseUniExtApiImports(code) {
|
||||
if (!process.env.UNI_UTS_PLATFORM) {
|
||||
return [];
|
||||
}
|
||||
const extApis = (0, uni_cli_shared_1.parseUniExtApiNamespacesJsOnce)(process.env.UNI_UTS_PLATFORM, process.env.UNI_UTS_TARGET_LANGUAGE);
|
||||
const pattern = /uni\.(\w+)/g;
|
||||
const apis = new Set();
|
||||
let match;
|
||||
while ((match = pattern.exec(code)) !== null) {
|
||||
apis.add(match[1]);
|
||||
}
|
||||
const imports = [];
|
||||
apis.forEach((api) => {
|
||||
const extApi = extApis[api];
|
||||
if (extApi) {
|
||||
imports.push(`import "${extApi[0]}"`);
|
||||
}
|
||||
});
|
||||
return imports;
|
||||
}
|
||||
function kotlinOutDir() {
|
||||
return path_1.default.join(process.env.UNI_OUTPUT_DIR, '../.kotlin');
|
||||
}
|
||||
exports.kotlinOutDir = kotlinOutDir;
|
||||
function isVue(filename) {
|
||||
return filename.endsWith('.vue') || filename.endsWith('.uvue');
|
||||
}
|
||||
exports.isVue = isVue;
|
||||
function stringifyMap(obj, ts = false) {
|
||||
return serialize(obj, ts);
|
||||
}
|
||||
exports.stringifyMap = stringifyMap;
|
||||
function serialize(obj, ts = false) {
|
||||
if ((0, shared_1.isString)(obj)) {
|
||||
return `"${obj}"`;
|
||||
}
|
||||
else if ((0, shared_1.isPlainObject)(obj)) {
|
||||
const entries = Object.entries(obj).map(([key, value]) => `[${serialize(key, ts)},${serialize(value, ts)}]`);
|
||||
if (entries.length) {
|
||||
return `utsMapOf([${entries.join(',')}])`;
|
||||
}
|
||||
if (ts) {
|
||||
return `utsMapOf<string, any | null>()`;
|
||||
}
|
||||
return `utsMapOf()`;
|
||||
}
|
||||
else if ((0, shared_1.isArray)(obj)) {
|
||||
return `[${obj.map((item) => serialize(item, ts)).join(',')}]`;
|
||||
}
|
||||
else {
|
||||
return String(obj);
|
||||
}
|
||||
}
|
||||
function parseUTSRelativeFilename(filename, root) {
|
||||
if (!path_1.default.isAbsolute(filename)) {
|
||||
return filename;
|
||||
}
|
||||
return (0, uni_cli_shared_1.normalizeNodeModules)(path_1.default.relative(root ?? process.env.UNI_INPUT_DIR, filename));
|
||||
}
|
||||
exports.parseUTSRelativeFilename = parseUTSRelativeFilename;
|
||||
function parseUTSImportFilename(filename) {
|
||||
if (!path_1.default.isAbsolute(filename)) {
|
||||
return filename;
|
||||
}
|
||||
return ('@/' +
|
||||
(0, uni_cli_shared_1.normalizeNodeModules)(path_1.default.relative(process.env.UNI_INPUT_DIR, filename)));
|
||||
}
|
||||
exports.parseUTSImportFilename = parseUTSImportFilename;
|
||||
let uniCloudSpaceList;
|
||||
function getUniCloudSpaceList() {
|
||||
if (uniCloudSpaceList) {
|
||||
return uniCloudSpaceList;
|
||||
}
|
||||
if (!process.env.UNI_CLOUD_SPACES) {
|
||||
uniCloudSpaceList = [];
|
||||
return uniCloudSpaceList;
|
||||
}
|
||||
try {
|
||||
const spaces = JSON.parse(process.env.UNI_CLOUD_SPACES);
|
||||
if (!Array.isArray(spaces)) {
|
||||
uniCloudSpaceList = [];
|
||||
return uniCloudSpaceList;
|
||||
}
|
||||
uniCloudSpaceList = spaces.map((space) => {
|
||||
if (space.provider === 'tcb') {
|
||||
space.provider = 'tencent';
|
||||
}
|
||||
if (!space.provider && space.clientSecret) {
|
||||
space.provider = 'aliyun';
|
||||
}
|
||||
switch (space.provider) {
|
||||
case 'aliyun':
|
||||
case 'dcloud':
|
||||
return {
|
||||
provider: space.provider || 'aliyun',
|
||||
spaceName: space.name,
|
||||
spaceId: space.id,
|
||||
clientSecret: space.clientSecret,
|
||||
endpoint: space.apiEndpoint,
|
||||
workspaceFolder: space.workspaceFolder,
|
||||
};
|
||||
case 'alipay': {
|
||||
return {
|
||||
provider: space.provider,
|
||||
spaceName: space.name,
|
||||
spaceId: space.id,
|
||||
spaceAppId: space.spaceAppId,
|
||||
accessKey: space.accessKey,
|
||||
secretKey: space.secretKey,
|
||||
workspaceFolder: space.workspaceFolder,
|
||||
};
|
||||
}
|
||||
case 'tencent':
|
||||
default: {
|
||||
return {
|
||||
provider: space.provider,
|
||||
spaceName: space.name,
|
||||
spaceId: space.id,
|
||||
workspaceFolder: space.workspaceFolder,
|
||||
};
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
uniCloudSpaceList = uniCloudSpaceList || [];
|
||||
if (uniCloudSpaceList.length > 1) {
|
||||
console.warn('Multi uniCloud space is not supported yet.');
|
||||
}
|
||||
return uniCloudSpaceList;
|
||||
}
|
||||
exports.getUniCloudSpaceList = getUniCloudSpaceList;
|
||||
function getUniCloudObjectInfo(uniCloudSpaceList) {
|
||||
let uniCloudWorkspaceFolder = process.env.UNI_INPUT_DIR.endsWith('src')
|
||||
? path_1.default.resolve(process.env.UNI_INPUT_DIR, '..')
|
||||
: process.env.UNI_INPUT_DIR;
|
||||
let serviceProvider = 'aliyun';
|
||||
if (uniCloudSpaceList && uniCloudSpaceList.length > 0) {
|
||||
const space = uniCloudSpaceList[0];
|
||||
if (space.workspaceFolder) {
|
||||
uniCloudWorkspaceFolder = space.workspaceFolder;
|
||||
}
|
||||
serviceProvider = space.provider === 'tencent' ? 'tcb' : space.provider;
|
||||
}
|
||||
else {
|
||||
serviceProvider =
|
||||
['aliyun', 'tcb', 'alipay', 'dcloud'].find((item) => fs_1.default.existsSync(path_1.default.resolve(uniCloudWorkspaceFolder, 'uniCloud-' + item))) || 'aliyun';
|
||||
}
|
||||
try {
|
||||
const { getWorkspaceObjectInfo } = require('../../../lib/unicloud-utils');
|
||||
return getWorkspaceObjectInfo(uniCloudWorkspaceFolder, serviceProvider);
|
||||
}
|
||||
catch (e) {
|
||||
console.error(e.message);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
exports.getUniCloudObjectInfo = getUniCloudObjectInfo;
|
||||
async function transformAutoImport(code, id, ignore = []) {
|
||||
const { matchedImports } = await detectAutoImports(code, id, ignore);
|
||||
if (matchedImports.length) {
|
||||
return {
|
||||
code: code + '\n' + genAutoImportsCode(matchedImports),
|
||||
};
|
||||
}
|
||||
return { code };
|
||||
}
|
||||
exports.transformAutoImport = transformAutoImport;
|
||||
function genAutoImportsCode(imports) {
|
||||
const codes = [];
|
||||
imports.forEach(({ name, as, from }) => {
|
||||
if (as && name !== as) {
|
||||
codes.push(`import { ${name} as ${as} } from "${parseUTSImportFilename(from)}"`);
|
||||
}
|
||||
else {
|
||||
codes.push(`import { ${name} } from "${parseUTSImportFilename(from)}"`);
|
||||
}
|
||||
});
|
||||
return codes.join('\n');
|
||||
}
|
||||
exports.genAutoImportsCode = genAutoImportsCode;
|
||||
let detectImports;
|
||||
function transformUniCloudMixinDataCom(code) {
|
||||
// 将 uniCloud.mixinDatacom 替换为 uniCloudMixinDatacom
|
||||
// 然后 autoImport 会自动导入 uniCloudMixinDatacom
|
||||
if (code.includes('uniCloud.mixinDatacom')) {
|
||||
return code.replace(/uniCloud\.mixinDatacom/g, 'uniCloudMixinDatacom');
|
||||
}
|
||||
return code;
|
||||
}
|
||||
exports.transformUniCloudMixinDataCom = transformUniCloudMixinDataCom;
|
||||
function detectAutoImports(code, id, ignore = []) {
|
||||
// 目前硬编码
|
||||
if (id.includes('index.module.uts')) {
|
||||
return { matchedImports: [] };
|
||||
}
|
||||
if (!detectImports) {
|
||||
detectImports = initAutoImport().detectImports;
|
||||
}
|
||||
else {
|
||||
const autoImports = (0, uni_cli_shared_1.getUTSEasyComAutoImports)();
|
||||
const sources = Object.keys(autoImports);
|
||||
if (detectImports.key !== sources.sort().join(',')) {
|
||||
detectImports = initAutoImport().detectImports;
|
||||
}
|
||||
}
|
||||
return detectImports(code, id, ignore);
|
||||
}
|
||||
exports.detectAutoImports = detectAutoImports;
|
||||
function initAutoImport() {
|
||||
const autoImports = (0, uni_cli_shared_1.getUTSEasyComAutoImports)();
|
||||
const sources = Object.keys(autoImports);
|
||||
if (!sources.length) {
|
||||
const detectImports = async (_code, _id, _ignore = []) => {
|
||||
return { matchedImports: [] };
|
||||
};
|
||||
detectImports.key = 'default';
|
||||
return {
|
||||
detectImports,
|
||||
};
|
||||
}
|
||||
const imports = [];
|
||||
sources.forEach((source) => {
|
||||
autoImports[source].forEach(([name, as]) => {
|
||||
imports.push({
|
||||
name,
|
||||
as,
|
||||
from: source,
|
||||
});
|
||||
});
|
||||
});
|
||||
const { detectImports: uniDetectImports } = (0, unimport_1.createUnimport)({
|
||||
imports,
|
||||
});
|
||||
const detectImports = async function (code, id, ignore = []) {
|
||||
// const start = Date.now()
|
||||
const result = await uniDetectImports(code);
|
||||
// console.log('detectImports[' + id + ']耗时:' + (Date.now() - start))
|
||||
return {
|
||||
matchedImports: result.matchedImports.filter((item) => {
|
||||
if (item.as && item.name !== item.as) {
|
||||
return !ignore.includes(item.as);
|
||||
}
|
||||
return !ignore.includes(item.name);
|
||||
}),
|
||||
};
|
||||
};
|
||||
detectImports.key = sources.sort().join(',');
|
||||
return {
|
||||
detectImports,
|
||||
};
|
||||
}
|
||||
Generated
Vendored
+5
@@ -0,0 +1,5 @@
|
||||
import type { SFCDescriptor } from '@vue/compiler-sfc';
|
||||
export declare function genScript({ script }: SFCDescriptor, { genDefaultAs }: {
|
||||
genDefaultAs?: string;
|
||||
}): string;
|
||||
export declare function genDefaultScriptCode(genDefaultAs?: string): string;
|
||||
Generated
Vendored
+22
@@ -0,0 +1,22 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.genDefaultScriptCode = exports.genScript = void 0;
|
||||
function genScript({ script }, { genDefaultAs }) {
|
||||
if (!script) {
|
||||
return genDefaultScriptCode(genDefaultAs);
|
||||
}
|
||||
return ('\n'.repeat(script.loc.start.line - 1) +
|
||||
`${script.content}
|
||||
`);
|
||||
}
|
||||
exports.genScript = genScript;
|
||||
function genDefaultScriptCode(genDefaultAs) {
|
||||
if (genDefaultAs) {
|
||||
return `const ${genDefaultAs} = defineComponent({})
|
||||
export default ${genDefaultAs}`;
|
||||
}
|
||||
return `
|
||||
export default {}
|
||||
`;
|
||||
}
|
||||
exports.genDefaultScriptCode = genDefaultScriptCode;
|
||||
Generated
Vendored
+13
@@ -0,0 +1,13 @@
|
||||
import type { SFCDescriptor } from '@vue/compiler-sfc';
|
||||
import type { PluginContext, TransformPluginContext } from 'rollup';
|
||||
import { type ResolvedOptions } from '../descriptorCache';
|
||||
export declare function genStyle(_: SFCDescriptor, { className }: {
|
||||
className: string;
|
||||
}): string;
|
||||
export declare function genJsStylesCode(descriptor: SFCDescriptor, pluginContext: PluginContext): Promise<string>;
|
||||
export declare function transformStyle(code: string, descriptor: SFCDescriptor, index: number, options: ResolvedOptions, pluginContext: TransformPluginContext, filename: string): Promise<{
|
||||
code: string;
|
||||
map: {
|
||||
mappings: '';
|
||||
};
|
||||
} | null>;
|
||||
Generated
Vendored
+92
@@ -0,0 +1,92 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.transformStyle = exports.genJsStylesCode = exports.genStyle = void 0;
|
||||
const descriptorCache_1 = require("../descriptorCache");
|
||||
function genStyle(_, { className }) {
|
||||
return `/*${className}Styles*/`;
|
||||
}
|
||||
exports.genStyle = genStyle;
|
||||
async function genJsStylesCode(descriptor, pluginContext) {
|
||||
let stylesCode = ``;
|
||||
if (descriptor.styles.length) {
|
||||
for (let i = 0; i < descriptor.styles.length; i++) {
|
||||
const style = descriptor.styles[i];
|
||||
if (style.src) {
|
||||
await linkSrcToDescriptor(style.src, descriptor, pluginContext);
|
||||
}
|
||||
const src = style.src || descriptor.filename;
|
||||
// do not include module in default query, since we use it to indicate
|
||||
// that the module needs to export the modules json
|
||||
const attrsQuery = attrsToQuery(style.attrs, 'css');
|
||||
const srcQuery = style.src ? '&src=true' : '';
|
||||
const query = `?vue&type=style&index=${i}${srcQuery}`;
|
||||
const styleRequest = src + query + attrsQuery;
|
||||
stylesCode += `\nimport ${JSON.stringify(styleRequest)}`;
|
||||
}
|
||||
}
|
||||
return stylesCode;
|
||||
}
|
||||
exports.genJsStylesCode = genJsStylesCode;
|
||||
/**
|
||||
* For blocks with src imports, it is important to link the imported file
|
||||
* with its owner SFC descriptor so that we can get the information about
|
||||
* the owner SFC when compiling that file in the transform phase.
|
||||
*/
|
||||
async function linkSrcToDescriptor(src, descriptor, pluginContext) {
|
||||
const srcFile = (await pluginContext.resolve(src, descriptor.filename))?.id || src;
|
||||
// #1812 if the src points to a dep file, the resolved id may contain a
|
||||
// version query.
|
||||
(0, descriptorCache_1.setSrcDescriptor)(srcFile.replace(/\?.*$/, ''), descriptor);
|
||||
}
|
||||
// these are built-in query parameters so should be ignored
|
||||
// if the user happen to add them as attrs
|
||||
const ignoreList = ['id', 'index', 'src', 'type', 'lang', 'module', 'scoped'];
|
||||
function attrsToQuery(attrs, langFallback, forceLangFallback = false) {
|
||||
let query = ``;
|
||||
for (const name in attrs) {
|
||||
const value = attrs[name];
|
||||
if (!ignoreList.includes(name)) {
|
||||
query += `&${encodeURIComponent(name)}${value ? `=${encodeURIComponent(value)}` : ``}`;
|
||||
}
|
||||
}
|
||||
if (langFallback || attrs.lang) {
|
||||
query +=
|
||||
`lang` in attrs
|
||||
? forceLangFallback
|
||||
? `&lang.${langFallback}`
|
||||
: `&lang.${attrs.lang}`
|
||||
: `&lang.${langFallback}`;
|
||||
}
|
||||
return query;
|
||||
}
|
||||
async function transformStyle(code, descriptor, index, options, pluginContext, filename) {
|
||||
const block = descriptor.styles[index];
|
||||
// vite already handles pre-processors and CSS module so this is only
|
||||
// applying SFC-specific transforms like scoped mode and CSS vars rewrite (v-bind(var))
|
||||
const result = await options.compiler.compileStyleAsync({
|
||||
filename: descriptor.filename,
|
||||
id: `data-v-${descriptor.id}`,
|
||||
isProd: true,
|
||||
source: code,
|
||||
});
|
||||
if (result.errors.length) {
|
||||
result.errors.forEach((error) => {
|
||||
if (error.line && error.column) {
|
||||
error.loc = {
|
||||
file: descriptor.filename,
|
||||
line: error.line + block.loc.start.line,
|
||||
column: error.column,
|
||||
};
|
||||
}
|
||||
pluginContext.error(error);
|
||||
});
|
||||
return null;
|
||||
}
|
||||
return {
|
||||
code: result.code,
|
||||
map: {
|
||||
mappings: '',
|
||||
},
|
||||
};
|
||||
}
|
||||
exports.transformStyle = transformStyle;
|
||||
Generated
Vendored
+8
@@ -0,0 +1,8 @@
|
||||
import type { SFCDescriptor } from '@vue/compiler-sfc';
|
||||
import type { CodegenResult, TemplateCompilerOptions } from '../compiler/options';
|
||||
import type { TransformPluginContext } from 'rollup';
|
||||
export declare function genTemplate({ template }: SFCDescriptor, options: TemplateCompilerOptions & {
|
||||
genDefaultAs?: string;
|
||||
}): CodegenResult;
|
||||
export declare const genTemplateCode: typeof genTemplate;
|
||||
export declare function tryResolveTemplateSrc(descriptor: SFCDescriptor, pluginContext?: TransformPluginContext): Promise<void>;
|
||||
Generated
Vendored
+74
@@ -0,0 +1,74 @@
|
||||
"use strict";
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.tryResolveTemplateSrc = exports.genTemplateCode = exports.genTemplate = void 0;
|
||||
const fs_extra_1 = __importDefault(require("fs-extra"));
|
||||
const uni_cli_shared_1 = require("@dcloudio/uni-cli-shared");
|
||||
const compiler_1 = require("../compiler");
|
||||
const utils_1 = require("../compiler/utils");
|
||||
const descriptorCache_1 = require("../descriptorCache");
|
||||
function genTemplate({ template }, options) {
|
||||
if (!template || !template.content) {
|
||||
return {
|
||||
code: options.mode === 'module'
|
||||
? (0, utils_1.genRenderFunctionDecl)(options) + ` { return null }`
|
||||
: `null`,
|
||||
easyComponentAutoImports: {},
|
||||
preamble: '',
|
||||
elements: [],
|
||||
imports: [],
|
||||
};
|
||||
}
|
||||
const { preprocessLang, preprocessOptions } = options;
|
||||
const preprocessor = preprocessLang
|
||||
? require('@vue/consolidate')[preprocessLang]
|
||||
: false;
|
||||
return (0, compiler_1.compile)(preprocessor
|
||||
? preprocess({ source: template.content, filename: '', preprocessOptions }, preprocessor)
|
||||
: template.content, options);
|
||||
}
|
||||
exports.genTemplate = genTemplate;
|
||||
exports.genTemplateCode = genTemplate;
|
||||
function preprocess({ source, filename, preprocessOptions, }, preprocessor) {
|
||||
// Consolidate exposes a callback based API, but the callback is in fact
|
||||
// called synchronously for most templating engines. In our case, we have to
|
||||
// expose a synchronous API so that it is usable in Jest transforms (which
|
||||
// have to be sync because they are applied via Node.js require hooks)
|
||||
let res = '';
|
||||
let err = null;
|
||||
preprocessor.render(source, { filename, ...preprocessOptions }, (_err, _res) => {
|
||||
if (_err)
|
||||
err = _err;
|
||||
res = _res;
|
||||
});
|
||||
if (err)
|
||||
throw err;
|
||||
return res;
|
||||
}
|
||||
async function tryResolveTemplateSrc(descriptor, pluginContext) {
|
||||
if (!pluginContext) {
|
||||
return;
|
||||
}
|
||||
if (!descriptor.template) {
|
||||
return;
|
||||
}
|
||||
if (descriptor.template.src) {
|
||||
const resolved = await pluginContext.resolve(descriptor.template.src, descriptor.filename);
|
||||
if (resolved) {
|
||||
const filename = resolved.id;
|
||||
// 如果引入的vue文件,读取对应的template
|
||||
if ((0, uni_cli_shared_1.isVueSfcFile)(filename)) {
|
||||
const srcDescriptor = (0, descriptorCache_1.getDescriptor)(filename, (0, descriptorCache_1.getResolvedOptions)());
|
||||
if (srcDescriptor && srcDescriptor.template?.content) {
|
||||
descriptor.template.content = srcDescriptor.template.content;
|
||||
}
|
||||
}
|
||||
else {
|
||||
descriptor.template.content = (0, uni_cli_shared_1.preUVueHtml)(fs_extra_1.default.readFileSync(filename, 'utf-8'), filename);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
exports.tryResolveTemplateSrc = tryResolveTemplateSrc;
|
||||
Generated
Vendored
+25
@@ -0,0 +1,25 @@
|
||||
import { SourceMapGenerator } from 'source-map-js';
|
||||
import { type JSChildNode, type RootNode, type SSRCodegenNode, type TemplateChildNode } from '@vue/compiler-core';
|
||||
import { type ParserPlugin } from '@babel/parser';
|
||||
import type { CodegenOptions, CodegenResult } from './options';
|
||||
type CodegenNode = TemplateChildNode | JSChildNode | SSRCodegenNode;
|
||||
export interface CodegenContext extends Required<Omit<CodegenOptions, 'sourceMapGeneratedLine' | 'className' | 'originalLineOffset' | 'generatedLineOffset' | 'inMap'>> {
|
||||
source: string;
|
||||
code: string;
|
||||
easyComponentAutoImports: Record<string, [string, string]>;
|
||||
line: number;
|
||||
column: number;
|
||||
offset: number;
|
||||
indentLevel: number;
|
||||
map?: SourceMapGenerator;
|
||||
expressionPlugins: ParserPlugin[];
|
||||
helper(key: symbol): string;
|
||||
push(code: string, node?: CodegenNode): void;
|
||||
indent(): void;
|
||||
deindent(withoutNewLine?: boolean): void;
|
||||
newline(): void;
|
||||
}
|
||||
export declare function generate(ast: RootNode, options?: CodegenOptions & {
|
||||
genDefaultAs?: string;
|
||||
}): CodegenResult;
|
||||
export {};
|
||||
Generated
Vendored
+668
@@ -0,0 +1,668 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.generate = void 0;
|
||||
const source_map_js_1 = require("source-map-js");
|
||||
const compiler_core_1 = require("@vue/compiler-core");
|
||||
const shared_1 = require("@vue/shared");
|
||||
const parser_1 = require("@babel/parser");
|
||||
const uni_cli_shared_1 = require("@dcloudio/uni-cli-shared");
|
||||
const utils_1 = require("./utils");
|
||||
const runtimeHelpers_1 = require("./runtimeHelpers");
|
||||
const transformExpression_1 = require("./transforms/transformExpression");
|
||||
const types_1 = require("@babel/types");
|
||||
const transformSlotPropsDestructuring_1 = require("./transforms/transformSlotPropsDestructuring");
|
||||
function createCodegenContext(ast, { rootDir = '', targetLanguage = 'kotlin', mode = 'default', prefixIdentifiers = mode === 'module', bindingMetadata = {}, inline = false, sourceMap = false, filename = '', matchEasyCom = shared_1.NOOP, parseUTSComponent = shared_1.NOOP, parseUTSCustomElement = shared_1.NOOP, originalLineOffset = 0, generatedLineOffset = 0, }) {
|
||||
const context = {
|
||||
rootDir,
|
||||
targetLanguage,
|
||||
mode,
|
||||
prefixIdentifiers,
|
||||
bindingMetadata,
|
||||
inline,
|
||||
sourceMap,
|
||||
filename,
|
||||
source: ast.loc.source,
|
||||
code: ``,
|
||||
easyComponentAutoImports: {},
|
||||
column: 1,
|
||||
line: 1,
|
||||
offset: 0,
|
||||
indentLevel: 0,
|
||||
map: undefined,
|
||||
expressionPlugins: ['typescript'],
|
||||
matchEasyCom,
|
||||
parseUTSComponent,
|
||||
parseUTSCustomElement,
|
||||
helper(key) {
|
||||
return `${compiler_core_1.helperNameMap[key]}`;
|
||||
},
|
||||
push(code, node) {
|
||||
context.code += code;
|
||||
if (context.map) {
|
||||
if (node) {
|
||||
let name;
|
||||
if (node.type === compiler_core_1.NodeTypes.SIMPLE_EXPRESSION) {
|
||||
const content = node.content.replace(/^_ctx\./, '');
|
||||
if (content !== node.content && (0, compiler_core_1.isSimpleIdentifier)(content)) {
|
||||
name = content;
|
||||
}
|
||||
}
|
||||
addMapping(node.loc.start, name);
|
||||
}
|
||||
(0, compiler_core_1.advancePositionWithMutation)(context, code);
|
||||
if (node && node.loc !== compiler_core_1.locStub) {
|
||||
addMapping(node.loc.end);
|
||||
}
|
||||
}
|
||||
},
|
||||
indent() {
|
||||
newline(++context.indentLevel);
|
||||
},
|
||||
deindent(withoutNewLine = false) {
|
||||
if (withoutNewLine) {
|
||||
--context.indentLevel;
|
||||
}
|
||||
else {
|
||||
newline(--context.indentLevel);
|
||||
}
|
||||
},
|
||||
newline() {
|
||||
newline(context.indentLevel);
|
||||
},
|
||||
};
|
||||
function newline(n) {
|
||||
context.push('\n' + ` `.repeat(n));
|
||||
}
|
||||
function addMapping(loc, name) {
|
||||
context.map.addMapping({
|
||||
name,
|
||||
source: context.filename,
|
||||
original: {
|
||||
line: loc.line + originalLineOffset,
|
||||
column: loc.column - 1, // source-map column is 0 based
|
||||
},
|
||||
generated: {
|
||||
line: context.line + generatedLineOffset,
|
||||
column: context.column - 1,
|
||||
},
|
||||
});
|
||||
}
|
||||
if (sourceMap) {
|
||||
// lazy require source-map implementation, only in non-browser builds
|
||||
context.map = new source_map_js_1.SourceMapGenerator();
|
||||
context.map.setSourceContent(filename, context.source);
|
||||
}
|
||||
return context;
|
||||
}
|
||||
function generate(ast, options = {}) {
|
||||
const context = createCodegenContext(ast, options);
|
||||
const { mode, deindent, indent, push, newline } = context;
|
||||
const isSetupInlined = !!options.inline;
|
||||
// preambles
|
||||
// in setup() inline mode, the preamble is generated in a sub context
|
||||
// and returned separately.
|
||||
// const preambleContext = isSetupInlined
|
||||
// ? createCodegenContext(ast, options)
|
||||
// : context
|
||||
const preambleContext = createCodegenContext(ast, options);
|
||||
if (mode === 'module') {
|
||||
genEasyComImports(ast.components, preambleContext);
|
||||
if (ast.imports.length) {
|
||||
genImports(ast.imports, preambleContext);
|
||||
}
|
||||
push((0, utils_1.genRenderFunctionDecl)(options) + ` {`);
|
||||
newline();
|
||||
if (!isSetupInlined) {
|
||||
push(`const _ctx = this`);
|
||||
newline();
|
||||
push(`const _cache = this.$.renderCache`);
|
||||
}
|
||||
// generate asset resolution statements
|
||||
if (ast.components.length) {
|
||||
newline();
|
||||
genAssets(ast.components, 'component', context);
|
||||
if (ast.directives.length || ast.temps > 0) {
|
||||
newline();
|
||||
}
|
||||
}
|
||||
if (ast.directives.length) {
|
||||
genAssets(ast.directives, 'directive', context);
|
||||
if (ast.temps > 0) {
|
||||
newline();
|
||||
}
|
||||
}
|
||||
if (ast.components.length || ast.directives.length || ast.temps) {
|
||||
newline();
|
||||
}
|
||||
indent();
|
||||
push(`return `);
|
||||
}
|
||||
if (ast.codegenNode) {
|
||||
genNode(ast.codegenNode, context);
|
||||
}
|
||||
else {
|
||||
push(`null`);
|
||||
}
|
||||
if (mode === 'module') {
|
||||
deindent();
|
||||
push(`}`);
|
||||
}
|
||||
return {
|
||||
ast,
|
||||
code: context.code,
|
||||
preamble: preambleContext.code,
|
||||
easyComponentAutoImports: context.easyComponentAutoImports,
|
||||
// SourceMapGenerator does have toJSON() method but it's not in the types
|
||||
map: context.map ? context.map.toJSON() : undefined,
|
||||
// @ts-expect-error
|
||||
elements: ast.elements,
|
||||
};
|
||||
}
|
||||
exports.generate = generate;
|
||||
function genImports(importsOptions, context) {
|
||||
if (!importsOptions.length) {
|
||||
return;
|
||||
}
|
||||
importsOptions.forEach((imports) => {
|
||||
if ((0, shared_1.isString)(imports.exp)) {
|
||||
if (imports.exp) {
|
||||
context.push(`import ${imports.exp} from '${imports.path}'`);
|
||||
}
|
||||
else {
|
||||
context.push(`import '${imports.path}'`);
|
||||
}
|
||||
}
|
||||
else if ((0, uni_cli_shared_1.isSimpleExpressionNode)(imports.exp)) {
|
||||
// 解决静态资源导入 sourcemap 映射问题
|
||||
context.push(`import ${imports.exp.content} from '${imports.path}'`, imports.exp);
|
||||
}
|
||||
else {
|
||||
context.push(`import `);
|
||||
genNode(imports.exp, context);
|
||||
context.push(` from '${imports.path}'`);
|
||||
}
|
||||
context.newline();
|
||||
});
|
||||
}
|
||||
function genEasyComImports(components, { push, newline, matchEasyCom, rootDir }) {
|
||||
for (let i = 0; i < components.length; i++) {
|
||||
let id = components[i];
|
||||
const maybeSelfReference = id.endsWith('__self');
|
||||
if (maybeSelfReference) {
|
||||
id = id.slice(0, -6);
|
||||
}
|
||||
const source = matchEasyCom(id, true);
|
||||
if (source) {
|
||||
if (source.includes('?uts-proxy')) {
|
||||
push(`import { ${genEncryptUniModuleEasyComClass(id, parseUniModuleId(source))} } from '${source}';`);
|
||||
}
|
||||
else {
|
||||
const componentId = (0, compiler_core_1.toValidAssetId)(id, 'easycom');
|
||||
push(`import ${componentId} from '${source}'`);
|
||||
}
|
||||
newline();
|
||||
}
|
||||
}
|
||||
}
|
||||
function genAssets(assets, type, { helper, push, newline, easyComponentAutoImports, matchEasyCom, rootDir, }) {
|
||||
const resolver = helper(type === 'component' ? runtimeHelpers_1.RESOLVE_COMPONENT : runtimeHelpers_1.RESOLVE_DIRECTIVE);
|
||||
for (let i = 0; i < assets.length; i++) {
|
||||
let id = assets[i];
|
||||
// potential component implicit self-reference inferred from SFC filename
|
||||
const maybeSelfReference = id.endsWith('__self');
|
||||
if (maybeSelfReference) {
|
||||
id = id.slice(0, -6);
|
||||
}
|
||||
let assetCode = '';
|
||||
if (type === 'component') {
|
||||
const source = matchEasyCom(id, false);
|
||||
if (source) {
|
||||
const componentId = (0, compiler_core_1.toValidAssetId)(id, type);
|
||||
// 加密 easyCom
|
||||
if (source.includes('?uts-proxy')) {
|
||||
const easyComponentId = genEncryptUniModuleEasyComClass(id, parseUniModuleId(source));
|
||||
assetCode = `const ${componentId} = ${helper(runtimeHelpers_1.RESOLVE_EASY_COMPONENT)}(${JSON.stringify(id)},${easyComponentId})`;
|
||||
}
|
||||
else {
|
||||
const easyComponentId = (0, compiler_core_1.toValidAssetId)(id, 'easycom');
|
||||
assetCode = `const ${componentId} = ${helper(runtimeHelpers_1.RESOLVE_EASY_COMPONENT)}(${JSON.stringify(id)},${easyComponentId})`;
|
||||
}
|
||||
(0, utils_1.addEasyComponentAutoImports)(easyComponentAutoImports, rootDir, id, source);
|
||||
}
|
||||
}
|
||||
if (!assetCode) {
|
||||
assetCode = `const ${(0, compiler_core_1.toValidAssetId)(id, type)} = ${resolver}(${JSON.stringify(id)}${maybeSelfReference ? `, true` : ``})`;
|
||||
}
|
||||
push(assetCode);
|
||||
if (i < assets.length - 1) {
|
||||
newline();
|
||||
}
|
||||
}
|
||||
}
|
||||
function parseUniModuleId(source) {
|
||||
const parts = source.split('/');
|
||||
return parts[parts.length - 1].replace('?uts-proxy', '');
|
||||
}
|
||||
// GenUniModulesTestCom1ComponentsTestCom11TestCom11Class
|
||||
function genEncryptUniModuleEasyComClass(componentName, uniModuleId) {
|
||||
return (0, shared_1.capitalize)((0, shared_1.camelize)(`gen-uni-modules-${uniModuleId}-components-${componentName}-${componentName}-class`));
|
||||
}
|
||||
function isText(n) {
|
||||
return ((0, shared_1.isString)(n) ||
|
||||
n.type === compiler_core_1.NodeTypes.SIMPLE_EXPRESSION ||
|
||||
n.type === compiler_core_1.NodeTypes.TEXT ||
|
||||
n.type === compiler_core_1.NodeTypes.INTERPOLATION ||
|
||||
n.type === compiler_core_1.NodeTypes.COMPOUND_EXPRESSION);
|
||||
}
|
||||
function genNodeListAsArray(nodes, context) {
|
||||
const multilines = nodes.length > 3 || nodes.some((n) => (0, shared_1.isArray)(n) || !isText(n));
|
||||
context.push(`[`);
|
||||
multilines && context.indent();
|
||||
genNodeList(nodes, context, multilines);
|
||||
multilines && context.deindent();
|
||||
context.push(`]`);
|
||||
}
|
||||
function genNodeList(nodes, context, multilines = false, comma = true) {
|
||||
const { push, newline } = context;
|
||||
for (let i = 0; i < nodes.length; i++) {
|
||||
const node = nodes[i];
|
||||
if ((0, shared_1.isString)(node)) {
|
||||
push(node);
|
||||
}
|
||||
else if ((0, shared_1.isArray)(node)) {
|
||||
genNodeListAsArray(node, context);
|
||||
}
|
||||
else {
|
||||
genNode(node, context);
|
||||
}
|
||||
if (i < nodes.length - 1) {
|
||||
if (multilines) {
|
||||
comma && push(',');
|
||||
newline();
|
||||
}
|
||||
else {
|
||||
comma && push(', ');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
function genNode(node, context) {
|
||||
if ((0, shared_1.isString)(node)) {
|
||||
context.push(node);
|
||||
return;
|
||||
}
|
||||
if ((0, shared_1.isSymbol)(node)) {
|
||||
context.push(context.helper(node));
|
||||
return;
|
||||
}
|
||||
switch (node.type) {
|
||||
case compiler_core_1.NodeTypes.ELEMENT:
|
||||
case compiler_core_1.NodeTypes.IF:
|
||||
case compiler_core_1.NodeTypes.FOR:
|
||||
genNode(node.codegenNode, context);
|
||||
break;
|
||||
case compiler_core_1.NodeTypes.TEXT:
|
||||
genText(node, context);
|
||||
break;
|
||||
case compiler_core_1.NodeTypes.SIMPLE_EXPRESSION:
|
||||
genExpression(node, context);
|
||||
break;
|
||||
case compiler_core_1.NodeTypes.INTERPOLATION:
|
||||
genInterpolation(node, context);
|
||||
break;
|
||||
case compiler_core_1.NodeTypes.TEXT_CALL:
|
||||
genNode(node.codegenNode, context);
|
||||
break;
|
||||
case compiler_core_1.NodeTypes.COMPOUND_EXPRESSION:
|
||||
genCompoundExpression(node, context);
|
||||
break;
|
||||
case compiler_core_1.NodeTypes.COMMENT:
|
||||
genComment(node, context);
|
||||
break;
|
||||
case compiler_core_1.NodeTypes.VNODE_CALL:
|
||||
genVNodeCall(node, context);
|
||||
break;
|
||||
case compiler_core_1.NodeTypes.JS_CALL_EXPRESSION:
|
||||
genCallExpression(node, context);
|
||||
break;
|
||||
case compiler_core_1.NodeTypes.JS_OBJECT_EXPRESSION:
|
||||
genObjectExpression(node, context);
|
||||
break;
|
||||
case compiler_core_1.NodeTypes.JS_ARRAY_EXPRESSION:
|
||||
genArrayExpression(node, context);
|
||||
break;
|
||||
case compiler_core_1.NodeTypes.JS_FUNCTION_EXPRESSION:
|
||||
genFunctionExpression(node, context);
|
||||
break;
|
||||
case compiler_core_1.NodeTypes.JS_CONDITIONAL_EXPRESSION:
|
||||
genConditionalExpression(node, context);
|
||||
break;
|
||||
case compiler_core_1.NodeTypes.JS_CACHE_EXPRESSION:
|
||||
genCacheExpression(node, context);
|
||||
break;
|
||||
case compiler_core_1.NodeTypes.JS_BLOCK_STATEMENT:
|
||||
genNodeList(node.body, context, true, false);
|
||||
break;
|
||||
/* istanbul ignore next */
|
||||
case compiler_core_1.NodeTypes.IF_BRANCH:
|
||||
// noop
|
||||
break;
|
||||
default:
|
||||
}
|
||||
}
|
||||
function genText(node, context) {
|
||||
context.push(JSON.stringify(node.content), node);
|
||||
}
|
||||
function genExpression(node, context) {
|
||||
const { content, isStatic } = node;
|
||||
context.push(isStatic ? JSON.stringify(content) : content, node);
|
||||
}
|
||||
function genInterpolation(node, context) {
|
||||
const { push, helper } = context;
|
||||
push(`${helper(compiler_core_1.TO_DISPLAY_STRING)}(`);
|
||||
genNode(node.content, context);
|
||||
push(`)`);
|
||||
}
|
||||
function genCompoundExpression(node, context) {
|
||||
for (let i = 0; i < node.children.length; i++) {
|
||||
const child = node.children[i];
|
||||
if ((0, shared_1.isString)(child)) {
|
||||
context.push(child);
|
||||
}
|
||||
else {
|
||||
genNode(child, context);
|
||||
}
|
||||
}
|
||||
}
|
||||
function genExpressionAsPropertyKey(node, context) {
|
||||
const { push } = context;
|
||||
if (node.type === compiler_core_1.NodeTypes.COMPOUND_EXPRESSION) {
|
||||
push(`[`);
|
||||
genCompoundExpression(node, context);
|
||||
push(`]`);
|
||||
}
|
||||
else if (node.isStatic) {
|
||||
// only quote keys if necessary
|
||||
const text = (0, compiler_core_1.isSimpleIdentifier)(node.content)
|
||||
? node.content
|
||||
: JSON.stringify(node.content);
|
||||
push(text, node);
|
||||
}
|
||||
else {
|
||||
push(`[${node.content}]`, node);
|
||||
}
|
||||
}
|
||||
function genComment(node, context) {
|
||||
const { push, helper } = context;
|
||||
push(`${helper(compiler_core_1.CREATE_COMMENT)}(${JSON.stringify(node.content)})`, node);
|
||||
}
|
||||
function parseTag(tag, curNode, { parseUTSComponent, parseUTSCustomElement, targetLanguage }) {
|
||||
if ((0, shared_1.isString)(tag)) {
|
||||
// 原生UTS customElements组件
|
||||
// const utsCustomElementOptions = parseUTSCustomElement(
|
||||
// tag.slice(1, -1),
|
||||
// targetLanguage
|
||||
// )
|
||||
// if (utsCustomElementOptions) {
|
||||
// return createSimpleExpression(
|
||||
// utsCustomElementOptions.className + '.name',
|
||||
// false,
|
||||
// curNode.loc
|
||||
// )
|
||||
// } else {
|
||||
// 原生UTS组件
|
||||
const utsComponentOptions = parseUTSComponent(tag.slice(1, -1), targetLanguage);
|
||||
if (utsComponentOptions) {
|
||||
return (0, compiler_core_1.createSimpleExpression)(utsComponentOptions.className + '.name', false, curNode.loc);
|
||||
}
|
||||
// }
|
||||
}
|
||||
return tag;
|
||||
}
|
||||
function genVNodeCall(node, context) {
|
||||
const { push, helper } = context;
|
||||
const { tag, props, children, patchFlag, dynamicProps, directives,
|
||||
// isBlock,
|
||||
disableTracking, isComponent, } = node;
|
||||
if (directives) {
|
||||
push(helper(compiler_core_1.WITH_DIRECTIVES) + `(`);
|
||||
}
|
||||
const isBlock = false;
|
||||
if (isBlock) {
|
||||
push(`(${helper(compiler_core_1.OPEN_BLOCK)}(${disableTracking ? `true` : ``}), `);
|
||||
}
|
||||
const callHelper = isBlock
|
||||
? (0, compiler_core_1.getVNodeBlockHelper)(false, isComponent)
|
||||
: (0, compiler_core_1.getVNodeHelper)(false, isComponent);
|
||||
push(helper(callHelper) + `(`, node);
|
||||
genNodeList(genNullableArgs([
|
||||
parseTag(tag, node, context),
|
||||
props,
|
||||
children,
|
||||
patchFlag,
|
||||
dynamicProps,
|
||||
]), context);
|
||||
push(`)`);
|
||||
if (isBlock) {
|
||||
push(`)`);
|
||||
}
|
||||
if (directives) {
|
||||
push(`, `);
|
||||
genNode(directives, context);
|
||||
push(`)`);
|
||||
}
|
||||
}
|
||||
function genNullableArgs(args) {
|
||||
let i = args.length;
|
||||
while (i--) {
|
||||
if (args[i] != null)
|
||||
break;
|
||||
}
|
||||
return args.slice(0, i + 1).map((arg) => arg || `null`);
|
||||
}
|
||||
// JavaScript
|
||||
function genCallExpression(node, context) {
|
||||
const { push, helper } = context;
|
||||
const callee = (0, shared_1.isString)(node.callee) ? node.callee : helper(node.callee);
|
||||
push(callee + `(`, node);
|
||||
if (callee === helper(runtimeHelpers_1.RENDER_LIST)) {
|
||||
genRenderList(node);
|
||||
}
|
||||
genNodeList(node.arguments, context);
|
||||
push(`)`);
|
||||
}
|
||||
function genRenderList(node) {
|
||||
node.arguments.forEach((argument) => {
|
||||
if (argument.type === compiler_core_1.NodeTypes.JS_FUNCTION_EXPRESSION) {
|
||||
argument.returnType = 'any';
|
||||
}
|
||||
});
|
||||
}
|
||||
function genObjectExpression(node, context) {
|
||||
const { push, indent, deindent, newline } = context;
|
||||
const { properties } = node;
|
||||
if (!properties.length) {
|
||||
push(`utsMapOf()`, node);
|
||||
return;
|
||||
}
|
||||
push(`utsMapOf(`);
|
||||
const multilines = properties.length > 1 ||
|
||||
properties.some((p) => p.value.type !== compiler_core_1.NodeTypes.SIMPLE_EXPRESSION);
|
||||
push(multilines ? `{` : `{ `);
|
||||
multilines && indent();
|
||||
for (let i = 0; i < properties.length; i++) {
|
||||
const { key, value } = properties[i];
|
||||
// key
|
||||
genExpressionAsPropertyKey(key, context);
|
||||
push(`: `);
|
||||
// value
|
||||
genNode(value, context);
|
||||
if (i < properties.length - 1) {
|
||||
// will only reach this if it's multilines
|
||||
push(`,`);
|
||||
newline();
|
||||
}
|
||||
}
|
||||
multilines && deindent();
|
||||
push(multilines ? `}` : ` }`);
|
||||
push(`)`);
|
||||
}
|
||||
function genArrayExpression(node, context) {
|
||||
genNodeListAsArray(node.elements, context);
|
||||
}
|
||||
function genFunctionExpression(node, context) {
|
||||
const { push, indent, deindent } = context;
|
||||
const { params, returns, body, newline, isSlot } = node;
|
||||
if (isSlot) {
|
||||
// wrap slot functions with owner context
|
||||
push(`${compiler_core_1.helperNameMap[params ? runtimeHelpers_1.WITH_SCOPED_SLOT_CTX : runtimeHelpers_1.WITH_SLOT_CTX]}(`);
|
||||
}
|
||||
push(`(`, node);
|
||||
if ((0, shared_1.isArray)(params)) {
|
||||
genNodeList(params, context);
|
||||
}
|
||||
else if (params) {
|
||||
if ((0, transformSlotPropsDestructuring_1.isDestructuringSlotProps)(isSlot, params) ||
|
||||
params?.content === '{}') {
|
||||
push(transformSlotPropsDestructuring_1.SLOT_PROPS_NAME);
|
||||
}
|
||||
else {
|
||||
genNode(params, context);
|
||||
}
|
||||
}
|
||||
if (node.returnType) {
|
||||
push(`): ${node.returnType} => `);
|
||||
}
|
||||
else {
|
||||
if (isSlot) {
|
||||
if (params) {
|
||||
// { data } :Qux
|
||||
const paramsStr = (0, transformExpression_1.stringifyExpression)(params);
|
||||
let code = ': Record<string, any | null>): any[] => ';
|
||||
if (paramsStr.includes(':')) {
|
||||
const ast = (0, parser_1.parseExpression)(`(${paramsStr})=>{}`, {
|
||||
plugins: context.expressionPlugins,
|
||||
});
|
||||
// 判断是否已经指定了类型
|
||||
if ((0, types_1.isArrowFunctionExpression)(ast) && ast.params[0].typeAnnotation) {
|
||||
code = `): any[] => `;
|
||||
}
|
||||
}
|
||||
push(code);
|
||||
if ((0, transformSlotPropsDestructuring_1.isDestructuringSlotProps)(isSlot, params)) {
|
||||
push('{');
|
||||
(0, transformSlotPropsDestructuring_1.createDestructuringSlotProps)(params, context);
|
||||
context.newline();
|
||||
push('return ');
|
||||
}
|
||||
}
|
||||
else {
|
||||
push(`): any[] => `);
|
||||
}
|
||||
}
|
||||
else {
|
||||
push(`) => `);
|
||||
}
|
||||
}
|
||||
if (newline || body) {
|
||||
push(`{`);
|
||||
indent();
|
||||
}
|
||||
if (returns) {
|
||||
if (newline) {
|
||||
push(`return `);
|
||||
}
|
||||
if ((0, shared_1.isArray)(returns)) {
|
||||
genNodeListAsArray(returns, context);
|
||||
}
|
||||
else {
|
||||
genNode(returns, context);
|
||||
}
|
||||
}
|
||||
else if (body) {
|
||||
genNode(body, context);
|
||||
}
|
||||
if (newline || body) {
|
||||
deindent();
|
||||
push(`}`);
|
||||
}
|
||||
if (isSlot) {
|
||||
if ((0, transformSlotPropsDestructuring_1.isDestructuringSlotProps)(isSlot, params)) {
|
||||
push('}');
|
||||
}
|
||||
push(`)`);
|
||||
}
|
||||
}
|
||||
const booleanBinExprOperators = ['==', '===', '!=', '!==', '<', '>', '<=', '>='];
|
||||
function shouldWrapperConditionalTest(test, context) {
|
||||
const isSimpleExpr = (0, uni_cli_shared_1.isSimpleExpressionNode)(test);
|
||||
if (isSimpleExpr) {
|
||||
const { content } = test;
|
||||
if (content === 'true' || content === 'false') {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (isSimpleExpr || (0, uni_cli_shared_1.isCompoundExpressionNode)(test)) {
|
||||
const code = (0, transformExpression_1.stringifyExpression)(test);
|
||||
const ast = (0, parser_1.parseExpression)(code, {
|
||||
plugins: context.expressionPlugins,
|
||||
});
|
||||
if ((0, types_1.isBinaryExpression)(ast)) {
|
||||
// 先简易解析
|
||||
if (booleanBinExprOperators.includes(ast.operator)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
function genConditionalExpression(node, context) {
|
||||
const { test, consequent, alternate, newline: needNewline } = node;
|
||||
const { push, indent, deindent, newline } = context;
|
||||
const wrapper = shouldWrapperConditionalTest(test, context);
|
||||
wrapper && push(`${context.helper(runtimeHelpers_1.IS_TRUE)}(`);
|
||||
if (test.type === compiler_core_1.NodeTypes.SIMPLE_EXPRESSION) {
|
||||
genExpression(test, context);
|
||||
}
|
||||
else {
|
||||
genNode(test, context);
|
||||
}
|
||||
wrapper && push(`)`);
|
||||
needNewline && indent();
|
||||
context.indentLevel++;
|
||||
needNewline || push(` `);
|
||||
push(`? `);
|
||||
genNode(consequent, context);
|
||||
context.indentLevel--;
|
||||
needNewline && newline();
|
||||
needNewline || push(` `);
|
||||
push(`: `);
|
||||
const isNested = alternate.type === compiler_core_1.NodeTypes.JS_CONDITIONAL_EXPRESSION;
|
||||
if (!isNested) {
|
||||
context.indentLevel++;
|
||||
}
|
||||
genNode(alternate, context);
|
||||
if (!isNested) {
|
||||
context.indentLevel--;
|
||||
}
|
||||
needNewline && deindent(true /* without newline */);
|
||||
}
|
||||
function genCacheExpression(node, context) {
|
||||
const { push, helper, indent, deindent, newline } = context;
|
||||
push(`${compiler_core_1.helperNameMap[runtimeHelpers_1.RESOLVE_CACHE]}(_cache, ${node.index}, (): VNode => {`);
|
||||
if (node.isVNode) {
|
||||
indent();
|
||||
push(`${helper(compiler_core_1.SET_BLOCK_TRACKING)}(-1)`);
|
||||
newline();
|
||||
}
|
||||
push(`_cache[${node.index}] = `);
|
||||
genNode(node.value, context);
|
||||
if (node.isVNode) {
|
||||
newline();
|
||||
push(`${helper(compiler_core_1.SET_BLOCK_TRACKING)}(1)`);
|
||||
newline();
|
||||
push(`return _cache[${node.index}] as VNode`);
|
||||
deindent();
|
||||
}
|
||||
push(`})`);
|
||||
}
|
||||
Generated
Vendored
+74
@@ -0,0 +1,74 @@
|
||||
import type { SourceLocation } from '@vue/compiler-core';
|
||||
export interface CompilerError extends SyntaxError {
|
||||
code: number | string;
|
||||
loc?: SourceLocation;
|
||||
errorType?: 'css';
|
||||
}
|
||||
export interface CoreCompilerError extends CompilerError {
|
||||
code: ErrorCodes;
|
||||
}
|
||||
export declare function defaultOnError(error: CompilerError): void;
|
||||
export declare function defaultOnWarn(msg: CompilerError): void;
|
||||
export declare function createDOMCompilerError(code: ErrorCodes, loc?: SourceLocation): CoreCompilerError;
|
||||
type InferCompilerError<T> = T extends ErrorCodes ? CoreCompilerError : CompilerError;
|
||||
export declare function createCompilerError<T extends number>(code: T, loc?: SourceLocation, messages?: {
|
||||
[code: number]: string;
|
||||
}, additionalMessage?: string): InferCompilerError<T>;
|
||||
export declare const enum ErrorCodes {
|
||||
ABRUPT_CLOSING_OF_EMPTY_COMMENT = 0,
|
||||
CDATA_IN_HTML_CONTENT = 1,
|
||||
DUPLICATE_ATTRIBUTE = 2,
|
||||
END_TAG_WITH_ATTRIBUTES = 3,
|
||||
END_TAG_WITH_TRAILING_SOLIDUS = 4,
|
||||
EOF_BEFORE_TAG_NAME = 5,
|
||||
EOF_IN_CDATA = 6,
|
||||
EOF_IN_COMMENT = 7,
|
||||
EOF_IN_SCRIPT_HTML_COMMENT_LIKE_TEXT = 8,
|
||||
EOF_IN_TAG = 9,
|
||||
INCORRECTLY_CLOSED_COMMENT = 10,
|
||||
INCORRECTLY_OPENED_COMMENT = 11,
|
||||
INVALID_FIRST_CHARACTER_OF_TAG_NAME = 12,
|
||||
MISSING_ATTRIBUTE_VALUE = 13,
|
||||
MISSING_END_TAG_NAME = 14,
|
||||
MISSING_WHITESPACE_BETWEEN_ATTRIBUTES = 15,
|
||||
NESTED_COMMENT = 16,
|
||||
UNEXPECTED_CHARACTER_IN_ATTRIBUTE_NAME = 17,
|
||||
UNEXPECTED_CHARACTER_IN_UNQUOTED_ATTRIBUTE_VALUE = 18,
|
||||
UNEXPECTED_EQUALS_SIGN_BEFORE_ATTRIBUTE_NAME = 19,
|
||||
UNEXPECTED_NULL_CHARACTER = 20,
|
||||
UNEXPECTED_QUESTION_MARK_INSTEAD_OF_TAG_NAME = 21,
|
||||
UNEXPECTED_SOLIDUS_IN_TAG = 22,
|
||||
X_INVALID_END_TAG = 23,
|
||||
X_MISSING_END_TAG = 24,
|
||||
X_MISSING_INTERPOLATION_END = 25,
|
||||
X_MISSING_DIRECTIVE_NAME = 26,
|
||||
X_MISSING_DYNAMIC_DIRECTIVE_ARGUMENT_END = 27,
|
||||
X_V_IF_NO_EXPRESSION = 28,
|
||||
X_V_IF_SAME_KEY = 29,
|
||||
X_V_ELSE_NO_ADJACENT_IF = 30,
|
||||
X_V_FOR_NO_EXPRESSION = 31,
|
||||
X_V_FOR_MALFORMED_EXPRESSION = 32,
|
||||
X_V_FOR_TEMPLATE_KEY_PLACEMENT = 33,
|
||||
X_V_BIND_NO_EXPRESSION = 34,
|
||||
X_V_ON_NO_EXPRESSION = 35,
|
||||
X_V_SLOT_UNEXPECTED_DIRECTIVE_ON_SLOT_OUTLET = 36,
|
||||
X_V_SLOT_MIXED_SLOT_USAGE = 37,
|
||||
X_V_SLOT_DUPLICATE_SLOT_NAMES = 38,
|
||||
X_V_SLOT_EXTRANEOUS_DEFAULT_SLOT_CHILDREN = 39,
|
||||
X_V_SLOT_MISPLACED = 40,
|
||||
X_V_MODEL_NO_EXPRESSION = 41,
|
||||
X_V_MODEL_MALFORMED_EXPRESSION = 42,
|
||||
X_V_MODEL_ON_SCOPE_VARIABLE = 43,
|
||||
X_V_MODEL_ON_PROPS = 44,
|
||||
X_INVALID_EXPRESSION = 45,
|
||||
X_KEEP_ALIVE_INVALID_CHILDREN = 46,
|
||||
X_V_HTML_NO_EXPRESSION = 53,
|
||||
X_V_HTML_WITH_CHILDREN = 54,
|
||||
X_PREFIX_ID_NOT_SUPPORTED = 55,
|
||||
X_MODULE_MODE_NOT_SUPPORTED = 56,
|
||||
X_CACHE_HANDLER_NOT_SUPPORTED = 57,
|
||||
X_SCOPE_ID_NOT_SUPPORTED = 58,
|
||||
__EXTEND_POINT__ = 59
|
||||
}
|
||||
export declare const errorMessages: Record<ErrorCodes, string>;
|
||||
export {};
|
||||
Generated
Vendored
+88
@@ -0,0 +1,88 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.errorMessages = exports.createCompilerError = exports.createDOMCompilerError = exports.defaultOnWarn = exports.defaultOnError = void 0;
|
||||
function defaultOnError(error) {
|
||||
throw error;
|
||||
}
|
||||
exports.defaultOnError = defaultOnError;
|
||||
function defaultOnWarn(msg) {
|
||||
console.warn(`[Vue warn] ${msg.message}`);
|
||||
}
|
||||
exports.defaultOnWarn = defaultOnWarn;
|
||||
function createDOMCompilerError(code, loc) {
|
||||
return createCompilerError(code, loc);
|
||||
}
|
||||
exports.createDOMCompilerError = createDOMCompilerError;
|
||||
function createCompilerError(code, loc, messages, additionalMessage) {
|
||||
const msg = (messages || exports.errorMessages)[code] + (additionalMessage || ``);
|
||||
const error = new SyntaxError(String(msg));
|
||||
error.code = code;
|
||||
error.loc = loc;
|
||||
return error;
|
||||
}
|
||||
exports.createCompilerError = createCompilerError;
|
||||
exports.errorMessages = {
|
||||
// parse errors
|
||||
[0 /* ErrorCodes.ABRUPT_CLOSING_OF_EMPTY_COMMENT */]: 'Illegal comment.',
|
||||
[1 /* ErrorCodes.CDATA_IN_HTML_CONTENT */]: 'CDATA section is allowed only in XML context.',
|
||||
[2 /* ErrorCodes.DUPLICATE_ATTRIBUTE */]: 'Duplicate attribute.',
|
||||
[3 /* ErrorCodes.END_TAG_WITH_ATTRIBUTES */]: 'End tag cannot have attributes.',
|
||||
[4 /* ErrorCodes.END_TAG_WITH_TRAILING_SOLIDUS */]: "Illegal '/' in tags.",
|
||||
[5 /* ErrorCodes.EOF_BEFORE_TAG_NAME */]: 'Unexpected EOF in tag.',
|
||||
[6 /* ErrorCodes.EOF_IN_CDATA */]: 'Unexpected EOF in CDATA section.',
|
||||
[7 /* ErrorCodes.EOF_IN_COMMENT */]: 'Unexpected EOF in comment.',
|
||||
[8 /* ErrorCodes.EOF_IN_SCRIPT_HTML_COMMENT_LIKE_TEXT */]: 'Unexpected EOF in script.',
|
||||
[9 /* ErrorCodes.EOF_IN_TAG */]: 'Unexpected EOF in tag.',
|
||||
[10 /* ErrorCodes.INCORRECTLY_CLOSED_COMMENT */]: 'Incorrectly closed comment.',
|
||||
[11 /* ErrorCodes.INCORRECTLY_OPENED_COMMENT */]: 'Incorrectly opened comment.',
|
||||
[12 /* ErrorCodes.INVALID_FIRST_CHARACTER_OF_TAG_NAME */]: "Illegal tag name. Use '<' to print '<'.",
|
||||
[13 /* ErrorCodes.MISSING_ATTRIBUTE_VALUE */]: 'Attribute value was expected.',
|
||||
[14 /* ErrorCodes.MISSING_END_TAG_NAME */]: 'End tag name was expected.',
|
||||
[15 /* ErrorCodes.MISSING_WHITESPACE_BETWEEN_ATTRIBUTES */]: 'Whitespace was expected.',
|
||||
[16 /* ErrorCodes.NESTED_COMMENT */]: "Unexpected '<!--' in comment.",
|
||||
[17 /* ErrorCodes.UNEXPECTED_CHARACTER_IN_ATTRIBUTE_NAME */]: 'Attribute name cannot contain U+0022 ("), U+0027 (\'), and U+003C (<).',
|
||||
[18 /* ErrorCodes.UNEXPECTED_CHARACTER_IN_UNQUOTED_ATTRIBUTE_VALUE */]: 'Unquoted attribute value cannot contain U+0022 ("), U+0027 (\'), U+003C (<), U+003D (=), and U+0060 (`).',
|
||||
[19 /* ErrorCodes.UNEXPECTED_EQUALS_SIGN_BEFORE_ATTRIBUTE_NAME */]: "Attribute name cannot start with '='.",
|
||||
[21 /* ErrorCodes.UNEXPECTED_QUESTION_MARK_INSTEAD_OF_TAG_NAME */]: "'<?' is allowed only in XML context.",
|
||||
[20 /* ErrorCodes.UNEXPECTED_NULL_CHARACTER */]: `Unexpected null character.`,
|
||||
[22 /* ErrorCodes.UNEXPECTED_SOLIDUS_IN_TAG */]: "Illegal '/' in tags.",
|
||||
// Vue-specific parse errors
|
||||
[23 /* ErrorCodes.X_INVALID_END_TAG */]: 'Invalid end tag.',
|
||||
[24 /* ErrorCodes.X_MISSING_END_TAG */]: 'Element is missing end tag.',
|
||||
[25 /* ErrorCodes.X_MISSING_INTERPOLATION_END */]: 'Interpolation end sign was not found.',
|
||||
[27 /* ErrorCodes.X_MISSING_DYNAMIC_DIRECTIVE_ARGUMENT_END */]: 'End bracket for dynamic directive argument was not found. ' +
|
||||
'Note that dynamic directive argument cannot contain spaces.',
|
||||
[26 /* ErrorCodes.X_MISSING_DIRECTIVE_NAME */]: 'Legal directive name was expected.',
|
||||
// transform errors
|
||||
[28 /* ErrorCodes.X_V_IF_NO_EXPRESSION */]: `v-if/v-else-if is missing expression.`,
|
||||
[29 /* ErrorCodes.X_V_IF_SAME_KEY */]: `v-if/else branches must use unique keys.`,
|
||||
[30 /* ErrorCodes.X_V_ELSE_NO_ADJACENT_IF */]: `v-else/v-else-if has no adjacent v-if or v-else-if.`,
|
||||
[31 /* ErrorCodes.X_V_FOR_NO_EXPRESSION */]: `v-for is missing expression.`,
|
||||
[32 /* ErrorCodes.X_V_FOR_MALFORMED_EXPRESSION */]: `v-for has invalid expression.`,
|
||||
[33 /* ErrorCodes.X_V_FOR_TEMPLATE_KEY_PLACEMENT */]: `<template v-for> key should be placed on the <template> tag.`,
|
||||
[34 /* ErrorCodes.X_V_BIND_NO_EXPRESSION */]: `v-bind is missing expression.`,
|
||||
[35 /* ErrorCodes.X_V_ON_NO_EXPRESSION */]: `v-on is missing expression.`,
|
||||
[36 /* ErrorCodes.X_V_SLOT_UNEXPECTED_DIRECTIVE_ON_SLOT_OUTLET */]: `Unexpected custom directive on <slot> outlet.`,
|
||||
[37 /* ErrorCodes.X_V_SLOT_MIXED_SLOT_USAGE */]: `Mixed v-slot usage on both the component and nested <template>. ` +
|
||||
`When there are multiple named slots, all slots should use <template> ` +
|
||||
`syntax to avoid scope ambiguity.`,
|
||||
[38 /* ErrorCodes.X_V_SLOT_DUPLICATE_SLOT_NAMES */]: `Duplicate slot names found. `,
|
||||
[39 /* ErrorCodes.X_V_SLOT_EXTRANEOUS_DEFAULT_SLOT_CHILDREN */]: `Extraneous children found when component already has explicitly named ` +
|
||||
`default slot. These children will be ignored.`,
|
||||
[40 /* ErrorCodes.X_V_SLOT_MISPLACED */]: `v-slot can only be used on components or <template> tags.`,
|
||||
[41 /* ErrorCodes.X_V_MODEL_NO_EXPRESSION */]: `v-model is missing expression.`,
|
||||
[42 /* ErrorCodes.X_V_MODEL_MALFORMED_EXPRESSION */]: `v-model value must be a valid JavaScript member expression.`,
|
||||
[43 /* ErrorCodes.X_V_MODEL_ON_SCOPE_VARIABLE */]: `v-model cannot be used on v-for or v-slot scope variables because they are not writable.`,
|
||||
[44 /* ErrorCodes.X_V_MODEL_ON_PROPS */]: `v-model cannot be used on a prop, because local prop bindings are not writable.\nUse a v-bind binding combined with a v-on listener that emits update:x event instead.`,
|
||||
[45 /* ErrorCodes.X_INVALID_EXPRESSION */]: `Error parsing JavaScript expression: `,
|
||||
[46 /* ErrorCodes.X_KEEP_ALIVE_INVALID_CHILDREN */]: `<KeepAlive> expects exactly one child component.`,
|
||||
[53 /* ErrorCodes.X_V_HTML_NO_EXPRESSION */]: `v-html is missing expression.`,
|
||||
[54 /* ErrorCodes.X_V_HTML_WITH_CHILDREN */]: `v-html will override element children.`,
|
||||
// generic errors
|
||||
[55 /* ErrorCodes.X_PREFIX_ID_NOT_SUPPORTED */]: `"prefixIdentifiers" option is not supported in this build of compiler.`,
|
||||
[56 /* ErrorCodes.X_MODULE_MODE_NOT_SUPPORTED */]: `ES module mode is not supported in this build of compiler.`,
|
||||
[57 /* ErrorCodes.X_CACHE_HANDLER_NOT_SUPPORTED */]: `"cacheHandlers" option is only supported when the "prefixIdentifiers" option is enabled.`,
|
||||
[58 /* ErrorCodes.X_SCOPE_ID_NOT_SUPPORTED */]: `"scopeId" option is only supported in module mode.`,
|
||||
// just to fulfill types
|
||||
[59 /* ErrorCodes.__EXTEND_POINT__ */]: ``,
|
||||
};
|
||||
Generated
Vendored
+9
@@ -0,0 +1,9 @@
|
||||
import './runtimeHelpers';
|
||||
import type { CodegenResult, TemplateCompilerOptions } from './options';
|
||||
import { type DirectiveTransform, type NodeTransform } from './transform';
|
||||
export type TransformPreset = [
|
||||
NodeTransform[],
|
||||
Record<string, DirectiveTransform>
|
||||
];
|
||||
export declare function getBaseTransformPreset(prefixIdentifiers?: boolean): TransformPreset;
|
||||
export declare function compile(template: string, options: TemplateCompilerOptions): CodegenResult;
|
||||
Generated
Vendored
+191
@@ -0,0 +1,191 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.compile = exports.getBaseTransformPreset = void 0;
|
||||
const shared_1 = require("@vue/shared");
|
||||
const compiler_core_1 = require("@vue/compiler-core");
|
||||
const uni_shared_1 = require("@dcloudio/uni-shared");
|
||||
const uni_cli_shared_1 = require("@dcloudio/uni-cli-shared");
|
||||
require("./runtimeHelpers");
|
||||
const codegen_1 = require("./codegen");
|
||||
const transform_1 = require("./transform");
|
||||
const vIf_1 = require("./transforms/vIf");
|
||||
const vFor_1 = require("./transforms/vFor");
|
||||
const vModel_1 = require("./transforms/vModel");
|
||||
const vShow_1 = require("./transforms/vShow");
|
||||
const vText_1 = require("./transforms/vText");
|
||||
const transformInterpolation_1 = require("./transforms/transformInterpolation");
|
||||
const transformText_1 = require("./transforms/transformText");
|
||||
const vOnWithModifier_1 = require("./transforms/vOnWithModifier");
|
||||
const vBind_1 = require("./transforms/vBind");
|
||||
const transformSlotOutlet_1 = require("./transforms/transformSlotOutlet");
|
||||
const transformObjectExpression_1 = require("./transforms/transformObjectExpression");
|
||||
const transformExpression_1 = require("./transforms/transformExpression");
|
||||
const transformElements_1 = require("./transforms/transformElements");
|
||||
const transformStyle_1 = require("./transforms/transformStyle");
|
||||
const vHtml_1 = require("./transforms/vHtml");
|
||||
const vMemo_1 = require("./transforms/vMemo");
|
||||
const vOnce_1 = require("./transforms/vOnce");
|
||||
const source_map_js_1 = require("source-map-js");
|
||||
const vSlot_1 = require("./transforms/vSlot");
|
||||
const transformElement_1 = require("./transforms/transformElement");
|
||||
const transformAssetUrl_1 = require("../sfc/compiler/template/transformAssetUrl");
|
||||
const transformSrcset_1 = require("../sfc/compiler/template/transformSrcset");
|
||||
function getBaseTransformPreset(prefixIdentifiers) {
|
||||
return [
|
||||
[
|
||||
vOnce_1.transformOnce,
|
||||
vIf_1.transformIf,
|
||||
vMemo_1.transformMemo,
|
||||
vFor_1.transformFor,
|
||||
// order is important
|
||||
vSlot_1.trackVForSlotScopes,
|
||||
vHtml_1.transformVHtml,
|
||||
transformExpression_1.transformExpression,
|
||||
transformSlotOutlet_1.transformSlotOutlet,
|
||||
transformElement_1.transformElement,
|
||||
vSlot_1.trackSlotScopes,
|
||||
transformText_1.transformText,
|
||||
uni_cli_shared_1.transformTapToClick,
|
||||
transformInterpolation_1.transformInterpolation,
|
||||
transformObjectExpression_1.transformObjectExpression,
|
||||
transformElements_1.transformElements,
|
||||
transformStyle_1.transformStyle,
|
||||
],
|
||||
{
|
||||
on: vOnWithModifier_1.transformOn,
|
||||
bind: vBind_1.transformBind,
|
||||
model: vModel_1.transformModel,
|
||||
show: vShow_1.transformShow,
|
||||
text: vText_1.transformVText,
|
||||
},
|
||||
];
|
||||
}
|
||||
exports.getBaseTransformPreset = getBaseTransformPreset;
|
||||
function compile(template, options) {
|
||||
options.rootDir = options.rootDir || '';
|
||||
options.targetLanguage = options.targetLanguage || 'kotlin';
|
||||
options.prefixIdentifiers =
|
||||
'prefixIdentifiers' in options
|
||||
? options.prefixIdentifiers
|
||||
: options.mode === 'module';
|
||||
wrapOptionsLog(template, options);
|
||||
const isNativeTag = options?.isNativeTag ||
|
||||
function (tag) {
|
||||
return ((0, uni_shared_1.isAppUVueNativeTag)(tag) ||
|
||||
!!options.parseUTSCustomElement?.(tag, options.targetLanguage) ||
|
||||
!!options.parseUTSComponent?.(tag, options.targetLanguage));
|
||||
};
|
||||
const ast = (0, compiler_core_1.baseParse)(template, {
|
||||
comments: false,
|
||||
isNativeTag,
|
||||
onError: options.onError,
|
||||
});
|
||||
const [nodeTransforms, directiveTransforms] = getBaseTransformPreset(options.prefixIdentifiers);
|
||||
// 重要不能传入base
|
||||
const assetOptions = (0, transformAssetUrl_1.normalizeOptions)((0, uni_cli_shared_1.createUniVueTransformAssetUrls)(''));
|
||||
(0, transform_1.transform)(ast, (0, shared_1.extend)({}, options, {
|
||||
nodeTransforms: [
|
||||
...nodeTransforms,
|
||||
(0, transformAssetUrl_1.createAssetUrlTransformWithOptions)(assetOptions),
|
||||
(0, transformSrcset_1.createSrcsetTransformWithOptions)(assetOptions),
|
||||
...(0, uni_cli_shared_1.getBaseNodeTransforms)('/'),
|
||||
...(options.nodeTransforms || []), // user transforms
|
||||
(0, uni_cli_shared_1.createTransformTag)({ 'cover-image': 'image' }),
|
||||
],
|
||||
directiveTransforms: (0, shared_1.extend)({}, directiveTransforms, options.directiveTransforms || {} // user transforms
|
||||
),
|
||||
}));
|
||||
const result = (0, codegen_1.generate)(ast, options);
|
||||
// inMap should be the map produced by ./parse.ts which is a simple line-only
|
||||
// mapping. If it is present, we need to adjust the final map and errors to
|
||||
// reflect the original line numbers.
|
||||
if (options.inMap) {
|
||||
if (options.sourceMap) {
|
||||
result.map = mapLines(options.inMap, result.map);
|
||||
}
|
||||
// if (result.errors.length) {
|
||||
// patchErrors(errors, source, inMap)
|
||||
// }
|
||||
}
|
||||
return result;
|
||||
}
|
||||
exports.compile = compile;
|
||||
function mapLines(oldMap, newMap) {
|
||||
if (!oldMap)
|
||||
return newMap;
|
||||
if (!newMap)
|
||||
return oldMap;
|
||||
const oldMapConsumer = new source_map_js_1.SourceMapConsumer(oldMap);
|
||||
const newMapConsumer = new source_map_js_1.SourceMapConsumer(newMap);
|
||||
const mergedMapGenerator = new source_map_js_1.SourceMapGenerator();
|
||||
newMapConsumer.eachMapping((m) => {
|
||||
if (m.originalLine == null) {
|
||||
return;
|
||||
}
|
||||
const origPosInOldMap = oldMapConsumer.originalPositionFor({
|
||||
line: m.originalLine,
|
||||
column: m.originalColumn ?? 0,
|
||||
});
|
||||
if (origPosInOldMap.source == null) {
|
||||
return;
|
||||
}
|
||||
mergedMapGenerator.addMapping({
|
||||
generated: {
|
||||
line: m.generatedLine,
|
||||
column: m.generatedColumn,
|
||||
},
|
||||
original: {
|
||||
line: origPosInOldMap.line, // map line
|
||||
// use current column, since the oldMap produced by @vue/compiler-sfc
|
||||
// does not
|
||||
column: m.originalColumn ?? 0,
|
||||
},
|
||||
source: origPosInOldMap.source,
|
||||
name: origPosInOldMap.name,
|
||||
});
|
||||
});
|
||||
// source-map's type definition is incomplete
|
||||
const generator = mergedMapGenerator;
|
||||
oldMapConsumer.sources.forEach((sourceFile) => {
|
||||
generator._sources.add(sourceFile);
|
||||
const sourceContent = oldMapConsumer.sourceContentFor(sourceFile);
|
||||
if (sourceContent != null) {
|
||||
mergedMapGenerator.setSourceContent(sourceFile, sourceContent);
|
||||
}
|
||||
});
|
||||
generator._sourceRoot = oldMap.sourceRoot;
|
||||
generator._file = oldMap.file;
|
||||
return generator.toJSON();
|
||||
}
|
||||
function wrapOptionsLog(source, options) {
|
||||
const { onWarn, onError, inMap } = options;
|
||||
if (inMap && inMap.sourcesContent?.length) {
|
||||
if (onWarn || onError) {
|
||||
const originalSource = inMap.sourcesContent[0];
|
||||
const offset = originalSource.indexOf(source);
|
||||
const lineOffset = originalSource.slice(0, offset).split(/\r?\n/).length - 1;
|
||||
if (onWarn) {
|
||||
options.onWarn = (err) => {
|
||||
patchError(err, lineOffset, offset);
|
||||
onWarn(err);
|
||||
};
|
||||
}
|
||||
if (onError) {
|
||||
options.onError = (err) => {
|
||||
patchError(err, lineOffset, offset);
|
||||
onError(err);
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
function patchError(err, lineOffset, offset) {
|
||||
if (err.loc) {
|
||||
err.loc.start.line += lineOffset;
|
||||
err.loc.start.offset += offset;
|
||||
if (err.loc.end !== err.loc.start) {
|
||||
err.loc.end.line += lineOffset;
|
||||
err.loc.end.offset += offset;
|
||||
}
|
||||
}
|
||||
}
|
||||
Generated
Vendored
+146
@@ -0,0 +1,146 @@
|
||||
import type { BindingMetadata, CompilerError, RootNode } from '@vue/compiler-core';
|
||||
import type { TransformPluginContext } from 'rollup';
|
||||
import type { RawSourceMap } from 'source-map-js';
|
||||
import type { DirectiveTransform, NodeTransform } from './transform';
|
||||
interface SharedTransformCodegenOptions {
|
||||
/**
|
||||
* @default 'default'
|
||||
*/
|
||||
mode?: 'default' | 'module';
|
||||
rootDir?: string;
|
||||
targetLanguage?: 'kotlin' | 'swift';
|
||||
/**
|
||||
* Transform expressions like {{ foo }} to `_ctx.foo`.
|
||||
* @default false
|
||||
*/
|
||||
prefixIdentifiers?: boolean;
|
||||
/**
|
||||
* Optional binding metadata analyzed from script - used to optimize
|
||||
* binding access when `prefixIdentifiers` is enabled.
|
||||
*/
|
||||
bindingMetadata?: BindingMetadata;
|
||||
/**
|
||||
* Compile the function for inlining inside setup().
|
||||
* This allows the function to directly access setup() local bindings.
|
||||
*/
|
||||
inline?: boolean;
|
||||
/**
|
||||
* Filename for source map generation.
|
||||
* Also used for self-recursive reference in templates
|
||||
* @default ''
|
||||
*/
|
||||
filename?: string;
|
||||
/**
|
||||
* 编译的模板类名
|
||||
*/
|
||||
className?: string;
|
||||
/**
|
||||
* 解析 uts component 组件
|
||||
* @param name
|
||||
* @param type
|
||||
*/
|
||||
parseUTSComponent?: (name: string, type: 'kotlin' | 'swift') => {
|
||||
className: string;
|
||||
namespace: string;
|
||||
source: string;
|
||||
} | undefined | void;
|
||||
/**
|
||||
* 解析 uts customElements 组件
|
||||
* @param name
|
||||
* @param type
|
||||
* @returns
|
||||
*/
|
||||
parseUTSCustomElement?: (name: string, type: 'kotlin' | 'swift') => {
|
||||
className: string;
|
||||
namespace: string;
|
||||
source: string;
|
||||
} | undefined | void;
|
||||
}
|
||||
export interface CodegenOptions extends SharedTransformCodegenOptions {
|
||||
inMap?: RawSourceMap;
|
||||
/**
|
||||
* Generate source map?
|
||||
* @default false
|
||||
*/
|
||||
sourceMap?: boolean;
|
||||
/**
|
||||
* 匹配 easycom 组件
|
||||
* @param tag
|
||||
*/
|
||||
matchEasyCom?: (tag: string, uts: boolean) => string | false | undefined | void;
|
||||
/**
|
||||
* template的offset
|
||||
*/
|
||||
originalLineOffset?: number;
|
||||
/**
|
||||
* script的offset
|
||||
*/
|
||||
generatedLineOffset?: number;
|
||||
}
|
||||
export interface ErrorHandlingOptions {
|
||||
onWarn?: (warning: CompilerError) => void;
|
||||
onError?: (error: CompilerError) => void;
|
||||
}
|
||||
export interface TransformOptions extends SharedTransformCodegenOptions, ErrorHandlingOptions {
|
||||
rootDir?: string;
|
||||
/**
|
||||
* Cache v-on handlers to avoid creating new inline functions on each render,
|
||||
* also avoids the need for dynamically patching the handlers by wrapping it.
|
||||
* e.g `@click="foo"` by default is compiled to `{ onClick: foo }`. With this
|
||||
* option it's compiled to:
|
||||
* ```js
|
||||
* { onClick: _cache[0] || (_cache[0] = e => _ctx.foo(e)) }
|
||||
* ```
|
||||
* - Requires "prefixIdentifiers" to be enabled because it relies on scope
|
||||
* analysis to determine if a handler is safe to cache.
|
||||
* @default false
|
||||
*/
|
||||
cacheHandlers?: boolean;
|
||||
/**
|
||||
* An array of node transforms to be applied to every AST node.
|
||||
*/
|
||||
nodeTransforms?: NodeTransform[];
|
||||
/**
|
||||
* An object of { name: transform } to be applied to every directive attribute
|
||||
* node found on element nodes.
|
||||
*/
|
||||
directiveTransforms?: Record<string, DirectiveTransform | undefined>;
|
||||
/**
|
||||
* If the pairing runtime provides additional built-in elements, use this to
|
||||
* mark them as built-in so the compiler will generate component vnodes
|
||||
* for them.
|
||||
*/
|
||||
isBuiltInComponent?: (tag: string) => symbol | void;
|
||||
/**
|
||||
* Used by some transforms that expects only native elements
|
||||
*/
|
||||
isCustomElement?: (tag: string) => boolean | void;
|
||||
/**
|
||||
* SFC scoped styles ID
|
||||
*/
|
||||
scopeId?: string | null;
|
||||
/**
|
||||
* Indicates this SFC template has used :slotted in its styles
|
||||
* Defaults to `true` for backwards compatibility - SFC tooling should set it
|
||||
* to `false` if no `:slotted` usage is detected in `<style>`
|
||||
*/
|
||||
slotted?: boolean;
|
||||
}
|
||||
export type TemplateCompilerOptions = {
|
||||
/**
|
||||
* e.g. platform native elements, e.g. `<div>` for browsers
|
||||
*/
|
||||
isNativeTag?: (tag: string) => boolean;
|
||||
preprocessLang?: string;
|
||||
preprocessOptions?: any;
|
||||
pluginContext?: TransformPluginContext;
|
||||
} & TransformOptions & CodegenOptions;
|
||||
export interface CodegenResult {
|
||||
ast?: RootNode;
|
||||
code: string;
|
||||
preamble?: string;
|
||||
easyComponentAutoImports: Record<string, [string, string]>;
|
||||
elements: string[];
|
||||
map?: RawSourceMap;
|
||||
}
|
||||
export {};
|
||||
Generated
Vendored
+2
@@ -0,0 +1,2 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
Generated
Vendored
+17
@@ -0,0 +1,17 @@
|
||||
export declare const IS_TRUE: unique symbol;
|
||||
export declare const V_SHOW: unique symbol;
|
||||
export declare const RENDER_LIST: unique symbol;
|
||||
export declare const FRAGMENT: unique symbol;
|
||||
export declare const OPEN_BLOCK: unique symbol;
|
||||
export declare const RESOLVE_COMPONENT: unique symbol;
|
||||
export declare const RESOLVE_DIRECTIVE: unique symbol;
|
||||
export declare const RESOLVE_EASY_COMPONENT: unique symbol;
|
||||
export declare const RENDER_SLOT: unique symbol;
|
||||
export declare const TO_HANDLERS: unique symbol;
|
||||
export declare const V_ON_WITH_MODIFIERS: unique symbol;
|
||||
export declare const WITH_SLOT_CTX: unique symbol;
|
||||
export declare const WITH_SCOPED_SLOT_CTX: unique symbol;
|
||||
export declare const RESOLVE_CACHE: unique symbol;
|
||||
export declare const TRY_SET_REF_VALUE: unique symbol;
|
||||
export declare const TRY_UPDATE_REF_NUMBER: unique symbol;
|
||||
export declare const LOOSE_TO_NUMBER: unique symbol;
|
||||
TongjiUniApp/node_modules/@dcloudio/uni-app-uts/dist/plugins/android/uvue/compiler/runtimeHelpers.js
Generated
Vendored
+39
@@ -0,0 +1,39 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.LOOSE_TO_NUMBER = exports.TRY_UPDATE_REF_NUMBER = exports.TRY_SET_REF_VALUE = exports.RESOLVE_CACHE = exports.WITH_SCOPED_SLOT_CTX = exports.WITH_SLOT_CTX = exports.V_ON_WITH_MODIFIERS = exports.TO_HANDLERS = exports.RENDER_SLOT = exports.RESOLVE_EASY_COMPONENT = exports.RESOLVE_DIRECTIVE = exports.RESOLVE_COMPONENT = exports.OPEN_BLOCK = exports.FRAGMENT = exports.RENDER_LIST = exports.V_SHOW = exports.IS_TRUE = void 0;
|
||||
const compiler_core_1 = require("@vue/compiler-core");
|
||||
exports.IS_TRUE = Symbol(`isTrue`);
|
||||
exports.V_SHOW = Symbol(`vShow`);
|
||||
exports.RENDER_LIST = Symbol(`renderList`);
|
||||
exports.FRAGMENT = Symbol(`Fragment`);
|
||||
exports.OPEN_BLOCK = Symbol(`openBlock`);
|
||||
exports.RESOLVE_COMPONENT = Symbol(`resolveComponent`);
|
||||
exports.RESOLVE_DIRECTIVE = Symbol(`resolveDirective`);
|
||||
exports.RESOLVE_EASY_COMPONENT = Symbol(`resolveEasyComponent`);
|
||||
exports.RENDER_SLOT = Symbol(`renderSlot`);
|
||||
exports.TO_HANDLERS = Symbol(`toHandlers`);
|
||||
exports.V_ON_WITH_MODIFIERS = Symbol(`vOnModifiersGuard`);
|
||||
exports.WITH_SLOT_CTX = Symbol(`withSlotCtx`);
|
||||
exports.WITH_SCOPED_SLOT_CTX = Symbol(`withScopedSlotCtx`);
|
||||
exports.RESOLVE_CACHE = Symbol(`resolveCache`);
|
||||
exports.TRY_SET_REF_VALUE = Symbol(`trySetRefValue`);
|
||||
exports.TRY_UPDATE_REF_NUMBER = Symbol(`tryUpdateRefNumber`);
|
||||
exports.LOOSE_TO_NUMBER = Symbol(`looseToNumber`);
|
||||
(0, compiler_core_1.registerRuntimeHelpers)({
|
||||
[exports.IS_TRUE]: 'isTrue',
|
||||
[exports.V_SHOW]: 'vShow',
|
||||
[exports.RENDER_LIST]: 'RenderHelpers.renderList',
|
||||
[exports.FRAGMENT]: 'Fragment',
|
||||
[exports.RESOLVE_COMPONENT]: 'resolveComponent',
|
||||
[exports.RESOLVE_EASY_COMPONENT]: 'resolveEasyComponent',
|
||||
[exports.RESOLVE_DIRECTIVE]: 'resolveDirective',
|
||||
[exports.RENDER_SLOT]: `renderSlot`,
|
||||
[exports.TO_HANDLERS]: `toHandlers`,
|
||||
[exports.V_ON_WITH_MODIFIERS]: `withModifiers`,
|
||||
[exports.WITH_SLOT_CTX]: `withSlotCtx`,
|
||||
[exports.WITH_SCOPED_SLOT_CTX]: `withScopedSlotCtx`,
|
||||
[exports.RESOLVE_CACHE]: `resolveCache`,
|
||||
[exports.TRY_SET_REF_VALUE]: `trySetRefValue`,
|
||||
[exports.TRY_UPDATE_REF_NUMBER]: `tryUpdateRefNumber`,
|
||||
[exports.LOOSE_TO_NUMBER]: `looseToNumber`,
|
||||
});
|
||||
Generated
Vendored
+57
@@ -0,0 +1,57 @@
|
||||
import { type CacheExpression, type ComponentNode, type ConstantTypes, type DirectiveNode, type ElementNode, type ExpressionNode, type JSChildNode, type ParentNode, type PlainElementNode, type Property, type RootNode, type TemplateChildNode, type TemplateLiteral, type TemplateNode } from '@vue/compiler-core';
|
||||
import type { TransformOptions } from './options';
|
||||
import type { ParserPlugin } from '@babel/parser';
|
||||
export type NodeTransform = (node: RootNode | TemplateChildNode, context: TransformContext) => void | (() => void) | (() => void)[];
|
||||
export type DirectiveTransform = (dir: DirectiveNode, node: ElementNode, context: TransformContext, augmentor?: (ret: DirectiveTransformResult) => DirectiveTransformResult) => DirectiveTransformResult;
|
||||
export interface DirectiveTransformResult {
|
||||
props: Property[];
|
||||
needRuntime?: boolean | symbol;
|
||||
ssrTagParts?: TemplateLiteral['elements'];
|
||||
}
|
||||
export type StructuralDirectiveTransform = (node: ElementNode, dir: DirectiveNode, context: TransformContext) => void | (() => void);
|
||||
export interface ImportItem {
|
||||
exp: string | ExpressionNode;
|
||||
path: string;
|
||||
}
|
||||
export interface TransformContext extends Required<Omit<TransformOptions, 'filename' | 'className'>> {
|
||||
inSSR?: false;
|
||||
selfName: string | null;
|
||||
root: RootNode;
|
||||
helpers: Map<symbol, number>;
|
||||
components: Set<string>;
|
||||
directives: Set<string>;
|
||||
imports: ImportItem[];
|
||||
temps: number;
|
||||
cached: number;
|
||||
identifiers: {
|
||||
[name: string]: number | undefined;
|
||||
};
|
||||
scopes: {
|
||||
vFor: number;
|
||||
vSlot: number;
|
||||
vPre: number;
|
||||
vOnce: number;
|
||||
};
|
||||
parent: ParentNode | null;
|
||||
childIndex: number;
|
||||
currentNode: RootNode | TemplateChildNode | null;
|
||||
inVOnce: boolean;
|
||||
expressionPlugins: ParserPlugin[];
|
||||
helper<T extends symbol>(name: T): T;
|
||||
removeHelper<T extends symbol>(name: T): void;
|
||||
helperString(name: symbol): string;
|
||||
replaceNode(node: TemplateChildNode): void;
|
||||
removeNode(node?: TemplateChildNode): void;
|
||||
onNodeRemoved(): void;
|
||||
addIdentifiers(exp: ExpressionNode | string): void;
|
||||
removeIdentifiers(exp: ExpressionNode | string): void;
|
||||
cache<T extends JSChildNode>(exp: T, isVNode?: boolean): CacheExpression | T;
|
||||
constantCache: Map<TemplateChildNode, ConstantTypes>;
|
||||
elements: Set<string>;
|
||||
}
|
||||
export declare function createTransformContext(root: RootNode, { mode, rootDir, targetLanguage, filename, cacheHandlers, prefixIdentifiers, nodeTransforms, directiveTransforms, scopeId, slotted, bindingMetadata, inline, isBuiltInComponent, isCustomElement, onError, onWarn, parseUTSComponent, parseUTSCustomElement, }: TransformOptions): TransformContext;
|
||||
export declare function transform(root: RootNode, options: TransformOptions): void;
|
||||
export declare function isSingleElementRoot(root: RootNode, child: TemplateChildNode): child is PlainElementNode | ComponentNode | TemplateNode;
|
||||
export declare function traverseChildren(parent: ParentNode, context: TransformContext): void;
|
||||
export declare function traverseNode(node: RootNode | TemplateChildNode, context: TransformContext): void;
|
||||
export declare function createStructuralDirectiveTransform(name: string | RegExp, fn: StructuralDirectiveTransform): NodeTransform;
|
||||
Generated
Vendored
+311
@@ -0,0 +1,311 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.createStructuralDirectiveTransform = exports.traverseNode = exports.traverseChildren = exports.isSingleElementRoot = exports.transform = exports.createTransformContext = void 0;
|
||||
const compiler_core_1 = require("@vue/compiler-core");
|
||||
const shared_1 = require("@vue/shared");
|
||||
const errors_1 = require("./errors");
|
||||
const runtimeHelpers_1 = require("./runtimeHelpers");
|
||||
function createTransformContext(root, { mode = 'default', rootDir = '', targetLanguage = 'kotlin', filename = '', cacheHandlers = false, prefixIdentifiers = mode === 'module', nodeTransforms = [], directiveTransforms = {}, scopeId = null, slotted = true, bindingMetadata = shared_1.EMPTY_OBJ, inline = false, isBuiltInComponent = shared_1.NOOP, isCustomElement = shared_1.NOOP, onError = errors_1.defaultOnError, onWarn = errors_1.defaultOnWarn, parseUTSComponent = shared_1.NOOP, parseUTSCustomElement = shared_1.NOOP, }) {
|
||||
const nameMatch = filename.replace(/\?.*$/, '').match(/([^/\\]+)\.\w+$/);
|
||||
const context = {
|
||||
// options
|
||||
mode,
|
||||
rootDir,
|
||||
targetLanguage,
|
||||
selfName: nameMatch && (0, shared_1.capitalize)((0, shared_1.camelize)(nameMatch[1])),
|
||||
cacheHandlers,
|
||||
prefixIdentifiers,
|
||||
bindingMetadata,
|
||||
inline,
|
||||
nodeTransforms,
|
||||
directiveTransforms,
|
||||
elements: new Set(),
|
||||
isBuiltInComponent,
|
||||
isCustomElement,
|
||||
scopeId,
|
||||
slotted,
|
||||
onError,
|
||||
onWarn,
|
||||
parseUTSComponent,
|
||||
parseUTSCustomElement,
|
||||
// state
|
||||
root,
|
||||
helpers: new Map(),
|
||||
components: new Set(),
|
||||
directives: new Set(),
|
||||
imports: [],
|
||||
constantCache: new Map(),
|
||||
temps: 0,
|
||||
cached: 0,
|
||||
identifiers: Object.create(null),
|
||||
scopes: {
|
||||
vFor: 0,
|
||||
vSlot: 0,
|
||||
vPre: 0,
|
||||
vOnce: 0,
|
||||
},
|
||||
parent: null,
|
||||
currentNode: root,
|
||||
childIndex: 0,
|
||||
inVOnce: false,
|
||||
expressionPlugins: ['typescript'],
|
||||
// methods
|
||||
helper(name) {
|
||||
const count = context.helpers.get(name) || 0;
|
||||
context.helpers.set(name, count + 1);
|
||||
return name;
|
||||
},
|
||||
removeHelper(name) {
|
||||
const count = context.helpers.get(name);
|
||||
if (count) {
|
||||
const currentCount = count - 1;
|
||||
if (!currentCount) {
|
||||
context.helpers.delete(name);
|
||||
}
|
||||
else {
|
||||
context.helpers.set(name, currentCount);
|
||||
}
|
||||
}
|
||||
},
|
||||
helperString(name) {
|
||||
// return `_${helperNameMap[context.helper(name)]}`
|
||||
return `${compiler_core_1.helperNameMap[context.helper(name)]}`;
|
||||
},
|
||||
replaceNode(node) {
|
||||
if (!context.currentNode) {
|
||||
throw new Error(`Node being replaced is already removed.`);
|
||||
}
|
||||
if (!context.parent) {
|
||||
throw new Error(`Cannot replace root node.`);
|
||||
}
|
||||
context.parent.children[context.childIndex] = context.currentNode = node;
|
||||
},
|
||||
removeNode(node) {
|
||||
if (!context.parent) {
|
||||
throw new Error(`Cannot remove root node.`);
|
||||
}
|
||||
const list = context.parent.children;
|
||||
const removalIndex = node
|
||||
? list.indexOf(node)
|
||||
: context.currentNode
|
||||
? context.childIndex
|
||||
: -1;
|
||||
/* istanbul ignore if */
|
||||
if (removalIndex < 0) {
|
||||
throw new Error(`node being removed is not a child of current parent`);
|
||||
}
|
||||
if (!node || node === context.currentNode) {
|
||||
// current node removed
|
||||
context.currentNode = null;
|
||||
context.onNodeRemoved();
|
||||
}
|
||||
else {
|
||||
// sibling node removed
|
||||
if (context.childIndex > removalIndex) {
|
||||
context.childIndex--;
|
||||
context.onNodeRemoved();
|
||||
}
|
||||
}
|
||||
context.parent.children.splice(removalIndex, 1);
|
||||
},
|
||||
onNodeRemoved: () => { },
|
||||
addIdentifiers(exp) {
|
||||
// identifier tracking only happens in non-browser builds.
|
||||
if ((0, shared_1.isString)(exp)) {
|
||||
addId(exp);
|
||||
}
|
||||
else if (exp.identifiers) {
|
||||
exp.identifiers.forEach(addId);
|
||||
}
|
||||
else if (exp.type === compiler_core_1.NodeTypes.SIMPLE_EXPRESSION) {
|
||||
addId(exp.content);
|
||||
}
|
||||
},
|
||||
removeIdentifiers(exp) {
|
||||
if ((0, shared_1.isString)(exp)) {
|
||||
removeId(exp);
|
||||
}
|
||||
else if (exp.identifiers) {
|
||||
exp.identifiers.forEach(removeId);
|
||||
}
|
||||
else if (exp.type === compiler_core_1.NodeTypes.SIMPLE_EXPRESSION) {
|
||||
removeId(exp.content);
|
||||
}
|
||||
},
|
||||
cache(exp, isVNode = false) {
|
||||
return (0, compiler_core_1.createCacheExpression)(context.cached++, exp, isVNode);
|
||||
},
|
||||
};
|
||||
function addId(id) {
|
||||
const { identifiers } = context;
|
||||
if (identifiers[id] === undefined) {
|
||||
identifiers[id] = 0;
|
||||
}
|
||||
identifiers[id]++;
|
||||
}
|
||||
function removeId(id) {
|
||||
context.identifiers[id]--;
|
||||
}
|
||||
return context;
|
||||
}
|
||||
exports.createTransformContext = createTransformContext;
|
||||
function transform(root, options) {
|
||||
const context = createTransformContext(root, options);
|
||||
traverseNode(root, context);
|
||||
createRootCodegen(root, context);
|
||||
// finalize meta information
|
||||
root.helpers = new Set([...context.helpers.keys()]);
|
||||
root.components = [...context.components];
|
||||
root.directives = [...context.directives];
|
||||
root.imports = context.imports;
|
||||
// root.hoists = context.hoists
|
||||
root.temps = context.temps;
|
||||
root.cached = context.cached;
|
||||
// @ts-expect-error
|
||||
root.elements = Array.from(context.elements);
|
||||
}
|
||||
exports.transform = transform;
|
||||
function isSingleElementRoot(root, child) {
|
||||
const { children } = root;
|
||||
return (children.length === 1 &&
|
||||
child.type === compiler_core_1.NodeTypes.ELEMENT &&
|
||||
!(0, compiler_core_1.isSlotOutlet)(child));
|
||||
}
|
||||
exports.isSingleElementRoot = isSingleElementRoot;
|
||||
function createRootCodegen(root, context) {
|
||||
const { helper } = context;
|
||||
const { children } = root;
|
||||
if (children.length === 1) {
|
||||
const child = children[0];
|
||||
// if the single child is an element, turn it into a block.
|
||||
if (isSingleElementRoot(root, child) && child.codegenNode) {
|
||||
// single element root is never hoisted so codegenNode will never be
|
||||
// SimpleExpressionNode
|
||||
const codegenNode = child.codegenNode;
|
||||
if (codegenNode.type === compiler_core_1.NodeTypes.VNODE_CALL) {
|
||||
(0, compiler_core_1.convertToBlock)(codegenNode, context);
|
||||
}
|
||||
root.codegenNode = codegenNode;
|
||||
}
|
||||
else {
|
||||
// - single <slot/>, IfNode, ForNode: already blocks.
|
||||
// - single text node: always patched.
|
||||
// root codegen falls through via genNode()
|
||||
root.codegenNode = child;
|
||||
}
|
||||
}
|
||||
else if (children.length > 1) {
|
||||
// root has multiple nodes - return a fragment block.
|
||||
let patchFlag = shared_1.PatchFlags.STABLE_FRAGMENT;
|
||||
let patchFlagText = shared_1.PatchFlagNames[shared_1.PatchFlags.STABLE_FRAGMENT];
|
||||
// check if the fragment actually contains a single valid child with
|
||||
// the rest being comments
|
||||
if (children.filter((c) => c.type !== compiler_core_1.NodeTypes.COMMENT).length === 1) {
|
||||
patchFlag |= shared_1.PatchFlags.DEV_ROOT_FRAGMENT;
|
||||
patchFlagText += `, ${shared_1.PatchFlagNames[shared_1.PatchFlags.DEV_ROOT_FRAGMENT]}`;
|
||||
}
|
||||
root.codegenNode = (0, compiler_core_1.createVNodeCall)(
|
||||
// @ts-expect-error
|
||||
context, helper(runtimeHelpers_1.FRAGMENT), undefined, root.children, patchFlag + ` /* ${patchFlagText} */`, undefined, undefined, true, undefined, false /* isComponent */);
|
||||
}
|
||||
else {
|
||||
// no children = noop. codegen will return null.
|
||||
}
|
||||
}
|
||||
function traverseChildren(parent, context) {
|
||||
let i = 0;
|
||||
const nodeRemoved = () => {
|
||||
i--;
|
||||
};
|
||||
for (; i < parent.children.length; i++) {
|
||||
const child = parent.children[i];
|
||||
if ((0, shared_1.isString)(child))
|
||||
continue;
|
||||
context.parent = parent;
|
||||
context.childIndex = i;
|
||||
context.onNodeRemoved = nodeRemoved;
|
||||
traverseNode(child, context);
|
||||
}
|
||||
}
|
||||
exports.traverseChildren = traverseChildren;
|
||||
function traverseNode(node, context) {
|
||||
context.currentNode = node;
|
||||
// apply transform plugins
|
||||
const { nodeTransforms } = context;
|
||||
const exitFns = [];
|
||||
for (let i = 0; i < nodeTransforms.length; i++) {
|
||||
const onExit = nodeTransforms[i](node, context);
|
||||
if (onExit) {
|
||||
if ((0, shared_1.isArray)(onExit)) {
|
||||
exitFns.push(...onExit);
|
||||
}
|
||||
else {
|
||||
exitFns.push(onExit);
|
||||
}
|
||||
}
|
||||
if (!context.currentNode) {
|
||||
// node was removed
|
||||
return;
|
||||
}
|
||||
else {
|
||||
// node may have been replaced
|
||||
node = context.currentNode;
|
||||
}
|
||||
}
|
||||
switch (node.type) {
|
||||
case compiler_core_1.NodeTypes.COMMENT:
|
||||
break;
|
||||
case compiler_core_1.NodeTypes.INTERPOLATION:
|
||||
break;
|
||||
// for container types, further traverse downwards
|
||||
case compiler_core_1.NodeTypes.IF:
|
||||
for (let i = 0; i < node.branches.length; i++) {
|
||||
traverseNode(node.branches[i], context);
|
||||
}
|
||||
break;
|
||||
case compiler_core_1.NodeTypes.IF_BRANCH:
|
||||
case compiler_core_1.NodeTypes.FOR:
|
||||
case compiler_core_1.NodeTypes.ELEMENT:
|
||||
case compiler_core_1.NodeTypes.ROOT:
|
||||
traverseChildren(node, context);
|
||||
break;
|
||||
}
|
||||
// exit transforms
|
||||
context.currentNode = node;
|
||||
let i = exitFns.length;
|
||||
while (i--) {
|
||||
exitFns[i]();
|
||||
}
|
||||
}
|
||||
exports.traverseNode = traverseNode;
|
||||
function createStructuralDirectiveTransform(name, fn) {
|
||||
const matches = (0, shared_1.isString)(name)
|
||||
? (n) => n === name
|
||||
: (n) => name.test(n);
|
||||
return (node, context) => {
|
||||
if (node.type === compiler_core_1.NodeTypes.ELEMENT) {
|
||||
const { props } = node;
|
||||
// structural directive transforms are not concerned with slots
|
||||
// as they are handled separately in vSlot.ts
|
||||
if (node.tagType === compiler_core_1.ElementTypes.TEMPLATE && props.some(compiler_core_1.isVSlot)) {
|
||||
return;
|
||||
}
|
||||
const exitFns = [];
|
||||
for (let i = 0; i < props.length; i++) {
|
||||
const prop = props[i];
|
||||
if (prop.type === compiler_core_1.NodeTypes.DIRECTIVE && matches(prop.name)) {
|
||||
// structural directives are removed to avoid infinite recursion
|
||||
// also we remove them *before* applying so that it can further
|
||||
// traverse itself in case it moves the node around
|
||||
props.splice(i, 1);
|
||||
i--;
|
||||
const onExit = fn(node, prop, context);
|
||||
if (onExit)
|
||||
exitFns.push(onExit);
|
||||
}
|
||||
}
|
||||
return exitFns;
|
||||
}
|
||||
};
|
||||
}
|
||||
exports.createStructuralDirectiveTransform = createStructuralDirectiveTransform;
|
||||
Generated
Vendored
+13
@@ -0,0 +1,13 @@
|
||||
import type { NodeTransform, TransformContext } from '../transform';
|
||||
import { type ArrayExpression, type CallExpression, type ComponentNode, type DirectiveNode, type ElementNode, type ExpressionNode, type ObjectExpression } from '@vue/compiler-core';
|
||||
export declare const transformElement: NodeTransform;
|
||||
export declare function resolveComponentType(node: ComponentNode, context: TransformContext, ssr?: boolean): string | symbol | CallExpression;
|
||||
export type PropsExpression = ObjectExpression | CallExpression | ExpressionNode;
|
||||
export declare function buildProps(node: ElementNode, context: TransformContext, props: (DirectiveNode | import("@vue/compiler-core").AttributeNode)[] | undefined, isComponent: boolean, isDynamicComponent: boolean, ssr?: boolean): {
|
||||
props: PropsExpression | undefined;
|
||||
directives: DirectiveNode[];
|
||||
patchFlag: number;
|
||||
dynamicPropNames: string[];
|
||||
shouldUseBlock: boolean;
|
||||
};
|
||||
export declare function buildDirectiveArgs(dir: DirectiveNode, context: TransformContext): ArrayExpression;
|
||||
Generated
Vendored
+703
@@ -0,0 +1,703 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.buildDirectiveArgs = exports.buildProps = exports.resolveComponentType = exports.transformElement = void 0;
|
||||
const compiler_core_1 = require("@vue/compiler-core");
|
||||
const shared_1 = require("@vue/shared");
|
||||
const errors_1 = require("../errors");
|
||||
const compiler_core_2 = require("@vue/compiler-core");
|
||||
const compiler_core_3 = require("@vue/compiler-core");
|
||||
const vSlot_1 = require("./vSlot");
|
||||
const compiler_core_4 = require("@vue/compiler-core");
|
||||
const compiler_core_5 = require("@vue/compiler-core");
|
||||
const compiler_core_6 = require("@vue/compiler-core");
|
||||
const utils_1 = require("../utils");
|
||||
// some directive transforms (e.g. v-model) may return a symbol for runtime
|
||||
// import, which should be used instead of a resolveDirective call.
|
||||
const directiveImportMap = new WeakMap();
|
||||
// generate a JavaScript AST for this element's codegen
|
||||
const transformElement = (node, context) => {
|
||||
// perform the work on exit, after all child expressions have been
|
||||
// processed and merged.
|
||||
return function postTransformElement() {
|
||||
node = context.currentNode;
|
||||
if (!(node.type === compiler_core_1.NodeTypes.ELEMENT &&
|
||||
(node.tagType === compiler_core_1.ElementTypes.ELEMENT ||
|
||||
node.tagType === compiler_core_1.ElementTypes.COMPONENT))) {
|
||||
return;
|
||||
}
|
||||
const { tag, props } = node;
|
||||
const isComponent = node.tagType === compiler_core_1.ElementTypes.COMPONENT;
|
||||
// The goal of the transform is to create a codegenNode implementing the
|
||||
// VNodeCall interface.
|
||||
let vnodeTag = isComponent
|
||||
? resolveComponentType(node, context)
|
||||
: `"${tag}"`;
|
||||
const isDynamicComponent = (0, shared_1.isObject)(vnodeTag) && vnodeTag.callee === compiler_core_2.RESOLVE_DYNAMIC_COMPONENT;
|
||||
let vnodeProps;
|
||||
let vnodeChildren;
|
||||
let vnodePatchFlag;
|
||||
let patchFlag = 0;
|
||||
let vnodeDynamicProps;
|
||||
let dynamicPropNames;
|
||||
let vnodeDirectives;
|
||||
let shouldUseBlock =
|
||||
// dynamic component may resolve to plain elements
|
||||
isDynamicComponent ||
|
||||
vnodeTag === compiler_core_2.TELEPORT ||
|
||||
vnodeTag === compiler_core_2.SUSPENSE ||
|
||||
(!isComponent &&
|
||||
// <svg> and <foreignObject> must be forced into blocks so that block
|
||||
// updates inside get proper isSVG flag at runtime. (#639, #643)
|
||||
// This is technically web-specific, but splitting the logic out of core
|
||||
// leads to too much unnecessary complexity.
|
||||
(tag === 'svg' || tag === 'foreignObject'));
|
||||
// props
|
||||
if (props.length > 0) {
|
||||
const propsBuildResult = buildProps(node, context, undefined, isComponent, isDynamicComponent);
|
||||
vnodeProps = propsBuildResult.props;
|
||||
patchFlag = propsBuildResult.patchFlag;
|
||||
dynamicPropNames = propsBuildResult.dynamicPropNames;
|
||||
const directives = propsBuildResult.directives;
|
||||
vnodeDirectives =
|
||||
directives && directives.length
|
||||
? (0, compiler_core_1.createArrayExpression)(directives.map((dir) => buildDirectiveArgs(dir, context)))
|
||||
: undefined;
|
||||
if (propsBuildResult.shouldUseBlock) {
|
||||
shouldUseBlock = true;
|
||||
}
|
||||
}
|
||||
// children
|
||||
if (node.children.length > 0) {
|
||||
if (vnodeTag === compiler_core_2.KEEP_ALIVE) {
|
||||
// Although a built-in component, we compile KeepAlive with raw children
|
||||
// instead of slot functions so that it can be used inside Transition
|
||||
// or other Transition-wrapping HOCs.
|
||||
// To ensure correct updates with block optimizations, we need to:
|
||||
// 1. Force keep-alive into a block. This avoids its children being
|
||||
// collected by a parent block.
|
||||
shouldUseBlock = true;
|
||||
// 2. Force keep-alive to always be updated, since it uses raw children.
|
||||
patchFlag |= shared_1.PatchFlags.DYNAMIC_SLOTS;
|
||||
if (utils_1.__DEV__ && node.children.length > 1) {
|
||||
context.onError((0, errors_1.createCompilerError)(46 /* ErrorCodes.X_KEEP_ALIVE_INVALID_CHILDREN */, {
|
||||
start: node.children[0].loc.start,
|
||||
end: node.children[node.children.length - 1].loc.end,
|
||||
source: '',
|
||||
}));
|
||||
}
|
||||
}
|
||||
const shouldBuildAsSlots = isComponent &&
|
||||
// Teleport is not a real component and has dedicated runtime handling
|
||||
vnodeTag !== compiler_core_2.TELEPORT &&
|
||||
// explained above.
|
||||
vnodeTag !== compiler_core_2.KEEP_ALIVE;
|
||||
if (shouldBuildAsSlots) {
|
||||
const { slots, hasDynamicSlots } = (0, vSlot_1.buildSlots)(node, context);
|
||||
vnodeChildren = slots;
|
||||
if (hasDynamicSlots) {
|
||||
patchFlag |= shared_1.PatchFlags.DYNAMIC_SLOTS;
|
||||
}
|
||||
}
|
||||
else if (node.children.length === 1 && vnodeTag !== compiler_core_2.TELEPORT) {
|
||||
const child = node.children[0];
|
||||
const type = child.type;
|
||||
// check for dynamic text children
|
||||
const hasDynamicTextChild = type === compiler_core_1.NodeTypes.INTERPOLATION ||
|
||||
type === compiler_core_1.NodeTypes.COMPOUND_EXPRESSION;
|
||||
if (hasDynamicTextChild &&
|
||||
(0, compiler_core_4.getConstantType)(child, context) === compiler_core_1.ConstantTypes.NOT_CONSTANT) {
|
||||
patchFlag |= shared_1.PatchFlags.TEXT;
|
||||
}
|
||||
// pass directly if the only child is a text node
|
||||
// (plain / interpolation / expression)
|
||||
if (hasDynamicTextChild || type === compiler_core_1.NodeTypes.TEXT) {
|
||||
vnodeChildren = child;
|
||||
}
|
||||
else {
|
||||
vnodeChildren = node.children;
|
||||
}
|
||||
}
|
||||
else {
|
||||
vnodeChildren = node.children;
|
||||
}
|
||||
}
|
||||
// patchFlag & dynamicPropNames
|
||||
if (patchFlag !== 0) {
|
||||
if (utils_1.__DEV__) {
|
||||
if (patchFlag < 0) {
|
||||
// special flags (negative and mutually exclusive)
|
||||
vnodePatchFlag =
|
||||
patchFlag + ` /* ${shared_1.PatchFlagNames[patchFlag]} */`;
|
||||
}
|
||||
else {
|
||||
// bitwise flags
|
||||
const flagNames = Object.keys(shared_1.PatchFlagNames)
|
||||
.map(Number)
|
||||
.filter((n) => n > 0 && patchFlag & n)
|
||||
.map((n) => shared_1.PatchFlagNames[n])
|
||||
.join(`, `);
|
||||
vnodePatchFlag = patchFlag + ` /* ${flagNames} */`;
|
||||
}
|
||||
}
|
||||
else {
|
||||
vnodePatchFlag = String(patchFlag);
|
||||
}
|
||||
if (dynamicPropNames && dynamicPropNames.length) {
|
||||
vnodeDynamicProps = stringifyDynamicPropNames(dynamicPropNames);
|
||||
}
|
||||
}
|
||||
node.codegenNode = (0, compiler_core_1.createVNodeCall)(context, vnodeTag, vnodeProps, vnodeChildren, vnodePatchFlag, vnodeDynamicProps, vnodeDirectives, !!shouldUseBlock, false /* disableTracking */, isComponent, node.loc);
|
||||
};
|
||||
};
|
||||
exports.transformElement = transformElement;
|
||||
function resolveComponentType(node, context, ssr = false) {
|
||||
let { tag } = node;
|
||||
// 1. dynamic component
|
||||
const isExplicitDynamic = isComponentTag(tag);
|
||||
const isProp = (0, compiler_core_3.findProp)(node, 'is');
|
||||
if (isProp) {
|
||||
if (isExplicitDynamic ||
|
||||
(utils_1.__COMPAT__ &&
|
||||
(0, utils_1.isCompatEnabled)(compiler_core_6.CompilerDeprecationTypes.COMPILER_IS_ON_ELEMENT, context))) {
|
||||
const exp = isProp.type === compiler_core_1.NodeTypes.ATTRIBUTE
|
||||
? isProp.value && (0, compiler_core_1.createSimpleExpression)(isProp.value.content, true)
|
||||
: isProp.exp;
|
||||
if (exp) {
|
||||
return (0, compiler_core_1.createCallExpression)(context.helper(compiler_core_2.RESOLVE_DYNAMIC_COMPONENT), [
|
||||
exp,
|
||||
]);
|
||||
}
|
||||
}
|
||||
else if (isProp.type === compiler_core_1.NodeTypes.ATTRIBUTE &&
|
||||
isProp.value.content.startsWith('vue:')) {
|
||||
// <button is="vue:xxx">
|
||||
// if not <component>, only is value that starts with "vue:" will be
|
||||
// treated as component by the parse phase and reach here, unless it's
|
||||
// compat mode where all is values are considered components
|
||||
tag = isProp.value.content.slice(4);
|
||||
}
|
||||
}
|
||||
// 2. built-in components (Teleport, Transition, KeepAlive, Suspense...)
|
||||
const builtIn = (0, compiler_core_3.isCoreComponent)(tag) || context.isBuiltInComponent(tag);
|
||||
if (builtIn) {
|
||||
// built-ins are simply fallthroughs / have special handling during ssr
|
||||
// so we don't need to import their runtime equivalents
|
||||
if (!ssr)
|
||||
context.helper(builtIn);
|
||||
return builtIn;
|
||||
}
|
||||
// 3. user component (from setup bindings)
|
||||
// this is skipped in browser build since browser builds do not perform
|
||||
// binding analysis.
|
||||
if (!utils_1.__BROWSER__) {
|
||||
const fromSetup = resolveSetupReference(tag, context);
|
||||
if (fromSetup) {
|
||||
return fromSetup;
|
||||
}
|
||||
const dotIndex = tag.indexOf('.');
|
||||
if (dotIndex > 0) {
|
||||
const ns = resolveSetupReference(tag.slice(0, dotIndex), context);
|
||||
if (ns) {
|
||||
return ns + tag.slice(dotIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
// 4. Self referencing component (inferred from filename)
|
||||
if (!utils_1.__BROWSER__ &&
|
||||
context.selfName &&
|
||||
(0, shared_1.capitalize)((0, shared_1.camelize)(tag)) === context.selfName) {
|
||||
context.helper(compiler_core_2.RESOLVE_COMPONENT);
|
||||
// codegen.ts has special check for __self postfix when generating
|
||||
// component imports, which will pass additional `maybeSelfReference` flag
|
||||
// to `resolveComponent`.
|
||||
context.components.add(tag + `__self`);
|
||||
return (0, compiler_core_3.toValidAssetId)(tag, `component`);
|
||||
}
|
||||
// 5. user component (resolve)
|
||||
context.helper(compiler_core_2.RESOLVE_COMPONENT);
|
||||
context.components.add(tag);
|
||||
return (0, compiler_core_3.toValidAssetId)(tag, `component`);
|
||||
}
|
||||
exports.resolveComponentType = resolveComponentType;
|
||||
function resolveSetupReference(name, context) {
|
||||
const bindings = context.bindingMetadata;
|
||||
if (!bindings || bindings.__isScriptSetup === false) {
|
||||
return;
|
||||
}
|
||||
const camelName = (0, shared_1.camelize)(name);
|
||||
const PascalName = (0, shared_1.capitalize)(camelName);
|
||||
const checkType = (type) => {
|
||||
if (bindings[name] === type) {
|
||||
return name;
|
||||
}
|
||||
if (bindings[camelName] === type) {
|
||||
return camelName;
|
||||
}
|
||||
if (bindings[PascalName] === type) {
|
||||
return PascalName;
|
||||
}
|
||||
};
|
||||
const fromConst = checkType(compiler_core_5.BindingTypes.SETUP_CONST) ||
|
||||
checkType(compiler_core_5.BindingTypes.SETUP_REACTIVE_CONST) ||
|
||||
checkType(compiler_core_5.BindingTypes.LITERAL_CONST);
|
||||
if (fromConst) {
|
||||
return context.inline
|
||||
? // in inline mode, const setup bindings (e.g. imports) can be used as-is
|
||||
fromConst
|
||||
: `$setup[${JSON.stringify(fromConst)}]`;
|
||||
}
|
||||
const fromMaybeRef = checkType(compiler_core_5.BindingTypes.SETUP_LET) ||
|
||||
checkType(compiler_core_5.BindingTypes.SETUP_REF) ||
|
||||
checkType(compiler_core_5.BindingTypes.SETUP_MAYBE_REF);
|
||||
if (fromMaybeRef) {
|
||||
return context.inline
|
||||
? // setup scope bindings that may be refs need to be unrefed
|
||||
`${context.helperString(compiler_core_2.UNREF)}(${fromMaybeRef})`
|
||||
: `$setup[${JSON.stringify(fromMaybeRef)}]`;
|
||||
}
|
||||
const fromProps = checkType(compiler_core_5.BindingTypes.PROPS);
|
||||
if (fromProps) {
|
||||
return `${context.helperString(compiler_core_2.UNREF)}(${context.inline ? '__props' : '$props'}[${JSON.stringify(fromProps)}])`;
|
||||
}
|
||||
}
|
||||
function buildProps(node, context, props = node.props, isComponent, isDynamicComponent, ssr = false) {
|
||||
const { tag, loc: elementLoc, children } = node;
|
||||
let properties = [];
|
||||
const mergeArgs = [];
|
||||
const runtimeDirectives = [];
|
||||
const hasChildren = children.length > 0;
|
||||
let shouldUseBlock = false;
|
||||
// patchFlag analysis
|
||||
let patchFlag = 0;
|
||||
let hasRef = false;
|
||||
let hasClassBinding = false;
|
||||
let hasStyleBinding = false;
|
||||
let hasHydrationEventBinding = false;
|
||||
let hasDynamicKeys = false;
|
||||
let hasVnodeHook = false;
|
||||
const dynamicPropNames = [];
|
||||
const pushMergeArg = (arg) => {
|
||||
if (properties.length) {
|
||||
mergeArgs.push((0, compiler_core_1.createObjectExpression)(dedupeProperties(properties), elementLoc));
|
||||
properties = [];
|
||||
}
|
||||
if (arg)
|
||||
mergeArgs.push(arg);
|
||||
};
|
||||
const analyzePatchFlag = ({ key, value }) => {
|
||||
if ((0, compiler_core_3.isStaticExp)(key)) {
|
||||
const name = key.content;
|
||||
const isEventHandler = (0, shared_1.isOn)(name);
|
||||
if (isEventHandler &&
|
||||
(!isComponent || isDynamicComponent) &&
|
||||
// omit the flag for click handlers because hydration gives click
|
||||
// dedicated fast path.
|
||||
name.toLowerCase() !== 'onclick' &&
|
||||
// omit v-model handlers
|
||||
name !== 'onUpdate:modelValue' &&
|
||||
// omit onVnodeXXX hooks
|
||||
!(0, shared_1.isReservedProp)(name)) {
|
||||
hasHydrationEventBinding = true;
|
||||
}
|
||||
if (isEventHandler && (0, shared_1.isReservedProp)(name)) {
|
||||
hasVnodeHook = true;
|
||||
}
|
||||
if (isEventHandler && value.type === compiler_core_1.NodeTypes.JS_CALL_EXPRESSION) {
|
||||
// handler wrapped with internal helper e.g. withModifiers(fn)
|
||||
// extract the actual expression
|
||||
value = value.arguments[0];
|
||||
}
|
||||
if (value.type === compiler_core_1.NodeTypes.JS_CACHE_EXPRESSION ||
|
||||
((value.type === compiler_core_1.NodeTypes.SIMPLE_EXPRESSION ||
|
||||
value.type === compiler_core_1.NodeTypes.COMPOUND_EXPRESSION) &&
|
||||
(0, compiler_core_4.getConstantType)(value, context) > 0)) {
|
||||
// skip if the prop is a cached handler or has constant value
|
||||
return;
|
||||
}
|
||||
if (name === 'ref') {
|
||||
hasRef = true;
|
||||
}
|
||||
else if (name === 'class') {
|
||||
hasClassBinding = true;
|
||||
}
|
||||
else if (name === 'style') {
|
||||
hasStyleBinding = true;
|
||||
}
|
||||
else if (name !== 'key' && !dynamicPropNames.includes(name)) {
|
||||
dynamicPropNames.push(name);
|
||||
}
|
||||
// treat the dynamic class and style binding of the component as dynamic props
|
||||
if (isComponent &&
|
||||
(name === 'class' || name === 'style') &&
|
||||
!dynamicPropNames.includes(name)) {
|
||||
dynamicPropNames.push(name);
|
||||
}
|
||||
}
|
||||
else {
|
||||
hasDynamicKeys = true;
|
||||
}
|
||||
};
|
||||
for (let i = 0; i < props.length; i++) {
|
||||
// static attribute
|
||||
const prop = props[i];
|
||||
if (prop.type === compiler_core_1.NodeTypes.ATTRIBUTE) {
|
||||
const { loc, name, nameLoc, value } = prop;
|
||||
let isStatic = true;
|
||||
if (name === 'ref') {
|
||||
hasRef = true;
|
||||
if (context.scopes.vFor > 0) {
|
||||
properties.push((0, compiler_core_1.createObjectProperty)((0, compiler_core_1.createSimpleExpression)('ref_for', true), (0, compiler_core_1.createSimpleExpression)('true')));
|
||||
}
|
||||
// in inline mode there is no setupState object, so we can't use string
|
||||
// keys to set the ref. Instead, we need to transform it to pass the
|
||||
// actual ref instead.
|
||||
if (!utils_1.__BROWSER__ && value && context.inline) {
|
||||
const binding = context.bindingMetadata[value.content];
|
||||
if (binding === compiler_core_5.BindingTypes.SETUP_LET ||
|
||||
binding === compiler_core_5.BindingTypes.SETUP_REF ||
|
||||
binding === compiler_core_5.BindingTypes.SETUP_MAYBE_REF) {
|
||||
isStatic = false;
|
||||
properties.push((0, compiler_core_1.createObjectProperty)((0, compiler_core_1.createSimpleExpression)('ref_key', true), (0, compiler_core_1.createSimpleExpression)(value.content, true, value.loc)));
|
||||
}
|
||||
}
|
||||
}
|
||||
// skip is on <component>, or is="vue:xxx"
|
||||
if (name === 'is' &&
|
||||
(isComponentTag(tag) ||
|
||||
(value && value.content.startsWith('vue:')) ||
|
||||
(utils_1.__COMPAT__ &&
|
||||
(0, utils_1.isCompatEnabled)(compiler_core_6.CompilerDeprecationTypes.COMPILER_IS_ON_ELEMENT, context)))) {
|
||||
continue;
|
||||
}
|
||||
properties.push((0, compiler_core_1.createObjectProperty)((0, compiler_core_1.createSimpleExpression)(name, true, nameLoc), (0, compiler_core_1.createSimpleExpression)(value ? value.content : '', isStatic, value ? value.loc : loc)));
|
||||
}
|
||||
else {
|
||||
// directives
|
||||
const { name, arg, exp, loc, modifiers } = prop;
|
||||
const isVBind = name === 'bind';
|
||||
const isVOn = name === 'on';
|
||||
// skip v-slot - it is handled by its dedicated transform.
|
||||
if (name === 'slot') {
|
||||
if (!isComponent) {
|
||||
context.onError((0, errors_1.createCompilerError)(40 /* ErrorCodes.X_V_SLOT_MISPLACED */, loc));
|
||||
}
|
||||
continue;
|
||||
}
|
||||
// skip v-once/v-memo - they are handled by dedicated transforms.
|
||||
if (name === 'once' || name === 'memo') {
|
||||
continue;
|
||||
}
|
||||
// skip v-is and :is on <component>
|
||||
if (name === 'is' ||
|
||||
(isVBind &&
|
||||
(0, compiler_core_3.isStaticArgOf)(arg, 'is') &&
|
||||
(isComponentTag(tag) ||
|
||||
(utils_1.__COMPAT__ &&
|
||||
(0, utils_1.isCompatEnabled)(compiler_core_6.CompilerDeprecationTypes.COMPILER_IS_ON_ELEMENT, context))))) {
|
||||
continue;
|
||||
}
|
||||
// skip v-on in SSR compilation
|
||||
if (isVOn && ssr) {
|
||||
continue;
|
||||
}
|
||||
if (
|
||||
// #938: elements with dynamic keys should be forced into blocks
|
||||
(isVBind && (0, compiler_core_3.isStaticArgOf)(arg, 'key')) ||
|
||||
// inline before-update hooks need to force block so that it is invoked
|
||||
// before children
|
||||
(isVOn && hasChildren && (0, compiler_core_3.isStaticArgOf)(arg, 'vue:before-update'))) {
|
||||
shouldUseBlock = true;
|
||||
}
|
||||
if (isVBind && (0, compiler_core_3.isStaticArgOf)(arg, 'ref') && context.scopes.vFor > 0) {
|
||||
properties.push((0, compiler_core_1.createObjectProperty)((0, compiler_core_1.createSimpleExpression)('ref_for', true), (0, compiler_core_1.createSimpleExpression)('true')));
|
||||
}
|
||||
// special case for v-bind and v-on with no argument
|
||||
if (!arg && (isVBind || isVOn)) {
|
||||
hasDynamicKeys = true;
|
||||
if (exp) {
|
||||
if (isVBind) {
|
||||
// have to merge early for compat build check
|
||||
pushMergeArg();
|
||||
if (utils_1.__COMPAT__) {
|
||||
// 2.x v-bind object order compat
|
||||
if (utils_1.__DEV__) {
|
||||
const hasOverridableKeys = mergeArgs.some((arg) => {
|
||||
if (arg.type === compiler_core_1.NodeTypes.JS_OBJECT_EXPRESSION) {
|
||||
return arg.properties.some(({ key }) => {
|
||||
if (key.type !== compiler_core_1.NodeTypes.SIMPLE_EXPRESSION ||
|
||||
!key.isStatic) {
|
||||
return true;
|
||||
}
|
||||
return (key.content !== 'class' &&
|
||||
key.content !== 'style' &&
|
||||
!(0, shared_1.isOn)(key.content));
|
||||
});
|
||||
}
|
||||
else {
|
||||
// dynamic expression
|
||||
return true;
|
||||
}
|
||||
});
|
||||
if (hasOverridableKeys) {
|
||||
(0, compiler_core_6.checkCompatEnabled)(compiler_core_6.CompilerDeprecationTypes.COMPILER_V_BIND_OBJECT_ORDER, context, loc);
|
||||
}
|
||||
}
|
||||
if ((0, utils_1.isCompatEnabled)(compiler_core_6.CompilerDeprecationTypes.COMPILER_V_BIND_OBJECT_ORDER, context)) {
|
||||
mergeArgs.unshift(exp);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
mergeArgs.push(exp);
|
||||
}
|
||||
else {
|
||||
// v-on="obj" -> toHandlers(obj)
|
||||
pushMergeArg({
|
||||
type: compiler_core_1.NodeTypes.JS_CALL_EXPRESSION,
|
||||
loc,
|
||||
callee: context.helper(compiler_core_2.TO_HANDLERS),
|
||||
arguments: isComponent ? [exp] : [exp, `true`],
|
||||
});
|
||||
}
|
||||
}
|
||||
else {
|
||||
context.onError((0, errors_1.createCompilerError)(isVBind
|
||||
? 34 /* ErrorCodes.X_V_BIND_NO_EXPRESSION */
|
||||
: 35 /* ErrorCodes.X_V_ON_NO_EXPRESSION */, loc));
|
||||
}
|
||||
continue;
|
||||
}
|
||||
// force hydration for v-bind with .prop modifier
|
||||
if (isVBind && modifiers.includes('prop')) {
|
||||
patchFlag |= shared_1.PatchFlags.NEED_HYDRATION;
|
||||
}
|
||||
const directiveTransform = context.directiveTransforms[name];
|
||||
if (directiveTransform) {
|
||||
// has built-in directive transform.
|
||||
const { props, needRuntime } = directiveTransform(prop, node, context);
|
||||
!ssr && props.forEach(analyzePatchFlag);
|
||||
if (isVOn && arg && !(0, compiler_core_3.isStaticExp)(arg)) {
|
||||
pushMergeArg((0, compiler_core_1.createObjectExpression)(props, elementLoc));
|
||||
}
|
||||
else {
|
||||
properties.push(...props);
|
||||
}
|
||||
if (needRuntime) {
|
||||
runtimeDirectives.push(prop);
|
||||
if ((0, shared_1.isSymbol)(needRuntime)) {
|
||||
directiveImportMap.set(prop, needRuntime);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (!(0, shared_1.isBuiltInDirective)(name)) {
|
||||
// no built-in transform, this is a user custom directive.
|
||||
runtimeDirectives.push(prop);
|
||||
// custom dirs may use beforeUpdate so they need to force blocks
|
||||
// to ensure before-update gets called before children update
|
||||
if (hasChildren) {
|
||||
shouldUseBlock = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
let propsExpression = undefined;
|
||||
// has v-bind="object" or v-on="object", wrap with mergeProps
|
||||
if (mergeArgs.length) {
|
||||
// close up any not-yet-merged props
|
||||
pushMergeArg();
|
||||
if (mergeArgs.length > 1) {
|
||||
propsExpression = (0, compiler_core_1.createCallExpression)(context.helper(compiler_core_2.MERGE_PROPS), mergeArgs, elementLoc);
|
||||
}
|
||||
else {
|
||||
// single v-bind with nothing else - no need for a mergeProps call
|
||||
propsExpression = mergeArgs[0];
|
||||
}
|
||||
}
|
||||
else if (properties.length) {
|
||||
propsExpression = (0, compiler_core_1.createObjectExpression)(dedupeProperties(properties), elementLoc);
|
||||
}
|
||||
// patchFlag analysis
|
||||
if (hasDynamicKeys) {
|
||||
patchFlag |= shared_1.PatchFlags.FULL_PROPS;
|
||||
}
|
||||
else {
|
||||
if (hasClassBinding && !isComponent) {
|
||||
patchFlag |= shared_1.PatchFlags.CLASS;
|
||||
}
|
||||
if (hasStyleBinding && !isComponent) {
|
||||
patchFlag |= shared_1.PatchFlags.STYLE;
|
||||
}
|
||||
if (dynamicPropNames.length) {
|
||||
patchFlag |= shared_1.PatchFlags.PROPS;
|
||||
}
|
||||
if (hasHydrationEventBinding) {
|
||||
patchFlag |= shared_1.PatchFlags.NEED_HYDRATION;
|
||||
}
|
||||
}
|
||||
if (!shouldUseBlock &&
|
||||
(patchFlag === 0 || patchFlag === shared_1.PatchFlags.NEED_HYDRATION) &&
|
||||
(hasRef || hasVnodeHook || runtimeDirectives.length > 0)) {
|
||||
patchFlag |= shared_1.PatchFlags.NEED_PATCH;
|
||||
}
|
||||
// pre-normalize props, SSR is skipped for now
|
||||
if (!context.inSSR && propsExpression) {
|
||||
switch (propsExpression.type) {
|
||||
case compiler_core_1.NodeTypes.JS_OBJECT_EXPRESSION:
|
||||
// means that there is no v-bind,
|
||||
// but still need to deal with dynamic key binding
|
||||
let classKeyIndex = -1;
|
||||
let styleKeyIndex = -1;
|
||||
let hasDynamicKey = false;
|
||||
for (let i = 0; i < propsExpression.properties.length; i++) {
|
||||
const key = propsExpression.properties[i].key;
|
||||
if ((0, compiler_core_3.isStaticExp)(key)) {
|
||||
if (key.content === 'class') {
|
||||
classKeyIndex = i;
|
||||
}
|
||||
else if (key.content === 'style') {
|
||||
styleKeyIndex = i;
|
||||
}
|
||||
}
|
||||
else if (!key.isHandlerKey) {
|
||||
hasDynamicKey = true;
|
||||
}
|
||||
}
|
||||
const classProp = propsExpression.properties[classKeyIndex];
|
||||
const styleProp = propsExpression.properties[styleKeyIndex];
|
||||
// no dynamic key
|
||||
if (!hasDynamicKey) {
|
||||
if (classProp && !(0, compiler_core_3.isStaticExp)(classProp.value)) {
|
||||
classProp.value = (0, compiler_core_1.createCallExpression)(context.helper(compiler_core_2.NORMALIZE_CLASS), [classProp.value]);
|
||||
}
|
||||
if (styleProp &&
|
||||
// the static style is compiled into an object,
|
||||
// so use `hasStyleBinding` to ensure that it is a dynamic style binding
|
||||
(hasStyleBinding ||
|
||||
(styleProp.value.type === compiler_core_1.NodeTypes.SIMPLE_EXPRESSION &&
|
||||
styleProp.value.content.trim()[0] === `[`) ||
|
||||
// v-bind:style and style both exist,
|
||||
// v-bind:style with static literal object
|
||||
styleProp.value.type === compiler_core_1.NodeTypes.JS_ARRAY_EXPRESSION)) {
|
||||
styleProp.value = (0, compiler_core_1.createCallExpression)(context.helper(compiler_core_2.NORMALIZE_STYLE), [styleProp.value]);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// dynamic key binding, wrap with `normalizeProps`
|
||||
propsExpression = (0, compiler_core_1.createCallExpression)(context.helper(compiler_core_2.NORMALIZE_PROPS), [propsExpression]);
|
||||
}
|
||||
break;
|
||||
case compiler_core_1.NodeTypes.JS_CALL_EXPRESSION:
|
||||
// mergeProps call, do nothing
|
||||
break;
|
||||
default:
|
||||
// single v-bind
|
||||
propsExpression = (0, compiler_core_1.createCallExpression)(context.helper(compiler_core_2.NORMALIZE_PROPS), [
|
||||
(0, compiler_core_1.createCallExpression)(context.helper(compiler_core_2.GUARD_REACTIVE_PROPS), [
|
||||
propsExpression,
|
||||
]),
|
||||
]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return {
|
||||
props: propsExpression,
|
||||
directives: runtimeDirectives,
|
||||
patchFlag,
|
||||
dynamicPropNames,
|
||||
shouldUseBlock,
|
||||
};
|
||||
}
|
||||
exports.buildProps = buildProps;
|
||||
// Dedupe props in an object literal.
|
||||
// Literal duplicated attributes would have been warned during the parse phase,
|
||||
// however, it's possible to encounter duplicated `onXXX` handlers with different
|
||||
// modifiers. We also need to merge static and dynamic class / style attributes.
|
||||
// - onXXX handlers / style: merge into array
|
||||
// - class: merge into single expression with concatenation
|
||||
function dedupeProperties(properties) {
|
||||
const knownProps = new Map();
|
||||
const deduped = [];
|
||||
for (let i = 0; i < properties.length; i++) {
|
||||
const prop = properties[i];
|
||||
// dynamic keys are always allowed
|
||||
if (prop.key.type === compiler_core_1.NodeTypes.COMPOUND_EXPRESSION || !prop.key.isStatic) {
|
||||
deduped.push(prop);
|
||||
continue;
|
||||
}
|
||||
const name = prop.key.content;
|
||||
const existing = knownProps.get(name);
|
||||
if (existing) {
|
||||
if (name === 'style' || name === 'class' || (0, shared_1.isOn)(name)) {
|
||||
mergeAsArray(existing, prop);
|
||||
}
|
||||
// unexpected duplicate, should have emitted error during parse
|
||||
}
|
||||
else {
|
||||
knownProps.set(name, prop);
|
||||
deduped.push(prop);
|
||||
}
|
||||
}
|
||||
return deduped;
|
||||
}
|
||||
function mergeAsArray(existing, incoming) {
|
||||
if (existing.value.type === compiler_core_1.NodeTypes.JS_ARRAY_EXPRESSION) {
|
||||
existing.value.elements.push(incoming.value);
|
||||
}
|
||||
else {
|
||||
existing.value = (0, compiler_core_1.createArrayExpression)([existing.value, incoming.value], existing.loc);
|
||||
}
|
||||
}
|
||||
function buildDirectiveArgs(dir, context) {
|
||||
const dirArgs = [];
|
||||
const runtime = directiveImportMap.get(dir);
|
||||
if (runtime) {
|
||||
// built-in directive with runtime
|
||||
dirArgs.push(context.helperString(runtime));
|
||||
}
|
||||
else {
|
||||
// user directive.
|
||||
// see if we have directives exposed via <script setup>
|
||||
const fromSetup = !utils_1.__BROWSER__ && resolveSetupReference('v-' + dir.name, context);
|
||||
if (fromSetup) {
|
||||
dirArgs.push(fromSetup);
|
||||
}
|
||||
else {
|
||||
// inject statement for resolving directive
|
||||
context.helper(compiler_core_2.RESOLVE_DIRECTIVE);
|
||||
context.directives.add(dir.name);
|
||||
dirArgs.push((0, compiler_core_3.toValidAssetId)(dir.name, `directive`));
|
||||
}
|
||||
}
|
||||
const { loc } = dir;
|
||||
if (dir.exp)
|
||||
dirArgs.push(dir.exp);
|
||||
if (dir.arg) {
|
||||
if (!dir.exp) {
|
||||
dirArgs.push(`void 0`);
|
||||
}
|
||||
dirArgs.push(dir.arg);
|
||||
}
|
||||
if (Object.keys(dir.modifiers).length) {
|
||||
if (!dir.arg) {
|
||||
if (!dir.exp) {
|
||||
dirArgs.push(`void 0`);
|
||||
}
|
||||
dirArgs.push(`void 0`);
|
||||
}
|
||||
const trueExpression = (0, compiler_core_1.createSimpleExpression)(`true`, false, loc);
|
||||
dirArgs.push((0, compiler_core_1.createObjectExpression)(dir.modifiers.map((modifier) => (0, compiler_core_1.createObjectProperty)(modifier, trueExpression)), loc));
|
||||
}
|
||||
return (0, compiler_core_1.createArrayExpression)(dirArgs, dir.loc);
|
||||
}
|
||||
exports.buildDirectiveArgs = buildDirectiveArgs;
|
||||
function stringifyDynamicPropNames(props) {
|
||||
let propsNamesString = `[`;
|
||||
for (let i = 0, l = props.length; i < l; i++) {
|
||||
propsNamesString += JSON.stringify(props[i]);
|
||||
if (i < l - 1)
|
||||
propsNamesString += ', ';
|
||||
}
|
||||
return propsNamesString + `]`;
|
||||
}
|
||||
function isComponentTag(tag) {
|
||||
return tag === 'component' || tag === 'Component';
|
||||
}
|
||||
Generated
Vendored
+3
@@ -0,0 +1,3 @@
|
||||
import { type RootNode, type TemplateChildNode } from '@vue/compiler-core';
|
||||
import type { TransformContext } from '../transform';
|
||||
export declare function transformElements(node: RootNode | TemplateChildNode, context: TransformContext): void;
|
||||
Generated
Vendored
+38
@@ -0,0 +1,38 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.transformElements = void 0;
|
||||
const compiler_core_1 = require("@vue/compiler-core");
|
||||
const uni_shared_1 = require("@dcloudio/uni-shared");
|
||||
const uni_cli_shared_1 = require("@dcloudio/uni-cli-shared");
|
||||
function transformElements(node, context) {
|
||||
if (node.type === compiler_core_1.NodeTypes.ELEMENT &&
|
||||
(node.tagType === compiler_core_1.ElementTypes.ELEMENT ||
|
||||
(node.tagType === compiler_core_1.ElementTypes.COMPONENT &&
|
||||
(0, uni_shared_1.isAppUVueBuiltInEasyComponent)(node.tag)))) {
|
||||
context.elements.add(node.tag);
|
||||
// 原生UTS customElements组件
|
||||
const utsCustomElementOptions = context.parseUTSCustomElement(node.tag, 'kotlin');
|
||||
if (utsCustomElementOptions) {
|
||||
// const className = `{ ${capitalize(camelize(node.tag)) + 'Element'} }`
|
||||
const className = '';
|
||||
if (!context.imports.find((i) => i.path === utsCustomElementOptions.source && i.exp === className)) {
|
||||
context.imports.push({
|
||||
exp: className,
|
||||
path: utsCustomElementOptions.source,
|
||||
});
|
||||
}
|
||||
}
|
||||
// 原生UTS组件
|
||||
const utsComponentOptions = context.parseUTSComponent(node.tag, 'kotlin');
|
||||
if (utsComponentOptions) {
|
||||
const className = `{ ${(0, uni_cli_shared_1.capitalize)((0, uni_cli_shared_1.camelize)(node.tag)) + 'Component'} }`;
|
||||
if (!context.imports.find((i) => i.path === utsComponentOptions.source && i.exp === className)) {
|
||||
context.imports.push({
|
||||
exp: className,
|
||||
path: utsComponentOptions.source,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
exports.transformElements = transformElements;
|
||||
Generated
Vendored
+5
@@ -0,0 +1,5 @@
|
||||
import type { NodeTransform, TransformContext } from '../transform';
|
||||
import { type ExpressionNode, type SimpleExpressionNode } from '@vue/compiler-core';
|
||||
export declare const transformExpression: NodeTransform;
|
||||
export declare function processExpression(node: SimpleExpressionNode, context: TransformContext, asParams?: boolean, asRawStatements?: boolean, localVars?: Record<string, number>): ExpressionNode;
|
||||
export declare function stringifyExpression(exp: ExpressionNode | string | (ExpressionNode | string)[]): string;
|
||||
Generated
Vendored
+300
@@ -0,0 +1,300 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.stringifyExpression = exports.processExpression = exports.transformExpression = void 0;
|
||||
const shared_1 = require("@vue/shared");
|
||||
const parser_1 = require("@babel/parser");
|
||||
const compiler_core_1 = require("@vue/compiler-core");
|
||||
const errors_1 = require("../errors");
|
||||
const runtimeHelpers_1 = require("../runtimeHelpers");
|
||||
const GLOBALS_WHITE_LISTED = `Infinity,undefined,NaN,isFinite,isNaN,parseFloat,parseInt,decodeURI` +
|
||||
`,decodeURIComponent,encodeURI,encodeURIComponent,Math,Number,Date,Array` +
|
||||
`,Object,Boolean,String,RegExp,Map,Set,JSON,Intl,BigInt` +
|
||||
`,console`;
|
||||
const isGloballyWhitelisted = /*#__PURE__*/ (0, shared_1.makeMap)(GLOBALS_WHITE_LISTED);
|
||||
const isLiteralWhitelisted = /*#__PURE__*/ (0, shared_1.makeMap)('true,false,null,this');
|
||||
// a heuristic safeguard to bail constant expressions on presence of
|
||||
// likely function invocation and member access
|
||||
const constantBailRE = /\w\s*\(|\.[^\d]/;
|
||||
const transformExpression = (node, context) => {
|
||||
if (node.type === compiler_core_1.NodeTypes.INTERPOLATION) {
|
||||
node.content = processExpression(node.content, context);
|
||||
}
|
||||
else if (node.type === compiler_core_1.NodeTypes.ELEMENT) {
|
||||
// handle directives on element
|
||||
for (let i = 0; i < node.props.length; i++) {
|
||||
const dir = node.props[i];
|
||||
// do not process for v-on & v-for since they are special handled
|
||||
if (dir.type === compiler_core_1.NodeTypes.DIRECTIVE && dir.name !== 'for') {
|
||||
const exp = dir.exp;
|
||||
const arg = dir.arg;
|
||||
// do not process exp if this is v-on:arg - we need special handling
|
||||
// for wrapping inline statements.
|
||||
if (exp &&
|
||||
exp.type === compiler_core_1.NodeTypes.SIMPLE_EXPRESSION &&
|
||||
!(dir.name === 'on' && arg)) {
|
||||
dir.exp = processExpression(exp, context,
|
||||
// slot args must be processed as function params
|
||||
dir.name === 'slot');
|
||||
}
|
||||
if (arg && arg.type === compiler_core_1.NodeTypes.SIMPLE_EXPRESSION && !arg.isStatic) {
|
||||
dir.arg = processExpression(arg, context);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
exports.transformExpression = transformExpression;
|
||||
// Important: since this function uses Node.js only dependencies, it should
|
||||
// always be used with a leading !__BROWSER__ check so that it can be
|
||||
// tree-shaken from the browser build.
|
||||
function processExpression(node, context,
|
||||
// some expressions like v-slot props & v-for aliases should be parsed as
|
||||
// function params
|
||||
asParams = false,
|
||||
// v-on handler values may contain multiple statements
|
||||
asRawStatements = false, localVars = Object.create(context.identifiers)) {
|
||||
if (!context.prefixIdentifiers || !node.content.trim()) {
|
||||
return node;
|
||||
}
|
||||
const { inline, bindingMetadata } = context;
|
||||
const rewriteIdentifier = (raw, parent, id) => {
|
||||
const type = (0, shared_1.hasOwn)(bindingMetadata, raw) && bindingMetadata[raw];
|
||||
if (inline) {
|
||||
// x = y
|
||||
const isAssignmentLVal = parent && parent.type === 'AssignmentExpression' && parent.left === id;
|
||||
// x++
|
||||
const isUpdateArg = parent && parent.type === 'UpdateExpression' && parent.argument === id;
|
||||
// ({ x } = y)
|
||||
const isDestructureAssignment = parent && (0, compiler_core_1.isInDestructureAssignment)(parent, parentStack);
|
||||
if (isConst(type) ||
|
||||
type === compiler_core_1.BindingTypes.SETUP_REACTIVE_CONST ||
|
||||
localVars[raw]) {
|
||||
return raw;
|
||||
}
|
||||
else if (type === compiler_core_1.BindingTypes.SETUP_REF) {
|
||||
return `${raw}.value`;
|
||||
}
|
||||
else if (type === compiler_core_1.BindingTypes.SETUP_MAYBE_REF) {
|
||||
// const binding that may or may not be ref
|
||||
// if it's not a ref, then assignments don't make sense -
|
||||
// so we ignore the non-ref assignment case and generate code
|
||||
// that assumes the value to be a ref for more efficiency
|
||||
return isAssignmentLVal || isUpdateArg || isDestructureAssignment
|
||||
? `${raw}.value`
|
||||
: `${context.helperString(compiler_core_1.UNREF)}(${raw})`;
|
||||
}
|
||||
else if (type === compiler_core_1.BindingTypes.SETUP_LET) {
|
||||
if (isAssignmentLVal) {
|
||||
// let binding.
|
||||
// this is a bit more tricky as we need to cover the case where
|
||||
// let is a local non-ref value, and we need to replicate the
|
||||
// right hand side value.
|
||||
// x = y --> isRef(x) ? x.value = y : x = y
|
||||
const { right: rVal, operator } = parent;
|
||||
const rExp = rawExp.slice(rVal.start - 1, rVal.end - 1);
|
||||
const rExpString = stringifyExpression(processExpression((0, compiler_core_1.createSimpleExpression)(rExp, false), context, false, false, knownIds));
|
||||
const value = operator === '='
|
||||
? rExpString
|
||||
: `${context.helperString(compiler_core_1.UNREF)}(${raw}.also((_)=>{ ${raw} ${operator} ${rExpString} }))`;
|
||||
return `${context.helperString(compiler_core_1.IS_REF)}(${raw}) ? ${context.helperString(runtimeHelpers_1.TRY_SET_REF_VALUE)}(${raw}, ${value}) : ${raw}`;
|
||||
}
|
||||
else if (isUpdateArg) {
|
||||
// make id replace parent in the code range so the raw update operator
|
||||
// is removed
|
||||
id.start = parent.start;
|
||||
id.end = parent.end;
|
||||
const { prefix, operator } = parent;
|
||||
// let binding.
|
||||
// x++ --> isRef(a) ? a.value++ : a++
|
||||
return `${type === compiler_core_1.BindingTypes.SETUP_LET ? `${raw} = ` : ''}${context.helperString(runtimeHelpers_1.TRY_UPDATE_REF_NUMBER)}(${raw}, ${operator === '--' ? '-1' : '1'}, ${prefix})`;
|
||||
}
|
||||
else if (isDestructureAssignment) {
|
||||
// TODO
|
||||
// let binding in a destructure assignment - it's very tricky to
|
||||
// handle both possible cases here without altering the original
|
||||
// structure of the code, so we just assume it's not a ref here
|
||||
// for now
|
||||
return raw;
|
||||
}
|
||||
else {
|
||||
return `${context.helperString(compiler_core_1.UNREF)}(${raw})`;
|
||||
}
|
||||
}
|
||||
// else if (type === BindingTypes.PROPS) {
|
||||
// // use __props which is generated by compileScript so in ts mode
|
||||
// // it gets correct type
|
||||
// return genPropsAccessExp(raw)
|
||||
// } else if (type === BindingTypes.PROPS_ALIASED) {
|
||||
// // prop with a different local alias (from defineProps() destructure)
|
||||
// return genPropsAccessExp(bindingMetadata.__propsAliases![raw])
|
||||
// }
|
||||
}
|
||||
else {
|
||||
// if (
|
||||
// (type && type.startsWith('setup')) ||
|
||||
// type === BindingTypes.LITERAL_CONST
|
||||
// ) {
|
||||
// // setup bindings in non-inline mode
|
||||
// // return `$setup.${raw}`
|
||||
// return `$setup.${raw}`
|
||||
// } else if (type === BindingTypes.PROPS_ALIASED) {
|
||||
// return `$props['${bindingMetadata.__propsAliases![raw]}']`
|
||||
// } else if (type) {
|
||||
// return `$${type}.${raw}`
|
||||
// }
|
||||
}
|
||||
// fallback to ctx
|
||||
return `_ctx.${raw}`;
|
||||
};
|
||||
// fast path if expression is a simple identifier.
|
||||
const rawExp = node.content;
|
||||
// bail constant on parens (function invocation) and dot (member access)
|
||||
const bailConstant = constantBailRE.test(rawExp);
|
||||
if ((0, compiler_core_1.isSimpleIdentifier)(rawExp)) {
|
||||
const isScopeVarReference = context.identifiers[rawExp];
|
||||
const isAllowedGlobal = isGloballyWhitelisted(rawExp);
|
||||
const isLiteral = isLiteralWhitelisted(rawExp);
|
||||
if (!asParams &&
|
||||
!isScopeVarReference &&
|
||||
!isLiteral &&
|
||||
(!isAllowedGlobal || bindingMetadata[rawExp])) {
|
||||
// const bindings exposed from setup can be skipped for patching but
|
||||
// cannot be hoisted to module scope
|
||||
if (bindingMetadata[node.content] === compiler_core_1.BindingTypes.SETUP_CONST) {
|
||||
node.constType = compiler_core_1.ConstantTypes.CAN_SKIP_PATCH;
|
||||
}
|
||||
node.content = rewriteIdentifier(rawExp);
|
||||
}
|
||||
else if (!isScopeVarReference) {
|
||||
if (isLiteral) {
|
||||
node.constType = compiler_core_1.ConstantTypes.CAN_STRINGIFY;
|
||||
}
|
||||
else {
|
||||
node.constType = compiler_core_1.ConstantTypes.CAN_HOIST;
|
||||
}
|
||||
}
|
||||
return node;
|
||||
}
|
||||
let ast;
|
||||
// exp needs to be parsed differently:
|
||||
// 1. Multiple inline statements (v-on, with presence of `;`): parse as raw
|
||||
// exp, but make sure to pad with spaces for consistent ranges
|
||||
// 2. Expressions: wrap with parens (for e.g. object expressions)
|
||||
// 3. Function arguments (v-for, v-slot): place in a function argument position
|
||||
const source = asRawStatements
|
||||
? ` ${rawExp} `
|
||||
: `(${rawExp})${asParams ? `=>{}` : ``}`;
|
||||
try {
|
||||
ast = (0, parser_1.parse)(source, {
|
||||
plugins: context.expressionPlugins,
|
||||
}).program;
|
||||
}
|
||||
catch (e) {
|
||||
context.onError((0, errors_1.createCompilerError)(45 /* ErrorCodes.X_INVALID_EXPRESSION */, node.loc, undefined, e.message));
|
||||
return node;
|
||||
}
|
||||
const ids = [];
|
||||
const parentStack = [];
|
||||
const knownIds = Object.create(context.identifiers);
|
||||
(0, compiler_core_1.walkIdentifiers)(ast, (node, parent, _, isReferenced, isLocal) => {
|
||||
if ((0, compiler_core_1.isStaticPropertyKey)(node, parent)) {
|
||||
return;
|
||||
}
|
||||
const needPrefix = isReferenced && canPrefix(node);
|
||||
if (needPrefix && !isLocal) {
|
||||
if ((0, compiler_core_1.isStaticProperty)(parent) && parent.shorthand) {
|
||||
// property shorthand like { foo }, we need to add the key since
|
||||
// we rewrite the value
|
||||
;
|
||||
node.prefix = `${node.name}: `;
|
||||
}
|
||||
node.name = rewriteIdentifier(node.name, parent, node);
|
||||
ids.push(node);
|
||||
}
|
||||
else {
|
||||
// The identifier is considered constant unless it's pointing to a
|
||||
// local scope variable (a v-for alias, or a v-slot prop)
|
||||
if (!(needPrefix && isLocal) && !bailConstant) {
|
||||
;
|
||||
node.isConstant = true;
|
||||
}
|
||||
// also generate sub-expressions for other identifiers for better
|
||||
// source map support. (except for property keys which are static)
|
||||
ids.push(node);
|
||||
}
|
||||
}, true, // invoke on ALL identifiers
|
||||
parentStack, knownIds);
|
||||
// We break up the compound expression into an array of strings and sub
|
||||
// expressions (for identifiers that have been prefixed). In codegen, if
|
||||
// an ExpressionNode has the `.children` property, it will be used instead of
|
||||
// `.content`.
|
||||
const children = [];
|
||||
ids.sort((a, b) => a.start - b.start);
|
||||
ids.forEach((id, i) => {
|
||||
// range is offset by -1 due to the wrapping parens when parsed
|
||||
const start = id.start - 1;
|
||||
const end = id.end - 1;
|
||||
const last = ids[i - 1];
|
||||
const leadingText = rawExp.slice(last ? last.end - 1 : 0, start);
|
||||
if (leadingText.length || id.prefix) {
|
||||
children.push(leadingText + (id.prefix || ``));
|
||||
}
|
||||
const source = rawExp.slice(start, end);
|
||||
const child = (0, compiler_core_1.createSimpleExpression)(id.name, false, {
|
||||
source,
|
||||
start: (0, compiler_core_1.advancePositionWithClone)(node.loc.start, source, start),
|
||||
end: (0, compiler_core_1.advancePositionWithClone)(node.loc.start, source, end),
|
||||
}, id.isConstant ? compiler_core_1.ConstantTypes.CAN_STRINGIFY : compiler_core_1.ConstantTypes.NOT_CONSTANT);
|
||||
if (id.typeAnnotation?.type === 'TSTypeAnnotation') {
|
||||
child.content = child.loc.source;
|
||||
}
|
||||
children.push(child);
|
||||
if (i === ids.length - 1 && end < rawExp.length) {
|
||||
children.push(rawExp.slice(end));
|
||||
}
|
||||
});
|
||||
let ret;
|
||||
if (children.length) {
|
||||
ret = (0, compiler_core_1.createCompoundExpression)(children, node.loc);
|
||||
}
|
||||
else {
|
||||
ret = node;
|
||||
ret.constType = bailConstant
|
||||
? compiler_core_1.ConstantTypes.NOT_CONSTANT
|
||||
: compiler_core_1.ConstantTypes.CAN_STRINGIFY;
|
||||
}
|
||||
ret.identifiers = Object.keys(knownIds);
|
||||
return ret;
|
||||
}
|
||||
exports.processExpression = processExpression;
|
||||
function canPrefix(id) {
|
||||
// skip whitelisted globals
|
||||
if (isGloballyWhitelisted(id.name)) {
|
||||
return false;
|
||||
}
|
||||
// special case for webpack compilation
|
||||
if (id.name === 'require') {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
function stringifyExpression(exp) {
|
||||
if ((0, shared_1.isArray)(exp)) {
|
||||
return exp.map(stringifyExpression).join('');
|
||||
}
|
||||
else if ((0, shared_1.isString)(exp)) {
|
||||
return exp;
|
||||
}
|
||||
else if (exp.type === compiler_core_1.NodeTypes.SIMPLE_EXPRESSION) {
|
||||
return exp.content;
|
||||
}
|
||||
else {
|
||||
return exp.children
|
||||
.map(stringifyExpression)
|
||||
.join('');
|
||||
}
|
||||
}
|
||||
exports.stringifyExpression = stringifyExpression;
|
||||
function isConst(type) {
|
||||
return (type === compiler_core_1.BindingTypes.SETUP_CONST || type === compiler_core_1.BindingTypes.LITERAL_CONST);
|
||||
}
|
||||
Generated
Vendored
+4
@@ -0,0 +1,4 @@
|
||||
import type { NodeTransform } from '../transform';
|
||||
import { type InterpolationNode, type TemplateChildNode, type TextNode } from '@vue/compiler-core';
|
||||
export declare function isText(node: TemplateChildNode): node is TextNode | InterpolationNode;
|
||||
export declare const transformInterpolation: NodeTransform;
|
||||
Generated
Vendored
+106
@@ -0,0 +1,106 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.transformInterpolation = exports.isText = void 0;
|
||||
const compiler_core_1 = require("@vue/compiler-core");
|
||||
function isText(node) {
|
||||
return node.type === compiler_core_1.NodeTypes.INTERPOLATION || node.type === compiler_core_1.NodeTypes.TEXT;
|
||||
}
|
||||
exports.isText = isText;
|
||||
// Merge adjacent text nodes and expressions into a single expression
|
||||
// e.g. <div>abc {{ d }} {{ e }}</div> should have a single expression node as child.
|
||||
const transformInterpolation = (node, context) => {
|
||||
if (node.type === compiler_core_1.NodeTypes.ROOT ||
|
||||
node.type === compiler_core_1.NodeTypes.ELEMENT ||
|
||||
node.type === compiler_core_1.NodeTypes.FOR ||
|
||||
node.type === compiler_core_1.NodeTypes.IF_BRANCH) {
|
||||
// perform the transform on node exit so that all expressions have already
|
||||
// been processed.
|
||||
return () => {
|
||||
const children = node.children;
|
||||
let currentContainer = undefined;
|
||||
// let hasText = false
|
||||
for (let i = 0; i < children.length; i++) {
|
||||
const child = children[i];
|
||||
if (isText(child)) {
|
||||
// hasText = true
|
||||
for (let j = i + 1; j < children.length; j++) {
|
||||
const next = children[j];
|
||||
if (isText(next)) {
|
||||
if (!currentContainer) {
|
||||
currentContainer = children[i] = (0, compiler_core_1.createCompoundExpression)([child], child.loc);
|
||||
}
|
||||
// merge adjacent text node into current
|
||||
currentContainer.children.push(` + `, next);
|
||||
children.splice(j, 1);
|
||||
j--;
|
||||
}
|
||||
else {
|
||||
currentContainer = undefined;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// if (
|
||||
// !hasText ||
|
||||
// // if this is a plain element with a single text child, leave it
|
||||
// // as-is since the runtime has dedicated fast path for this by directly
|
||||
// // setting textContent of the element.
|
||||
// // for component root it's always normalized anyway.
|
||||
// (children.length === 1 &&
|
||||
// (node.type === NodeTypes.ROOT ||
|
||||
// (node.type === NodeTypes.ELEMENT &&
|
||||
// node.tagType === ElementTypes.ELEMENT &&
|
||||
// // #3756
|
||||
// // custom directives can potentially add DOM elements arbitrarily,
|
||||
// // we need to avoid setting textContent of the element at runtime
|
||||
// // to avoid accidentally overwriting the DOM elements added
|
||||
// // by the user through custom directives.
|
||||
// !node.props.find(
|
||||
// p =>
|
||||
// p.type === NodeTypes.DIRECTIVE &&
|
||||
// !context.directiveTransforms[p.name]
|
||||
// ) &&
|
||||
// // in compat mode, <template> tags with no special directives
|
||||
// // will be rendered as a fragment so its children must be
|
||||
// // converted into vnodes.
|
||||
// (node.tag !== 'template'))))
|
||||
// ) {
|
||||
// return
|
||||
// }
|
||||
// pre-convert text nodes into createTextVNode(text) calls to avoid
|
||||
// runtime normalization.
|
||||
// for (let i = 0; i < children.length; i++) {
|
||||
// const child = children[i]
|
||||
// if (isText(child) || child.type === NodeTypes.COMPOUND_EXPRESSION) {
|
||||
// const callArgs: CallExpression['arguments'] = []
|
||||
// // createTextVNode defaults to single whitespace, so if it is a
|
||||
// // single space the code could be an empty call to save bytes.
|
||||
// if (child.type !== NodeTypes.TEXT || child.content !== ' ') {
|
||||
// callArgs.push(child)
|
||||
// }
|
||||
// // mark dynamic text with flag so it gets patched inside a block
|
||||
// if (
|
||||
// !context.ssr &&
|
||||
// getConstantType(child, context) === ConstantTypes.NOT_CONSTANT
|
||||
// ) {
|
||||
// callArgs.push(
|
||||
// PatchFlags.TEXT +
|
||||
// (__DEV__ ? ` /* ${PatchFlagNames[PatchFlags.TEXT]} */` : ``)
|
||||
// )
|
||||
// }
|
||||
// children[i] = {
|
||||
// type: NodeTypes.TEXT_CALL,
|
||||
// content: child,
|
||||
// loc: child.loc,
|
||||
// codegenNode: createCallExpression(
|
||||
// context.helper(CREATE_TEXT),
|
||||
// callArgs
|
||||
// )
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
};
|
||||
}
|
||||
};
|
||||
exports.transformInterpolation = transformInterpolation;
|
||||
Generated
Vendored
+2
@@ -0,0 +1,2 @@
|
||||
import type { NodeTransform } from '../transform';
|
||||
export declare const transformObjectExpression: NodeTransform;
|
||||
Generated
Vendored
+53
@@ -0,0 +1,53 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.transformObjectExpression = void 0;
|
||||
const uni_cli_shared_1 = require("@dcloudio/uni-cli-shared");
|
||||
const utils_1 = require("../utils");
|
||||
const compiler_core_1 = require("@vue/compiler-core");
|
||||
const shared_1 = require("@vue/shared");
|
||||
const transformObjectExpression = (node, context) => {
|
||||
// 因为 v-bind without arg 是被 transformElements.ts 直接处理的,没办法在 vBind 中解析处理objectExpression
|
||||
// 所以 统一在这里拦截处理
|
||||
const needTransformAttributes = ['style', 'id', 'class', 'nodes'];
|
||||
return function postTransformObjectExpression() {
|
||||
node = context.currentNode;
|
||||
if (!(0, uni_cli_shared_1.isElementNode)(node)) {
|
||||
return;
|
||||
}
|
||||
node.props.forEach((p) => {
|
||||
if (!(0, uni_cli_shared_1.isDirectiveNode)(p) || !p.exp) {
|
||||
return;
|
||||
}
|
||||
if (p.name === 'bind' && !p.arg) {
|
||||
// v-bind="{key: value}"
|
||||
if (p.exp.type === compiler_core_1.NodeTypes.SIMPLE_EXPRESSION) {
|
||||
if (p.exp.content.startsWith('{') && p.exp.content.endsWith('}')) {
|
||||
p.exp.content = `utsMapOf(${p.exp.content})`;
|
||||
}
|
||||
// v-bind="x"
|
||||
}
|
||||
else if (p.exp.type === compiler_core_1.NodeTypes.COMPOUND_EXPRESSION) {
|
||||
const children = p.exp.children;
|
||||
if (children.length > 1 &&
|
||||
(0, shared_1.isString)(children[0]) &&
|
||||
(0, shared_1.isString)(children[children.length - 1]) &&
|
||||
children[0].startsWith('{') &&
|
||||
children[children.length - 1].endsWith('}')) {
|
||||
children[0] = `utsMapOf(${children[0]}`;
|
||||
children[children.length - 1] = `${children[children.length - 1]})`;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
if ((p.name === 'bind' &&
|
||||
needTransformAttributes.includes(p.arg?.content)) ||
|
||||
p.name === 'on') {
|
||||
const newExp = (0, utils_1.rewriteObjectExpression)(p.exp, context);
|
||||
if (newExp) {
|
||||
p.exp = newExp;
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
};
|
||||
exports.transformObjectExpression = transformObjectExpression;
|
||||
Generated
Vendored
+10
@@ -0,0 +1,10 @@
|
||||
import type { NodeTransform, TransformContext } from '../transform';
|
||||
import { type ExpressionNode, type SlotOutletNode } from '@vue/compiler-core';
|
||||
import type { PropsExpression } from '@vue/compiler-core';
|
||||
export declare const transformSlotOutlet: NodeTransform;
|
||||
interface SlotOutletProcessResult {
|
||||
slotName: string | ExpressionNode;
|
||||
slotProps: PropsExpression | undefined;
|
||||
}
|
||||
export declare function processSlotOutlet(node: SlotOutletNode, context: TransformContext): SlotOutletProcessResult;
|
||||
export {};
|
||||
Generated
Vendored
+82
@@ -0,0 +1,82 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.processSlotOutlet = exports.transformSlotOutlet = void 0;
|
||||
const compiler_core_1 = require("@vue/compiler-core");
|
||||
const compiler_core_2 = require("@vue/compiler-core");
|
||||
const runtimeHelpers_1 = require("../runtimeHelpers");
|
||||
const shared_1 = require("@vue/shared");
|
||||
const transformSlotOutlet = (node, context) => {
|
||||
if ((0, compiler_core_2.isSlotOutlet)(node)) {
|
||||
const { children, loc } = node;
|
||||
const { slotName, slotProps } = processSlotOutlet(node, context);
|
||||
const slotArgs = [
|
||||
context.prefixIdentifiers ? `_ctx.$slots` : `$slots`,
|
||||
slotName,
|
||||
'{}',
|
||||
'undefined',
|
||||
'true',
|
||||
];
|
||||
let expectedLen = 2;
|
||||
if (slotProps) {
|
||||
slotArgs[2] = slotProps;
|
||||
expectedLen = 3;
|
||||
}
|
||||
if (children.length) {
|
||||
let fn = (0, compiler_core_1.createFunctionExpression)([], children, false, false, loc);
|
||||
// @ts-expect-error 补充returnType
|
||||
fn.returnType = `any[]`;
|
||||
slotArgs[3] = fn;
|
||||
expectedLen = 4;
|
||||
}
|
||||
if (context.scopeId && !context.slotted) {
|
||||
expectedLen = 5;
|
||||
}
|
||||
slotArgs.splice(expectedLen) // remove unused arguments
|
||||
;
|
||||
node.codegenNode = (0, compiler_core_1.createCallExpression)(context.helper(runtimeHelpers_1.RENDER_SLOT), slotArgs, loc);
|
||||
}
|
||||
};
|
||||
exports.transformSlotOutlet = transformSlotOutlet;
|
||||
function processSlotOutlet(node, context) {
|
||||
let slotName = `"default"`;
|
||||
let slotProps = undefined;
|
||||
const nonNameProps = [];
|
||||
for (let i = 0; i < node.props.length; i++) {
|
||||
const p = node.props[i];
|
||||
if (p.type === compiler_core_1.NodeTypes.ATTRIBUTE) {
|
||||
if (p.value) {
|
||||
if (p.name === 'name') {
|
||||
slotName = JSON.stringify(p.value.content);
|
||||
}
|
||||
else {
|
||||
p.name = (0, shared_1.camelize)(p.name);
|
||||
nonNameProps.push(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (p.name === 'bind' && (0, compiler_core_2.isStaticArgOf)(p.arg, 'name')) {
|
||||
if (p.exp)
|
||||
slotName = p.exp;
|
||||
}
|
||||
else {
|
||||
if (p.name === 'bind' && p.arg && (0, compiler_core_2.isStaticExp)(p.arg)) {
|
||||
p.arg.content = (0, shared_1.camelize)(p.arg.content);
|
||||
}
|
||||
nonNameProps.push(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (nonNameProps.length > 0) {
|
||||
const { props, directives } = (0, compiler_core_1.buildProps)(node, context, nonNameProps, false, false);
|
||||
slotProps = props;
|
||||
if (directives.length) {
|
||||
context.onError((0, compiler_core_1.createCompilerError)(compiler_core_1.ErrorCodes.X_V_SLOT_UNEXPECTED_DIRECTIVE_ON_SLOT_OUTLET, directives[0].loc));
|
||||
}
|
||||
}
|
||||
return {
|
||||
slotName,
|
||||
slotProps,
|
||||
};
|
||||
}
|
||||
exports.processSlotOutlet = processSlotOutlet;
|
||||
Generated
Vendored
+5
@@ -0,0 +1,5 @@
|
||||
import { type CompoundExpressionNode } from '@vue/compiler-core';
|
||||
import type { CodegenContext } from '../codegen';
|
||||
export declare const SLOT_PROPS_NAME = "slotProps";
|
||||
export declare function isDestructuringSlotProps(isSlot: boolean, params: CompoundExpressionNode): boolean;
|
||||
export declare function createDestructuringSlotProps(params: CompoundExpressionNode, context: CodegenContext): void;
|
||||
Generated
Vendored
+56
@@ -0,0 +1,56 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.createDestructuringSlotProps = exports.isDestructuringSlotProps = exports.SLOT_PROPS_NAME = void 0;
|
||||
const compiler_core_1 = require("@vue/compiler-core");
|
||||
const shared_1 = require("@vue/shared");
|
||||
exports.SLOT_PROPS_NAME = 'slotProps';
|
||||
function isDestructuringSlotProps(isSlot, params) {
|
||||
if (isSlot && params?.children?.length > 2) {
|
||||
const firstParam = params.children[0];
|
||||
const lastParam = params.children[params.children.length - 1];
|
||||
return ((0, shared_1.isString)(firstParam) &&
|
||||
firstParam.startsWith('{') &&
|
||||
(0, shared_1.isString)(lastParam) &&
|
||||
lastParam.endsWith('}'));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
exports.isDestructuringSlotProps = isDestructuringSlotProps;
|
||||
function createDestructuringSlotProps(params, context) {
|
||||
params.children.forEach((child, index) => {
|
||||
if (child.type === compiler_core_1.NodeTypes.SIMPLE_EXPRESSION) {
|
||||
context.newline();
|
||||
const content = child.content;
|
||||
if (isRename(params, index)) {
|
||||
const originKey = getOriginKey(params.children[index - 1]);
|
||||
context.push(`const ${content} = ${exports.SLOT_PROPS_NAME}["${originKey}"]`);
|
||||
}
|
||||
else if (hasDefaultValue(params, index)) {
|
||||
const defaultValue = getDefaultValue(params.children[index + 1]);
|
||||
context.push(`const ${content} = ${exports.SLOT_PROPS_NAME}["${content}"] !== null ? ${exports.SLOT_PROPS_NAME}["${content}"] : ${defaultValue}`);
|
||||
}
|
||||
else {
|
||||
context.push(`const ${content} = ${exports.SLOT_PROPS_NAME}["${content}"]`);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
exports.createDestructuringSlotProps = createDestructuringSlotProps;
|
||||
function isRename(params, index) {
|
||||
const prevChild = params.children[index - 1];
|
||||
return (0, shared_1.isString)(prevChild) && prevChild.trim().endsWith(':');
|
||||
}
|
||||
function getOriginKey(prevChild) {
|
||||
const originKey = prevChild.substring(0, prevChild.indexOf(':')).trim();
|
||||
return originKey.startsWith('{') ? originKey.substring(1).trim() : originKey;
|
||||
}
|
||||
function hasDefaultValue(params, index) {
|
||||
const nextChild = params.children[index + 1];
|
||||
return (0, shared_1.isString)(nextChild) && nextChild.trim().startsWith('=');
|
||||
}
|
||||
function getDefaultValue(nextChild) {
|
||||
const defaultValue = nextChild.trim().substring(1).trim();
|
||||
return defaultValue.endsWith('}')
|
||||
? defaultValue.substring(0, defaultValue.length - 1).trim()
|
||||
: defaultValue;
|
||||
}
|
||||
Generated
Vendored
+2
@@ -0,0 +1,2 @@
|
||||
import type { NodeTransform } from '../transform';
|
||||
export declare const transformStyle: NodeTransform;
|
||||
Generated
Vendored
+74
@@ -0,0 +1,74 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.transformStyle = void 0;
|
||||
const compiler_core_1 = require("@vue/compiler-core");
|
||||
const uni_nvue_styler_1 = require("@dcloudio/uni-nvue-styler");
|
||||
const errors_1 = require("../errors");
|
||||
const shared_1 = require("@vue/shared");
|
||||
// Verify that the template style is in compliance with specifications
|
||||
const transformStyle = (node, context) => {
|
||||
if (node.type === compiler_core_1.NodeTypes.ELEMENT) {
|
||||
node.props.forEach((p, i) => {
|
||||
if (p.type === compiler_core_1.NodeTypes.ATTRIBUTE && p.name === 'style' && p.value) {
|
||||
// 静态 style 编译成对象,减少运行时解析
|
||||
const styleObjectStr = parseStyleString2ObjectString(p.value.content);
|
||||
node.props[i] = createVBindStyleExp(styleObjectStr, p.loc);
|
||||
(0, uni_nvue_styler_1.parse)(p.value.content, {
|
||||
logLevel: 'WARNING',
|
||||
map: true,
|
||||
ts: true,
|
||||
noCode: true,
|
||||
type: 'uvue',
|
||||
platform: process.env.UNI_UTS_PLATFORM,
|
||||
}).then(({ messages }) => {
|
||||
messages.forEach((message) => {
|
||||
const error = (0, errors_1.createCompilerError)(100, p.loc, {
|
||||
100: message.text.replace('ERROR: ', '').replace('WARNING: ', ''),
|
||||
});
|
||||
error.errorType = 'css';
|
||||
context.onWarn(error);
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
exports.transformStyle = transformStyle;
|
||||
function parseStyleString2ObjectString(styleString) {
|
||||
const styleObject = (0, shared_1.parseStringStyle)(styleString);
|
||||
return JSON.stringify(styleObject);
|
||||
}
|
||||
function createVBindStyleExp(styleObjectStr, loc) {
|
||||
return {
|
||||
type: compiler_core_1.NodeTypes.DIRECTIVE,
|
||||
name: 'bind',
|
||||
arg: {
|
||||
type: compiler_core_1.NodeTypes.SIMPLE_EXPRESSION,
|
||||
content: 'style',
|
||||
isStatic: true,
|
||||
constType: 3,
|
||||
loc: {
|
||||
end: loc.end,
|
||||
start: loc.start,
|
||||
source: 'style',
|
||||
},
|
||||
},
|
||||
exp: {
|
||||
constType: 0,
|
||||
content: styleObjectStr,
|
||||
isStatic: false,
|
||||
type: compiler_core_1.NodeTypes.SIMPLE_EXPRESSION,
|
||||
loc: {
|
||||
end: loc.end,
|
||||
start: loc.start,
|
||||
source: styleObjectStr,
|
||||
},
|
||||
},
|
||||
modifiers: [],
|
||||
loc: {
|
||||
end: loc.end,
|
||||
start: loc.start,
|
||||
source: `:style="${styleObjectStr}"`,
|
||||
},
|
||||
};
|
||||
}
|
||||
Generated
Vendored
+2
@@ -0,0 +1,2 @@
|
||||
import type { NodeTransform } from '../transform';
|
||||
export declare const transformText: NodeTransform;
|
||||
Generated
Vendored
+84
@@ -0,0 +1,84 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.transformText = void 0;
|
||||
const uni_cli_shared_1 = require("@dcloudio/uni-cli-shared");
|
||||
const compiler_core_1 = require("@vue/compiler-core");
|
||||
function isTextNode({ tag }) {
|
||||
// TODO 临时解决text节点嵌套的问题
|
||||
return tag === 'text' || tag === 'button';
|
||||
}
|
||||
function isTextElement(node) {
|
||||
return node.type === compiler_core_1.NodeTypes.ELEMENT && node.tag === 'text';
|
||||
}
|
||||
function isText(node) {
|
||||
const { type } = node;
|
||||
return (type === compiler_core_1.NodeTypes.TEXT ||
|
||||
type === compiler_core_1.NodeTypes.TEXT_CALL ||
|
||||
type === compiler_core_1.NodeTypes.INTERPOLATION ||
|
||||
type === compiler_core_1.NodeTypes.COMPOUND_EXPRESSION);
|
||||
}
|
||||
const transformText = (node, _) => {
|
||||
if (!(0, uni_cli_shared_1.isElementNode)(node)) {
|
||||
return;
|
||||
}
|
||||
if (isTextNode(node)) {
|
||||
return;
|
||||
}
|
||||
const { children } = node;
|
||||
if (!children.length) {
|
||||
return;
|
||||
}
|
||||
for (let i = 0; i < children.length; i++) {
|
||||
const child = children[i];
|
||||
if (isTextElement(child)) {
|
||||
parseText(child);
|
||||
}
|
||||
}
|
||||
};
|
||||
exports.transformText = transformText;
|
||||
/*
|
||||
1. 转换 \\n 为 \n
|
||||
2. u-text 下仅支持 slot 及 文本节点
|
||||
*/
|
||||
function parseText(node) {
|
||||
if (node.children.length) {
|
||||
let firstTextChild;
|
||||
for (let i = 0; i < node.children.length; i++) {
|
||||
const child = node.children[i];
|
||||
const content = child.content;
|
||||
if (isText(child) && typeof content === 'string') {
|
||||
if (!firstTextChild) {
|
||||
firstTextChild = child;
|
||||
firstTextChild.content = translateObliqueLine(content);
|
||||
}
|
||||
else {
|
||||
;
|
||||
firstTextChild.content += translateObliqueLine(content);
|
||||
node.children.splice(i, 1);
|
||||
i--;
|
||||
}
|
||||
}
|
||||
else if (child.type === 3) {
|
||||
node.children.splice(i, 1);
|
||||
i--;
|
||||
}
|
||||
else {
|
||||
firstTextChild = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
function translateObliqueLine(content) {
|
||||
const strFragments = content.split('\\n');
|
||||
return strFragments
|
||||
.map((str, index) => {
|
||||
if (index === strFragments.length - 1)
|
||||
return str;
|
||||
str += '\\n';
|
||||
if (!(str.split('\\').length % 2)) {
|
||||
str = str.replaceAll(/\\n/g, '\n');
|
||||
}
|
||||
return str.replaceAll(/\\\\/g, '\\');
|
||||
})
|
||||
.join('');
|
||||
}
|
||||
Generated
Vendored
+2
@@ -0,0 +1,2 @@
|
||||
import type { DirectiveTransform } from '../transform';
|
||||
export declare const transformBind: DirectiveTransform;
|
||||
Generated
Vendored
+69
@@ -0,0 +1,69 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.transformBind = void 0;
|
||||
const shared_1 = require("@vue/shared");
|
||||
const compiler_core_1 = require("@vue/compiler-core");
|
||||
const compiler_core_2 = require("@vue/compiler-core");
|
||||
const errors_1 = require("../errors");
|
||||
// v-bind without arg is handled directly in ./transformElements.ts due to it affecting
|
||||
// codegen for the entire props object. This transform here is only for v-bind
|
||||
// *with* args.
|
||||
const transformBind = (dir, _node, context) => {
|
||||
const { exp, modifiers, loc } = dir;
|
||||
const arg = dir.arg;
|
||||
if (arg.type !== compiler_core_2.NodeTypes.SIMPLE_EXPRESSION) {
|
||||
arg.children.unshift(`(`);
|
||||
arg.children.push(`) || ""`);
|
||||
}
|
||||
else if (!arg.isStatic) {
|
||||
arg.content = `${arg.content} !== null ? ${arg.content} : ""`;
|
||||
}
|
||||
// .sync is replaced by v-model:arg
|
||||
if (modifiers.includes('camel')) {
|
||||
if (arg.type === compiler_core_2.NodeTypes.SIMPLE_EXPRESSION) {
|
||||
if (arg.isStatic) {
|
||||
arg.content = (0, shared_1.camelize)(arg.content);
|
||||
}
|
||||
else {
|
||||
arg.content = `${context.helperString(compiler_core_1.CAMELIZE)}(${arg.content})`;
|
||||
}
|
||||
}
|
||||
else {
|
||||
arg.children.unshift(`${context.helperString(compiler_core_1.CAMELIZE)}(`);
|
||||
arg.children.push(`)`);
|
||||
}
|
||||
}
|
||||
if (!false) {
|
||||
if (modifiers.includes('prop')) {
|
||||
injectPrefix(arg, '.');
|
||||
}
|
||||
if (modifiers.includes('attr')) {
|
||||
injectPrefix(arg, '^');
|
||||
}
|
||||
}
|
||||
if (!exp ||
|
||||
(exp.type === compiler_core_2.NodeTypes.SIMPLE_EXPRESSION && !exp.content.trim())) {
|
||||
context.onError((0, errors_1.createCompilerError)(34 /* ErrorCodes.X_V_BIND_NO_EXPRESSION */, loc));
|
||||
return {
|
||||
props: [(0, compiler_core_2.createObjectProperty)(arg, (0, compiler_core_2.createSimpleExpression)('', true, loc))],
|
||||
};
|
||||
}
|
||||
return {
|
||||
props: [(0, compiler_core_2.createObjectProperty)(arg, exp)],
|
||||
};
|
||||
};
|
||||
exports.transformBind = transformBind;
|
||||
const injectPrefix = (arg, prefix) => {
|
||||
if (arg.type === compiler_core_2.NodeTypes.SIMPLE_EXPRESSION) {
|
||||
if (arg.isStatic) {
|
||||
arg.content = prefix + arg.content;
|
||||
}
|
||||
else {
|
||||
arg.content = `\`${prefix}\${${arg.content}}\``;
|
||||
}
|
||||
}
|
||||
else {
|
||||
arg.children.unshift(`'${prefix}' + (`);
|
||||
arg.children.push(`)`);
|
||||
}
|
||||
};
|
||||
Generated
Vendored
+13
@@ -0,0 +1,13 @@
|
||||
import { type DirectiveNode, type ElementNode, type ExpressionNode, type ForNode, type SimpleExpressionNode } from '@vue/compiler-core';
|
||||
import { type TransformContext } from '../transform';
|
||||
export declare const transformFor: import("../transform").NodeTransform;
|
||||
export declare function processFor(node: ElementNode, dir: DirectiveNode, context: TransformContext, processCodegen?: (forNode: ForNode) => (() => void) | undefined): (() => void) | undefined;
|
||||
export interface ForParseResult {
|
||||
source: ExpressionNode;
|
||||
value: ExpressionNode | undefined;
|
||||
key: ExpressionNode | undefined;
|
||||
index: ExpressionNode | undefined;
|
||||
finalized: boolean;
|
||||
}
|
||||
export declare function parseForExpression(input: SimpleExpressionNode, context: TransformContext): ForParseResult | undefined;
|
||||
export declare function createForLoopParams({ value, key, index }: ForParseResult, memoArgs: ExpressionNode): ExpressionNode[];
|
||||
Generated
Vendored
+321
@@ -0,0 +1,321 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.createForLoopParams = exports.parseForExpression = exports.processFor = exports.transformFor = void 0;
|
||||
const compiler_core_1 = require("@vue/compiler-core");
|
||||
const errors_1 = require("../errors");
|
||||
const compiler_core_2 = require("@vue/compiler-core");
|
||||
const uni_cli_shared_1 = require("@dcloudio/uni-cli-shared");
|
||||
const runtimeHelpers_1 = require("../runtimeHelpers");
|
||||
const transformExpression_1 = require("./transformExpression");
|
||||
// import { validateBrowserExpression } from '../validateExpression'
|
||||
const shared_1 = require("@vue/shared");
|
||||
const transform_1 = require("../transform");
|
||||
const utils_1 = require("../utils");
|
||||
exports.transformFor = (0, transform_1.createStructuralDirectiveTransform)('for', (node, dir, context) => {
|
||||
const { helper, removeHelper } = context;
|
||||
return processFor(node, dir, context, (forNode) => {
|
||||
// create the loop render function expression now, and add the
|
||||
// iterator on exit after all children have been traversed
|
||||
const renderExp = (0, compiler_core_1.createCallExpression)(helper(runtimeHelpers_1.RENDER_LIST), [
|
||||
forNode.source,
|
||||
]);
|
||||
const isTemplate = (0, compiler_core_2.isTemplateNode)(node);
|
||||
const memo = (0, compiler_core_1.findDir)(node, 'memo');
|
||||
const keyProp = (0, compiler_core_2.findProp)(node, `key`);
|
||||
const keyExp = keyProp &&
|
||||
(keyProp.type === compiler_core_1.NodeTypes.ATTRIBUTE
|
||||
? (0, compiler_core_1.createSimpleExpression)(keyProp.value.content, true)
|
||||
: keyProp.exp);
|
||||
const keyProperty = keyProp ? (0, compiler_core_1.createObjectProperty)(`key`, keyExp) : null;
|
||||
// if (!__BROWSER__ && isTemplate) {
|
||||
if (isTemplate) {
|
||||
// #2085 / #5288 process :key and v-memo expressions need to be
|
||||
// processed on `<template v-for>`. In this case the node is discarded
|
||||
// and never traversed so its binding expressions won't be processed
|
||||
// by the normal transforms.
|
||||
if (memo) {
|
||||
memo.exp = (0, transformExpression_1.processExpression)(memo.exp, context);
|
||||
}
|
||||
if (keyProperty && keyProp.type !== compiler_core_1.NodeTypes.ATTRIBUTE) {
|
||||
keyProperty.value = (0, transformExpression_1.processExpression)(keyProperty.value, context);
|
||||
}
|
||||
}
|
||||
const isStableFragment = forNode.source.type === compiler_core_1.NodeTypes.SIMPLE_EXPRESSION &&
|
||||
forNode.source.constType > compiler_core_1.ConstantTypes.NOT_CONSTANT;
|
||||
const fragmentFlag = isStableFragment
|
||||
? shared_1.PatchFlags.STABLE_FRAGMENT
|
||||
: keyProp
|
||||
? shared_1.PatchFlags.KEYED_FRAGMENT
|
||||
: shared_1.PatchFlags.UNKEYED_FRAGMENT;
|
||||
forNode.codegenNode = (0, compiler_core_1.createVNodeCall)(context, helper(runtimeHelpers_1.FRAGMENT), undefined, renderExp, fragmentFlag +
|
||||
// (__DEV__ ? ` /* ${PatchFlagNames[fragmentFlag]} */` : ``),
|
||||
` /* ${shared_1.PatchFlagNames[fragmentFlag]} */`, undefined, undefined, true /* isBlock */, !isStableFragment /* disableTracking */, false /* isComponent */, node.loc);
|
||||
return () => {
|
||||
// finish the codegen now that all children have been traversed
|
||||
let childBlock;
|
||||
const { children } = forNode;
|
||||
// check <template v-for> key placement
|
||||
// if ((__DEV__ || !__BROWSER__) && isTemplate) {
|
||||
if (isTemplate) {
|
||||
node.children.some((c) => {
|
||||
if (c.type === compiler_core_1.NodeTypes.ELEMENT) {
|
||||
const key = (0, compiler_core_2.findProp)(c, 'key');
|
||||
if (key) {
|
||||
context.onError((0, errors_1.createCompilerError)(33 /* ErrorCodes.X_V_FOR_TEMPLATE_KEY_PLACEMENT */, key.loc));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
const needFragmentWrapper = children.length !== 1 || children[0].type !== compiler_core_1.NodeTypes.ELEMENT;
|
||||
const slotOutlet = (0, compiler_core_2.isSlotOutlet)(node)
|
||||
? node
|
||||
: isTemplate &&
|
||||
node.children.length === 1 &&
|
||||
(0, compiler_core_2.isSlotOutlet)(node.children[0])
|
||||
? node.children[0] // api-extractor somehow fails to infer this
|
||||
: null;
|
||||
if (slotOutlet) {
|
||||
// <slot v-for="..."> or <template v-for="..."><slot/></template>
|
||||
childBlock = slotOutlet.codegenNode;
|
||||
if (isTemplate && keyProperty) {
|
||||
// <template v-for="..." :key="..."><slot/></template>
|
||||
// we need to inject the key to the renderSlot() call.
|
||||
// the props for renderSlot is passed as the 3rd argument.
|
||||
(0, compiler_core_2.injectProp)(childBlock, keyProperty, context);
|
||||
}
|
||||
}
|
||||
else if (needFragmentWrapper) {
|
||||
// <template v-for="..."> with text or multi-elements
|
||||
// should generate a fragment block for each loop
|
||||
childBlock = (0, compiler_core_1.createVNodeCall)(context, helper(runtimeHelpers_1.FRAGMENT), keyProperty ? (0, compiler_core_1.createObjectExpression)([keyProperty]) : undefined, node.children, shared_1.PatchFlags.STABLE_FRAGMENT +
|
||||
// (__DEV__
|
||||
// ? ` /* ${PatchFlagNames[PatchFlags.STABLE_FRAGMENT]} */`
|
||||
// : ``),
|
||||
` /* ${shared_1.PatchFlagNames[shared_1.PatchFlags.STABLE_FRAGMENT]} */`, undefined, undefined, true, undefined, false /* isComponent */);
|
||||
}
|
||||
else {
|
||||
// Normal element v-for. Directly use the child's codegenNode
|
||||
// but mark it as a block.
|
||||
childBlock = children[0]
|
||||
.codegenNode;
|
||||
if (isTemplate && keyProperty) {
|
||||
(0, compiler_core_2.injectProp)(childBlock, keyProperty, context);
|
||||
}
|
||||
if (childBlock.isBlock !== !isStableFragment) {
|
||||
if (childBlock.isBlock) {
|
||||
// switch from block to vnode
|
||||
removeHelper(runtimeHelpers_1.OPEN_BLOCK);
|
||||
removeHelper((0, compiler_core_2.getVNodeBlockHelper)(false, childBlock.isComponent));
|
||||
}
|
||||
else {
|
||||
// switch from vnode to block
|
||||
removeHelper((0, compiler_core_2.getVNodeHelper)(false, childBlock.isComponent));
|
||||
}
|
||||
}
|
||||
childBlock.isBlock = !isStableFragment;
|
||||
if (childBlock.isBlock) {
|
||||
helper(runtimeHelpers_1.OPEN_BLOCK);
|
||||
helper((0, compiler_core_2.getVNodeBlockHelper)(false, childBlock.isComponent));
|
||||
}
|
||||
else {
|
||||
helper((0, compiler_core_2.getVNodeHelper)(false, childBlock.isComponent));
|
||||
}
|
||||
}
|
||||
if (memo) {
|
||||
const loop = (0, compiler_core_1.createFunctionExpression)(createForLoopParams(forNode.parseResult, (0, compiler_core_1.createSimpleExpression)(`_cached`)));
|
||||
loop.body = (0, compiler_core_1.createBlockStatement)([
|
||||
(0, compiler_core_1.createCompoundExpression)([
|
||||
`const _memo: Array<any | null> = (`,
|
||||
memo.exp,
|
||||
`)`,
|
||||
]),
|
||||
(0, compiler_core_1.createCompoundExpression)([
|
||||
`if (_cached != null`,
|
||||
...(keyExp ? [` && _cached.key === `, keyExp] : []),
|
||||
` && ${context.helperString(compiler_core_1.IS_MEMO_SAME)}(_cached, _memo)) return _cached`,
|
||||
]),
|
||||
(0, compiler_core_1.createCompoundExpression)([`const _item = `, childBlock]),
|
||||
(0, compiler_core_1.createSimpleExpression)(`_item.memo = _memo`),
|
||||
(0, compiler_core_1.createSimpleExpression)(`return _item`),
|
||||
]);
|
||||
renderExp.arguments.push(loop, (0, compiler_core_1.createSimpleExpression)(`_cache`), (0, compiler_core_1.createSimpleExpression)(String(context.cached++)));
|
||||
}
|
||||
else {
|
||||
renderExp.arguments.push((0, compiler_core_1.createFunctionExpression)(createForLoopParams(forNode.parseResult, (0, compiler_core_1.createSimpleExpression)(`_cached`)), childBlock, true /* force newline */));
|
||||
}
|
||||
};
|
||||
});
|
||||
});
|
||||
// target-agnostic transform used for both Client and SSR
|
||||
function processFor(node, dir, context, processCodegen) {
|
||||
if (!dir.exp) {
|
||||
context.onError((0, errors_1.createCompilerError)(31 /* ErrorCodes.X_V_FOR_NO_EXPRESSION */, dir.loc));
|
||||
return;
|
||||
}
|
||||
const parseResult = parseForExpression(
|
||||
// can only be simple expression because vFor transform is applied
|
||||
// before expression transform.
|
||||
dir.exp, context);
|
||||
if (!parseResult) {
|
||||
context.onError((0, errors_1.createCompilerError)(32 /* ErrorCodes.X_V_FOR_MALFORMED_EXPRESSION */, dir.loc));
|
||||
return;
|
||||
}
|
||||
const { addIdentifiers, removeIdentifiers, scopes } = context;
|
||||
const { source, value, key, index } = parseResult;
|
||||
if (key === undefined) {
|
||||
parseResult.key = {
|
||||
constType: 2,
|
||||
content: '__key',
|
||||
isStatic: false,
|
||||
loc: value?.loc,
|
||||
type: 4,
|
||||
};
|
||||
}
|
||||
if (index === undefined) {
|
||||
parseResult.index = {
|
||||
constType: 2,
|
||||
content: '__index',
|
||||
isStatic: false,
|
||||
loc: value?.loc,
|
||||
type: 4,
|
||||
};
|
||||
}
|
||||
parseResult.finalized = true;
|
||||
const forNode = {
|
||||
type: compiler_core_1.NodeTypes.FOR,
|
||||
loc: dir.loc,
|
||||
source,
|
||||
valueAlias: value,
|
||||
keyAlias: key,
|
||||
objectIndexAlias: index,
|
||||
parseResult,
|
||||
children: (0, compiler_core_2.isTemplateNode)(node) ? node.children : [node],
|
||||
};
|
||||
context.replaceNode(forNode);
|
||||
// bookkeeping
|
||||
scopes.vFor++;
|
||||
// if (!__BROWSER__ && context.prefixIdentifiers) {
|
||||
if (context.prefixIdentifiers) {
|
||||
// scope management
|
||||
// inject identifiers to context
|
||||
value && addIdentifiers(value);
|
||||
key && addIdentifiers(key);
|
||||
index && addIdentifiers(index);
|
||||
}
|
||||
const onExit = processCodegen && processCodegen(forNode);
|
||||
return () => {
|
||||
scopes.vFor--;
|
||||
// if (!__BROWSER__ && context.prefixIdentifiers) {
|
||||
if (context.prefixIdentifiers) {
|
||||
value && removeIdentifiers(value);
|
||||
key && removeIdentifiers(key);
|
||||
index && removeIdentifiers(index);
|
||||
}
|
||||
if (onExit)
|
||||
onExit();
|
||||
};
|
||||
}
|
||||
exports.processFor = processFor;
|
||||
const forAliasRE = /([\s\S]*?)\s+(?:in|of)\s+([\s\S]*)/;
|
||||
// This regex doesn't cover the case if key or index aliases have destructuring,
|
||||
// but those do not make sense in the first place, so this works in practice.
|
||||
const forIteratorRE = /,([^,\}\]]*)(?:,([^,\}\]]*))?$/;
|
||||
const stripParensRE = /^\(|\)$/g;
|
||||
function parseForExpression(input, context) {
|
||||
const loc = input.loc;
|
||||
const exp = input.content;
|
||||
const inMatch = exp.match(forAliasRE);
|
||||
if (!inMatch)
|
||||
return;
|
||||
const [, LHS, RHS] = inMatch;
|
||||
const result = {
|
||||
source: createAliasExpression(loc, RHS.trim(), exp.indexOf(RHS, LHS.length)),
|
||||
value: undefined,
|
||||
key: undefined,
|
||||
index: undefined,
|
||||
finalized: false,
|
||||
};
|
||||
if (!utils_1.__BROWSER__ && context.prefixIdentifiers) {
|
||||
result.source = (0, transformExpression_1.processExpression)(result.source, context);
|
||||
}
|
||||
// if (__DEV__ && __BROWSER__) {
|
||||
// validateBrowserExpression(result.source as SimpleExpressionNode, context)
|
||||
// }
|
||||
let valueContent = LHS.trim().replace(stripParensRE, '').trim();
|
||||
const trimmedOffset = LHS.indexOf(valueContent);
|
||||
const iteratorMatch = valueContent.match(forIteratorRE);
|
||||
if (iteratorMatch) {
|
||||
valueContent = valueContent.replace(forIteratorRE, '').trim();
|
||||
const keyContent = iteratorMatch[1].trim();
|
||||
let keyOffset;
|
||||
if (keyContent) {
|
||||
keyOffset = exp.indexOf(keyContent, trimmedOffset + valueContent.length);
|
||||
result.key = createAliasExpression(loc, keyContent, keyOffset);
|
||||
// if (!__BROWSER__ && context.prefixIdentifiers) {
|
||||
if (context.prefixIdentifiers) {
|
||||
result.key = (0, transformExpression_1.processExpression)(result.key, context, true);
|
||||
}
|
||||
// if (__DEV__ && __BROWSER__) {
|
||||
// validateBrowserExpression(
|
||||
// result.key as SimpleExpressionNode,
|
||||
// context,
|
||||
// true
|
||||
// )
|
||||
// }
|
||||
}
|
||||
if (iteratorMatch[2]) {
|
||||
const indexContent = iteratorMatch[2].trim();
|
||||
if (indexContent) {
|
||||
result.index = createAliasExpression(loc, indexContent, exp.indexOf(indexContent, result.key
|
||||
? keyOffset + keyContent.length
|
||||
: trimmedOffset + valueContent.length));
|
||||
// if (!__BROWSER__ && context.prefixIdentifiers) {
|
||||
if (context.prefixIdentifiers) {
|
||||
result.index = (0, transformExpression_1.processExpression)(result.index, context, true);
|
||||
}
|
||||
// if (__DEV__ && __BROWSER__) {
|
||||
// validateBrowserExpression(
|
||||
// result.index as SimpleExpressionNode,
|
||||
// context,
|
||||
// true
|
||||
// )
|
||||
// }
|
||||
}
|
||||
}
|
||||
}
|
||||
if (valueContent) {
|
||||
result.value = createAliasExpression(loc, valueContent, trimmedOffset);
|
||||
// if (!__BROWSER__ && context.prefixIdentifiers) {
|
||||
if (context.prefixIdentifiers) {
|
||||
result.value = (0, transformExpression_1.processExpression)(result.value, context, true);
|
||||
}
|
||||
// if (__DEV__ && __BROWSER__) {
|
||||
// validateBrowserExpression(
|
||||
// result.value as SimpleExpressionNode,
|
||||
// context,
|
||||
// true
|
||||
// )
|
||||
// }
|
||||
}
|
||||
return result;
|
||||
}
|
||||
exports.parseForExpression = parseForExpression;
|
||||
function createAliasExpression(range, content, offset) {
|
||||
return (0, compiler_core_1.createSimpleExpression)(content, false, (0, uni_cli_shared_1.getInnerRange)(range, offset, content.length));
|
||||
}
|
||||
function createForLoopParams({ value, key, index }, memoArgs) {
|
||||
return createParamsList([value, key, index, memoArgs]);
|
||||
}
|
||||
exports.createForLoopParams = createForLoopParams;
|
||||
const paramNames = ['__value', '__key', '__item', '_cached'];
|
||||
function createParamsList(args) {
|
||||
let i = args.length;
|
||||
while (i--) {
|
||||
if (args[i])
|
||||
break;
|
||||
}
|
||||
return args
|
||||
.slice(0, i + 1)
|
||||
.map((arg, i) => arg || (0, compiler_core_1.createSimpleExpression)(paramNames[i], false));
|
||||
}
|
||||
Generated
Vendored
+2
@@ -0,0 +1,2 @@
|
||||
import { type NodeTransform } from '@vue/compiler-core';
|
||||
export declare const transformVHtml: NodeTransform;
|
||||
Generated
Vendored
+45
@@ -0,0 +1,45 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.transformVHtml = void 0;
|
||||
const compiler_core_1 = require("@vue/compiler-core");
|
||||
const errors_1 = require("../errors");
|
||||
const uni_cli_shared_1 = require("@dcloudio/uni-cli-shared");
|
||||
const transformVHtml = (node, context) => {
|
||||
if (node.tagType !== compiler_core_1.ElementTypes.ELEMENT) {
|
||||
return;
|
||||
}
|
||||
// check whether bind v-html
|
||||
if (node.props?.length) {
|
||||
;
|
||||
node.props.forEach((prop, index) => {
|
||||
if (prop.name === 'html' && prop.loc.source.startsWith('v-html=')) {
|
||||
if (!prop.exp ||
|
||||
!prop.exp?.content.trim()) {
|
||||
context.onError((0, errors_1.createDOMCompilerError)(53 /* ErrorCodes.X_V_HTML_NO_EXPRESSION */, prop.loc));
|
||||
}
|
||||
if (node.children.length) {
|
||||
context.onError((0, errors_1.createDOMCompilerError)(54 /* ErrorCodes.X_V_HTML_WITH_CHILDREN */, prop.loc));
|
||||
}
|
||||
;
|
||||
node.children = [
|
||||
createRichText(node, prop),
|
||||
];
|
||||
node.props.splice(index, 1);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
exports.transformVHtml = transformVHtml;
|
||||
function createRichText(node, prop) {
|
||||
return {
|
||||
tag: 'rich-text',
|
||||
type: compiler_core_1.NodeTypes.ELEMENT,
|
||||
tagType: compiler_core_1.ElementTypes.ELEMENT,
|
||||
props: [(0, uni_cli_shared_1.createBindDirectiveNode)('nodes', prop.exp || '')],
|
||||
isSelfClosing: true,
|
||||
children: [],
|
||||
codegenNode: undefined,
|
||||
ns: node.ns,
|
||||
loc: node.loc,
|
||||
};
|
||||
}
|
||||
Generated
Vendored
+4
@@ -0,0 +1,4 @@
|
||||
import { type DirectiveNode, type ElementNode, type IfBranchNode, type IfNode } from '@vue/compiler-core';
|
||||
import { type TransformContext } from '../transform';
|
||||
export declare const transformIf: import("../transform").NodeTransform;
|
||||
export declare function processIf(node: ElementNode, dir: DirectiveNode, context: TransformContext, processCodegen?: (node: IfNode, branch: IfBranchNode, isRoot: boolean) => (() => void) | undefined): (() => void) | undefined;
|
||||
TongjiUniApp/node_modules/@dcloudio/uni-app-uts/dist/plugins/android/uvue/compiler/transforms/vIf.js
Generated
Vendored
+212
@@ -0,0 +1,212 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.processIf = exports.transformIf = void 0;
|
||||
const shared_1 = require("@vue/shared");
|
||||
const compiler_core_1 = require("@vue/compiler-core");
|
||||
const transform_1 = require("../transform");
|
||||
const errors_1 = require("../errors");
|
||||
const transformExpression_1 = require("./transformExpression");
|
||||
exports.transformIf = (0, transform_1.createStructuralDirectiveTransform)(/^(if|else|else-if)$/, (node, dir, context) => {
|
||||
return processIf(node, dir, context, (ifNode, branch, isRoot) => {
|
||||
// #1587: We need to dynamically increment the key based on the current
|
||||
// node's sibling nodes, since chained v-if/else branches are
|
||||
// rendered at the same depth
|
||||
const siblings = context.parent.children;
|
||||
let i = siblings.indexOf(ifNode);
|
||||
let key = 0;
|
||||
while (i-- >= 0) {
|
||||
const sibling = siblings[i];
|
||||
if (sibling && sibling.type === compiler_core_1.NodeTypes.IF) {
|
||||
key += sibling.branches.length;
|
||||
}
|
||||
}
|
||||
// Exit callback. Complete the codegenNode when all children have been
|
||||
// transformed.
|
||||
return () => {
|
||||
if (isRoot) {
|
||||
ifNode.codegenNode = createCodegenNodeForBranch(branch, key, context);
|
||||
}
|
||||
else {
|
||||
// attach this branch's codegen node to the v-if root.
|
||||
const parentCondition = getParentCondition(ifNode.codegenNode);
|
||||
parentCondition.alternate = createCodegenNodeForBranch(branch, key + ifNode.branches.length - 1, context);
|
||||
}
|
||||
};
|
||||
});
|
||||
});
|
||||
// target-agnostic transform used for both Client and SSR
|
||||
function processIf(node, dir, context, processCodegen) {
|
||||
if (dir.name !== 'else' &&
|
||||
(!dir.exp || !dir.exp.content.trim())) {
|
||||
const loc = dir.exp ? dir.exp.loc : node.loc;
|
||||
context.onError((0, errors_1.createCompilerError)(28 /* ErrorCodes.X_V_IF_NO_EXPRESSION */, dir.loc));
|
||||
dir.exp = (0, compiler_core_1.createSimpleExpression)(`true`, false, loc);
|
||||
}
|
||||
if (context.prefixIdentifiers && dir.exp) {
|
||||
// dir.exp can only be simple expression because vIf transform is applied
|
||||
// before expression transform.
|
||||
dir.exp = (0, transformExpression_1.processExpression)(dir.exp, context);
|
||||
}
|
||||
if (dir.name === 'if') {
|
||||
const branch = createIfBranch(node, dir);
|
||||
const ifNode = {
|
||||
type: compiler_core_1.NodeTypes.IF,
|
||||
loc: node.loc,
|
||||
branches: [branch],
|
||||
};
|
||||
context.replaceNode(ifNode);
|
||||
if (processCodegen) {
|
||||
return processCodegen(ifNode, branch, true);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// locate the adjacent v-if
|
||||
const siblings = context.parent.children;
|
||||
let i = siblings.indexOf(node);
|
||||
while (i-- >= -1) {
|
||||
const sibling = siblings[i];
|
||||
if (sibling && sibling.type === compiler_core_1.NodeTypes.COMMENT) {
|
||||
context.removeNode(sibling);
|
||||
continue;
|
||||
}
|
||||
if (sibling &&
|
||||
((sibling.type === compiler_core_1.NodeTypes.TEXT && !sibling.content.trim().length) ||
|
||||
// handle tag text but type = NodeTypes.ELEMENT
|
||||
(sibling.type === compiler_core_1.NodeTypes.ELEMENT &&
|
||||
sibling.tag === 'text' &&
|
||||
!sibling.children[0].content.trim().length))) {
|
||||
context.removeNode(sibling);
|
||||
continue;
|
||||
}
|
||||
if (sibling && sibling.type === compiler_core_1.NodeTypes.IF) {
|
||||
// Check if v-else was followed by v-else-if
|
||||
if (dir.name === 'else-if' &&
|
||||
sibling.branches[sibling.branches.length - 1].condition === undefined) {
|
||||
context.onError((0, errors_1.createCompilerError)(30 /* ErrorCodes.X_V_ELSE_NO_ADJACENT_IF */, node.loc));
|
||||
}
|
||||
// move the node to the if node's branches
|
||||
context.removeNode();
|
||||
const branch = createIfBranch(node, dir);
|
||||
// check if user is forcing same key on different branches
|
||||
const key = branch.userKey;
|
||||
if (key) {
|
||||
sibling.branches.forEach(({ userKey }) => {
|
||||
if (isSameKey(userKey, key)) {
|
||||
context.onError((0, errors_1.createCompilerError)(29 /* ErrorCodes.X_V_IF_SAME_KEY */, branch.userKey.loc));
|
||||
}
|
||||
});
|
||||
}
|
||||
sibling.branches.push(branch);
|
||||
const onExit = processCodegen && processCodegen(sibling, branch, false);
|
||||
// since the branch was removed, it will not be traversed.
|
||||
// make sure to traverse here.
|
||||
(0, transform_1.traverseNode)(branch, context);
|
||||
// call on exit
|
||||
if (onExit)
|
||||
onExit();
|
||||
// make sure to reset currentNode after traversal to indicate this
|
||||
// node has been removed.
|
||||
context.currentNode = null;
|
||||
}
|
||||
else {
|
||||
context.onError((0, errors_1.createCompilerError)(30 /* ErrorCodes.X_V_ELSE_NO_ADJACENT_IF */, node.loc));
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
exports.processIf = processIf;
|
||||
function createIfBranch(node, dir) {
|
||||
const isTemplateIf = node.tagType === compiler_core_1.ElementTypes.TEMPLATE;
|
||||
return {
|
||||
type: compiler_core_1.NodeTypes.IF_BRANCH,
|
||||
loc: node.loc,
|
||||
condition: dir.name === 'else' ? undefined : dir.exp,
|
||||
children: isTemplateIf && !(0, compiler_core_1.findDir)(node, 'for') ? node.children : [node],
|
||||
userKey: (0, compiler_core_1.findProp)(node, `key`),
|
||||
isTemplateIf,
|
||||
};
|
||||
}
|
||||
function createCodegenNodeForBranch(branch, keyIndex, context) {
|
||||
if (branch.condition) {
|
||||
return (0, compiler_core_1.createConditionalExpression)(branch.condition, createChildrenCodegenNode(branch, keyIndex, context),
|
||||
// make sure to pass in asBlock: true so that the comment node call
|
||||
// closes the current block.
|
||||
(0, compiler_core_1.createCallExpression)(context.helper(compiler_core_1.CREATE_COMMENT), ['"v-if"', 'true']));
|
||||
}
|
||||
else {
|
||||
return createChildrenCodegenNode(branch, keyIndex, context);
|
||||
}
|
||||
}
|
||||
function createChildrenCodegenNode(branch, keyIndex, context) {
|
||||
const { helper } = context;
|
||||
const keyProperty = (0, compiler_core_1.createObjectProperty)(`key`, (0, compiler_core_1.createSimpleExpression)(`${keyIndex}`, false, compiler_core_1.locStub, compiler_core_1.ConstantTypes.CAN_HOIST));
|
||||
const { children } = branch;
|
||||
const firstChild = children[0];
|
||||
const needFragmentWrapper = children.length !== 1 || firstChild.type !== compiler_core_1.NodeTypes.ELEMENT;
|
||||
if (needFragmentWrapper) {
|
||||
if (children.length === 1 && firstChild.type === compiler_core_1.NodeTypes.FOR) {
|
||||
// optimize away nested fragments when child is a ForNode
|
||||
const vnodeCall = firstChild.codegenNode;
|
||||
(0, compiler_core_1.injectProp)(vnodeCall, keyProperty, context);
|
||||
return vnodeCall;
|
||||
}
|
||||
else {
|
||||
let patchFlag = shared_1.PatchFlags.STABLE_FRAGMENT;
|
||||
let patchFlagText = shared_1.PatchFlagNames[shared_1.PatchFlags.STABLE_FRAGMENT];
|
||||
// check if the fragment actually contains a single valid child with
|
||||
// the rest being comments
|
||||
return (0, compiler_core_1.createVNodeCall)(context, helper(compiler_core_1.FRAGMENT), (0, compiler_core_1.createObjectExpression)([keyProperty]), children, patchFlag + ` /* ${patchFlagText} */`, undefined, undefined, true, false, false /* isComponent */, branch.loc);
|
||||
}
|
||||
}
|
||||
else {
|
||||
const ret = firstChild.codegenNode;
|
||||
const vnodeCall = (0, compiler_core_1.getMemoedVNodeCall)(ret);
|
||||
// Change createVNode to createBlock.
|
||||
if (vnodeCall.type === compiler_core_1.NodeTypes.VNODE_CALL) {
|
||||
(0, compiler_core_1.convertToBlock)(vnodeCall, context);
|
||||
}
|
||||
// inject branch key
|
||||
(0, compiler_core_1.injectProp)(vnodeCall, keyProperty, context);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
function isSameKey(a, b) {
|
||||
if (!a || a.type !== b.type) {
|
||||
return false;
|
||||
}
|
||||
if (a.type === compiler_core_1.NodeTypes.ATTRIBUTE) {
|
||||
if (a.value.content !== b.value.content) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// directive
|
||||
const exp = a.exp;
|
||||
const branchExp = b.exp;
|
||||
if (exp.type !== branchExp.type) {
|
||||
return false;
|
||||
}
|
||||
if (exp.type !== compiler_core_1.NodeTypes.SIMPLE_EXPRESSION ||
|
||||
exp.isStatic !== branchExp.isStatic ||
|
||||
exp.content !== branchExp.content) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
function getParentCondition(node) {
|
||||
while (true) {
|
||||
if (node.type === compiler_core_1.NodeTypes.JS_CONDITIONAL_EXPRESSION) {
|
||||
if (node.alternate.type === compiler_core_1.NodeTypes.JS_CONDITIONAL_EXPRESSION) {
|
||||
node = node.alternate;
|
||||
}
|
||||
else {
|
||||
return node;
|
||||
}
|
||||
}
|
||||
else if (node.type === compiler_core_1.NodeTypes.JS_CACHE_EXPRESSION) {
|
||||
node = node.value;
|
||||
}
|
||||
}
|
||||
}
|
||||
Generated
Vendored
+4
@@ -0,0 +1,4 @@
|
||||
import { type FunctionExpression, type SourceLocation } from '@vue/compiler-core';
|
||||
import type { NodeTransform } from '../transform';
|
||||
export declare const transformMemo: NodeTransform;
|
||||
export declare function createFunctionExpression(params: FunctionExpression['params'], returns?: FunctionExpression['returns'], newline?: boolean, isSlot?: boolean, loc?: SourceLocation): FunctionExpression;
|
||||
Generated
Vendored
+44
@@ -0,0 +1,44 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.createFunctionExpression = exports.transformMemo = void 0;
|
||||
const compiler_core_1 = require("@vue/compiler-core");
|
||||
const seen = new WeakSet();
|
||||
const transformMemo = (node, context) => {
|
||||
if (node.type === compiler_core_1.NodeTypes.ELEMENT) {
|
||||
const dir = (0, compiler_core_1.findDir)(node, 'memo');
|
||||
if (!dir || seen.has(node)) {
|
||||
return;
|
||||
}
|
||||
seen.add(node);
|
||||
return () => {
|
||||
const codegenNode = node.codegenNode ||
|
||||
context.currentNode.codegenNode;
|
||||
if (codegenNode && codegenNode.type === compiler_core_1.NodeTypes.VNODE_CALL) {
|
||||
// non-component sub tree should be turned into a block
|
||||
if (node.tagType !== compiler_core_1.ElementTypes.COMPONENT) {
|
||||
(0, compiler_core_1.convertToBlock)(codegenNode, context);
|
||||
}
|
||||
const fn = createFunctionExpression(undefined, codegenNode);
|
||||
fn.returnType = 'VNode';
|
||||
node.codegenNode = (0, compiler_core_1.createCallExpression)(context.helper(compiler_core_1.WITH_MEMO), [
|
||||
dir.exp,
|
||||
fn,
|
||||
`_cache`,
|
||||
String(context.cached++),
|
||||
]);
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
exports.transformMemo = transformMemo;
|
||||
function createFunctionExpression(params, returns = undefined, newline = false, isSlot = false, loc = compiler_core_1.locStub) {
|
||||
return {
|
||||
type: compiler_core_1.NodeTypes.JS_FUNCTION_EXPRESSION,
|
||||
params,
|
||||
returns,
|
||||
newline,
|
||||
isSlot,
|
||||
loc,
|
||||
};
|
||||
}
|
||||
exports.createFunctionExpression = createFunctionExpression;
|
||||
Generated
Vendored
+2
@@ -0,0 +1,2 @@
|
||||
import type { DirectiveTransform } from '../transform';
|
||||
export declare const transformModel: DirectiveTransform;
|
||||
Generated
Vendored
+170
@@ -0,0 +1,170 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.transformModel = void 0;
|
||||
const shared_1 = require("@vue/shared");
|
||||
const compiler_core_1 = require("@vue/compiler-core");
|
||||
const transformExpression_1 = require("./transformExpression");
|
||||
const estree_walker_1 = require("estree-walker");
|
||||
const parser_1 = require("@babel/parser");
|
||||
const uni_cli_shared_1 = require("@dcloudio/uni-cli-shared");
|
||||
const errors_1 = require("../errors");
|
||||
const runtimeHelpers_1 = require("../runtimeHelpers");
|
||||
const INPUT_TAGS = ['input', 'textarea'];
|
||||
const AS = ' as ';
|
||||
const transformModel = (dir, node, context) => {
|
||||
// 组件 v-model 绑定了复杂表达式,且没有手动 as 类型
|
||||
if (node.tagType === compiler_core_1.ElementTypes.COMPONENT &&
|
||||
dir.exp?.children?.length > 1 &&
|
||||
!dir.loc.source.includes(AS)) {
|
||||
context.onError((0, errors_1.createCompilerError)(100, dir.loc, {
|
||||
100: `When custom components use "v-model" to bind complex expressions, you must specify the type using "as", 详见:https://uniapp.dcloud.net.cn/uni-app-x/component/#v-model-complex-expression`,
|
||||
}));
|
||||
}
|
||||
const { exp, arg } = dir;
|
||||
if (!exp) {
|
||||
context.onError((0, errors_1.createCompilerError)(41 /* ErrorCodes.X_V_MODEL_NO_EXPRESSION */, dir.loc));
|
||||
return createTransformProps();
|
||||
}
|
||||
let rawExp = exp.loc.source;
|
||||
let expType = '';
|
||||
if ((0, uni_cli_shared_1.isCompoundExpressionNode)(exp)) {
|
||||
if (rawExp.includes(AS)) {
|
||||
// 目前简单处理(a as string)
|
||||
if (rawExp.startsWith('(') && rawExp.endsWith(')')) {
|
||||
rawExp = rawExp.slice(1, -1);
|
||||
}
|
||||
const parts = rawExp.split(AS);
|
||||
rawExp = parts[0].trim();
|
||||
expType = parts[1].trim();
|
||||
const source = (0, transformExpression_1.stringifyExpression)(exp);
|
||||
const ast = (0, parser_1.parseExpression)(source, {
|
||||
plugins: context.expressionPlugins,
|
||||
});
|
||||
let str = '';
|
||||
(0, estree_walker_1.walk)(ast, {
|
||||
enter(node) {
|
||||
if (node.type === 'TSAsExpression') {
|
||||
str = source.slice(node.expression.start, node.expression.end);
|
||||
}
|
||||
},
|
||||
});
|
||||
exp.children = [(0, compiler_core_1.createSimpleExpression)(str)];
|
||||
}
|
||||
}
|
||||
const expString = exp.type === compiler_core_1.NodeTypes.SIMPLE_EXPRESSION ? exp.content : rawExp;
|
||||
// im SFC <script setup> inline mode, the exp may have been transformed into
|
||||
// _unref(exp)
|
||||
const bindingType = context.bindingMetadata[rawExp];
|
||||
// check props
|
||||
if (bindingType === compiler_core_1.BindingTypes.PROPS ||
|
||||
bindingType === compiler_core_1.BindingTypes.PROPS_ALIASED) {
|
||||
context.onError((0, errors_1.createCompilerError)(44 /* ErrorCodes.X_V_MODEL_ON_PROPS */, exp.loc));
|
||||
return createTransformProps();
|
||||
}
|
||||
const maybeRef = context.inline &&
|
||||
(bindingType === compiler_core_1.BindingTypes.SETUP_LET ||
|
||||
bindingType === compiler_core_1.BindingTypes.SETUP_REF ||
|
||||
bindingType === compiler_core_1.BindingTypes.SETUP_MAYBE_REF);
|
||||
if (!expString.trim() ||
|
||||
(!(0, compiler_core_1.isMemberExpression)(expString, context) && !maybeRef)) {
|
||||
context.onError((0, errors_1.createCompilerError)(42 /* ErrorCodes.X_V_MODEL_MALFORMED_EXPRESSION */, exp.loc));
|
||||
return createTransformProps();
|
||||
}
|
||||
if (context.prefixIdentifiers &&
|
||||
(0, compiler_core_1.isSimpleIdentifier)(expString) &&
|
||||
context.identifiers[expString]) {
|
||||
context.onError((0, errors_1.createCompilerError)(43 /* ErrorCodes.X_V_MODEL_ON_SCOPE_VARIABLE */, exp.loc));
|
||||
return createTransformProps();
|
||||
}
|
||||
const isInputElement = INPUT_TAGS.includes(node.tag);
|
||||
const propName = arg ? arg : (0, compiler_core_1.createSimpleExpression)('modelValue', true);
|
||||
let eventName = arg
|
||||
? (0, compiler_core_1.isStaticExp)(arg)
|
||||
? `onUpdate:${(0, shared_1.camelize)(arg.content)}`
|
||||
: (0, compiler_core_1.createCompoundExpression)(['"onUpdate:" + ', arg])
|
||||
: `onUpdate:modelValue`;
|
||||
if (isInputElement && eventName === 'onUpdate:modelValue') {
|
||||
eventName = getEventName(dir);
|
||||
}
|
||||
const eventType = isInputElement ? getEventParamsType(dir) : expType;
|
||||
let eventValue = isInputElement ? `$event.detail.value` : `$event`;
|
||||
if (withTrim(dir)) {
|
||||
eventValue = `${eventValue}.trim()`;
|
||||
}
|
||||
if (withNumber(dir)) {
|
||||
eventValue = `${context.helperString(runtimeHelpers_1.LOOSE_TO_NUMBER)}(${eventValue})`;
|
||||
}
|
||||
let assignmentExp;
|
||||
const eventArg = eventType ? `($event: ${eventType})` : `$event`;
|
||||
if (maybeRef) {
|
||||
if (bindingType === compiler_core_1.BindingTypes.SETUP_REF) {
|
||||
// v-model used on known ref.
|
||||
assignmentExp = (0, compiler_core_1.createCompoundExpression)([
|
||||
`${eventArg} => {(`,
|
||||
(0, compiler_core_1.createSimpleExpression)(rawExp, false, exp.loc),
|
||||
`).value = ${eventValue}}`,
|
||||
]);
|
||||
}
|
||||
else {
|
||||
// v-model used on a potentially ref binding in <script setup> inline mode.
|
||||
// the assignment needs to check whether the binding is actually a ref.
|
||||
// 如果是 const 仅设置值:trySetRefValue(innerValue, `$event`.detail.value)
|
||||
// 如果是 let 需要执行赋值动作 innerValue = trySetRefValue(innerValue, `$event`.detail.value)
|
||||
assignmentExp = (0, compiler_core_1.createCompoundExpression)([
|
||||
`${eventArg} => {${bindingType === compiler_core_1.BindingTypes.SETUP_LET ? `${rawExp} = ` : ''}${context.helperString(runtimeHelpers_1.TRY_SET_REF_VALUE)}(${rawExp}, ${eventValue})}`,
|
||||
]);
|
||||
}
|
||||
}
|
||||
else {
|
||||
assignmentExp = (0, compiler_core_1.createCompoundExpression)([
|
||||
`${eventArg} => {(`,
|
||||
exp,
|
||||
`) = ${eventValue}}`,
|
||||
]);
|
||||
}
|
||||
const props = [
|
||||
// modelValue: foo
|
||||
(0, compiler_core_1.createObjectProperty)(propName, exp),
|
||||
// "onUpdate:modelValue": $event => (foo = $event)
|
||||
(0, compiler_core_1.createObjectProperty)(eventName, assignmentExp),
|
||||
];
|
||||
// cache v-model handler if applicable (when it doesn't refer any scope vars)
|
||||
if (context.prefixIdentifiers &&
|
||||
!context.inVOnce &&
|
||||
context.cacheHandlers &&
|
||||
!(0, compiler_core_1.hasScopeRef)(exp, context.identifiers)) {
|
||||
props[1].value = context.cache(props[1].value);
|
||||
}
|
||||
// modelModifiers: { foo: true, "bar-baz": true }
|
||||
if (dir.modifiers.length && node.tagType === compiler_core_1.ElementTypes.COMPONENT) {
|
||||
const modifiers = dir.modifiers
|
||||
.map((m) => ((0, compiler_core_1.isSimpleIdentifier)(m) ? m : JSON.stringify(m)) + `: true`)
|
||||
.join(`, `);
|
||||
const modifiersKey = arg
|
||||
? (0, compiler_core_1.isStaticExp)(arg)
|
||||
? `${arg.content}Modifiers`
|
||||
: (0, compiler_core_1.createCompoundExpression)([arg, ' + "Modifiers"'])
|
||||
: `modelModifiers`;
|
||||
props.push((0, compiler_core_1.createObjectProperty)(modifiersKey, (0, compiler_core_1.createSimpleExpression)(`{ ${modifiers} }`, false, dir.loc, compiler_core_1.ConstantTypes.CAN_HOIST)));
|
||||
}
|
||||
return createTransformProps(props);
|
||||
};
|
||||
exports.transformModel = transformModel;
|
||||
function createTransformProps(props = []) {
|
||||
return { props };
|
||||
}
|
||||
function getEventName(dir) {
|
||||
return withLazy(dir) ? 'onBlur' : 'onInput';
|
||||
}
|
||||
function getEventParamsType(dir) {
|
||||
return withLazy(dir) ? 'InputBlurEvent' : 'InputEvent';
|
||||
}
|
||||
function withLazy(dir) {
|
||||
return dir.modifiers.includes('lazy');
|
||||
}
|
||||
function withNumber(dir) {
|
||||
return dir.modifiers.includes('number');
|
||||
}
|
||||
function withTrim(dir) {
|
||||
return dir.modifiers.includes('trim');
|
||||
}
|
||||
Generated
Vendored
+7
@@ -0,0 +1,7 @@
|
||||
import type { DirectiveTransform } from '../transform';
|
||||
import { type DirectiveNode, type ExpressionNode, type SimpleExpressionNode } from '@vue/compiler-core';
|
||||
export interface VOnDirectiveNode extends DirectiveNode {
|
||||
arg: ExpressionNode;
|
||||
exp: SimpleExpressionNode | undefined;
|
||||
}
|
||||
export declare const transformOn: DirectiveTransform;
|
||||
TongjiUniApp/node_modules/@dcloudio/uni-app-uts/dist/plugins/android/uvue/compiler/transforms/vOn.js
Generated
Vendored
+129
@@ -0,0 +1,129 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.transformOn = void 0;
|
||||
const compiler_core_1 = require("@vue/compiler-core");
|
||||
const shared_1 = require("@vue/shared");
|
||||
const errors_1 = require("../errors");
|
||||
const transformExpression_1 = require("./transformExpression");
|
||||
const fnExpRE = /^\s*([\w$_]+|(async\s*)?\([^)]*?\))\s*(:[^=]+)?=>|^\s*(async\s+)?function(?:\s+[\w$]+)?\s*\(/;
|
||||
// TODO: inline statement $event type complement
|
||||
const transformOn = (dir, node, context, augmentor) => {
|
||||
const { loc, modifiers, arg } = dir;
|
||||
if (!dir.exp && !modifiers.length) {
|
||||
context.onError((0, errors_1.createCompilerError)(35 /* ErrorCodes.X_V_ON_NO_EXPRESSION */, loc));
|
||||
}
|
||||
let eventName;
|
||||
if (arg.type === compiler_core_1.NodeTypes.SIMPLE_EXPRESSION) {
|
||||
if (arg.isStatic) {
|
||||
let rawName = arg.content;
|
||||
// TODO deprecate @vnodeXXX usage
|
||||
if (rawName.startsWith('vue:')) {
|
||||
rawName = `vnode-${rawName.slice(4)}`;
|
||||
}
|
||||
const eventString = node.tagType !== compiler_core_1.ElementTypes.ELEMENT ||
|
||||
rawName.startsWith('vnode') ||
|
||||
!/[A-Z]/.test(rawName)
|
||||
? // for non-element and vnode lifecycle event listeners, auto convert
|
||||
// it to camelCase. See issue #2249
|
||||
(0, shared_1.toHandlerKey)((0, shared_1.camelize)(rawName))
|
||||
: // preserve case for plain element listeners that have uppercase
|
||||
// letters, as these may be custom elements' custom events
|
||||
`on:${rawName}`;
|
||||
eventName = (0, compiler_core_1.createSimpleExpression)(eventString, true, arg.loc);
|
||||
}
|
||||
else {
|
||||
// #2388
|
||||
eventName = (0, compiler_core_1.createCompoundExpression)([
|
||||
`${context.helperString(compiler_core_1.TO_HANDLER_KEY)}(`,
|
||||
arg,
|
||||
`)`,
|
||||
]);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// already a compound expression.
|
||||
eventName = arg;
|
||||
eventName.children.unshift(`${context.helperString(compiler_core_1.TO_HANDLER_KEY)}(`);
|
||||
eventName.children.push(`)`);
|
||||
}
|
||||
// handler processing
|
||||
let exp = dir.exp;
|
||||
if (exp && !exp.content.trim()) {
|
||||
exp = undefined;
|
||||
}
|
||||
let shouldCache = context.cacheHandlers && !exp && !context.inVOnce;
|
||||
if (exp) {
|
||||
// @ts-expect-error
|
||||
const isMemberExp = (0, compiler_core_1.isMemberExpression)(exp.content, context);
|
||||
const isInlineStatement = !(isMemberExp || fnExpRE.test(exp.content));
|
||||
const hasMultipleStatements = exp.content.includes(`;`);
|
||||
// process the expression since it's been skipped
|
||||
if (context.prefixIdentifiers) {
|
||||
isInlineStatement && context.addIdentifiers(`$event`);
|
||||
exp = dir.exp = (0, transformExpression_1.processExpression)(exp, context, false, hasMultipleStatements);
|
||||
isInlineStatement && context.removeIdentifiers(`$event`);
|
||||
// with scope analysis, the function is hoistable if it has no reference
|
||||
// to scope variables.
|
||||
shouldCache =
|
||||
context.cacheHandlers &&
|
||||
// unnecessary to cache inside v-once
|
||||
!context.inVOnce &&
|
||||
// runtime constants don't need to be cached
|
||||
// (this is analyzed by compileScript in SFC <script setup>)
|
||||
!(exp.type === compiler_core_1.NodeTypes.SIMPLE_EXPRESSION && exp.constType > 0) &&
|
||||
// #1541 bail if this is a member exp handler passed to a component -
|
||||
// we need to use the original function to preserve arity,
|
||||
// e.g. <transition> relies on checking cb.length to determine
|
||||
// transition end handling. Inline function is ok since its arity
|
||||
// is preserved even when cached.
|
||||
!(isMemberExp && node.tagType === compiler_core_1.ElementTypes.COMPONENT) &&
|
||||
// bail if the function references closure variables (v-for, v-slot)
|
||||
// it must be passed fresh to avoid stale values.
|
||||
!(0, compiler_core_1.hasScopeRef)(exp, context.identifiers);
|
||||
// If the expression is optimizable and is a member expression pointing
|
||||
// to a function, turn it into invocation (and wrap in an arrow function
|
||||
// below) so that it always accesses the latest value when called - thus
|
||||
// avoiding the need to be patched.
|
||||
if (shouldCache && isMemberExp) {
|
||||
if (exp.type === compiler_core_1.NodeTypes.SIMPLE_EXPRESSION) {
|
||||
exp.content = `${exp.content} && ${exp.content}(...args)`;
|
||||
}
|
||||
else {
|
||||
exp.children = [...exp.children, ` && `, ...exp.children, `(...args)`];
|
||||
}
|
||||
}
|
||||
}
|
||||
if (isInlineStatement || (shouldCache && isMemberExp)) {
|
||||
// wrap inline statement in a function expression
|
||||
exp = (0, compiler_core_1.createCompoundExpression)([
|
||||
`${isInlineStatement
|
||||
? `${loc.source.includes('$event') ? '($event: any)' : '()'}`
|
||||
: `${``}(...args)`
|
||||
// } => ${hasMultipleStatements ? `{` : `(`}`,
|
||||
} => ${`{`}`,
|
||||
exp,
|
||||
// hasMultipleStatements ? `}` : `)`
|
||||
`}`,
|
||||
]);
|
||||
}
|
||||
}
|
||||
let ret = {
|
||||
props: [
|
||||
(0, compiler_core_1.createObjectProperty)(eventName, exp || (0, compiler_core_1.createSimpleExpression)(`() => {}`, false, loc)),
|
||||
],
|
||||
};
|
||||
// apply extended compiler augmentor
|
||||
if (augmentor) {
|
||||
ret = augmentor(ret);
|
||||
}
|
||||
if (shouldCache) {
|
||||
// cache handlers so that it's always the same handler being passed down.
|
||||
// this avoids unnecessary re-renders when users use inline handlers on
|
||||
// components.
|
||||
ret.props[0].value = context.cache(ret.props[0].value);
|
||||
}
|
||||
// mark the key as handler for props normalization check
|
||||
ret.props.forEach((p) => (p.key.isHandlerKey = true));
|
||||
return ret;
|
||||
};
|
||||
exports.transformOn = transformOn;
|
||||
Generated
Vendored
+2
@@ -0,0 +1,2 @@
|
||||
import type { DirectiveTransform } from '../transform';
|
||||
export declare const transformOn: DirectiveTransform;
|
||||
Generated
Vendored
+90
@@ -0,0 +1,90 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.transformOn = void 0;
|
||||
const shared_1 = require("@vue/shared");
|
||||
const compiler_core_1 = require("@vue/compiler-core");
|
||||
const vOn_1 = require("./vOn");
|
||||
const runtimeHelpers_1 = require("../runtimeHelpers");
|
||||
const errors_1 = require("../errors");
|
||||
const isEventOptionModifier = /*#__PURE__*/ (0, shared_1.makeMap)(`passive,once,capture`);
|
||||
const isNonKeyModifier = /*#__PURE__*/ (0, shared_1.makeMap)(
|
||||
// event propagation management
|
||||
`stop,prevent,self,` +
|
||||
// system modifiers + exact
|
||||
`ctrl,shift,alt,meta,exact,` +
|
||||
// mouse
|
||||
`middle`);
|
||||
// left & right could be mouse or key modifiers based on event type
|
||||
const maybeKeyModifier = /*#__PURE__*/ (0, shared_1.makeMap)('left,right');
|
||||
const resolveModifiers = (key, modifiers, context, loc) => {
|
||||
const keyModifiers = [];
|
||||
const nonKeyModifiers = [];
|
||||
const eventOptionModifiers = [];
|
||||
for (let i = 0; i < modifiers.length; i++) {
|
||||
const modifier = modifiers[i];
|
||||
if (isEventOptionModifier(modifier)) {
|
||||
// eventOptionModifiers: modifiers for addEventListener() options,
|
||||
// e.g. .passive & .capture
|
||||
if (modifier !== 'once') {
|
||||
onModifierWarn(modifier, context, loc);
|
||||
}
|
||||
else {
|
||||
eventOptionModifiers.push(modifier);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// runtimeModifiers: modifiers that needs runtime guards
|
||||
if (maybeKeyModifier(modifier)) {
|
||||
onModifierWarn(modifier, context, loc);
|
||||
}
|
||||
else {
|
||||
if (isNonKeyModifier(modifier)) {
|
||||
if (modifier !== 'stop' && modifier !== 'prevent') {
|
||||
onModifierWarn(modifier, context, loc);
|
||||
}
|
||||
else {
|
||||
nonKeyModifiers.push(modifier);
|
||||
}
|
||||
}
|
||||
else {
|
||||
onModifierWarn(modifier, context, loc);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return {
|
||||
keyModifiers,
|
||||
nonKeyModifiers,
|
||||
eventOptionModifiers,
|
||||
};
|
||||
};
|
||||
const transformOn = (dir, node, context) => {
|
||||
return (0, vOn_1.transformOn)(dir, node, context, (baseResult) => {
|
||||
const { modifiers } = dir;
|
||||
if (!modifiers.length)
|
||||
return baseResult;
|
||||
let { key, value: handlerExp } = baseResult.props[0];
|
||||
const { nonKeyModifiers, eventOptionModifiers } = resolveModifiers(key, modifiers, context, dir.loc);
|
||||
if (nonKeyModifiers.length) {
|
||||
handlerExp = (0, compiler_core_1.createCallExpression)(context.helper(runtimeHelpers_1.V_ON_WITH_MODIFIERS), [
|
||||
handlerExp,
|
||||
JSON.stringify(nonKeyModifiers),
|
||||
]);
|
||||
}
|
||||
if (eventOptionModifiers.length) {
|
||||
const modifierPostfix = eventOptionModifiers.map(shared_1.capitalize).join('');
|
||||
key = (0, compiler_core_1.isStaticExp)(key)
|
||||
? (0, compiler_core_1.createSimpleExpression)(`${key.content}${modifierPostfix}`, true)
|
||||
: (0, compiler_core_1.createCompoundExpression)([`(`, key, `) + "${modifierPostfix}"`]);
|
||||
}
|
||||
return {
|
||||
props: [(0, compiler_core_1.createObjectProperty)(key, handlerExp)],
|
||||
};
|
||||
});
|
||||
};
|
||||
exports.transformOn = transformOn;
|
||||
function onModifierWarn(modifier, context, loc) {
|
||||
context.onWarn((0, errors_1.createCompilerError)(100, loc, {
|
||||
100: '.' + modifier + ' is not supported',
|
||||
}));
|
||||
}
|
||||
Generated
Vendored
+2
@@ -0,0 +1,2 @@
|
||||
import type { NodeTransform } from '../transform';
|
||||
export declare const transformOnce: NodeTransform;
|
||||
Generated
Vendored
+23
@@ -0,0 +1,23 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.transformOnce = void 0;
|
||||
const compiler_core_1 = require("@vue/compiler-core");
|
||||
const seen = new WeakSet();
|
||||
const transformOnce = (node, context) => {
|
||||
if (node.type === compiler_core_1.NodeTypes.ELEMENT && (0, compiler_core_1.findDir)(node, 'once', true)) {
|
||||
if (seen.has(node) || context.inVOnce) {
|
||||
return;
|
||||
}
|
||||
seen.add(node);
|
||||
context.inVOnce = true;
|
||||
context.helper(compiler_core_1.SET_BLOCK_TRACKING);
|
||||
return () => {
|
||||
context.inVOnce = false;
|
||||
const cur = context.currentNode;
|
||||
if (cur.codegenNode) {
|
||||
cur.codegenNode = context.cache(cur.codegenNode, true /* isVNode */);
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
exports.transformOnce = transformOnce;
|
||||
Generated
Vendored
+2
@@ -0,0 +1,2 @@
|
||||
import type { DirectiveTransform } from '@vue/compiler-core';
|
||||
export declare const transformShow: DirectiveTransform;
|
||||
Generated
Vendored
+11
@@ -0,0 +1,11 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.transformShow = void 0;
|
||||
const runtimeHelpers_1 = require("../runtimeHelpers");
|
||||
const transformShow = (dir, node, context) => {
|
||||
return {
|
||||
props: [],
|
||||
needRuntime: context.helper(runtimeHelpers_1.V_SHOW),
|
||||
};
|
||||
};
|
||||
exports.transformShow = transformShow;
|
||||
Generated
Vendored
+9
@@ -0,0 +1,9 @@
|
||||
import { type ElementNode, type ExpressionNode, type FunctionExpression, type SlotsExpression, type SourceLocation, type TemplateChildNode } from '@vue/compiler-core';
|
||||
import type { NodeTransform, TransformContext } from '../transform';
|
||||
export declare const trackSlotScopes: NodeTransform;
|
||||
export declare const trackVForSlotScopes: NodeTransform;
|
||||
export type SlotFnBuilder = (slotProps: ExpressionNode | undefined, slotChildren: TemplateChildNode[], loc: SourceLocation) => FunctionExpression;
|
||||
export declare function buildSlots(node: ElementNode, context: TransformContext, buildSlotFn?: SlotFnBuilder): {
|
||||
slots: SlotsExpression;
|
||||
hasDynamicSlots: boolean;
|
||||
};
|
||||
Generated
Vendored
+283
@@ -0,0 +1,283 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.buildSlots = exports.trackVForSlotScopes = exports.trackSlotScopes = void 0;
|
||||
const shared_1 = require("@vue/shared");
|
||||
const compiler_core_1 = require("@vue/compiler-core");
|
||||
const errors_1 = require("../errors");
|
||||
const vFor_1 = require("./vFor");
|
||||
const runtimeHelpers_1 = require("../runtimeHelpers");
|
||||
const utils_1 = require("../utils");
|
||||
const defaultFallback = (0, compiler_core_1.createSimpleExpression)(`null`, false);
|
||||
// A NodeTransform that:
|
||||
// 1. Tracks scope identifiers for scoped slots so that they don't get prefixed
|
||||
// by transformExpression. This is only applied in non-browser builds with
|
||||
// { prefixIdentifiers: true }.
|
||||
// 2. Track v-slot depths so that we know a slot is inside another slot.
|
||||
// Note the exit callback is executed before buildSlots() on the same node,
|
||||
// so only nested slots see positive numbers.
|
||||
const trackSlotScopes = (node, context) => {
|
||||
if (node.type === compiler_core_1.NodeTypes.ELEMENT &&
|
||||
(node.tagType === compiler_core_1.ElementTypes.COMPONENT ||
|
||||
node.tagType === compiler_core_1.ElementTypes.TEMPLATE)) {
|
||||
// We are only checking non-empty v-slot here
|
||||
// since we only care about slots that introduce scope variables.
|
||||
const vSlot = (0, compiler_core_1.findDir)(node, 'slot');
|
||||
if (vSlot) {
|
||||
const slotProps = vSlot.exp;
|
||||
// if (!__BROWSER__ && context.prefixIdentifiers) {
|
||||
if (context.prefixIdentifiers) {
|
||||
slotProps && context.addIdentifiers(slotProps);
|
||||
}
|
||||
context.scopes.vSlot++;
|
||||
return () => {
|
||||
// if (!__BROWSER__ && context.prefixIdentifiers) {
|
||||
if (context.prefixIdentifiers) {
|
||||
slotProps && context.removeIdentifiers(slotProps);
|
||||
}
|
||||
context.scopes.vSlot--;
|
||||
};
|
||||
}
|
||||
}
|
||||
};
|
||||
exports.trackSlotScopes = trackSlotScopes;
|
||||
// A NodeTransform that tracks scope identifiers for scoped slots with v-for.
|
||||
// This transform is only applied in non-browser builds with { prefixIdentifiers: true }
|
||||
const trackVForSlotScopes = (node, context) => {
|
||||
let vFor;
|
||||
if ((0, compiler_core_1.isTemplateNode)(node) &&
|
||||
node.props.some(compiler_core_1.isVSlot) &&
|
||||
(vFor = (0, compiler_core_1.findDir)(node, 'for'))) {
|
||||
const result = (vFor.forParseResult = (0, vFor_1.parseForExpression)(vFor.exp, context));
|
||||
if (result) {
|
||||
const { value, key, index } = result;
|
||||
const { addIdentifiers, removeIdentifiers } = context;
|
||||
value && addIdentifiers(value);
|
||||
key && addIdentifiers(key);
|
||||
index && addIdentifiers(index);
|
||||
return () => {
|
||||
value && removeIdentifiers(value);
|
||||
key && removeIdentifiers(key);
|
||||
index && removeIdentifiers(index);
|
||||
};
|
||||
}
|
||||
}
|
||||
};
|
||||
exports.trackVForSlotScopes = trackVForSlotScopes;
|
||||
const buildClientSlotFn = (props, children, loc) => (0, compiler_core_1.createFunctionExpression)(props, children, false /* newline */, true /* isSlot */, children.length ? children[0].loc : loc);
|
||||
// Instead of being a DirectiveTransform, v-slot processing is called during
|
||||
// transformElement to build the slots object for a component.
|
||||
function buildSlots(node, context, buildSlotFn = buildClientSlotFn) {
|
||||
context.helper(compiler_core_1.WITH_CTX);
|
||||
const { children, loc } = node;
|
||||
const slotsProperties = [];
|
||||
const dynamicSlots = [];
|
||||
// If the slot is inside a v-for or another v-slot, force it to be dynamic
|
||||
// since it likely uses a scope variable.
|
||||
let hasDynamicSlots = context.scopes.vSlot > 0 || context.scopes.vFor > 0;
|
||||
// with `prefixIdentifiers: true`, this can be further optimized to make
|
||||
// it dynamic only when the slot actually uses the scope variables.
|
||||
// if (!__BROWSER__ && !context.ssr && context.prefixIdentifiers) {
|
||||
if (context.prefixIdentifiers) {
|
||||
hasDynamicSlots = (0, compiler_core_1.hasScopeRef)(node, context.identifiers);
|
||||
}
|
||||
// 1. Check for slot with slotProps on component itself.
|
||||
// <Comp v-slot="{ prop }"/>
|
||||
const onComponentSlot = (0, compiler_core_1.findDir)(node, 'slot', true);
|
||||
if (onComponentSlot) {
|
||||
const { arg, exp } = onComponentSlot;
|
||||
if (arg && !(0, compiler_core_1.isStaticExp)(arg)) {
|
||||
hasDynamicSlots = true;
|
||||
}
|
||||
slotsProperties.push((0, compiler_core_1.createObjectProperty)(arg || (0, compiler_core_1.createSimpleExpression)('default', true), buildSlotFn(exp, children, loc)));
|
||||
}
|
||||
// 2. Iterate through children and check for template slots
|
||||
// <template v-slot:foo="{ prop }">
|
||||
let hasTemplateSlots = false;
|
||||
let hasNamedDefaultSlot = false;
|
||||
const implicitDefaultChildren = [];
|
||||
const seenSlotNames = new Set();
|
||||
let conditionalBranchIndex = 0;
|
||||
for (let i = 0; i < children.length; i++) {
|
||||
const slotElement = children[i];
|
||||
let slotDir;
|
||||
if (!(0, compiler_core_1.isTemplateNode)(slotElement) ||
|
||||
!(slotDir = (0, compiler_core_1.findDir)(slotElement, 'slot', true))) {
|
||||
// not a <template v-slot>, skip.
|
||||
if (slotElement.type !== compiler_core_1.NodeTypes.COMMENT) {
|
||||
implicitDefaultChildren.push(slotElement);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (onComponentSlot) {
|
||||
// already has on-component slot - this is incorrect usage.
|
||||
context.onError((0, errors_1.createCompilerError)(37 /* ErrorCodes.X_V_SLOT_MIXED_SLOT_USAGE */, slotDir.loc));
|
||||
break;
|
||||
}
|
||||
hasTemplateSlots = true;
|
||||
const { children: slotChildren, loc: slotLoc } = slotElement;
|
||||
const { arg: slotName = (0, compiler_core_1.createSimpleExpression)(`default`, true), exp: slotProps, loc: dirLoc, } = slotDir;
|
||||
// check if name is dynamic.
|
||||
let staticSlotName;
|
||||
if ((0, compiler_core_1.isStaticExp)(slotName)) {
|
||||
staticSlotName = slotName ? slotName.content : `default`;
|
||||
}
|
||||
else {
|
||||
hasDynamicSlots = true;
|
||||
}
|
||||
const slotFunction = buildSlotFn(slotProps, slotChildren, slotLoc);
|
||||
// check if this slot is conditional (v-if/v-for)
|
||||
let vIf;
|
||||
let vElse;
|
||||
let vFor;
|
||||
if ((vIf = (0, compiler_core_1.findDir)(slotElement, 'if'))) {
|
||||
hasDynamicSlots = true;
|
||||
dynamicSlots.push((0, compiler_core_1.createConditionalExpression)(vIf.exp, buildDynamicSlot(slotName, slotFunction, conditionalBranchIndex++), defaultFallback));
|
||||
}
|
||||
else if ((vElse = (0, compiler_core_1.findDir)(slotElement, /^else(-if)?$/, true /* allowEmpty */))) {
|
||||
// find adjacent v-if
|
||||
let j = i;
|
||||
let prev;
|
||||
while (j--) {
|
||||
prev = children[j];
|
||||
if (prev.type !== compiler_core_1.NodeTypes.COMMENT) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (prev && (0, compiler_core_1.isTemplateNode)(prev) && (0, compiler_core_1.findDir)(prev, 'if')) {
|
||||
// remove node
|
||||
children.splice(i, 1);
|
||||
i--;
|
||||
// __TEST__ && assert(dynamicSlots.length > 0)
|
||||
// attach this slot to previous conditional
|
||||
let conditional = dynamicSlots[dynamicSlots.length - 1];
|
||||
while (conditional.alternate.type === compiler_core_1.NodeTypes.JS_CONDITIONAL_EXPRESSION) {
|
||||
conditional = conditional.alternate;
|
||||
}
|
||||
conditional.alternate = vElse.exp
|
||||
? (0, compiler_core_1.createConditionalExpression)(vElse.exp, buildDynamicSlot(slotName, slotFunction, conditionalBranchIndex++), defaultFallback)
|
||||
: buildDynamicSlot(slotName, slotFunction, conditionalBranchIndex++);
|
||||
}
|
||||
else {
|
||||
context.onError((0, errors_1.createCompilerError)(30 /* ErrorCodes.X_V_ELSE_NO_ADJACENT_IF */, vElse.loc));
|
||||
}
|
||||
}
|
||||
else if ((vFor = (0, compiler_core_1.findDir)(slotElement, 'for'))) {
|
||||
hasDynamicSlots = true;
|
||||
const parseResult = vFor.forParseResult ||
|
||||
(0, vFor_1.parseForExpression)(vFor.exp, context);
|
||||
if (parseResult) {
|
||||
// Render the dynamic slots as an array and add it to the createSlot()
|
||||
// args. The runtime knows how to handle it appropriately.
|
||||
dynamicSlots.push((0, compiler_core_1.createCallExpression)(context.helper(runtimeHelpers_1.RENDER_LIST), [
|
||||
parseResult.source,
|
||||
(0, compiler_core_1.createFunctionExpression)((0, vFor_1.createForLoopParams)(parseResult, (0, compiler_core_1.createSimpleExpression)(`_cached`)), buildDynamicSlot(slotName, slotFunction), true /* force newline */),
|
||||
]));
|
||||
}
|
||||
else {
|
||||
context.onError((0, errors_1.createCompilerError)(32 /* ErrorCodes.X_V_FOR_MALFORMED_EXPRESSION */, vFor.loc));
|
||||
}
|
||||
}
|
||||
else {
|
||||
// check duplicate static names
|
||||
if (staticSlotName) {
|
||||
if (seenSlotNames.has(staticSlotName)) {
|
||||
context.onError((0, errors_1.createCompilerError)(38 /* ErrorCodes.X_V_SLOT_DUPLICATE_SLOT_NAMES */, dirLoc));
|
||||
continue;
|
||||
}
|
||||
seenSlotNames.add(staticSlotName);
|
||||
if (staticSlotName === 'default') {
|
||||
hasNamedDefaultSlot = true;
|
||||
}
|
||||
}
|
||||
slotsProperties.push((0, compiler_core_1.createObjectProperty)(slotName, slotFunction));
|
||||
}
|
||||
}
|
||||
if (!onComponentSlot) {
|
||||
const buildDefaultSlotProperty = (props, children) => {
|
||||
const fn = buildSlotFn(props, children, loc);
|
||||
// if (__COMPAT__ && context.compatConfig) {
|
||||
// fn.isNonScopedSlot = true
|
||||
// }
|
||||
return (0, compiler_core_1.createObjectProperty)(`default`, fn);
|
||||
};
|
||||
if (!hasTemplateSlots) {
|
||||
// implicit default slot (on component)
|
||||
slotsProperties.push(buildDefaultSlotProperty(undefined, children));
|
||||
}
|
||||
else if (implicitDefaultChildren.length &&
|
||||
// #3766
|
||||
// with whitespace: 'preserve', whitespaces between slots will end up in
|
||||
// implicitDefaultChildren. Ignore if all implicit children are whitespaces.
|
||||
implicitDefaultChildren.some((node) => isNonWhitespaceContent(node))) {
|
||||
// implicit default slot (mixed with named slots)
|
||||
if (hasNamedDefaultSlot) {
|
||||
context.onError((0, errors_1.createCompilerError)(39 /* ErrorCodes.X_V_SLOT_EXTRANEOUS_DEFAULT_SLOT_CHILDREN */, implicitDefaultChildren[0].loc));
|
||||
}
|
||||
else {
|
||||
slotsProperties.push(buildDefaultSlotProperty(undefined, implicitDefaultChildren));
|
||||
}
|
||||
}
|
||||
}
|
||||
const slotFlag = hasDynamicSlots
|
||||
? shared_1.SlotFlags.DYNAMIC
|
||||
: hasForwardedSlots(node.children)
|
||||
? shared_1.SlotFlags.FORWARDED
|
||||
: shared_1.SlotFlags.STABLE;
|
||||
let slots = (0, compiler_core_1.createObjectExpression)(slotsProperties.concat((0, compiler_core_1.createObjectProperty)(`_`,
|
||||
// 2 = compiled but dynamic = can skip normalization, but must run diff
|
||||
// 1 = compiled and static = can skip normalization AND diff as optimized
|
||||
(0, compiler_core_1.createSimpleExpression)(slotFlag + (utils_1.__DEV__ ? ` /* ${shared_1.slotFlagsText[slotFlag]} */` : ``), false))), loc);
|
||||
if (dynamicSlots.length) {
|
||||
slots = (0, compiler_core_1.createCallExpression)(context.helper(compiler_core_1.CREATE_SLOTS), [
|
||||
slots,
|
||||
(0, compiler_core_1.createArrayExpression)(dynamicSlots),
|
||||
]);
|
||||
}
|
||||
return {
|
||||
slots,
|
||||
hasDynamicSlots,
|
||||
};
|
||||
}
|
||||
exports.buildSlots = buildSlots;
|
||||
function buildDynamicSlot(name, fn, index) {
|
||||
const props = [
|
||||
(0, compiler_core_1.createObjectProperty)(`name`, name),
|
||||
(0, compiler_core_1.createObjectProperty)(`fn`, fn),
|
||||
];
|
||||
if (index != null) {
|
||||
props.push((0, compiler_core_1.createObjectProperty)(`key`, (0, compiler_core_1.createSimpleExpression)(String(index), true)));
|
||||
}
|
||||
return (0, compiler_core_1.createObjectExpression)(props);
|
||||
}
|
||||
function hasForwardedSlots(children) {
|
||||
for (let i = 0; i < children.length; i++) {
|
||||
const child = children[i];
|
||||
switch (child.type) {
|
||||
case compiler_core_1.NodeTypes.ELEMENT:
|
||||
if (child.tagType === compiler_core_1.ElementTypes.SLOT ||
|
||||
hasForwardedSlots(child.children)) {
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case compiler_core_1.NodeTypes.IF:
|
||||
if (hasForwardedSlots(child.branches))
|
||||
return true;
|
||||
break;
|
||||
case compiler_core_1.NodeTypes.IF_BRANCH:
|
||||
case compiler_core_1.NodeTypes.FOR:
|
||||
if (hasForwardedSlots(child.children))
|
||||
return true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
function isNonWhitespaceContent(node) {
|
||||
if (node.type !== compiler_core_1.NodeTypes.TEXT && node.type !== compiler_core_1.NodeTypes.TEXT_CALL)
|
||||
return true;
|
||||
return node.type === compiler_core_1.NodeTypes.TEXT
|
||||
? !!node.content.trim()
|
||||
: isNonWhitespaceContent(node.content);
|
||||
}
|
||||
Generated
Vendored
+2
@@ -0,0 +1,2 @@
|
||||
import { type DirectiveTransform } from '@vue/compiler-core';
|
||||
export declare const transformVText: DirectiveTransform;
|
||||
Generated
Vendored
+29
@@ -0,0 +1,29 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.transformVText = void 0;
|
||||
const compiler_core_1 = require("@vue/compiler-core");
|
||||
// import { createDOMCompilerError, DOMErrorCodes } from '../errors'
|
||||
const transformVText = (dir, node, context) => {
|
||||
const { exp, loc } = dir;
|
||||
// if (!exp) {
|
||||
// context.onError(
|
||||
// createDOMCompilerError(DOMErrorCodes.X_V_TEXT_NO_EXPRESSION, loc)
|
||||
// )
|
||||
// }
|
||||
// if (node.children.length) {
|
||||
// context.onError(
|
||||
// createDOMCompilerError(DOMErrorCodes.X_V_TEXT_WITH_CHILDREN, loc)
|
||||
// )
|
||||
// node.children.length = 0
|
||||
// }
|
||||
return {
|
||||
props: [
|
||||
(0, compiler_core_1.createObjectProperty)((0, compiler_core_1.createSimpleExpression)(`value`, true), exp
|
||||
? (0, compiler_core_1.getConstantType)(exp, context) > 0
|
||||
? exp
|
||||
: (0, compiler_core_1.createCallExpression)(context.helperString(compiler_core_1.TO_DISPLAY_STRING), [exp], loc)
|
||||
: (0, compiler_core_1.createSimpleExpression)('', true)),
|
||||
],
|
||||
};
|
||||
};
|
||||
exports.transformVText = transformVText;
|
||||
Generated
Vendored
+15
@@ -0,0 +1,15 @@
|
||||
import { type ExpressionNode } from '@vue/compiler-core';
|
||||
import type { TemplateCompilerOptions } from './options';
|
||||
import type { TransformContext } from './transform';
|
||||
import type { CompilerError } from './errors';
|
||||
export declare const __DEV__ = true;
|
||||
export declare const __BROWSER__ = false;
|
||||
export declare const __COMPAT__ = false;
|
||||
export declare function isCompatEnabled(...args: any[]): boolean;
|
||||
export declare function genRenderFunctionDecl({ className, genDefaultAs, inline, }: TemplateCompilerOptions & {
|
||||
genDefaultAs?: string;
|
||||
}): string;
|
||||
export declare function rewriteObjectExpression(exp: ExpressionNode, context: TransformContext): import("@vue/compiler-core").SimpleExpressionNode | undefined;
|
||||
export declare function onCompilerError(error: CompilerError): void;
|
||||
export declare function parseSource(fileName: string, rootDir: string): string;
|
||||
export declare function addEasyComponentAutoImports(easyComponentAutoImports: Record<string, [string, string]>, rootDir: string, tagName: string, fileName: string): void;
|
||||
Generated
Vendored
+86
@@ -0,0 +1,86 @@
|
||||
"use strict";
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.addEasyComponentAutoImports = exports.parseSource = exports.onCompilerError = exports.rewriteObjectExpression = exports.genRenderFunctionDecl = exports.isCompatEnabled = exports.__COMPAT__ = exports.__BROWSER__ = exports.__DEV__ = void 0;
|
||||
const path_1 = __importDefault(require("path"));
|
||||
const compiler_core_1 = require("@vue/compiler-core");
|
||||
const estree_walker_1 = require("estree-walker");
|
||||
const parser_1 = require("@babel/parser");
|
||||
const magic_string_1 = __importDefault(require("magic-string"));
|
||||
const uni_cli_shared_1 = require("@dcloudio/uni-cli-shared");
|
||||
const transformExpression_1 = require("./transforms/transformExpression");
|
||||
exports.__DEV__ = true;
|
||||
exports.__BROWSER__ = false;
|
||||
exports.__COMPAT__ = false;
|
||||
function isCompatEnabled(...args) {
|
||||
return false;
|
||||
}
|
||||
exports.isCompatEnabled = isCompatEnabled;
|
||||
function genRenderFunctionDecl({ className, genDefaultAs, inline = false, }) {
|
||||
if (inline) {
|
||||
return `(): any | null =>`;
|
||||
}
|
||||
// 调整返回值类型为 any | null, 支持 <template>some text</template>
|
||||
const thisCode = genDefaultAs
|
||||
? `this: InstanceType<typeof ${genDefaultAs}>`
|
||||
: '';
|
||||
return `function ${className || ''}Render(${thisCode}): any | null`;
|
||||
}
|
||||
exports.genRenderFunctionDecl = genRenderFunctionDecl;
|
||||
function rewriteObjectExpression(exp, context) {
|
||||
const source = (0, transformExpression_1.stringifyExpression)(exp);
|
||||
if (source.includes('{')) {
|
||||
const s = new magic_string_1.default(source);
|
||||
const ast = (0, parser_1.parseExpression)(source, {
|
||||
plugins: context.expressionPlugins,
|
||||
});
|
||||
(0, estree_walker_1.walk)(ast, {
|
||||
enter(node) {
|
||||
if (node.type === 'ObjectExpression') {
|
||||
s.prependLeft(node.start, node.properties.length > 0
|
||||
? 'utsMapOf('
|
||||
: 'utsMapOf<string, any | null>(');
|
||||
s.prependRight(node.end, ')');
|
||||
}
|
||||
},
|
||||
});
|
||||
return (0, compiler_core_1.createSimpleExpression)(s.toString(), false, exp.loc);
|
||||
}
|
||||
}
|
||||
exports.rewriteObjectExpression = rewriteObjectExpression;
|
||||
function onCompilerError(error) { }
|
||||
exports.onCompilerError = onCompilerError;
|
||||
function parseSource(fileName, rootDir) {
|
||||
if (fileName.includes('@dcloudio')) {
|
||||
return fileName;
|
||||
}
|
||||
rootDir = (0, uni_cli_shared_1.normalizePath)(rootDir);
|
||||
if (path_1.default.isAbsolute(fileName) && fileName.startsWith(rootDir)) {
|
||||
return '@/' + (0, uni_cli_shared_1.normalizePath)(path_1.default.relative(rootDir, fileName));
|
||||
}
|
||||
return fileName;
|
||||
}
|
||||
exports.parseSource = parseSource;
|
||||
function addEasyComponentAutoImports(easyComponentAutoImports, rootDir, tagName, fileName) {
|
||||
if (easyComponentAutoImports[fileName]) {
|
||||
return;
|
||||
}
|
||||
// 内置easycom,如 unicloud-db
|
||||
if (fileName.includes('@dcloudio')) {
|
||||
return;
|
||||
}
|
||||
rootDir = (0, uni_cli_shared_1.normalizePath)(rootDir);
|
||||
if (path_1.default.isAbsolute(fileName) && fileName.startsWith(rootDir)) {
|
||||
fileName = '@/' + (0, uni_cli_shared_1.normalizePath)(path_1.default.relative(rootDir, fileName));
|
||||
}
|
||||
// 加密插件easycom类型导入
|
||||
if (fileName.includes('?uts-proxy')) {
|
||||
const moduleId = path_1.default.basename(fileName.split('?uts-proxy')[0]);
|
||||
fileName = `uts.sdk.modules.${(0, uni_cli_shared_1.camelize)(moduleId)}`;
|
||||
}
|
||||
const ident = (0, uni_cli_shared_1.genUTSComponentPublicInstanceIdent)(tagName);
|
||||
easyComponentAutoImports[fileName] = [ident, ident];
|
||||
}
|
||||
exports.addEasyComponentAutoImports = addEasyComponentAutoImports;
|
||||
Generated
Vendored
+28
@@ -0,0 +1,28 @@
|
||||
import type * as _compiler from '@vue/compiler-sfc';
|
||||
import type { CompilerError, SFCDescriptor } from '@vue/compiler-sfc';
|
||||
export interface ResolvedOptions {
|
||||
compiler: typeof _compiler;
|
||||
root: string;
|
||||
sourceMap: boolean;
|
||||
targetLanguage?: 'kotlin';
|
||||
classNamePrefix?: string;
|
||||
genDefaultAs?: string;
|
||||
}
|
||||
export declare function getResolvedOptions(): ResolvedOptions;
|
||||
export interface SFCParseResult {
|
||||
descriptor: SFCDescriptor;
|
||||
errors: Array<CompilerError | SyntaxError>;
|
||||
}
|
||||
export declare const cache: Map<string, _compiler.SFCDescriptor>;
|
||||
declare module '@vue/compiler-sfc' {
|
||||
interface SFCDescriptor {
|
||||
id: string;
|
||||
relativeFilename: string;
|
||||
}
|
||||
}
|
||||
export declare function createDescriptor(filename: string, source: string, { root, sourceMap, compiler, }: ResolvedOptions & {
|
||||
compiler: typeof _compiler;
|
||||
}): SFCParseResult;
|
||||
export declare function getDescriptor(filename: string, options: ResolvedOptions, createIfNotFound?: boolean): SFCDescriptor | undefined;
|
||||
export declare function getSrcDescriptor(filename: string): SFCDescriptor;
|
||||
export declare function setSrcDescriptor(filename: string, entry: SFCDescriptor): void;
|
||||
Generated
Vendored
+68
@@ -0,0 +1,68 @@
|
||||
"use strict";
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.setSrcDescriptor = exports.getSrcDescriptor = exports.getDescriptor = exports.createDescriptor = exports.cache = exports.getResolvedOptions = void 0;
|
||||
const fs_1 = __importDefault(require("fs"));
|
||||
const crypto_1 = require("crypto");
|
||||
const uni_cli_shared_1 = require("@dcloudio/uni-cli-shared");
|
||||
const utils_1 = require("../utils");
|
||||
const script_1 = require("./sfc/script");
|
||||
function getResolvedOptions() {
|
||||
const options = {
|
||||
root: process.env.UNI_INPUT_DIR,
|
||||
sourceMap: (0, uni_cli_shared_1.enableSourceMap)(),
|
||||
// eslint-disable-next-line no-restricted-globals
|
||||
compiler: require('@vue/compiler-sfc'),
|
||||
targetLanguage: process.env.UNI_UTS_TARGET_LANGUAGE,
|
||||
genDefaultAs: script_1.scriptIdentifier,
|
||||
};
|
||||
if (process.env.UNI_COMPILE_TARGET === 'ext-api') {
|
||||
options.classNamePrefix = 'Uni';
|
||||
}
|
||||
return options;
|
||||
}
|
||||
exports.getResolvedOptions = getResolvedOptions;
|
||||
exports.cache = new Map();
|
||||
function createDescriptor(filename, source, { root, sourceMap, compiler, }) {
|
||||
// ensure the path is normalized in a way that is consistent inside
|
||||
// project (relative to root) and on different systems.
|
||||
const relativeFilename = (0, utils_1.parseUTSRelativeFilename)(filename, root);
|
||||
// 传入normalizedPath是为了让sourcemap记录的是相对路径
|
||||
const { descriptor, errors } = compiler.parse(source, {
|
||||
filename: relativeFilename,
|
||||
sourceMap,
|
||||
});
|
||||
descriptor.relativeFilename = relativeFilename;
|
||||
// 重置为绝对路径
|
||||
descriptor.filename = filename;
|
||||
descriptor.id = getHash(relativeFilename);
|
||||
exports.cache.set(filename, descriptor);
|
||||
return { descriptor, errors };
|
||||
}
|
||||
exports.createDescriptor = createDescriptor;
|
||||
function getDescriptor(filename, options, createIfNotFound = true) {
|
||||
if (exports.cache.has(filename)) {
|
||||
return exports.cache.get(filename);
|
||||
}
|
||||
if (createIfNotFound) {
|
||||
const { descriptor, errors } = createDescriptor(filename, (0, uni_cli_shared_1.preUVueJs)((0, uni_cli_shared_1.preUVueHtml)(fs_1.default.readFileSync(filename, 'utf-8'), filename), filename), options);
|
||||
if (errors.length) {
|
||||
throw errors[0];
|
||||
}
|
||||
return descriptor;
|
||||
}
|
||||
}
|
||||
exports.getDescriptor = getDescriptor;
|
||||
function getSrcDescriptor(filename) {
|
||||
return exports.cache.get(filename);
|
||||
}
|
||||
exports.getSrcDescriptor = getSrcDescriptor;
|
||||
function setSrcDescriptor(filename, entry) {
|
||||
exports.cache.set(filename, entry);
|
||||
}
|
||||
exports.setSrcDescriptor = setSrcDescriptor;
|
||||
function getHash(text) {
|
||||
return (0, crypto_1.createHash)('sha256').update(text).digest('hex').substring(0, 8);
|
||||
}
|
||||
Generated
Vendored
+2
@@ -0,0 +1,2 @@
|
||||
import type { Plugin } from 'vite';
|
||||
export declare function uniAppUVuePlugin(): Plugin;
|
||||
Generated
Vendored
+117
@@ -0,0 +1,117 @@
|
||||
"use strict";
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.uniAppUVuePlugin = void 0;
|
||||
const path_1 = __importDefault(require("path"));
|
||||
const fs_extra_1 = __importDefault(require("fs-extra"));
|
||||
const shared_1 = require("@vue/shared");
|
||||
const uni_cli_shared_1 = require("@dcloudio/uni-cli-shared");
|
||||
const descriptorCache_1 = require("./descriptorCache");
|
||||
const utils_1 = require("../utils");
|
||||
const style_1 = require("./code/style");
|
||||
const main_1 = require("./sfc/main");
|
||||
function uniAppUVuePlugin() {
|
||||
const options = (0, descriptorCache_1.getResolvedOptions)();
|
||||
const appVue = (0, uni_cli_shared_1.resolveAppVue)(process.env.UNI_INPUT_DIR);
|
||||
function isAppVue(id) {
|
||||
return (0, uni_cli_shared_1.normalizePath)(id) === appVue;
|
||||
}
|
||||
return {
|
||||
name: 'uni:app-uvue',
|
||||
apply: 'build',
|
||||
async resolveId(id) {
|
||||
// serve sub-part requests (*?vue) as virtual modules
|
||||
if ((0, uni_cli_shared_1.parseVueRequest)(id).query.vue) {
|
||||
return id;
|
||||
}
|
||||
},
|
||||
load(id) {
|
||||
const { filename, query } = (0, uni_cli_shared_1.parseVueRequest)(id);
|
||||
// select corresponding block for sub-part virtual modules
|
||||
if (query.vue) {
|
||||
if (query.src) {
|
||||
return fs_extra_1.default.readFileSync(filename, 'utf-8');
|
||||
}
|
||||
const descriptor = (0, descriptorCache_1.getDescriptor)(filename, options);
|
||||
let block;
|
||||
if (query.type === 'style') {
|
||||
block = descriptor.styles[query.index];
|
||||
}
|
||||
else if (query.index != null) {
|
||||
block = descriptor.customBlocks[query.index];
|
||||
}
|
||||
if (block) {
|
||||
return {
|
||||
code: block.content,
|
||||
map: block.map,
|
||||
};
|
||||
}
|
||||
}
|
||||
},
|
||||
async transform(code, id) {
|
||||
const { filename, query } = (0, uni_cli_shared_1.parseVueRequest)(id);
|
||||
if (!(0, utils_1.isVue)(filename)) {
|
||||
return;
|
||||
}
|
||||
if (!query.vue) {
|
||||
// main request
|
||||
return (0, main_1.transformMain)((0, utils_1.transformUniCloudMixinDataCom)(code), filename, {
|
||||
...options,
|
||||
componentType: isAppVue(filename)
|
||||
? 'app'
|
||||
: query.type === 'page'
|
||||
? 'page'
|
||||
: 'component',
|
||||
}, this);
|
||||
}
|
||||
else {
|
||||
// sub block request
|
||||
const descriptor = query.src
|
||||
? (0, descriptorCache_1.getSrcDescriptor)(filename)
|
||||
: (0, descriptorCache_1.getDescriptor)(filename, options);
|
||||
if (query.type === 'style') {
|
||||
return (0, style_1.transformStyle)(code, descriptor, Number(query.index), options, this, filename);
|
||||
}
|
||||
}
|
||||
},
|
||||
generateBundle(_, bundle) {
|
||||
// 遍历vue文件,填充style,尽量减少全局变量
|
||||
Object.keys(bundle).forEach((name) => {
|
||||
const file = bundle[name];
|
||||
if (file &&
|
||||
file.type === 'asset' &&
|
||||
isVueFile(file.fileName) &&
|
||||
(0, shared_1.isString)(file.source)) {
|
||||
let fileName = (0, uni_cli_shared_1.normalizePath)(file.fileName);
|
||||
if (process.env.UNI_APP_X_TSC === 'true') {
|
||||
fileName = fileName.replace('.ts', '');
|
||||
}
|
||||
const className = process.env.UNI_COMPILE_TARGET === 'ext-api'
|
||||
? // components/map/map.vue => UniMap
|
||||
(0, uni_cli_shared_1.genUTSClassName)(path_1.default.basename(fileName), options.classNamePrefix)
|
||||
: (0, uni_cli_shared_1.genUTSClassName)(fileName, options.classNamePrefix);
|
||||
const classNameComment = `/*${className}Styles*/`;
|
||||
if (file.source.includes(classNameComment)) {
|
||||
const styleAssetName = fileName + '.style.uts';
|
||||
const styleAsset = bundle[styleAssetName];
|
||||
if (styleAsset &&
|
||||
styleAsset.type === 'asset' &&
|
||||
(0, shared_1.isString)(styleAsset.source)) {
|
||||
file.source = file.source.replace(classNameComment, styleAsset.source.replace('export ', ''));
|
||||
delete bundle[styleAssetName];
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
};
|
||||
}
|
||||
exports.uniAppUVuePlugin = uniAppUVuePlugin;
|
||||
function isVueFile(filename) {
|
||||
return (filename.endsWith('.uvue') ||
|
||||
filename.endsWith('.vue') ||
|
||||
filename.endsWith('.uvue.ts') ||
|
||||
filename.endsWith('.vue.ts'));
|
||||
}
|
||||
Generated
Vendored
+113
@@ -0,0 +1,113 @@
|
||||
import type { SFCDescriptor, SFCScriptBlock } from '@vue/compiler-sfc';
|
||||
import type { ParserPlugin } from '@babel/parser';
|
||||
import type { SFCTemplateCompileOptions } from '@vue/compiler-sfc';
|
||||
export declare const normalScriptDefaultVar = "__default__";
|
||||
export declare const DEFAULT_FILENAME = "anonymous.vue";
|
||||
export interface SFCScriptCompileOptions {
|
||||
root: string;
|
||||
/**
|
||||
* 类型
|
||||
*/
|
||||
componentType: 'app' | 'page' | 'component';
|
||||
/**
|
||||
* 是否同时支持使用 <script> 和 <script setup>
|
||||
*/
|
||||
scriptAndScriptSetup?: boolean;
|
||||
/**
|
||||
* Class name
|
||||
*/
|
||||
className: string;
|
||||
/**
|
||||
* Scope ID for prefixing injected CSS variables.
|
||||
* This must be consistent with the `id` passed to `compileStyle`.
|
||||
*/
|
||||
id: string;
|
||||
/**
|
||||
* Production mode. Used to determine whether to generate hashed CSS variables
|
||||
*/
|
||||
isProd?: boolean;
|
||||
/**
|
||||
* Enable/disable source map. Defaults to true.
|
||||
*/
|
||||
sourceMap?: boolean;
|
||||
/**
|
||||
* https://babeljs.io/docs/en/babel-parser#plugins
|
||||
*/
|
||||
babelParserPlugins?: ParserPlugin[];
|
||||
/**
|
||||
* A list of files to parse for global types to be made available for type
|
||||
* resolving in SFC macros. The list must be fully resolved file system paths.
|
||||
*/
|
||||
globalTypeFiles?: string[];
|
||||
/**
|
||||
* Compile the template and inline the resulting render function
|
||||
* directly inside setup().
|
||||
* - Only affects `<script setup>`
|
||||
* - This should only be used in production because it prevents the template
|
||||
* from being hot-reloaded separately from component state.
|
||||
*/
|
||||
inlineTemplate?: boolean;
|
||||
/**
|
||||
* Generate the final component as a variable instead of default export.
|
||||
* This is useful in e.g. @vitejs/plugin-vue where the script needs to be
|
||||
* placed inside the main module.
|
||||
*/
|
||||
genDefaultAs?: string;
|
||||
/**
|
||||
* Options for template compilation when inlining. Note these are options that
|
||||
* would normally be passed to `compiler-sfc`'s own `compileTemplate()`, not
|
||||
* options passed to `compiler-dom`.
|
||||
*/
|
||||
templateOptions?: Partial<SFCTemplateCompileOptions>;
|
||||
/**
|
||||
* Hoist <script setup> static constants.
|
||||
* - Only enables when one `<script setup>` exists.
|
||||
* @default true
|
||||
*/
|
||||
hoistStatic?: boolean;
|
||||
/**
|
||||
* (**Experimental**) Enable macro `defineModel`
|
||||
* @default false
|
||||
*/
|
||||
defineModel?: boolean;
|
||||
/**
|
||||
* (**Experimental**) Enable reactive destructure for `defineProps`
|
||||
* @default false
|
||||
*/
|
||||
propsDestructure?: boolean;
|
||||
/**
|
||||
* File system access methods to be used when resolving types
|
||||
* imported in SFC macros. Defaults to ts.sys in Node.js, can be overwritten
|
||||
* to use a virtual file system for use in browsers (e.g. in REPLs)
|
||||
*/
|
||||
fs?: {
|
||||
fileExists(file: string): boolean;
|
||||
readFile(file: string): string | undefined;
|
||||
};
|
||||
/**
|
||||
* (Experimental) Enable syntax transform for using refs without `.value` and
|
||||
* using destructured props with reactivity
|
||||
* @deprecated the Reactivity Transform proposal has been dropped. This
|
||||
* feature will be removed from Vue core in 3.4. If you intend to continue
|
||||
* using it, disable this and switch to the [Vue Macros implementation](https://vue-macros.sxzz.moe/features/reactivity-transform.html).
|
||||
*/
|
||||
reactivityTransform?: boolean;
|
||||
/**
|
||||
* Transform Vue SFCs into custom elements.
|
||||
*/
|
||||
customElement?: boolean | ((filename: string) => boolean);
|
||||
}
|
||||
export interface ImportBinding {
|
||||
isType: boolean;
|
||||
imported: string;
|
||||
local: string;
|
||||
source: string;
|
||||
isFromSetup: boolean;
|
||||
isUsedInTemplate: boolean;
|
||||
}
|
||||
/**
|
||||
* Compile `<script setup>`
|
||||
* It requires the whole SFC descriptor because we need to handle and merge
|
||||
* normal `<script>` + `<script setup>` if both are present.
|
||||
*/
|
||||
export declare function compileScript(sfc: SFCDescriptor, options: SFCScriptCompileOptions): SFCScriptBlock;
|
||||
Generated
Vendored
+989
@@ -0,0 +1,989 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.compileScript = exports.DEFAULT_FILENAME = exports.normalScriptDefaultVar = void 0;
|
||||
const compiler_dom_1 = require("@vue/compiler-dom");
|
||||
const estree_walker_1 = require("estree-walker");
|
||||
const source_map_js_1 = require("source-map-js");
|
||||
const normalScript_1 = require("./script/normalScript");
|
||||
const warn_1 = require("./warn");
|
||||
const context_1 = require("./script/context");
|
||||
const defineProps_1 = require("./script/defineProps");
|
||||
const defineEmits_1 = require("./script/defineEmits");
|
||||
const defineExpose_1 = require("./script/defineExpose");
|
||||
const defineOptions_1 = require("./script/defineOptions");
|
||||
const defineSlots_1 = require("./script/defineSlots");
|
||||
const defineModel_1 = require("./script/defineModel");
|
||||
const utils_1 = require("./script/utils");
|
||||
const analyzeScriptBindings_1 = require("./script/analyzeScriptBindings");
|
||||
const rewriteConsole_1 = require("./script/rewriteConsole");
|
||||
const rewriteDebugError_1 = require("./script/rewriteDebugError");
|
||||
const rewriteSourceMap_1 = require("./script/rewriteSourceMap");
|
||||
exports.normalScriptDefaultVar = `__default__`;
|
||||
exports.DEFAULT_FILENAME = 'anonymous.vue';
|
||||
/**
|
||||
* Compile `<script setup>`
|
||||
* It requires the whole SFC descriptor because we need to handle and merge
|
||||
* normal `<script>` + `<script setup>` if both are present.
|
||||
*/
|
||||
function compileScript(sfc, options) {
|
||||
if (!options.id) {
|
||||
(0, warn_1.warnOnce)(`compileScript now requires passing the \`id\` option.\n` +
|
||||
`Upgrade your vite or vue-loader version for compatibility with ` +
|
||||
`the latest experimental proposals.`);
|
||||
}
|
||||
const ctx = new context_1.ScriptCompileContext(sfc, options);
|
||||
const { script, scriptSetup, source, filename } = sfc;
|
||||
const hoistStatic = options.hoistStatic !== false && !script;
|
||||
const scopeId = options.id ? options.id.replace(/^data-v-/, '') : '';
|
||||
// 目前暂不提供<script setup>和<script>同时使用
|
||||
// 目前给了个开关,用于单元测试
|
||||
if (!options.scriptAndScriptSetup) {
|
||||
if (script && scriptSetup) {
|
||||
throw new Error(`<script setup> and <script> cannot be used together.`);
|
||||
}
|
||||
}
|
||||
// TODO remove in 3.4
|
||||
// const enableReactivityTransform = !!options.reactivityTransform
|
||||
let refBindings;
|
||||
if (!scriptSetup) {
|
||||
if (!script) {
|
||||
throw new Error(`[@vue/compiler-sfc] SFC contains no <script> tags.`);
|
||||
}
|
||||
// normal <script> only
|
||||
return (0, normalScript_1.processNormalScript)(ctx, scopeId);
|
||||
}
|
||||
// if (script && scriptLang !== scriptSetupLang) {
|
||||
// throw new Error(
|
||||
// `[@vue/compiler-sfc] <script> and <script setup> must have the same ` +
|
||||
// `language type.`
|
||||
// )
|
||||
// }
|
||||
// if (scriptSetupLang && !ctx.isJS && !ctx.isTS) {
|
||||
// // do not process non js/ts script blocks
|
||||
// return scriptSetup
|
||||
// }
|
||||
// metadata that needs to be returned
|
||||
// const ctx.bindingMetadata: BindingMetadata = {}
|
||||
const scriptBindings = Object.create(null);
|
||||
const setupBindings = Object.create(null);
|
||||
let defaultExport;
|
||||
let hasAwait = false;
|
||||
// let hasInlinedSsrRenderFn = false
|
||||
// string offsets
|
||||
const startOffset = ctx.startOffset;
|
||||
const endOffset = ctx.endOffset;
|
||||
const scriptStartOffset = script && script.loc.start.offset;
|
||||
const scriptEndOffset = script && script.loc.end.offset;
|
||||
function hoistNode(node) {
|
||||
const start = node.start + startOffset;
|
||||
let end = node.end + startOffset;
|
||||
// locate comment
|
||||
if (node.trailingComments && node.trailingComments.length > 0) {
|
||||
const lastCommentNode = node.trailingComments[node.trailingComments.length - 1];
|
||||
end = lastCommentNode.end + startOffset;
|
||||
}
|
||||
// locate the end of whitespace between this statement and the next
|
||||
while (end <= source.length) {
|
||||
if (!/\s/.test(source.charAt(end))) {
|
||||
break;
|
||||
}
|
||||
end++;
|
||||
}
|
||||
ctx.s.move(start, end, 0);
|
||||
}
|
||||
function registerUserImport(source, local, imported, isType, isFromSetup, needTemplateUsageCheck) {
|
||||
ctx.userImports[local] = {
|
||||
isType,
|
||||
imported,
|
||||
local,
|
||||
source,
|
||||
isFromSetup,
|
||||
isUsedInTemplate: needTemplateUsageCheck,
|
||||
};
|
||||
}
|
||||
function checkInvalidScopeReference(node, method) {
|
||||
if (!node)
|
||||
return;
|
||||
(0, compiler_dom_1.walkIdentifiers)(node, (id) => {
|
||||
const binding = setupBindings[id.name];
|
||||
if (binding && binding !== compiler_dom_1.BindingTypes.LITERAL_CONST) {
|
||||
ctx.error(`\`${method}()\` in <script setup> cannot reference locally ` +
|
||||
`declared variables because it will be hoisted outside of the ` +
|
||||
`setup() function. If your component options require initialization ` +
|
||||
`in the module scope, use a separate normal <script> to export ` +
|
||||
`the options instead.`, id);
|
||||
}
|
||||
});
|
||||
}
|
||||
const scriptAst = ctx.scriptAst;
|
||||
const scriptSetupAst = ctx.scriptSetupAst;
|
||||
const relativeFilename = ctx.descriptor.relativeFilename;
|
||||
// 处理 console 的日志输出源码位置,不然就需要rust端读取 sourcemap 做映射
|
||||
if (process.env.NODE_ENV === 'development' ||
|
||||
process.env.UNI_RUST_TEST === 'true') {
|
||||
if (scriptAst) {
|
||||
// 仅 dev 处理
|
||||
const scriptContent = ctx.descriptor.script.content;
|
||||
const startLine = (ctx.descriptor.script.loc.start.line || 1) - 1;
|
||||
const startOffset = ctx.descriptor.script.loc.start.offset || 0;
|
||||
if ((0, rewriteDebugError_1.hasDebugError)(scriptContent)) {
|
||||
(0, rewriteDebugError_1.rewriteDebugError)(scriptAst, ctx.s, {
|
||||
fileName: relativeFilename,
|
||||
startLine,
|
||||
startOffset,
|
||||
});
|
||||
}
|
||||
if (scriptContent.includes('console.')) {
|
||||
(0, rewriteConsole_1.rewriteConsole)(scriptAst, ctx.s, {
|
||||
fileName: relativeFilename,
|
||||
startLine,
|
||||
startOffset,
|
||||
});
|
||||
}
|
||||
(0, rewriteSourceMap_1.rewriteSourceMap)(scriptAst, ctx.s, {
|
||||
fileName: relativeFilename,
|
||||
startLine,
|
||||
startOffset,
|
||||
});
|
||||
}
|
||||
if (scriptSetupAst) {
|
||||
const scriptSetupContent = ctx.descriptor.scriptSetup.content;
|
||||
const startLine = (ctx.descriptor.scriptSetup.loc.start.line || 1) - 1;
|
||||
const startOffset = ctx.descriptor.scriptSetup.loc.start.offset || 0;
|
||||
if ((0, rewriteDebugError_1.hasDebugError)(scriptSetupContent)) {
|
||||
(0, rewriteDebugError_1.rewriteDebugError)(scriptSetupAst, ctx.s, {
|
||||
fileName: relativeFilename,
|
||||
startLine,
|
||||
startOffset,
|
||||
});
|
||||
}
|
||||
if ((0, rewriteConsole_1.hasConsole)(scriptSetupContent)) {
|
||||
(0, rewriteConsole_1.rewriteConsole)(scriptSetupAst, ctx.s, {
|
||||
fileName: relativeFilename,
|
||||
startLine,
|
||||
startOffset,
|
||||
});
|
||||
}
|
||||
(0, rewriteSourceMap_1.rewriteSourceMap)(scriptSetupAst, ctx.s, {
|
||||
fileName: relativeFilename,
|
||||
startLine,
|
||||
startOffset,
|
||||
});
|
||||
}
|
||||
}
|
||||
// 1.1 walk import declarations of <script>
|
||||
if (scriptAst) {
|
||||
for (const node of scriptAst.body) {
|
||||
if (node.type === 'ImportDeclaration') {
|
||||
// record imports for dedupe
|
||||
for (const specifier of node.specifiers) {
|
||||
const imported = (0, utils_1.getImportedName)(specifier);
|
||||
registerUserImport(node.source.value, specifier.local.name, imported, node.importKind === 'type' ||
|
||||
(specifier.type === 'ImportSpecifier' &&
|
||||
specifier.importKind === 'type'), false, !options.inlineTemplate);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// 1.2 walk import declarations of <script setup>
|
||||
for (const node of scriptSetupAst.body) {
|
||||
if (node.type === 'ImportDeclaration') {
|
||||
// import declarations are moved to top
|
||||
hoistNode(node);
|
||||
// dedupe imports
|
||||
let removed = 0;
|
||||
const removeSpecifier = (i) => {
|
||||
const removeLeft = i > removed;
|
||||
removed++;
|
||||
const current = node.specifiers[i];
|
||||
const next = node.specifiers[i + 1];
|
||||
ctx.s.remove(removeLeft
|
||||
? node.specifiers[i - 1].end + startOffset
|
||||
: current.start + startOffset, next && !removeLeft
|
||||
? next.start + startOffset
|
||||
: current.end + startOffset);
|
||||
};
|
||||
for (let i = 0; i < node.specifiers.length; i++) {
|
||||
const specifier = node.specifiers[i];
|
||||
const local = specifier.local.name;
|
||||
const imported = (0, utils_1.getImportedName)(specifier);
|
||||
const source = node.source.value;
|
||||
const existing = ctx.userImports[local];
|
||||
if (source === 'vue' &&
|
||||
(imported === defineProps_1.DEFINE_PROPS ||
|
||||
imported === defineEmits_1.DEFINE_EMITS ||
|
||||
imported === defineExpose_1.DEFINE_EXPOSE)) {
|
||||
(0, warn_1.warnOnce)(`\`${imported}\` is a compiler macro and no longer needs to be imported.`);
|
||||
removeSpecifier(i);
|
||||
}
|
||||
else if (existing) {
|
||||
if (existing.source === source && existing.imported === imported) {
|
||||
// already imported in <script setup>, dedupe
|
||||
removeSpecifier(i);
|
||||
}
|
||||
else {
|
||||
ctx.error(`different imports aliased to same local name.`, specifier);
|
||||
}
|
||||
}
|
||||
else {
|
||||
registerUserImport(source, local, imported, node.importKind === 'type' ||
|
||||
(specifier.type === 'ImportSpecifier' &&
|
||||
specifier.importKind === 'type'), true, !options.inlineTemplate);
|
||||
}
|
||||
}
|
||||
if (node.specifiers.length && removed === node.specifiers.length) {
|
||||
ctx.s.remove(node.start + startOffset, node.end + startOffset);
|
||||
}
|
||||
}
|
||||
}
|
||||
// 1.3 resolve possible user import alias of `ref` and `reactive`
|
||||
const vueImportAliases = {};
|
||||
for (const key in ctx.userImports) {
|
||||
const { source, imported, local } = ctx.userImports[key];
|
||||
if (source === 'vue')
|
||||
vueImportAliases[imported] = local;
|
||||
}
|
||||
// 2.1 process normal <script> body
|
||||
if (script && scriptAst) {
|
||||
const scriptScope = {
|
||||
offset: script.loc.start.offset,
|
||||
filename: ctx.filename,
|
||||
source: ctx.descriptor.source,
|
||||
};
|
||||
for (const node of scriptAst.body) {
|
||||
if (node.type === 'ExportDefaultDeclaration') {
|
||||
if (!options.scriptAndScriptSetup) {
|
||||
ctx.error(`When <script> and <script setup> are used together, export default is not supported within <script>.`, node, scriptScope);
|
||||
}
|
||||
else {
|
||||
// export default
|
||||
defaultExport = node;
|
||||
// check if user has manually specified `name` or 'render` option in
|
||||
// export default
|
||||
// if has name, skip name inference
|
||||
// if has render and no template, generate return object instead of
|
||||
// empty render function (#4980)
|
||||
let optionProperties;
|
||||
if (defaultExport.declaration.type === 'ObjectExpression') {
|
||||
optionProperties = defaultExport.declaration.properties;
|
||||
}
|
||||
else if (defaultExport.declaration.type === 'CallExpression' &&
|
||||
defaultExport.declaration.arguments[0] &&
|
||||
defaultExport.declaration.arguments[0].type === 'ObjectExpression') {
|
||||
optionProperties = defaultExport.declaration.arguments[0].properties;
|
||||
}
|
||||
if (optionProperties) {
|
||||
for (const p of optionProperties) {
|
||||
if (p.type === 'ObjectProperty' &&
|
||||
p.key.type === 'Identifier' &&
|
||||
p.key.name === 'name') {
|
||||
ctx.hasDefaultExportName = true;
|
||||
}
|
||||
if ((p.type === 'ObjectMethod' || p.type === 'ObjectProperty') &&
|
||||
p.key.type === 'Identifier' &&
|
||||
p.key.name === 'render') {
|
||||
// TODO warn when we provide a better way to do it?
|
||||
ctx.hasDefaultExportRender = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
// export default { ... } --> const __default__ = { ... }
|
||||
const start = node.start + scriptStartOffset;
|
||||
const end = node.declaration.start + scriptStartOffset;
|
||||
ctx.s.overwrite(start, end, `const ${exports.normalScriptDefaultVar} = `);
|
||||
}
|
||||
}
|
||||
else if (node.type === 'ExportNamedDeclaration') {
|
||||
if (!options.scriptAndScriptSetup) {
|
||||
ctx.error(`When <script> and <script setup> are used together, export is not supported within <script>.`, node, scriptScope);
|
||||
}
|
||||
else {
|
||||
const defaultSpecifier = node.specifiers.find((s) => s.exported.type === 'Identifier' && s.exported.name === 'default');
|
||||
if (defaultSpecifier) {
|
||||
defaultExport = node;
|
||||
// 1. remove specifier
|
||||
if (node.specifiers.length > 1) {
|
||||
ctx.s.remove(defaultSpecifier.start + scriptStartOffset, defaultSpecifier.end + scriptStartOffset);
|
||||
}
|
||||
else {
|
||||
ctx.s.remove(node.start + scriptStartOffset, node.end + scriptStartOffset);
|
||||
}
|
||||
if (node.source) {
|
||||
// export { x as default } from './x'
|
||||
// rewrite to `import { x as __default__ } from './x'` and
|
||||
// add to top
|
||||
ctx.s.prepend(`import { ${defaultSpecifier.local.name} as ${exports.normalScriptDefaultVar} } from '${node.source.value}'\n`);
|
||||
}
|
||||
else {
|
||||
// export { x as default }
|
||||
// rewrite to `const __default__ = x` and move to end
|
||||
ctx.s.appendLeft(scriptEndOffset, `\nconst ${exports.normalScriptDefaultVar} = ${defaultSpecifier.local.name}\n`);
|
||||
}
|
||||
}
|
||||
if (node.declaration) {
|
||||
walkDeclaration('script', node.declaration, scriptBindings, vueImportAliases, hoistStatic);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ((node.type === 'VariableDeclaration' ||
|
||||
node.type === 'FunctionDeclaration' ||
|
||||
node.type === 'ClassDeclaration' ||
|
||||
node.type === 'TSEnumDeclaration') &&
|
||||
!node.declare) {
|
||||
walkDeclaration('script', node, scriptBindings, vueImportAliases, hoistStatic);
|
||||
}
|
||||
}
|
||||
// apply reactivity transform
|
||||
// TODO remove in 3.4
|
||||
// if (enableReactivityTransform && shouldTransform(script.content)) {
|
||||
// const { rootRefs, importedHelpers } = transformAST(
|
||||
// scriptAst,
|
||||
// ctx.s,
|
||||
// scriptStartOffset!
|
||||
// )
|
||||
// refBindings = rootRefs
|
||||
// for (const h of importedHelpers) {
|
||||
// ctx.helperImports.add(h)
|
||||
// }
|
||||
// }
|
||||
// <script> after <script setup>
|
||||
// we need to move the block up so that `const __default__` is
|
||||
// declared before being used in the actual component definition
|
||||
if (scriptStartOffset > startOffset) {
|
||||
// if content doesn't end with newline, add one
|
||||
if (!/\n$/.test(script.content.trim())) {
|
||||
ctx.s.appendLeft(scriptEndOffset, `\n`);
|
||||
}
|
||||
ctx.s.move(scriptStartOffset, scriptEndOffset, 0);
|
||||
}
|
||||
}
|
||||
// 2.2 process <script setup> body
|
||||
for (const node of scriptSetupAst.body) {
|
||||
if (node.type === 'ExpressionStatement') {
|
||||
const expr = (0, utils_1.unwrapTSNode)(node.expression);
|
||||
// process `defineProps` and `defineEmit(s)` calls
|
||||
if ((0, defineProps_1.processDefineProps)(ctx, expr) ||
|
||||
(0, defineEmits_1.processDefineEmits)(ctx, expr) ||
|
||||
(0, defineOptions_1.processDefineOptions)(ctx, expr) ||
|
||||
(0, defineSlots_1.processDefineSlots)(ctx, expr)) {
|
||||
ctx.s.remove(node.start + startOffset, node.end + startOffset);
|
||||
}
|
||||
else if ((0, defineExpose_1.processDefineExpose)(ctx, expr)) {
|
||||
// defineExpose({}) -> expose({})
|
||||
const callee = expr.callee;
|
||||
ctx.s.overwrite(callee.start + startOffset, callee.end + startOffset, '__expose');
|
||||
}
|
||||
else {
|
||||
(0, defineModel_1.processDefineModel)(ctx, expr);
|
||||
}
|
||||
}
|
||||
if (node.type === 'VariableDeclaration' && !node.declare) {
|
||||
const total = node.declarations.length;
|
||||
let left = total;
|
||||
let lastNonRemoved;
|
||||
for (let i = 0; i < total; i++) {
|
||||
const decl = node.declarations[i];
|
||||
const init = decl.init && (0, utils_1.unwrapTSNode)(decl.init);
|
||||
if (init) {
|
||||
if ((0, defineOptions_1.processDefineOptions)(ctx, init)) {
|
||||
ctx.error(`${defineOptions_1.DEFINE_OPTIONS}() has no returning value, it cannot be assigned.`, node);
|
||||
}
|
||||
// defineProps / defineEmits
|
||||
const isDefineProps = (0, defineProps_1.processDefineProps)(ctx, init, decl.id);
|
||||
const isDefineEmits = !isDefineProps && (0, defineEmits_1.processDefineEmits)(ctx, init, decl.id);
|
||||
!isDefineEmits &&
|
||||
((0, defineSlots_1.processDefineSlots)(ctx, init, decl.id) ||
|
||||
(0, defineModel_1.processDefineModel)(ctx, init, decl.id));
|
||||
if (isDefineProps &&
|
||||
!ctx.propsDestructureRestId &&
|
||||
ctx.propsDestructureDecl) {
|
||||
if (left === 1) {
|
||||
ctx.s.remove(node.start + startOffset, node.end + startOffset);
|
||||
}
|
||||
else {
|
||||
let start = decl.start + startOffset;
|
||||
let end = decl.end + startOffset;
|
||||
if (i === total - 1) {
|
||||
// last one, locate the end of the last one that is not removed
|
||||
// if we arrive at this branch, there must have been a
|
||||
// non-removed decl before us, so lastNonRemoved is non-null.
|
||||
start = node.declarations[lastNonRemoved].end + startOffset;
|
||||
}
|
||||
else {
|
||||
// not the last one, locate the start of the next
|
||||
end = node.declarations[i + 1].start + startOffset;
|
||||
}
|
||||
ctx.s.remove(start, end);
|
||||
left--;
|
||||
}
|
||||
}
|
||||
else if (isDefineEmits) {
|
||||
if (decl.id.type === 'Identifier') {
|
||||
ctx.s.overwrite(startOffset + node.start, startOffset + node.end, `function ${decl.id.name}(event: string, ...do_not_transform_spread: Array<any | null>) {
|
||||
__ins.emit(event, ...do_not_transform_spread)
|
||||
}`);
|
||||
}
|
||||
// ctx.s.overwrite(
|
||||
// startOffset + init.start!,
|
||||
// startOffset + init.end!,
|
||||
// '__emit'
|
||||
// )
|
||||
}
|
||||
else {
|
||||
lastNonRemoved = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
let isAllLiteral = false;
|
||||
// walk declarations to record declared bindings
|
||||
if ((node.type === 'VariableDeclaration' ||
|
||||
node.type === 'FunctionDeclaration' ||
|
||||
node.type === 'ClassDeclaration' ||
|
||||
node.type === 'TSEnumDeclaration') &&
|
||||
!node.declare) {
|
||||
isAllLiteral = walkDeclaration('scriptSetup', node, setupBindings, vueImportAliases, hoistStatic);
|
||||
}
|
||||
// hoist literal constants
|
||||
if (hoistStatic && isAllLiteral) {
|
||||
hoistNode(node);
|
||||
}
|
||||
// walk statements & named exports / variable declarations for top level
|
||||
// await
|
||||
if ((node.type === 'VariableDeclaration' && !node.declare) ||
|
||||
node.type.endsWith('Statement')) {
|
||||
const scope = [scriptSetupAst.body];
|
||||
(0, estree_walker_1.walk)(node, {
|
||||
enter(child, parent) {
|
||||
if ((0, compiler_dom_1.isFunctionType)(child)) {
|
||||
this.skip();
|
||||
}
|
||||
if (child.type === 'BlockStatement') {
|
||||
scope.push(child.body);
|
||||
}
|
||||
if (child.type === 'AwaitExpression') {
|
||||
ctx.error(`<script setup> cannot contain Top-level await.`, node);
|
||||
// hasAwait = true
|
||||
// // if the await expression is an expression statement and
|
||||
// // - is in the root scope
|
||||
// // - or is not the first statement in a nested block scope
|
||||
// // then it needs a semicolon before the generated code.
|
||||
// const currentScope = scope[scope.length - 1]
|
||||
// const needsSemi = currentScope.some((n, i) => {
|
||||
// return (
|
||||
// (scope.length === 1 || i > 0) &&
|
||||
// n.type === 'ExpressionStatement' &&
|
||||
// n.start === child.start
|
||||
// )
|
||||
// })
|
||||
// processAwait(
|
||||
// ctx,
|
||||
// child,
|
||||
// needsSemi,
|
||||
// parent!.type === 'ExpressionStatement'
|
||||
// )
|
||||
}
|
||||
},
|
||||
exit(node) {
|
||||
if (node.type === 'BlockStatement')
|
||||
scope.pop();
|
||||
},
|
||||
});
|
||||
}
|
||||
if ((node.type === 'ExportNamedDeclaration' && node.exportKind !== 'type') ||
|
||||
node.type === 'ExportAllDeclaration' ||
|
||||
node.type === 'ExportDefaultDeclaration') {
|
||||
ctx.error(`<script setup> cannot contain ES module exports. ` +
|
||||
`If you are using a previous version of <script setup>, please ` +
|
||||
`consult the updated RFC at https://github.com/vuejs/rfcs/pull/227.`, node);
|
||||
}
|
||||
// move all Type declarations to outer scope
|
||||
if (node.type.startsWith('TS') ||
|
||||
(node.type === 'ExportNamedDeclaration' && node.exportKind === 'type') ||
|
||||
(node.type === 'VariableDeclaration' && node.declare)) {
|
||||
if (node.type !== 'TSEnumDeclaration') {
|
||||
hoistNode(node);
|
||||
}
|
||||
}
|
||||
}
|
||||
// 3 props destructure transform
|
||||
// if (ctx.propsDestructureDecl) {
|
||||
// transformDestructuredProps(ctx, vueImportAliases)
|
||||
// }
|
||||
// 4. Apply reactivity transform
|
||||
// TODO remove in 3.4
|
||||
// if (
|
||||
// enableReactivityTransform &&
|
||||
// // normal <script> had ref bindings that maybe used in <script setup>
|
||||
// (refBindings || shouldTransform(scriptSetup.content))
|
||||
// ) {
|
||||
// const { rootRefs, importedHelpers } = transformAST(
|
||||
// scriptSetupAst,
|
||||
// ctx.s,
|
||||
// startOffset,
|
||||
// refBindings
|
||||
// )
|
||||
// refBindings = refBindings ? [...refBindings, ...rootRefs] : rootRefs
|
||||
// for (const h of importedHelpers) {
|
||||
// ctx.helperImports.add(h)
|
||||
// }
|
||||
// }
|
||||
// 5. check macro args to make sure it doesn't reference setup scope
|
||||
// variables
|
||||
checkInvalidScopeReference(ctx.propsRuntimeDecl, defineProps_1.DEFINE_PROPS);
|
||||
checkInvalidScopeReference(ctx.propsRuntimeDefaults, defineProps_1.DEFINE_PROPS);
|
||||
checkInvalidScopeReference(ctx.propsDestructureDecl, defineProps_1.DEFINE_PROPS);
|
||||
checkInvalidScopeReference(ctx.emitsRuntimeDecl, defineEmits_1.DEFINE_EMITS);
|
||||
checkInvalidScopeReference(ctx.optionsRuntimeDecl, defineOptions_1.DEFINE_OPTIONS);
|
||||
// 6. remove non-script content
|
||||
if (script) {
|
||||
if (startOffset < scriptStartOffset) {
|
||||
// <script setup> before <script>
|
||||
ctx.s.remove(0, startOffset);
|
||||
ctx.s.remove(endOffset, scriptStartOffset);
|
||||
ctx.s.remove(scriptEndOffset, source.length);
|
||||
}
|
||||
else {
|
||||
// <script> before <script setup>
|
||||
ctx.s.remove(0, scriptStartOffset);
|
||||
ctx.s.remove(scriptEndOffset, startOffset);
|
||||
ctx.s.remove(endOffset, source.length);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// only <script setup>
|
||||
ctx.s.remove(0, startOffset);
|
||||
ctx.s.remove(endOffset, source.length);
|
||||
}
|
||||
// 7. analyze binding metadata
|
||||
// `defineProps` & `defineModel` also register props bindings
|
||||
if (scriptAst) {
|
||||
Object.assign(ctx.bindingMetadata, (0, analyzeScriptBindings_1.analyzeScriptBindings)(scriptAst.body));
|
||||
}
|
||||
for (const [key, { isType, imported, source }] of Object.entries(ctx.userImports)) {
|
||||
if (isType)
|
||||
continue;
|
||||
ctx.bindingMetadata[key] =
|
||||
imported === '*' ||
|
||||
(imported === 'default' && source.endsWith('.vue')) ||
|
||||
source === 'vue'
|
||||
? compiler_dom_1.BindingTypes.SETUP_CONST
|
||||
: compiler_dom_1.BindingTypes.SETUP_MAYBE_REF;
|
||||
}
|
||||
for (const key in scriptBindings) {
|
||||
ctx.bindingMetadata[key] = scriptBindings[key];
|
||||
}
|
||||
for (const key in setupBindings) {
|
||||
ctx.bindingMetadata[key] = setupBindings[key];
|
||||
}
|
||||
// known ref bindings
|
||||
if (refBindings) {
|
||||
for (const key of refBindings) {
|
||||
ctx.bindingMetadata[key] = compiler_dom_1.BindingTypes.SETUP_REF;
|
||||
}
|
||||
}
|
||||
// 8. inject `useCssVars` calls
|
||||
// if (
|
||||
// sfc.cssVars.length &&
|
||||
// // no need to do this when targeting SSR
|
||||
// !options.templateOptions?.ssr
|
||||
// ) {
|
||||
// ctx.helperImports.add(CSS_VARS_HELPER)
|
||||
// ctx.helperImports.add('unref')
|
||||
// ctx.s.prependLeft(
|
||||
// startOffset,
|
||||
// `\n${genCssVarsCode(
|
||||
// sfc.cssVars,
|
||||
// ctx.bindingMetadata,
|
||||
// scopeId,
|
||||
// !!options.isProd
|
||||
// )}\n`
|
||||
// )
|
||||
// }
|
||||
// 9. finalize setup() argument signature
|
||||
let args = `__props`;
|
||||
// inject user assignment of props
|
||||
// we use a default __props so that template expressions referencing props
|
||||
// can use it directly
|
||||
if (ctx.propsDecl) {
|
||||
if (ctx.propsDestructureRestId) {
|
||||
ctx.s.overwrite(startOffset + ctx.propsCall.start, startOffset + ctx.propsCall.end, `${ctx.helper(`createPropsRestProxy`)}(__props, ${JSON.stringify(Object.keys(ctx.propsDestructuredBindings))})`);
|
||||
ctx.s.overwrite(startOffset + ctx.propsDestructureDecl.start, startOffset + ctx.propsDestructureDecl.end, ctx.propsDestructureRestId);
|
||||
}
|
||||
else if (!ctx.propsDestructureDecl) {
|
||||
ctx.s.overwrite(startOffset + ctx.propsCall.start, startOffset + ctx.propsCall.end, '__props');
|
||||
}
|
||||
}
|
||||
// inject temp variables for async context preservation
|
||||
// if (hasAwait) {
|
||||
// const any = `: any`
|
||||
// ctx.s.prependLeft(startOffset, `\nlet __temp${any}, __restore${any}\n`)
|
||||
// }
|
||||
const destructureElements = ctx.hasDefineExposeCall || !options.inlineTemplate
|
||||
? [`expose: __expose`]
|
||||
: [];
|
||||
// emit 是个函数且不定参数,不通过解构处理
|
||||
// if (ctx.emitDecl) {
|
||||
// destructureElements.push(`emit: __emit`)
|
||||
// }
|
||||
if (destructureElements.length) {
|
||||
args += `, { ${destructureElements.join(', ')} }: SetupContext`;
|
||||
}
|
||||
// 10. finalize default export
|
||||
const genDefaultAs = options.genDefaultAs
|
||||
? `const ${options.genDefaultAs} =`
|
||||
: `export default`;
|
||||
if (options.genDefaultAs) {
|
||||
ctx.s.append(`\nexport default ${options.genDefaultAs}`);
|
||||
}
|
||||
let runtimeOptions = ``;
|
||||
if (!ctx.hasDefaultExportName && filename && filename !== exports.DEFAULT_FILENAME) {
|
||||
const match = filename.match(/([^/\\]+)\.\w+$/);
|
||||
if (match) {
|
||||
runtimeOptions += `\n __name: '${match[1]}',`;
|
||||
}
|
||||
}
|
||||
// if (hasInlinedSsrRenderFn) {
|
||||
// runtimeOptions += `\n __ssrInlineRender: true,`
|
||||
// }
|
||||
if (ctx.optionsRuntimeDecl) {
|
||||
runtimeOptions +=
|
||||
`\n` +
|
||||
scriptSetup.content
|
||||
.slice(ctx.optionsRuntimeDecl.start, ctx.optionsRuntimeDecl.end)
|
||||
.trim()
|
||||
.slice(1, -1) +
|
||||
`,`;
|
||||
}
|
||||
const slotsDecl = (0, defineSlots_1.genRuntimeSlots)(ctx);
|
||||
if (slotsDecl)
|
||||
runtimeOptions += `\n slots: ${slotsDecl},`;
|
||||
const propsDecl = (0, defineProps_1.genRuntimeProps)(ctx);
|
||||
if (propsDecl) {
|
||||
if (ctx.propsInterfaceDecl) {
|
||||
runtimeOptions += `\n __props: ${ctx.propsInterfaceDecl.id.name},`;
|
||||
}
|
||||
runtimeOptions += `\n props: ${propsDecl},`;
|
||||
}
|
||||
const emitsDecl = (0, defineEmits_1.genRuntimeEmits)(ctx);
|
||||
if (emitsDecl)
|
||||
runtimeOptions += `\n emits: ${emitsDecl},`;
|
||||
// <script setup> components are closed by default. If the user did not
|
||||
// explicitly call `defineExpose`, call expose() with no args.
|
||||
const exposeCall = ``;
|
||||
// ctx.hasDefineExposeCall || options.inlineTemplate ? `` : ` __expose();\n`
|
||||
// wrap setup code with function.
|
||||
// for TS, make sure the exported type is still valid type with
|
||||
// correct props information
|
||||
// we have to use object spread for types to be merged properly
|
||||
// user's TS setting should compile it down to proper targets
|
||||
// export default defineComponent({ ...__default__, ... })
|
||||
ctx.s.prependLeft(startOffset, `\n${genDefaultAs} ${ctx.helper((0, utils_1.resolveDefineCode)(ctx.options.componentType))}({${runtimeOptions}\n ` +
|
||||
`${hasAwait ? `async ` : ``}setup(${args}): any | null {
|
||||
const __ins = getCurrentInstance()!;
|
||||
const _ctx = __ins.proxy${options.genDefaultAs
|
||||
? ` as InstanceType<typeof ${options.genDefaultAs}>`
|
||||
: ''};
|
||||
const _cache = __ins.renderCache;
|
||||
${exposeCall}`);
|
||||
let scriptMap;
|
||||
// 11. generate return statement
|
||||
// 剩余由 rust 编译器处理
|
||||
if (options.componentType !== 'app') {
|
||||
const { code, preamble, map } = (0, normalScript_1.processTemplate)(sfc, {
|
||||
relativeFilename,
|
||||
bindingMetadata: ctx.bindingMetadata,
|
||||
rootDir: options.root,
|
||||
className: options.className,
|
||||
});
|
||||
if (preamble) {
|
||||
ctx.s.prepend(preamble);
|
||||
}
|
||||
// 放到最后,以免查找 offset 有问题
|
||||
let offset = map ? (ctx.s.toString().match(/\r?\n/g)?.length ?? 0) + 1 : 1;
|
||||
if (options.genDefaultAs) {
|
||||
offset = offset - 2; // 排除 export default __sfc__
|
||||
}
|
||||
ctx.s.appendRight(endOffset, `\nreturn ${code}\n}\n\n})`);
|
||||
ctx.s.trim();
|
||||
scriptMap =
|
||||
options.sourceMap !== false
|
||||
? ctx.s.generateMap({
|
||||
source: relativeFilename,
|
||||
hires: true,
|
||||
includeContent: true,
|
||||
})
|
||||
: undefined;
|
||||
if (map && scriptMap) {
|
||||
scriptMap = generateScriptMap(offset, map, scriptMap);
|
||||
}
|
||||
}
|
||||
else {
|
||||
ctx.s.appendRight(endOffset, `})`);
|
||||
ctx.s.trim();
|
||||
scriptMap =
|
||||
options.sourceMap !== false
|
||||
? ctx.s.generateMap({
|
||||
source: relativeFilename,
|
||||
hires: true,
|
||||
includeContent: true,
|
||||
})
|
||||
: undefined;
|
||||
}
|
||||
// 12. finalize Vue helper imports
|
||||
// if (ctx.helperImports.size > 0) {
|
||||
// ctx.s.prepend(
|
||||
// `import { ${[...ctx.helperImports]
|
||||
// .map((h) => `${h} as _${h}`)
|
||||
// .join(', ')} } from 'vue'\n`
|
||||
// )
|
||||
// }
|
||||
return {
|
||||
...scriptSetup,
|
||||
bindings: ctx.bindingMetadata,
|
||||
imports: ctx.userImports,
|
||||
content: ctx.s.toString(),
|
||||
map: scriptMap,
|
||||
scriptAst: scriptAst?.body,
|
||||
scriptSetupAst: scriptSetupAst?.body,
|
||||
deps: ctx.deps ? [...ctx.deps] : undefined,
|
||||
};
|
||||
}
|
||||
exports.compileScript = compileScript;
|
||||
function generateScriptMap(offset, templateMap, scriptMap) {
|
||||
const templateMapConsumer = new source_map_js_1.SourceMapConsumer(templateMap);
|
||||
const scriptMapConsumer = new source_map_js_1.SourceMapConsumer(scriptMap);
|
||||
const scriptMapGenerator = new source_map_js_1.SourceMapGenerator();
|
||||
scriptMapConsumer.eachMapping((m) => {
|
||||
scriptMapGenerator.addMapping({
|
||||
original: {
|
||||
line: m.originalLine ?? 0,
|
||||
column: m.originalColumn ?? 0,
|
||||
},
|
||||
generated: {
|
||||
line: m.generatedLine,
|
||||
column: m.generatedColumn,
|
||||
},
|
||||
source: m.source,
|
||||
name: m.name,
|
||||
});
|
||||
});
|
||||
templateMapConsumer.eachMapping((m) => {
|
||||
scriptMapGenerator.addMapping({
|
||||
original: {
|
||||
line: m.originalLine ?? 0,
|
||||
column: m.originalColumn ?? 0,
|
||||
},
|
||||
generated: {
|
||||
line: m.generatedLine + offset,
|
||||
column: m.generatedColumn,
|
||||
},
|
||||
source: m.source,
|
||||
name: m.name,
|
||||
});
|
||||
});
|
||||
scriptMap.sources.forEach(function (sourceFile) {
|
||||
const sourceContent = scriptMapConsumer.sourceContentFor(sourceFile);
|
||||
if (sourceContent != null) {
|
||||
scriptMapGenerator.setSourceContent(sourceFile, sourceContent);
|
||||
}
|
||||
});
|
||||
return JSON.parse(scriptMapGenerator.toString());
|
||||
}
|
||||
function registerBinding(bindings, node, type) {
|
||||
bindings[node.name] = type;
|
||||
}
|
||||
function walkDeclaration(from, node, bindings, userImportAliases, hoistStatic) {
|
||||
let isAllLiteral = false;
|
||||
if (node.type === 'VariableDeclaration') {
|
||||
const isConst = node.kind === 'const';
|
||||
isAllLiteral =
|
||||
isConst &&
|
||||
node.declarations.every((decl) => decl.id.type === 'Identifier' && isStaticNode(decl.init));
|
||||
// export const foo = ...
|
||||
for (const { id, init: _init } of node.declarations) {
|
||||
const init = _init && (0, utils_1.unwrapTSNode)(_init);
|
||||
const isDefineCall = !!(isConst &&
|
||||
(0, utils_1.isCallOf)(init, (c) => c === defineProps_1.DEFINE_PROPS || c === defineEmits_1.DEFINE_EMITS || c === defineProps_1.WITH_DEFAULTS));
|
||||
if (id.type === 'Identifier') {
|
||||
let bindingType;
|
||||
const userReactiveBinding = userImportAliases['reactive'];
|
||||
if ((hoistStatic || from === 'script') &&
|
||||
(isAllLiteral || (isConst && isStaticNode(init)))) {
|
||||
bindingType = compiler_dom_1.BindingTypes.LITERAL_CONST;
|
||||
}
|
||||
else if ((0, utils_1.isCallOf)(init, userReactiveBinding)) {
|
||||
// treat reactive() calls as let since it's meant to be mutable
|
||||
bindingType = isConst
|
||||
? compiler_dom_1.BindingTypes.SETUP_REACTIVE_CONST
|
||||
: compiler_dom_1.BindingTypes.SETUP_LET;
|
||||
}
|
||||
else if (
|
||||
// if a declaration is a const literal, we can mark it so that
|
||||
// the generated render fn code doesn't need to unref() it
|
||||
isDefineCall ||
|
||||
(isConst && canNeverBeRef(init, userReactiveBinding))) {
|
||||
bindingType = (0, utils_1.isCallOf)(init, defineProps_1.DEFINE_PROPS)
|
||||
? compiler_dom_1.BindingTypes.SETUP_REACTIVE_CONST
|
||||
: compiler_dom_1.BindingTypes.SETUP_CONST;
|
||||
}
|
||||
else if (isConst) {
|
||||
if ((0, utils_1.isCallOf)(init, (m) => m === userImportAliases['ref'] ||
|
||||
m === userImportAliases['computed'] ||
|
||||
m === userImportAliases['shallowRef'] ||
|
||||
m === userImportAliases['customRef'] ||
|
||||
m === userImportAliases['toRef'] ||
|
||||
m === defineModel_1.DEFINE_MODEL)) {
|
||||
bindingType = compiler_dom_1.BindingTypes.SETUP_REF;
|
||||
}
|
||||
else {
|
||||
bindingType = compiler_dom_1.BindingTypes.SETUP_MAYBE_REF;
|
||||
}
|
||||
}
|
||||
else {
|
||||
bindingType = compiler_dom_1.BindingTypes.SETUP_LET;
|
||||
}
|
||||
registerBinding(bindings, id, bindingType);
|
||||
}
|
||||
else {
|
||||
if ((0, utils_1.isCallOf)(init, defineProps_1.DEFINE_PROPS)) {
|
||||
continue;
|
||||
}
|
||||
if (id.type === 'ObjectPattern') {
|
||||
walkObjectPattern(id, bindings, isConst, isDefineCall);
|
||||
}
|
||||
else if (id.type === 'ArrayPattern') {
|
||||
walkArrayPattern(id, bindings, isConst, isDefineCall);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (node.type === 'TSEnumDeclaration') {
|
||||
isAllLiteral = node.members.every((member) => !member.initializer || isStaticNode(member.initializer));
|
||||
bindings[node.id.name] = isAllLiteral
|
||||
? compiler_dom_1.BindingTypes.LITERAL_CONST
|
||||
: compiler_dom_1.BindingTypes.SETUP_CONST;
|
||||
}
|
||||
else if (node.type === 'FunctionDeclaration' ||
|
||||
node.type === 'ClassDeclaration') {
|
||||
// export function foo() {} / export class Foo {}
|
||||
// export declarations must be named.
|
||||
bindings[node.id.name] = compiler_dom_1.BindingTypes.SETUP_CONST;
|
||||
}
|
||||
return isAllLiteral;
|
||||
}
|
||||
function walkObjectPattern(node, bindings, isConst, isDefineCall = false) {
|
||||
for (const p of node.properties) {
|
||||
if (p.type === 'ObjectProperty') {
|
||||
if (p.key.type === 'Identifier' && p.key === p.value) {
|
||||
// shorthand: const { x } = ...
|
||||
const type = isDefineCall
|
||||
? compiler_dom_1.BindingTypes.SETUP_CONST
|
||||
: isConst
|
||||
? compiler_dom_1.BindingTypes.SETUP_MAYBE_REF
|
||||
: compiler_dom_1.BindingTypes.SETUP_LET;
|
||||
registerBinding(bindings, p.key, type);
|
||||
}
|
||||
else {
|
||||
walkPattern(p.value, bindings, isConst, isDefineCall);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// ...rest
|
||||
// argument can only be identifier when destructuring
|
||||
const type = isConst ? compiler_dom_1.BindingTypes.SETUP_CONST : compiler_dom_1.BindingTypes.SETUP_LET;
|
||||
registerBinding(bindings, p.argument, type);
|
||||
}
|
||||
}
|
||||
}
|
||||
function walkArrayPattern(node, bindings, isConst, isDefineCall = false) {
|
||||
for (const e of node.elements) {
|
||||
e && walkPattern(e, bindings, isConst, isDefineCall);
|
||||
}
|
||||
}
|
||||
function walkPattern(node, bindings, isConst, isDefineCall = false) {
|
||||
if (node.type === 'Identifier') {
|
||||
const type = isDefineCall
|
||||
? compiler_dom_1.BindingTypes.SETUP_CONST
|
||||
: isConst
|
||||
? compiler_dom_1.BindingTypes.SETUP_MAYBE_REF
|
||||
: compiler_dom_1.BindingTypes.SETUP_LET;
|
||||
registerBinding(bindings, node, type);
|
||||
}
|
||||
else if (node.type === 'RestElement') {
|
||||
// argument can only be identifier when destructuring
|
||||
const type = isConst ? compiler_dom_1.BindingTypes.SETUP_CONST : compiler_dom_1.BindingTypes.SETUP_LET;
|
||||
registerBinding(bindings, node.argument, type);
|
||||
}
|
||||
else if (node.type === 'ObjectPattern') {
|
||||
walkObjectPattern(node, bindings, isConst);
|
||||
}
|
||||
else if (node.type === 'ArrayPattern') {
|
||||
walkArrayPattern(node, bindings, isConst);
|
||||
}
|
||||
else if (node.type === 'AssignmentPattern') {
|
||||
if (node.left.type === 'Identifier') {
|
||||
const type = isDefineCall
|
||||
? compiler_dom_1.BindingTypes.SETUP_CONST
|
||||
: isConst
|
||||
? compiler_dom_1.BindingTypes.SETUP_MAYBE_REF
|
||||
: compiler_dom_1.BindingTypes.SETUP_LET;
|
||||
registerBinding(bindings, node.left, type);
|
||||
}
|
||||
else {
|
||||
walkPattern(node.left, bindings, isConst);
|
||||
}
|
||||
}
|
||||
}
|
||||
function canNeverBeRef(node, userReactiveImport) {
|
||||
if ((0, utils_1.isCallOf)(node, userReactiveImport)) {
|
||||
return true;
|
||||
}
|
||||
switch (node.type) {
|
||||
case 'UnaryExpression':
|
||||
case 'BinaryExpression':
|
||||
case 'ArrayExpression':
|
||||
case 'ObjectExpression':
|
||||
case 'FunctionExpression':
|
||||
case 'ArrowFunctionExpression':
|
||||
case 'UpdateExpression':
|
||||
case 'ClassExpression':
|
||||
case 'TaggedTemplateExpression':
|
||||
return true;
|
||||
case 'SequenceExpression':
|
||||
return canNeverBeRef(node.expressions[node.expressions.length - 1], userReactiveImport);
|
||||
default:
|
||||
if ((0, utils_1.isLiteralNode)(node)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
function isStaticNode(node) {
|
||||
node = (0, utils_1.unwrapTSNode)(node);
|
||||
switch (node.type) {
|
||||
case 'UnaryExpression': // void 0, !true
|
||||
return isStaticNode(node.argument);
|
||||
case 'LogicalExpression': // 1 > 2
|
||||
case 'BinaryExpression': // 1 + 2
|
||||
return isStaticNode(node.left) && isStaticNode(node.right);
|
||||
case 'ConditionalExpression': {
|
||||
// 1 ? 2 : 3
|
||||
return (isStaticNode(node.test) &&
|
||||
isStaticNode(node.consequent) &&
|
||||
isStaticNode(node.alternate));
|
||||
}
|
||||
case 'SequenceExpression': // (1, 2)
|
||||
case 'TemplateLiteral': // `foo${1}`
|
||||
return node.expressions.every((expr) => isStaticNode(expr));
|
||||
case 'ParenthesizedExpression': // (1)
|
||||
return isStaticNode(node.expression);
|
||||
case 'StringLiteral':
|
||||
case 'NumericLiteral':
|
||||
case 'BooleanLiteral':
|
||||
case 'NullLiteral':
|
||||
case 'BigIntLiteral':
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
Generated
Vendored
+10
@@ -0,0 +1,10 @@
|
||||
import MagicString from 'magic-string';
|
||||
import type { ParserPlugin } from '@babel/parser';
|
||||
import type { Statement } from '@babel/types';
|
||||
export declare function rewriteDefault(input: string, as: string, define: string, parserPlugins?: ParserPlugin[]): string;
|
||||
/**
|
||||
* Utility for rewriting `export default` in a script block into a variable
|
||||
* declaration so that we can inject things into it
|
||||
*/
|
||||
export declare function rewriteDefaultAST(ast: Statement[], s: MagicString, as: string, define: string): void;
|
||||
export declare function hasDefaultExport(ast: Statement[]): boolean;
|
||||
Generated
Vendored
+105
@@ -0,0 +1,105 @@
|
||||
"use strict";
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.hasDefaultExport = exports.rewriteDefaultAST = exports.rewriteDefault = void 0;
|
||||
const parser_1 = require("@babel/parser");
|
||||
const magic_string_1 = __importDefault(require("magic-string"));
|
||||
function rewriteDefault(input, as, define, parserPlugins) {
|
||||
const ast = (0, parser_1.parse)(input, {
|
||||
sourceType: 'module',
|
||||
plugins: parserPlugins,
|
||||
}).program.body;
|
||||
const s = new magic_string_1.default(input);
|
||||
rewriteDefaultAST(ast, s, as, define);
|
||||
return s.toString();
|
||||
}
|
||||
exports.rewriteDefault = rewriteDefault;
|
||||
/**
|
||||
* Utility for rewriting `export default` in a script block into a variable
|
||||
* declaration so that we can inject things into it
|
||||
*/
|
||||
function rewriteDefaultAST(ast, s, as, define) {
|
||||
if (!hasDefaultExport(ast)) {
|
||||
s.append(`\nconst ${as} = ${define}({})`);
|
||||
return;
|
||||
}
|
||||
// if the script somehow still contains `default export`, it probably has
|
||||
// multi-line comments or template strings. fallback to a full parse.
|
||||
ast.forEach((node) => {
|
||||
if (node.type === 'ExportDefaultDeclaration') {
|
||||
if (node.declaration.type === 'ClassDeclaration' && node.declaration.id) {
|
||||
let start = node.declaration.decorators && node.declaration.decorators.length > 0
|
||||
? node.declaration.decorators[node.declaration.decorators.length - 1].end
|
||||
: node.start;
|
||||
s.overwrite(start, node.declaration.id.start, ` class `);
|
||||
s.append(`\nconst ${as} = ${define}(${node.declaration.id.name})`);
|
||||
}
|
||||
else {
|
||||
s.overwrite(node.start, node.declaration.start, `const ${as} = ${define}(`);
|
||||
s.appendRight(node.declaration.end, ')');
|
||||
}
|
||||
}
|
||||
else if (node.type === 'ExportNamedDeclaration') {
|
||||
for (const specifier of node.specifiers) {
|
||||
if (specifier.type === 'ExportSpecifier' &&
|
||||
specifier.exported.type === 'Identifier' &&
|
||||
specifier.exported.name === 'default') {
|
||||
if (node.source) {
|
||||
if (specifier.local.name === 'default') {
|
||||
s.prepend(`import { default as __VUE_DEFAULT__ } from '${node.source.value}'\n`);
|
||||
const end = specifierEnd(s, specifier.local.end, node.end);
|
||||
s.remove(specifier.start, end);
|
||||
s.append(`\nconst ${as} = ${define}(__VUE_DEFAULT___)`);
|
||||
continue;
|
||||
}
|
||||
else {
|
||||
s.prepend(`import { ${s.slice(specifier.local.start, specifier.local.end)} as __VUE_DEFAULT__ } from '${node.source.value}'\n`);
|
||||
const end = specifierEnd(s, specifier.exported.end, node.end);
|
||||
s.remove(specifier.start, end);
|
||||
s.append(`\nconst ${as} = ${define}(__VUE_DEFAULT__)`);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
const end = specifierEnd(s, specifier.end, node.end);
|
||||
s.remove(specifier.start, end);
|
||||
s.append(`\nconst ${as} = ${specifier.local.name}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
exports.rewriteDefaultAST = rewriteDefaultAST;
|
||||
function hasDefaultExport(ast) {
|
||||
for (const stmt of ast) {
|
||||
if (stmt.type === 'ExportDefaultDeclaration') {
|
||||
return true;
|
||||
}
|
||||
else if (stmt.type === 'ExportNamedDeclaration' &&
|
||||
stmt.specifiers.some((spec) => spec.exported.name === 'default')) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
exports.hasDefaultExport = hasDefaultExport;
|
||||
function specifierEnd(s, end, nodeEnd) {
|
||||
// export { default , foo } ...
|
||||
let hasCommas = false;
|
||||
let oldEnd = end;
|
||||
while (end < nodeEnd) {
|
||||
if (/\s/.test(s.slice(end, end + 1))) {
|
||||
end++;
|
||||
}
|
||||
else if (s.slice(end, end + 1) === ',') {
|
||||
end++;
|
||||
hasCommas = true;
|
||||
break;
|
||||
}
|
||||
else if (s.slice(end, end + 1) === '}') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return hasCommas ? end : oldEnd;
|
||||
}
|
||||
Generated
Vendored
+9
@@ -0,0 +1,9 @@
|
||||
import type { Node, Statement } from '@babel/types';
|
||||
import { type BindingMetadata } from '@vue/compiler-dom';
|
||||
/**
|
||||
* Analyze bindings in normal `<script>`
|
||||
* Note that `compileScriptSetup` already analyzes bindings as part of its
|
||||
* compilation process so this should only be used on single `<script>` SFCs.
|
||||
*/
|
||||
export declare function analyzeScriptBindings(ast: Statement[]): BindingMetadata;
|
||||
export declare function getObjectOrArrayExpressionKeys(value: Node): string[];
|
||||
Generated
Vendored
+113
@@ -0,0 +1,113 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.getObjectOrArrayExpressionKeys = exports.analyzeScriptBindings = void 0;
|
||||
const compiler_dom_1 = require("@vue/compiler-dom");
|
||||
const utils_1 = require("./utils");
|
||||
/**
|
||||
* Analyze bindings in normal `<script>`
|
||||
* Note that `compileScriptSetup` already analyzes bindings as part of its
|
||||
* compilation process so this should only be used on single `<script>` SFCs.
|
||||
*/
|
||||
function analyzeScriptBindings(ast) {
|
||||
for (const node of ast) {
|
||||
if (node.type === 'ExportDefaultDeclaration' &&
|
||||
node.declaration.type === 'ObjectExpression') {
|
||||
return analyzeBindingsFromOptions(node.declaration);
|
||||
}
|
||||
}
|
||||
return {};
|
||||
}
|
||||
exports.analyzeScriptBindings = analyzeScriptBindings;
|
||||
function analyzeBindingsFromOptions(node) {
|
||||
const bindings = {};
|
||||
// #3270, #3275
|
||||
// mark non-script-setup so we don't resolve components/directives from these
|
||||
Object.defineProperty(bindings, '__isScriptSetup', {
|
||||
enumerable: false,
|
||||
value: false,
|
||||
});
|
||||
for (const property of node.properties) {
|
||||
if (property.type === 'ObjectProperty' &&
|
||||
!property.computed &&
|
||||
property.key.type === 'Identifier') {
|
||||
// props
|
||||
if (property.key.name === 'props') {
|
||||
// props: ['foo']
|
||||
// props: { foo: ... }
|
||||
for (const key of getObjectOrArrayExpressionKeys(property.value)) {
|
||||
bindings[key] = compiler_dom_1.BindingTypes.PROPS;
|
||||
}
|
||||
}
|
||||
// inject
|
||||
else if (property.key.name === 'inject') {
|
||||
// inject: ['foo']
|
||||
// inject: { foo: {} }
|
||||
for (const key of getObjectOrArrayExpressionKeys(property.value)) {
|
||||
bindings[key] = compiler_dom_1.BindingTypes.OPTIONS;
|
||||
}
|
||||
}
|
||||
// computed & methods
|
||||
else if (property.value.type === 'ObjectExpression' &&
|
||||
(property.key.name === 'computed' || property.key.name === 'methods')) {
|
||||
// methods: { foo() {} }
|
||||
// computed: { foo() {} }
|
||||
for (const key of getObjectExpressionKeys(property.value)) {
|
||||
bindings[key] = compiler_dom_1.BindingTypes.OPTIONS;
|
||||
}
|
||||
}
|
||||
}
|
||||
// setup & data
|
||||
else if (property.type === 'ObjectMethod' &&
|
||||
property.key.type === 'Identifier' &&
|
||||
(property.key.name === 'setup' || property.key.name === 'data')) {
|
||||
for (const bodyItem of property.body.body) {
|
||||
// setup() {
|
||||
// return {
|
||||
// foo: null
|
||||
// }
|
||||
// }
|
||||
if (bodyItem.type === 'ReturnStatement' &&
|
||||
bodyItem.argument &&
|
||||
bodyItem.argument.type === 'ObjectExpression') {
|
||||
for (const key of getObjectExpressionKeys(bodyItem.argument)) {
|
||||
bindings[key] =
|
||||
property.key.name === 'setup'
|
||||
? compiler_dom_1.BindingTypes.SETUP_MAYBE_REF
|
||||
: compiler_dom_1.BindingTypes.DATA;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return bindings;
|
||||
}
|
||||
function getObjectExpressionKeys(node) {
|
||||
const keys = [];
|
||||
for (const prop of node.properties) {
|
||||
if (prop.type === 'SpreadElement')
|
||||
continue;
|
||||
const key = (0, utils_1.resolveObjectKey)(prop.key, prop.computed);
|
||||
if (key)
|
||||
keys.push(String(key));
|
||||
}
|
||||
return keys;
|
||||
}
|
||||
function getArrayExpressionKeys(node) {
|
||||
const keys = [];
|
||||
for (const element of node.elements) {
|
||||
if (element && element.type === 'StringLiteral') {
|
||||
keys.push(element.value);
|
||||
}
|
||||
}
|
||||
return keys;
|
||||
}
|
||||
function getObjectOrArrayExpressionKeys(value) {
|
||||
if (value.type === 'ArrayExpression') {
|
||||
return getArrayExpressionKeys(value);
|
||||
}
|
||||
if (value.type === 'ObjectExpression') {
|
||||
return getObjectExpressionKeys(value);
|
||||
}
|
||||
return [];
|
||||
}
|
||||
exports.getObjectOrArrayExpressionKeys = getObjectOrArrayExpressionKeys;
|
||||
Generated
Vendored
+61
@@ -0,0 +1,61 @@
|
||||
import type { CallExpression, Node, ObjectPattern, Program, TSInterfaceDeclaration, TSTypeLiteral } from '@babel/types';
|
||||
import type { SFCDescriptor } from '@vue/compiler-sfc';
|
||||
import { type ParserPlugin } from '@babel/parser';
|
||||
import type { ImportBinding, SFCScriptCompileOptions } from '../compileScript';
|
||||
import type { PropsDestructureBindings } from './defineProps';
|
||||
import type { ModelDecl } from './defineModel';
|
||||
import type { BindingMetadata } from '@vue/compiler-core';
|
||||
import MagicString from 'magic-string';
|
||||
import type { TypeScope } from './resolveType';
|
||||
export declare class ScriptCompileContext {
|
||||
descriptor: SFCDescriptor;
|
||||
options: Partial<SFCScriptCompileOptions>;
|
||||
scriptAst: Program | null;
|
||||
scriptSetupAst: Program | null;
|
||||
source: string;
|
||||
filename: string;
|
||||
s: MagicString;
|
||||
startOffset: number | undefined;
|
||||
endOffset: number | undefined;
|
||||
scope?: TypeScope;
|
||||
globalScopes?: TypeScope[];
|
||||
userImports: Record<string, ImportBinding>;
|
||||
hasDefinePropsCall: boolean;
|
||||
hasDefineEmitCall: boolean;
|
||||
hasDefineExposeCall: boolean;
|
||||
hasDefaultExportName: boolean;
|
||||
hasDefaultExportRender: boolean;
|
||||
hasDefineOptionsCall: boolean;
|
||||
hasDefineSlotsCall: boolean;
|
||||
hasDefineModelCall: boolean;
|
||||
propsCall: CallExpression | undefined;
|
||||
propsDecl: Node | undefined;
|
||||
propsRuntimeDecl: Node | undefined;
|
||||
propsTypeDecl: Node | undefined;
|
||||
propsDestructureDecl: ObjectPattern | undefined;
|
||||
propsDestructuredBindings: PropsDestructureBindings;
|
||||
propsDestructureRestId: string | undefined;
|
||||
propsRuntimeDefaults: Node | undefined;
|
||||
propsInterfaceDecl: TSInterfaceDeclaration | undefined;
|
||||
emitsRuntimeDecl: Node | undefined;
|
||||
emitsTypeDecl: Node | undefined;
|
||||
emitDecl: Node | undefined;
|
||||
modelDecls: Record<string, ModelDecl>;
|
||||
optionsRuntimeDecl: Node | undefined;
|
||||
slotsRuntimeDecl: TSTypeLiteral | undefined;
|
||||
bindingMetadata: BindingMetadata;
|
||||
helperImports: Set<string>;
|
||||
helper(key: string): string;
|
||||
/**
|
||||
* to be exposed on compiled script block for HMR cache busting
|
||||
*/
|
||||
deps?: Set<string>;
|
||||
/**
|
||||
* cache for resolved fs
|
||||
*/
|
||||
fs?: NonNullable<SFCScriptCompileOptions['fs']>;
|
||||
constructor(descriptor: SFCDescriptor, options: Partial<SFCScriptCompileOptions>);
|
||||
getString(node: Node, scriptSetup?: boolean): string;
|
||||
error(msg: string, node: Node, scope?: TypeScope): never;
|
||||
}
|
||||
export declare function resolveParserPlugins(lang: string, userPlugins?: ParserPlugin[], dts?: boolean): (import("@babel/parser").ParserPluginWithOptions | ("asyncDoExpressions" | "asyncGenerators" | "bigInt" | "classPrivateMethods" | "classPrivateProperties" | "classProperties" | "classStaticBlock" | "decimal" | "decorators-legacy" | "deferredImportEvaluation" | "decoratorAutoAccessors" | "destructuringPrivate" | "doExpressions" | "dynamicImport" | "explicitResourceManagement" | "exportDefaultFrom" | "exportNamespaceFrom" | "flow" | "flowComments" | "functionBind" | "functionSent" | "importMeta" | "jsx" | "logicalAssignment" | "importAssertions" | "importAttributes" | "importReflection" | "moduleBlocks" | "moduleStringNames" | "nullishCoalescingOperator" | "numericSeparator" | "objectRestSpread" | "optionalCatchBinding" | "optionalChaining" | "partialApplication" | "placeholders" | "privateIn" | "regexpUnicodeSets" | "sourcePhaseImports" | "throwExpressions" | "topLevelAwait" | "v8intrinsic" | "decorators" | "estree" | "moduleAttributes" | "optionalChainingAssign" | "pipelineOperator" | "recordAndTuple" | "typescript"))[];
|
||||
Generated
Vendored
+105
@@ -0,0 +1,105 @@
|
||||
"use strict";
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.resolveParserPlugins = exports.ScriptCompileContext = void 0;
|
||||
const shared_1 = require("@vue/shared");
|
||||
const parser_1 = require("@babel/parser");
|
||||
const magic_string_1 = __importDefault(require("magic-string"));
|
||||
class ScriptCompileContext {
|
||||
helper(key) {
|
||||
this.helperImports.add(key);
|
||||
return `${key}`;
|
||||
}
|
||||
constructor(descriptor, options) {
|
||||
this.descriptor = descriptor;
|
||||
this.options = options;
|
||||
this.source = this.descriptor.source;
|
||||
this.filename = this.descriptor.filename;
|
||||
this.s = new magic_string_1.default(this.source);
|
||||
this.startOffset = this.descriptor.scriptSetup?.loc.start.offset;
|
||||
this.endOffset = this.descriptor.scriptSetup?.loc.end.offset;
|
||||
this.userImports = Object.create(null);
|
||||
// macros presence check
|
||||
this.hasDefinePropsCall = false;
|
||||
this.hasDefineEmitCall = false;
|
||||
this.hasDefineExposeCall = false;
|
||||
this.hasDefaultExportName = false;
|
||||
this.hasDefaultExportRender = false;
|
||||
this.hasDefineOptionsCall = false;
|
||||
this.hasDefineSlotsCall = false;
|
||||
this.hasDefineModelCall = false;
|
||||
this.propsDestructuredBindings = Object.create(null);
|
||||
// defineModel
|
||||
this.modelDecls = Object.create(null);
|
||||
// codegen
|
||||
this.bindingMetadata = {};
|
||||
this.helperImports = new Set();
|
||||
// resolve parser plugins
|
||||
const plugins = resolveParserPlugins('ts', options.babelParserPlugins);
|
||||
function parse(input, offset, startLine) {
|
||||
try {
|
||||
return (0, parser_1.parse)(input, {
|
||||
plugins,
|
||||
sourceType: 'module',
|
||||
// 阻止语法解析报错,不影响后续的语法解析,比如
|
||||
// This member cannot have an 'override' modifier because its containing class does not extend another class.
|
||||
errorRecovery: true,
|
||||
}).program;
|
||||
}
|
||||
catch (e) {
|
||||
if (e.loc && startLine) {
|
||||
e.loc.line = e.loc.line + (startLine - 1);
|
||||
}
|
||||
e.message = `[vue/compiler-sfc] ${e.message}\n\n${descriptor.filename}\n${(0, shared_1.generateCodeFrame)(descriptor.source, e.pos + offset, e.pos + offset + 1)}`;
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
this.scriptAst =
|
||||
descriptor.script &&
|
||||
parse(descriptor.script.content, descriptor.script.loc.start.offset, descriptor.script.loc.start.line);
|
||||
this.scriptSetupAst =
|
||||
descriptor.scriptSetup &&
|
||||
parse(descriptor.scriptSetup.content, this.startOffset, descriptor.scriptSetup.loc.start.line);
|
||||
}
|
||||
getString(node, scriptSetup = true) {
|
||||
const block = scriptSetup
|
||||
? this.descriptor.scriptSetup
|
||||
: this.descriptor.script;
|
||||
return block.content.slice(node.start, node.end);
|
||||
}
|
||||
error(msg, node, scope) {
|
||||
const offset = scope ? scope.offset : this.startOffset;
|
||||
throw new Error(`[@vue/compiler-sfc] ${msg}\n\n${(scope || this.descriptor).filename}\n${(0, shared_1.generateCodeFrame)((scope || this.descriptor).source, node.start + offset, node.end + offset)}`);
|
||||
}
|
||||
}
|
||||
exports.ScriptCompileContext = ScriptCompileContext;
|
||||
function resolveParserPlugins(lang, userPlugins, dts = false) {
|
||||
const plugins = [];
|
||||
if (!userPlugins ||
|
||||
!userPlugins.some((p) => p === 'importAssertions' ||
|
||||
p === 'importAttributes' ||
|
||||
((0, shared_1.isArray)(p) && p[0] === 'importAttributes'))) {
|
||||
plugins.push('importAttributes');
|
||||
}
|
||||
if (lang === 'jsx' || lang === 'tsx') {
|
||||
plugins.push('jsx');
|
||||
}
|
||||
else if (userPlugins) {
|
||||
// If don't match the case of adding jsx
|
||||
// should remove the jsx from user options
|
||||
userPlugins = userPlugins.filter((p) => p !== 'jsx');
|
||||
}
|
||||
if (lang === 'ts' || lang === 'tsx') {
|
||||
plugins.push(['typescript', { dts }], 'explicitResourceManagement');
|
||||
if (!userPlugins || !userPlugins.includes('decorators')) {
|
||||
plugins.push('decorators-legacy');
|
||||
}
|
||||
}
|
||||
if (userPlugins) {
|
||||
plugins.push(...userPlugins);
|
||||
}
|
||||
return plugins;
|
||||
}
|
||||
exports.resolveParserPlugins = resolveParserPlugins;
|
||||
Generated
Vendored
+5
@@ -0,0 +1,5 @@
|
||||
import type { LVal, Node } from '@babel/types';
|
||||
import type { ScriptCompileContext } from './context';
|
||||
export declare const DEFINE_EMITS = "defineEmits";
|
||||
export declare function processDefineEmits(ctx: ScriptCompileContext, node: Node, declId?: LVal): boolean;
|
||||
export declare function genRuntimeEmits(ctx: ScriptCompileContext): string | undefined;
|
||||
Generated
Vendored
+88
@@ -0,0 +1,88 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.genRuntimeEmits = exports.processDefineEmits = exports.DEFINE_EMITS = void 0;
|
||||
const utils_1 = require("./utils");
|
||||
const resolveType_1 = require("./resolveType");
|
||||
exports.DEFINE_EMITS = 'defineEmits';
|
||||
function processDefineEmits(ctx, node, declId) {
|
||||
if (!(0, utils_1.isCallOf)(node, exports.DEFINE_EMITS)) {
|
||||
return false;
|
||||
}
|
||||
if (ctx.hasDefineEmitCall) {
|
||||
ctx.error(`duplicate ${exports.DEFINE_EMITS}() call`, node);
|
||||
}
|
||||
ctx.hasDefineEmitCall = true;
|
||||
ctx.emitsRuntimeDecl = node.arguments[0];
|
||||
if (node.typeParameters) {
|
||||
if (ctx.emitsRuntimeDecl) {
|
||||
ctx.error(`${exports.DEFINE_EMITS}() cannot accept both type and non-type arguments ` +
|
||||
`at the same time. Use one or the other.`, node);
|
||||
}
|
||||
ctx.emitsTypeDecl = node.typeParameters.params[0];
|
||||
}
|
||||
ctx.emitDecl = declId;
|
||||
return true;
|
||||
}
|
||||
exports.processDefineEmits = processDefineEmits;
|
||||
function genRuntimeEmits(ctx) {
|
||||
let emitsDecl = '';
|
||||
if (ctx.emitsRuntimeDecl) {
|
||||
emitsDecl = ctx.getString(ctx.emitsRuntimeDecl).trim();
|
||||
}
|
||||
else if (ctx.emitsTypeDecl) {
|
||||
const typeDeclaredEmits = extractRuntimeEmits(ctx);
|
||||
emitsDecl = typeDeclaredEmits.size
|
||||
? `[${Array.from(typeDeclaredEmits)
|
||||
.map((k) => JSON.stringify(k))
|
||||
.join(', ')}]`
|
||||
: ``;
|
||||
}
|
||||
if (ctx.hasDefineModelCall) {
|
||||
let modelEmitsDecl = `[${Object.keys(ctx.modelDecls)
|
||||
.map((n) => JSON.stringify(`update:${n}`))
|
||||
.join(', ')}]`;
|
||||
emitsDecl = emitsDecl
|
||||
? `/*#__PURE__*/${ctx.helper('mergeModels')}(${emitsDecl}, ${modelEmitsDecl})`
|
||||
: modelEmitsDecl;
|
||||
}
|
||||
return emitsDecl;
|
||||
}
|
||||
exports.genRuntimeEmits = genRuntimeEmits;
|
||||
function extractRuntimeEmits(ctx) {
|
||||
const emits = new Set();
|
||||
const node = ctx.emitsTypeDecl;
|
||||
if (node.type === 'TSFunctionType') {
|
||||
extractEventNames(ctx, node.parameters[0], emits);
|
||||
return emits;
|
||||
}
|
||||
const { props, calls } = (0, resolveType_1.resolveTypeElements)(ctx, node);
|
||||
let hasProperty = false;
|
||||
for (const key in props) {
|
||||
emits.add(key);
|
||||
hasProperty = true;
|
||||
}
|
||||
if (calls) {
|
||||
if (hasProperty) {
|
||||
ctx.error(`defineEmits() type cannot mixed call signature and property syntax.`, node);
|
||||
}
|
||||
for (const call of calls) {
|
||||
extractEventNames(ctx, call.parameters[0], emits);
|
||||
}
|
||||
}
|
||||
return emits;
|
||||
}
|
||||
function extractEventNames(ctx, eventName, emits) {
|
||||
if (eventName.type === 'Identifier' &&
|
||||
eventName.typeAnnotation &&
|
||||
eventName.typeAnnotation.type === 'TSTypeAnnotation') {
|
||||
const types = (0, resolveType_1.resolveUnionType)(ctx, eventName.typeAnnotation.typeAnnotation);
|
||||
for (const type of types) {
|
||||
if (type.type === 'TSLiteralType') {
|
||||
if (type.literal.type !== 'UnaryExpression' &&
|
||||
type.literal.type !== 'TemplateLiteral') {
|
||||
emits.add(String(type.literal.value));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Generated
Vendored
+4
@@ -0,0 +1,4 @@
|
||||
import type { Node } from '@babel/types';
|
||||
import type { ScriptCompileContext } from './context';
|
||||
export declare const DEFINE_EXPOSE = "defineExpose";
|
||||
export declare function processDefineExpose(ctx: ScriptCompileContext, node: Node): boolean;
|
||||
Generated
Vendored
+16
@@ -0,0 +1,16 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.processDefineExpose = exports.DEFINE_EXPOSE = void 0;
|
||||
const utils_1 = require("./utils");
|
||||
exports.DEFINE_EXPOSE = 'defineExpose';
|
||||
function processDefineExpose(ctx, node) {
|
||||
if ((0, utils_1.isCallOf)(node, exports.DEFINE_EXPOSE)) {
|
||||
if (ctx.hasDefineExposeCall) {
|
||||
ctx.error(`duplicate ${exports.DEFINE_EXPOSE}() call`, node);
|
||||
}
|
||||
ctx.hasDefineExposeCall = true;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
exports.processDefineExpose = processDefineExpose;
|
||||
Generated
Vendored
+10
@@ -0,0 +1,10 @@
|
||||
import type { LVal, Node, TSType } from '@babel/types';
|
||||
import type { ScriptCompileContext } from './context';
|
||||
export declare const DEFINE_MODEL = "defineModel";
|
||||
export interface ModelDecl {
|
||||
type: TSType | undefined;
|
||||
options: string | undefined;
|
||||
identifier: string | undefined;
|
||||
}
|
||||
export declare function processDefineModel(ctx: ScriptCompileContext, node: Node, declId?: LVal): boolean;
|
||||
export declare function genModelProps(ctx: ScriptCompileContext): string | undefined;
|
||||
Generated
Vendored
+147
@@ -0,0 +1,147 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.genModelProps = exports.processDefineModel = exports.DEFINE_MODEL = void 0;
|
||||
const resolveType_1 = require("./resolveType");
|
||||
const utils_1 = require("./utils");
|
||||
const compiler_dom_1 = require("@vue/compiler-dom");
|
||||
// import { warnOnce } from '../warn'
|
||||
exports.DEFINE_MODEL = 'defineModel';
|
||||
const RUNTIME_TYPES = {
|
||||
Boolean: 'boolean',
|
||||
String: 'string',
|
||||
Number: 'number',
|
||||
};
|
||||
function processDefineModel(ctx, node, declId) {
|
||||
if (!(0, utils_1.isCallOf)(node, exports.DEFINE_MODEL)) {
|
||||
return false;
|
||||
}
|
||||
// if (!ctx.options.defineModel) {
|
||||
// warnOnce(
|
||||
// `defineModel() is an experimental feature and disabled by default.\n` +
|
||||
// `To enable it, follow the RFC at https://github.com/vuejs/rfcs/discussions/503.`
|
||||
// )
|
||||
// return false
|
||||
// }
|
||||
// warnOnce(
|
||||
// `This project is using defineModel(), which is an experimental ` +
|
||||
// `feature. It may receive breaking changes or be removed in the future, so ` +
|
||||
// `use at your own risk.\n` +
|
||||
// `To stay updated, follow the RFC at https://github.com/vuejs/rfcs/discussions/503.`
|
||||
// )
|
||||
ctx.hasDefineModelCall = true;
|
||||
const type = (node.typeParameters && node.typeParameters.params[0]) || undefined;
|
||||
let modelName;
|
||||
let options;
|
||||
const arg0 = node.arguments[0] && (0, utils_1.unwrapTSNode)(node.arguments[0]);
|
||||
if (arg0 && arg0.type === 'StringLiteral') {
|
||||
modelName = arg0.value;
|
||||
options = node.arguments[1];
|
||||
}
|
||||
else {
|
||||
modelName = 'modelValue';
|
||||
options = arg0;
|
||||
}
|
||||
if (ctx.modelDecls[modelName]) {
|
||||
ctx.error(`duplicate model name ${JSON.stringify(modelName)}`, node);
|
||||
}
|
||||
if (options) {
|
||||
if (options.type !== 'ObjectExpression') {
|
||||
ctx.error(`options must be an object expression`, options);
|
||||
}
|
||||
if (options.properties.find((p) => p.type === 'SpreadElement')) {
|
||||
ctx.error(`options does not support spread properties.`, options);
|
||||
}
|
||||
}
|
||||
const optionsString = options && ctx.getString(options);
|
||||
ctx.modelDecls[modelName] = {
|
||||
type,
|
||||
options: optionsString,
|
||||
identifier: declId && declId.type === 'Identifier' ? declId.name : undefined,
|
||||
};
|
||||
// register binding type
|
||||
ctx.bindingMetadata[modelName] = compiler_dom_1.BindingTypes.PROPS;
|
||||
const runtimeTypes = type && (0, resolveType_1.inferRuntimeType)(ctx, type, 'defineModel');
|
||||
let runtimeType = runtimeTypes && runtimeTypes.length === 1 ? runtimeTypes[0] : undefined;
|
||||
if (runtimeType) {
|
||||
runtimeType = RUNTIME_TYPES[runtimeType] || runtimeType;
|
||||
}
|
||||
let runtimeOptions = '';
|
||||
if (options) {
|
||||
if (options.type === 'ObjectExpression') {
|
||||
if (!runtimeType) {
|
||||
// 未指定泛型,但指定了 options 中的 type
|
||||
const type = options.properties.find((p) => p.type === 'ObjectProperty' &&
|
||||
((p.key.type === 'Identifier' && p.key.name === 'type') ||
|
||||
(p.key.type === 'StringLiteral' && p.key.value === 'type')));
|
||||
if (type) {
|
||||
if (type.value.type === 'TSAsExpression') {
|
||||
// Array as PropType<string[]>
|
||||
if (type.value.typeAnnotation.type === 'TSTypeReference' &&
|
||||
type.value.typeAnnotation.typeParameters) {
|
||||
runtimeType = ctx.getString(type.value.typeAnnotation.typeParameters.params[0]);
|
||||
}
|
||||
}
|
||||
else {
|
||||
runtimeType = ctx.getString(type.value);
|
||||
}
|
||||
}
|
||||
}
|
||||
const local = options.properties.find((p) => p.type === 'ObjectProperty' &&
|
||||
((p.key.type === 'Identifier' && p.key.name === 'local') ||
|
||||
(p.key.type === 'StringLiteral' && p.key.value === 'local')));
|
||||
if (local) {
|
||||
runtimeOptions = `{ ${ctx.getString(local)} }`;
|
||||
}
|
||||
else {
|
||||
for (const p of options.properties) {
|
||||
if (p.type === 'SpreadElement' || p.computed) {
|
||||
runtimeOptions = optionsString;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
runtimeOptions = optionsString;
|
||||
}
|
||||
}
|
||||
ctx.s.overwrite(ctx.startOffset + node.start, ctx.startOffset + node.end, `${ctx.helper('useModel')}<${runtimeType || 'any'}>(__ins.props, ${JSON.stringify(modelName)}${runtimeOptions ? `, ${runtimeOptions}` : ``})`);
|
||||
return true;
|
||||
}
|
||||
exports.processDefineModel = processDefineModel;
|
||||
function genModelProps(ctx) {
|
||||
if (!ctx.hasDefineModelCall)
|
||||
return;
|
||||
let modelPropsDecl = '';
|
||||
for (const [name, { type, options }] of Object.entries(ctx.modelDecls)) {
|
||||
let skipCheck = false;
|
||||
let runtimeTypes = type && (0, resolveType_1.inferRuntimeType)(ctx, type, 'defineProps');
|
||||
if (runtimeTypes) {
|
||||
const hasUnknownType = runtimeTypes.includes(utils_1.UNKNOWN_TYPE);
|
||||
runtimeTypes = runtimeTypes.filter((el) => {
|
||||
if (el === utils_1.UNKNOWN_TYPE)
|
||||
return false;
|
||||
return true;
|
||||
});
|
||||
skipCheck = hasUnknownType && runtimeTypes.length > 0;
|
||||
}
|
||||
let runtimeType = (runtimeTypes &&
|
||||
runtimeTypes.length > 0 &&
|
||||
(0, utils_1.toRuntimeTypeString)(runtimeTypes)) ||
|
||||
undefined;
|
||||
const codegenOptions = (0, utils_1.concatStrings)([
|
||||
runtimeType && `type: ${runtimeType}`,
|
||||
skipCheck && 'skipCheck: true',
|
||||
]);
|
||||
let decl;
|
||||
if (runtimeType && options) {
|
||||
decl = `{ ${codegenOptions}, ...${options} }`;
|
||||
}
|
||||
else {
|
||||
decl = options || (runtimeType ? `{ ${codegenOptions} }` : '{}');
|
||||
}
|
||||
modelPropsDecl += `\n ${JSON.stringify(name)}: ${decl},`;
|
||||
}
|
||||
return `{${modelPropsDecl}\n }`;
|
||||
}
|
||||
exports.genModelProps = genModelProps;
|
||||
Generated
Vendored
+4
@@ -0,0 +1,4 @@
|
||||
import type { Node } from '@babel/types';
|
||||
import type { ScriptCompileContext } from './context';
|
||||
export declare const DEFINE_OPTIONS = "defineOptions";
|
||||
export declare function processDefineOptions(ctx: ScriptCompileContext, node: Node): boolean;
|
||||
Generated
Vendored
+63
@@ -0,0 +1,63 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.processDefineOptions = exports.DEFINE_OPTIONS = void 0;
|
||||
const utils_1 = require("./utils");
|
||||
const defineProps_1 = require("./defineProps");
|
||||
const defineEmits_1 = require("./defineEmits");
|
||||
const defineExpose_1 = require("./defineExpose");
|
||||
const defineSlots_1 = require("./defineSlots");
|
||||
exports.DEFINE_OPTIONS = 'defineOptions';
|
||||
function processDefineOptions(ctx, node) {
|
||||
if (!(0, utils_1.isCallOf)(node, exports.DEFINE_OPTIONS)) {
|
||||
return false;
|
||||
}
|
||||
if (ctx.hasDefineOptionsCall) {
|
||||
ctx.error(`duplicate ${exports.DEFINE_OPTIONS}() call`, node);
|
||||
}
|
||||
if (node.typeParameters) {
|
||||
ctx.error(`${exports.DEFINE_OPTIONS}() cannot accept type arguments`, node);
|
||||
}
|
||||
if (!node.arguments[0])
|
||||
return true;
|
||||
ctx.hasDefineOptionsCall = true;
|
||||
ctx.optionsRuntimeDecl = (0, utils_1.unwrapTSNode)(node.arguments[0]);
|
||||
let propsOption = undefined;
|
||||
let emitsOption = undefined;
|
||||
let exposeOption = undefined;
|
||||
let slotsOption = undefined;
|
||||
if (ctx.optionsRuntimeDecl.type === 'ObjectExpression') {
|
||||
for (const prop of ctx.optionsRuntimeDecl.properties) {
|
||||
if ((prop.type === 'ObjectProperty' || prop.type === 'ObjectMethod') &&
|
||||
prop.key.type === 'Identifier') {
|
||||
if (prop.key.name === 'props')
|
||||
propsOption = prop;
|
||||
if (prop.key.name === 'emits')
|
||||
emitsOption = prop;
|
||||
if (prop.key.name === 'expose')
|
||||
exposeOption = prop;
|
||||
if (prop.key.name === 'slots')
|
||||
slotsOption = prop;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
ctx.error(`${exports.DEFINE_OPTIONS}() options must be an object expression`, ctx.optionsRuntimeDecl);
|
||||
}
|
||||
if (ctx.optionsRuntimeDecl.properties.find((p) => p.type === 'SpreadElement')) {
|
||||
ctx.error(`options does not support spread properties.`, ctx.optionsRuntimeDecl);
|
||||
}
|
||||
if (propsOption) {
|
||||
ctx.error(`${exports.DEFINE_OPTIONS}() cannot be used to declare props. Use ${defineProps_1.DEFINE_PROPS}() instead.`, propsOption);
|
||||
}
|
||||
if (emitsOption) {
|
||||
ctx.error(`${exports.DEFINE_OPTIONS}() cannot be used to declare emits. Use ${defineEmits_1.DEFINE_EMITS}() instead.`, emitsOption);
|
||||
}
|
||||
if (exposeOption) {
|
||||
ctx.error(`${exports.DEFINE_OPTIONS}() cannot be used to declare expose. Use ${defineExpose_1.DEFINE_EXPOSE}() instead.`, exposeOption);
|
||||
}
|
||||
if (slotsOption) {
|
||||
ctx.error(`${exports.DEFINE_OPTIONS}() cannot be used to declare slots. Use ${defineSlots_1.DEFINE_SLOTS}() instead.`, slotsOption);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
exports.processDefineOptions = processDefineOptions;
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user