UNPKG

@marko/translator-default

Version:
146 lines (116 loc) 4.98 kB
"use strict";var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");exports.__esModule = true;exports.default = _default;var _babelUtils = require("@marko/babel-utils"); var _compiler = require("@marko/compiler"); var _withPreviousLocation = _interopRequireDefault(require("../util/with-previous-location")); var _dynamicTag = _interopRequireDefault(require("./dynamic-tag")); var _nativeTag = _interopRequireDefault(require("./native-tag")); var _util = require("./util"); function _default(path, isNullable) { const { hub: { file }, node } = path; const { markoOpts } = file; const { name, key } = node; (0, _babelUtils.assertNoArgs)(path); let tagIdentifier; if (_compiler.types.isStringLiteral(name)) { const tagName = name.value; let relativePath = node.extra && node.extra.relativePath; if (!relativePath) { const tagDef = (0, _babelUtils.getTagDef)(path); if (tagDef && tagDef.renderer) { // Normally new tags should not be added in the translate stage. // We make an exception here for core tags, init-components & _preserve being the primary culprits. // TODO: in the future refactor so this is not needed. relativePath = (0, _babelUtils.resolveRelativePath)(file, tagDef.renderer); } } let binding = !relativePath && path.scope.getBinding(tagName); if (binding && !binding.identifier.loc) binding = null; if (binding && binding.kind === "module") { const importSource = binding.path.parent.source; relativePath = (0, _babelUtils.resolveTagImport)(path, importSource.value) || importSource.value; (node.extra ??= {}).tagNameImported = relativePath; binding = undefined; } const childFile = (0, _babelUtils.loadFileForTag)(path); const childProgram = childFile?.ast.program; if (childProgram?.extra?.featureType === "tags") { const compatRuntimeFile = `marko/src/runtime/helpers/tags-compat/${ markoOpts.output === "html" ? "html" : "dom"}${ markoOpts.optimize ? "" : "-debug"}.${markoOpts.modules === "esm" ? "mjs" : "js"}`; (0, _babelUtils.importDefault)(file, compatRuntimeFile); path.set("name", (0, _babelUtils.importDefault)(file, relativePath, path.node.name.value)); return (0, _dynamicTag.default)(path); } else if (relativePath) { if (binding) { // TODO: implement auto migration for conflicts here // and log below warning // console.warn( // path.buildCodeFrameError( // `The <${tagName}> tag has been resolved from the filesystem, however a local variable with the same name exists. In the next major version of Marko the local variable will tag precedence.` // ) // ); }tagIdentifier = (0, _babelUtils.importDefault)(file, relativePath, tagName);} else if (binding) {path.set("name", _compiler.types.identifier(tagName));return (0, _dynamicTag.default)(path);} else if (markoOpts.ignoreUnrecognizedTags) {return (0, _nativeTag.default)(path); } else { throw path. get("name"). buildCodeFrameError( `Unable to find entry point for custom tag <${tagName}>.` ); } } else { tagIdentifier = name; } const foundAttrs = (0, _util.getAttrs)(path); const customTagRenderCall = (0, _withPreviousLocation.default)( _compiler.types.expressionStatement( _compiler.types.callExpression( (0, _babelUtils.importDefault)( file, "marko/src/runtime/helpers/render-tag.js", "marko_tag" ), [ tagIdentifier, // TODO: this could be left as null if we froze input mutations and used a default object in the runtime. _compiler.types.isNullLiteral(foundAttrs) ? _compiler.types.objectExpression([]) : foundAttrs, _compiler.types.identifier("out"), file._componentDefIdentifier, key, ...(0, _util.buildEventHandlerArray)(path)] ) ), node ); if (isNullable) { let renderBodyIdentifier; const renderBodyProp = _compiler.types.isObjectExpression(foundAttrs) && foundAttrs.properties.find( (prop) => prop.key && prop.key.value === "renderBody" ); if (renderBodyProp) { renderBodyIdentifier = path.scope.generateUidIdentifier("renderBody"); path.insertBefore( _compiler.types.variableDeclaration("const", [ _compiler.types.variableDeclarator(renderBodyIdentifier, renderBodyProp.value)] ) ); renderBodyProp.value = renderBodyIdentifier; } path.replaceWith( _compiler.types.ifStatement( name, customTagRenderCall, renderBodyIdentifier && _compiler.types.expressionStatement( _compiler.types.callExpression(renderBodyIdentifier, [_compiler.types.identifier("out")]) ) ) ); } else { path.replaceWith(customTagRenderCall); } }