UNPKG

marko

Version:

UI Components + streaming, async, high performance, HTML templating for Node.js and the browser.

168 lines (143 loc) 4.55 kB
"use strict";var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");exports.__esModule = true;exports.analyzeStaticVDOM = analyzeStaticVDOM;exports.optimizeStaticVDOM = optimizeStaticVDOM;var _compiler = require("@marko/compiler"); var _babelUtils = require("@marko/compiler/babel-utils"); var _he = require("he"); var _attributes = _interopRequireDefault(require("../tag/native-tag[vdom]/attributes")); var _keyManager = require("./key-manager"); var _vdomOutWrite = _interopRequireDefault(require("./vdom-out-write")); const skipDirectives = new Set([ "key", "w-bind", "no-update", "no-update-if", "no-update-body", "no-update-body-if"] ); const staticNodes = new WeakSet(); const mergeStaticCreateVisitor = { MarkoText(path, state) { const { node } = path; state.currentRoot = _compiler.types.callExpression( _compiler.types.memberExpression(state.currentRoot, _compiler.types.identifier("t")), [_compiler.types.stringLiteral((0, _he.decode)(node.value))] ); }, MarkoPlaceholder(path, state) { const computed = (0, _babelUtils.computeNode)(path.node.value); state.currentRoot = _compiler.types.callExpression( _compiler.types.memberExpression(state.currentRoot, _compiler.types.identifier("t")), [ _compiler.types.stringLiteral( computed && computed.value != null ? `${computed.value}` : "" )] ); }, MarkoTag(path, state) { (0, _keyManager.getKeyManager)(path).resolveKey(path); state.currentRoot = _compiler.types.callExpression( _compiler.types.memberExpression(state.currentRoot, _compiler.types.identifier("e")), getConstElementArgs(path) ); } }; const analyzeStaticVisitor = { MarkoText(path) { staticNodes.add(path.node); }, MarkoPlaceholder(path) { if (path.node.escape) { const computed = (0, _babelUtils.computeNode)(path.node.value); if (computed) { staticNodes.add(path.node); } } }, MarkoTag: { enter(path) { // needed to handle global keys on elements that don't have specific key attributes if ((0, _babelUtils.isLoopTag)(path)) path.skip(); }, exit(path) { // check name let isStatic = (0, _babelUtils.isNativeTag)(path) && !path.node.attributeTags.length && !path.node.body.attributeTags && !path.node.body.params.length && !path.node.arguments && !(0, _keyManager.hasUserKey)(path); const tagDef = (0, _babelUtils.getTagDef)(path); isStatic = isStatic && ( !tagDef.translator || tagDef.name === "script" || tagDef.name === "style"); // check attributes isStatic = isStatic && path. get("attributes"). every( (attr) => _compiler.types.isMarkoAttribute(attr) && !( attr.node.arguments || attr.node.modifier || skipDirectives.has(attr.node.name) || !(0, _babelUtils.computeNode)(attr.node.value)) ); // check children isStatic = isStatic && path. get("body"). get("body"). every((t) => staticNodes.has(t.node)); if (isStatic) staticNodes.add(path.node); } } }; function optimizeStaticVDOM(path) { const { hub: { file } } = path; if ( !shouldRun(file.markoOpts) || !staticNodes.has(path.node) || staticNodes.has(path.parentPath.parentPath.node)) { return; } const identifier = path.scope.generateUidIdentifier("marko_node"); const state = { currentRoot: _compiler.types.callExpression( (0, _babelUtils.importDefault)( file, "marko/src/runtime/vdom/helpers/const-element.js", "marko_constElement" ), getConstElementArgs(path) ) }; path.traverse(mergeStaticCreateVisitor, state); const d = _compiler.types.variableDeclaration("const", [ _compiler.types.variableDeclarator(identifier, state.currentRoot)] ); file.path.node.body.push(d); path.replaceWith((0, _vdomOutWrite.default)("n", identifier, file._componentInstanceIdentifier)); path.skip(); } function analyzeStaticVDOM(path) { if (shouldRun(path.hub.file.markoOpts)) { path.traverse(analyzeStaticVisitor); } } function shouldRun(markoOpts) { return markoOpts.optimize && markoOpts.output !== "html"; } function getConstElementArgs(path) { const { node } = path; return [ node.name, (0, _attributes.default)(path, path.get("attributes")), _compiler.types.numericLiteral(node.body.body.length)]; }