| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646 |
- "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, originalLineOffset = 0, generatedLineOffset = 0, }) {
- const context = {
- rootDir,
- targetLanguage,
- mode,
- prefixIdentifiers,
- bindingMetadata,
- inline,
- sourceMap,
- filename,
- source: ast.loc.source,
- code: ``,
- easyComponentAutoImports: {},
- importEasyComponents: [],
- importUTSComponents: [],
- importUTSElements: [],
- column: 1,
- line: 1,
- offset: 0,
- indentLevel: 0,
- map: undefined,
- expressionPlugins: ['typescript'],
- matchEasyCom,
- parseUTSComponent,
- helper(key) {
- return `${compiler_core_1.helperNameMap[key]}`;
- },
- push(code, node) {
- context.code += code;
- if (context.map) {
- if (node) {
- let name;
- if (node.type === 4 /* 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;
- }
- const UTS_COMPONENT_ELEMENT_IMPORTS = `/*UTS-COMPONENTS-IMPORTS*/`;
- 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 = context;
- if (mode === 'module') {
- preambleContext.push(UTS_COMPONENT_ELEMENT_IMPORTS);
- newline();
- genEasyComImports(ast.components, preambleContext);
- if (ast.imports.length) {
- genImports(ast.imports, preambleContext);
- newline();
- }
- 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(`}`);
- }
- preambleContext.code = preambleContext.code.replace(UTS_COMPONENT_ELEMENT_IMPORTS, context.importUTSElements.length
- ? context.importUTSElements.join(';') + ';'
- : '');
- return {
- ast,
- code: context.code,
- // preamble: isSetupInlined ? preambleContext.code : ``,
- easyComponentAutoImports: context.easyComponentAutoImports,
- importEasyComponents: context.importEasyComponents,
- importUTSComponents: context.importUTSComponents,
- imports: ast.imports.map((item) => `import '${item.path}'`),
- // SourceMapGenerator does have toJSON() method but it's not in the types
- map: context.map ? context.map.toJSON() : undefined,
- // @ts-ignore
- elements: ast.elements,
- };
- }
- exports.generate = generate;
- function genImports(importsOptions, context) {
- if (!importsOptions.length) {
- return;
- }
- importsOptions.forEach((imports) => {
- if ((0, shared_1.isString)(imports.exp)) {
- context.push(`import ${imports.exp} from '${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) {
- const componentId = (0, compiler_core_1.toValidAssetId)(id, 'easycom');
- push(`import ${componentId} from '${source}'`);
- newline();
- }
- }
- }
- function genAssets(assets, type, { helper, push, newline, importEasyComponents, 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 easyComponentId = (0, compiler_core_1.toValidAssetId)(id, 'easycom');
- const componentId = (0, compiler_core_1.toValidAssetId)(id, type);
- assetCode = `const ${componentId} = ${helper(runtimeHelpers_1.RESOLVE_EASY_COMPONENT)}(${JSON.stringify(id)},${easyComponentId})`;
- const importCode = `import ${easyComponentId} from '${source}';`;
- if (!importEasyComponents.includes(importCode)) {
- importEasyComponents.push(importCode);
- (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 isText(n) {
- return ((0, shared_1.isString)(n) ||
- n.type === 4 /* NodeTypes.SIMPLE_EXPRESSION */ ||
- n.type === 2 /* NodeTypes.TEXT */ ||
- n.type === 5 /* NodeTypes.INTERPOLATION */ ||
- n.type === 8 /* 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 1 /* NodeTypes.ELEMENT */:
- case 9 /* NodeTypes.IF */:
- case 11 /* NodeTypes.FOR */:
- genNode(node.codegenNode, context);
- break;
- case 2 /* NodeTypes.TEXT */:
- genText(node, context);
- break;
- case 4 /* NodeTypes.SIMPLE_EXPRESSION */:
- genExpression(node, context);
- break;
- case 5 /* NodeTypes.INTERPOLATION */:
- genInterpolation(node, context);
- break;
- case 12 /* NodeTypes.TEXT_CALL */:
- genNode(node.codegenNode, context);
- break;
- case 8 /* NodeTypes.COMPOUND_EXPRESSION */:
- genCompoundExpression(node, context);
- break;
- case 3 /* NodeTypes.COMMENT */:
- genComment(node, context);
- break;
- case 13 /* NodeTypes.VNODE_CALL */:
- genVNodeCall(node, context);
- break;
- case 14 /* NodeTypes.JS_CALL_EXPRESSION */:
- genCallExpression(node, context);
- break;
- case 15 /* NodeTypes.JS_OBJECT_EXPRESSION */:
- genObjectExpression(node, context);
- break;
- case 17 /* NodeTypes.JS_ARRAY_EXPRESSION */:
- genArrayExpression(node, context);
- break;
- case 18 /* NodeTypes.JS_FUNCTION_EXPRESSION */:
- genFunctionExpression(node, context);
- break;
- case 19 /* NodeTypes.JS_CONDITIONAL_EXPRESSION */:
- genConditionalExpression(node, context);
- break;
- case 20 /* NodeTypes.JS_CACHE_EXPRESSION */:
- genCacheExpression(node, context);
- break;
- case 21 /* NodeTypes.JS_BLOCK_STATEMENT */:
- genNodeList(node.body, context, true, false);
- break;
- /* istanbul ignore next */
- case 10 /* 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 === 8 /* 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, targetLanguage, importUTSComponents, importUTSElements, }) {
- if ((0, shared_1.isString)(tag)) {
- // 原生UTS组件
- const utsComponentOptions = parseUTSComponent(tag.slice(1, -1), targetLanguage);
- if (utsComponentOptions) {
- const importCode = `import '${utsComponentOptions.source}';`;
- if (!importUTSComponents.includes(importCode)) {
- importUTSComponents.push(importCode);
- }
- const importElementCode = `import { ${utsComponentOptions.className.replace(/Component$/, 'Element')} } from '${utsComponentOptions.namespace}'`;
- if (!importUTSElements.includes(importElementCode)) {
- importUTSElements.push(importElementCode);
- }
- return (0, compiler_core_1.createSimpleExpression)(utsComponentOptions.namespace +
- '.' +
- 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 === 18 /* NodeTypes.JS_FUNCTION_EXPRESSION */) {
- argument.returnType = 'VNode';
- }
- });
- }
- 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 !== 4 /* 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) {
- push(`: Map<string, any | null>): any[] => `);
- 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 === 4 /* 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 === 19 /* 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(`})`);
- }
|