From 0545aa8d2929a6f2db12c0e1773cf738abfd9b47 Mon Sep 17 00:00:00 2001 From: Dylan Piercey Date: Tue, 7 Jul 2020 11:11:13 -0700 Subject: [PATCH] refactor: extend babels file API and use their hub (#1578) --- packages/babel-utils/src/tags.js | 12 +- packages/compiler/src/babel-plugin/file.js | 205 ++++++++++++++++++ packages/compiler/src/babel-plugin/hub.js | 172 --------------- packages/compiler/src/babel-plugin/index.js | 64 +++--- packages/compiler/src/babel-plugin/parser.js | 75 ++++--- .../src/babel-plugin/plugins/migrate.js | 11 +- .../src/babel-plugin/plugins/transform.js | 16 +- .../src/babel-plugin/util/code-frame-error.js | 14 -- .../babel-plugin/util/code-frame-warning.js | 25 --- .../src/babel-plugin/util/create-file.js | 21 -- .../src/babel-plugin/util/parse-arguments.js | 4 +- .../src/babel-plugin/util/parse-attributes.js | 14 +- .../util/parse-classname-shorthand.js | 8 +- .../babel-plugin/util/parse-id-shorthand.js | 11 +- .../src/babel-plugin/util/parse-params.js | 4 +- .../translator-default/src/cdata/index.js | 6 +- packages/translator-default/src/class.js | 9 +- .../translator-default/src/comment/index.js | 6 +- .../src/declaration/index.js | 6 +- .../src/document-type/index.js | 6 +- packages/translator-default/src/index.js | 87 ++++---- .../src/placeholder/index.js | 6 +- .../src/placeholder/index[html].js | 11 +- .../src/tag/attribute/directives/class.js | 6 +- .../src/tag/attribute/directives/style.js | 6 +- .../src/tag/attribute/index.js | 12 +- .../src/tag/attribute/modifiers/no-update.js | 13 +- .../src/tag/attribute/modifiers/scoped.js | 9 +- .../translator-default/src/tag/custom-tag.js | 25 ++- .../translator-default/src/tag/dynamic-tag.js | 9 +- packages/translator-default/src/tag/index.js | 2 +- .../translator-default/src/tag/native-tag.js | 10 +- .../src/tag/native-tag[html]/attributes.js | 6 +- .../src/tag/native-tag[html]/index.js | 21 +- .../src/tag/native-tag[vdom]/index.js | 12 +- packages/translator-default/src/tag/util.js | 9 +- .../src/taglib/core/macro/transform.js | 8 +- .../src/taglib/core/parse-class.js | 20 +- .../src/taglib/core/parse-export.js | 7 +- .../src/taglib/core/parse-import.js | 7 +- .../src/taglib/core/parse-module-code.js | 8 +- .../src/taglib/core/parse-static.js | 7 +- .../src/taglib/core/transform-await.js | 2 +- .../src/taglib/core/transform-body.js | 2 +- .../src/taglib/core/transform-server-only.js | 2 +- .../src/taglib/core/translate-html-comment.js | 3 +- .../taglib/core/translate-include-content.js | 6 +- .../src/taglib/core/translate-style.js | 9 +- packages/translator-default/src/text/index.js | 5 +- .../src/util/get-component-files.js | 2 +- .../generated-error-expected.txt | 2 +- 51 files changed, 544 insertions(+), 479 deletions(-) create mode 100644 packages/compiler/src/babel-plugin/file.js delete mode 100644 packages/compiler/src/babel-plugin/hub.js delete mode 100644 packages/compiler/src/babel-plugin/util/code-frame-error.js delete mode 100644 packages/compiler/src/babel-plugin/util/code-frame-warning.js delete mode 100644 packages/compiler/src/babel-plugin/util/create-file.js diff --git a/packages/babel-utils/src/tags.js b/packages/babel-utils/src/tags.js index d69f20612..b924bab1c 100644 --- a/packages/babel-utils/src/tags.js +++ b/packages/babel-utils/src/tags.js @@ -30,7 +30,9 @@ export function isMacroTag(path) { } export function getMacroIdentifier(path) { - return !isDynamicTag(path) && path.hub.macros[path.get("name.value").node]; + return ( + !isDynamicTag(path) && path.hub.file._macros[path.get("name.value").node] + ); } export function getTagDef(path) { @@ -40,8 +42,10 @@ export function getTagDef(path) { return cached.node; } - const { hub } = path; - const { lookup } = hub; + const { + hub: { file } + } = path; + const { _lookup } = file; let tagName; if (!(isMacroTag(path) || isDynamicTag(path))) { @@ -50,7 +54,7 @@ export function getTagDef(path) { : path.get("name.value").node; } - const tagDef = (tagName && lookup.getTag(tagName)) || null; + const tagDef = (tagName && _lookup.getTag(tagName)) || null; path.set("tagDef", tagDef); return tagDef; } diff --git a/packages/compiler/src/babel-plugin/file.js b/packages/compiler/src/babel-plugin/file.js new file mode 100644 index 000000000..5f975dcb8 --- /dev/null +++ b/packages/compiler/src/babel-plugin/file.js @@ -0,0 +1,205 @@ +import path from "path"; +import { types as t } from "@marko/babel-types"; +import { File } from "@babel/core"; +import { parse, parseExpression } from "@babel/parser"; +import { codeFrameColumns } from "@babel/code-frame"; +import { getClientPath } from "lasso-modules-client/transport"; +import { buildLookup } from "../taglib"; +import { getLoc, getLocRange } from "./util/get-loc"; +import checksum from "./util/checksum"; +const CWD = process.cwd(); + +export class MarkoFile extends File { + constructor(filename, code, jsParseOptions, markoOptions) { + const start = { line: 0, column: 0 }; + const end = getLoc(code, code.length); + const loc = { start, end, loc: { start, end } }; + super( + { + filename, + code + }, + { + code, + ast: { + type: "File", + ...loc, + program: { + type: "Program", + sourceType: "module", + ...loc, + body: [], + directives: [] + } + } + } + ); + + this._jsParseOptions = jsParseOptions; + this._markoOptions = markoOptions; + this._lookup = buildLookup(path.dirname(filename), markoOptions.translator); + this._imports = Object.create(null); + this._macros = Object.create(null); + this._meta = { + id: checksum(this.getClientPath(filename)), + deps: [], + tags: [] + }; + } + + addHelper() { + throw new Error("addHelper is not supported during a Marko transform"); + } + + buildCodeFrameError(node, msg, Error = SyntaxError) { + const start = getLoc(this.code, node.start); + const end = node.end != null && getLoc(this.code, node.end); + const frame = codeFrameColumns( + this.code, + { start, end }, + { highlightCode: true } + ); + const position = start.column + ? `(${start.line},${start.column})` + : `:${start.line || 0}`; + return new Error( + `${path.relative(CWD, this.opts.filename)}${position}: ${msg}\n${frame}` + ); + } + + // TODO: all methods not implemented by `@babel/core File` should be moved into helpers in `@marko/babel-utils`. + getWhitespaceBefore(pos) { + return ( + this._codeAsWhitespace || + (this._codeAsWhitespace = this.code.replace(/[^\n\r ]/g, " ")) + ).slice(0, pos); + } + + getClientPath(filename) { + return getClientPath(filename); + } + + resolveRelativePath(filename) { + const dir = path.dirname(this.opts.filename); + let relativePath = path.isAbsolute(filename) + ? path.relative(dir, filename) + : filename; + if (/^[^./]/.test(relativePath)) relativePath = `./${relativePath}`; + return relativePath.replace(/^(?:\.{1,2}\/)+node_modules\//, ""); + } + + importDefault(path, filename, nameHint) { + filename = remapProductionMarkoBuild(path, filename); + const { _imports } = this; + let importDeclaration = _imports[filename]; + + if (!importDeclaration) { + importDeclaration = _imports[filename] = this.path.pushContainer( + "body", + t.importDeclaration([], t.stringLiteral(filename)) + )[0]; + } + + if (!nameHint) { + return; + } + + const specifiers = importDeclaration.get("specifiers"); + const specifier = specifiers.find(specifier => + specifier.isImportDefaultSpecifier() + ); + + if (!specifier) { + const identifier = path.scope.generateUidIdentifier(nameHint); + importDeclaration.pushContainer( + "specifiers", + t.importDefaultSpecifier(identifier) + ); + return identifier; + } + + return t.identifier(specifier.node.local.name); + } + + importNamed(path, filename, name, nameHint = name) { + filename = remapProductionMarkoBuild(path, filename); + const { _imports } = this; + let importDeclaration = _imports[filename]; + + if (!importDeclaration) { + importDeclaration = _imports[filename] = this.path.pushContainer( + "body", + t.importDeclaration([], t.stringLiteral(filename)) + )[0]; + } + + const specifiers = importDeclaration.get("specifiers"); + const specifier = specifiers.find( + specifier => + specifier.isImportSpecifier() && specifier.node.imported.name === name + ); + + if (!specifier) { + const identifier = path.scope.generateUidIdentifier(nameHint); + importDeclaration.pushContainer( + "specifiers", + t.importSpecifier(identifier, t.identifier(name)) + ); + return identifier; + } + + return t.identifier(specifier.node.local.name); + } + + addStaticNode(node) { + this.path.pushContainer("body", node); + } + + createNode(type, start, end, ...args) { + return { + ...t[type](...args), + ...getLocRange(this.code, start, end) + }; + } + + parse(str, start) { + return this._tryParseJS(false, str, start); + } + + parseExpression(str, start) { + return this._tryParseJS(true, str, start); + } + + _tryParseJS(isExpression, str, start) { + const opts = this._jsParseOptions; + str = this.getWhitespaceBefore(start) + str; + + try { + return isExpression + ? parseExpression(str, opts) + : parse(str, opts).program; + } catch (err) { + let { pos, message } = err; + if (pos) { + throw this.buildCodeFrameError( + { start: pos }, + message.replace(/ *\(\d+:\d+\)$/, "") + ); + } else { + throw err; + } + } + } +} + +function remapProductionMarkoBuild(path, filename) { + const { + hub: { + file: { + _markoOptions: { isProduction } + } + } + } = path; + if (!isProduction) return filename; + return filename.replace(/^marko\/src\//, "marko/dist/"); +} diff --git a/packages/compiler/src/babel-plugin/hub.js b/packages/compiler/src/babel-plugin/hub.js deleted file mode 100644 index a15d6d5a7..000000000 --- a/packages/compiler/src/babel-plugin/hub.js +++ /dev/null @@ -1,172 +0,0 @@ -import path from "path"; -import { types as t } from "@marko/babel-types"; -import { getClientPath } from "lasso-modules-client/transport"; -import { parse, parseExpression } from "@babel/parser"; -import createFile from "./util/create-file"; -import codeFrameError from "./util/code-frame-error"; -import codeFrameWarning from "./util/code-frame-warning"; -import { getLocRange } from "./util/get-loc"; -import checksum from "./util/checksum"; -export class Hub { - constructor(filename, code, options) { - this._code = code; - this.options = options; - this.filename = filename; - this.file = createFile(filename, code); - this.lookup = this.options.lookup; - this.macros = Object.create(null); - this.meta = this.file.markoMeta = { - id: checksum(this.getClientPath(this.filename)), - deps: [], - tags: [] - }; - this._imports = Object.create(null); - } - - getCode() { - return this._code; - } - - getWhitespaceBefore(pos) { - return ( - this._codeAsWhitespace || - (this._codeAsWhitespace = this._code.replace(/[^\n\r ]/g, " ")) - ).slice(0, pos); - } - - buildError(node, msg) { - return codeFrameError(this.filename, this._code, msg, node.start, node.end); - } - - buildWarning(node, msg) { - return codeFrameWarning(this.filename, this._code, msg, node); - } - - getClientPath(file) { - return getClientPath(file); - } - - resolveRelativePath(filename) { - const dir = path.dirname(this.filename); - let relativePath = path.isAbsolute(filename) - ? path.relative(dir, filename) - : filename; - if (/^[^./]/.test(relativePath)) relativePath = `./${relativePath}`; - return relativePath.replace(/^(?:\.{1,2}\/)+node_modules\//, ""); - } - - importDefault(path, file, nameHint) { - file = remapProductionMarkoBuild(path, file); - const { _imports } = this; - let importDeclaration = _imports[file]; - - if (!importDeclaration) { - importDeclaration = _imports[file] = this.program.pushContainer( - "body", - t.importDeclaration([], t.stringLiteral(file)) - )[0]; - } - - if (!nameHint) { - return; - } - - const specifiers = importDeclaration.get("specifiers"); - const specifier = specifiers.find(specifier => - specifier.isImportDefaultSpecifier() - ); - - if (!specifier) { - const identifier = path.scope.generateUidIdentifier(nameHint); - importDeclaration.pushContainer( - "specifiers", - t.importDefaultSpecifier(identifier) - ); - return identifier; - } - - return t.identifier(specifier.node.local.name); - } - - importNamed(path, file, name, nameHint = name) { - file = remapProductionMarkoBuild(path, file); - const { _imports } = this; - let importDeclaration = _imports[file]; - - if (!importDeclaration) { - importDeclaration = _imports[file] = this.program.pushContainer( - "body", - t.importDeclaration([], t.stringLiteral(file)) - )[0]; - } - - const specifiers = importDeclaration.get("specifiers"); - const specifier = specifiers.find( - specifier => - specifier.isImportSpecifier() && specifier.node.imported.name === name - ); - - if (!specifier) { - const identifier = path.scope.generateUidIdentifier(nameHint); - importDeclaration.pushContainer( - "specifiers", - t.importSpecifier(identifier, t.identifier(name)) - ); - return identifier; - } - - return t.identifier(specifier.node.local.name); - } - - addStaticNode(node) { - this.program.pushContainer("body", node); - } - - createNode(type, start, end, ...args) { - return { - ...t[type](...args), - ...getLocRange(this._code, start, end) - }; - } - - parse(str, start) { - return this._tryParseJS(false, str, start); - } - - parseExpression(str, start) { - return this._tryParseJS(true, str, start); - } - - _tryParseJS(isExpression, str, start) { - const opts = this.options.jsParseOptions; - str = this.getWhitespaceBefore(start) + str; - - try { - return isExpression - ? parseExpression(str, opts) - : parse(str, opts).program; - } catch (err) { - let { pos, message } = err; - if (pos) { - throw codeFrameError( - this.filename, - this._code, - message.replace(/ *\(\d+:\d+\)$/, ""), - pos - ); - } else { - throw err; - } - } - } -} - -function remapProductionMarkoBuild(path, file) { - const { - hub: { - options: { isProduction } - } - } = path; - if (!isProduction) return file; - return file.replace(/^marko\/src\//, "marko/dist/"); -} diff --git a/packages/compiler/src/babel-plugin/index.js b/packages/compiler/src/babel-plugin/index.js index e73f09e57..48008b277 100644 --- a/packages/compiler/src/babel-plugin/index.js +++ b/packages/compiler/src/babel-plugin/index.js @@ -1,18 +1,18 @@ -import { extname, dirname } from "path"; -import { Hub } from "./hub"; +import { extname } from "path"; +import { types as t } from "@marko/babel-types"; import { parse } from "./parser"; import { visitor as migrate } from "./plugins/migrate"; import { visitor as transform } from "./plugins/transform"; -import { NodePath, visitors } from "@babel/traverse"; -import { buildLookup } from "../taglib"; +import traverse, { visitors } from "@babel/traverse"; import markoModules from "../../modules"; +import { MarkoFile } from "./file"; -export default (api, options) => { +export default (api, markoOptions) => { api.assertVersion(7); - options.output = options.output || "html"; + markoOptions.output = markoOptions.output || "html"; const isProduction = api.env("production"); - const translator = options.translator; + const translator = markoOptions.translator; if (!translator || !translator.visitor) { throw new Error( @@ -24,57 +24,57 @@ export default (api, options) => { name: "marko", parserOverride(code, jsParseOptions) { const filename = jsParseOptions.sourceFileName; - const hub = new Hub(filename, code, { - ...options, - jsParseOptions, - isProduction, - lookup: buildLookup(dirname(filename), translator) + const file = new MarkoFile(filename, code, jsParseOptions, { + ...markoOptions, + isProduction }); // Only run on Marko files. - if (!(extname(filename) === ".marko" || options.allExtensions)) { - return hub.parse(code, 0); + if (!(extname(filename) === ".marko" || markoOptions.allExtensions)) { + return file.parse(code, 0); } - const nodePath = new NodePath(hub); - nodePath.node = hub.file; - hub.program = nodePath.get("program"); - parse(nodePath); + parse(file); // TODO: this package should be split into 4: // 1. babel-syntax-marko (removes the need for the _parseOnly option) // 2. babel-plugin-migrate-marko (removes the need for the _migrateOnly option) // 3. babel-plugin-transform-marko (only runs transformers without converting Marko nodes to js) // 4. babel-plugin-translate-marko (runs final translations) - if (!options._parseOnly) { - nodePath.get("program").scope.crawl(); // Initialize bindings. - const rootMigrators = Object.values(hub.lookup.taglibsById) + if (!markoOptions._parseOnly) { + file.path.scope.crawl(); // Initialize bindings. + const rootMigrators = Object.values(file._lookup.taglibsById) .map(it => it.migratorPath) .filter(Boolean) .map(it => markoModules.require(it)) - .map(it => (it.default || it)(api, options)); - nodePath.traverse( + .map(it => (it.default || it)(api, markoOptions)); + traverse( + file.ast, rootMigrators.length ? visitors.merge(rootMigrators.concat(migrate)) - : migrate + : migrate, + file.scope ); - if (!options._migrateOnly) { - const rootTransformers = hub.lookup.merged.transformers + if (!markoOptions._migrateOnly) { + const rootTransformers = file._lookup.merged.transformers .map(it => markoModules.require(it.path)) - .map(it => (it.default || it)(api, options)); - nodePath.traverse( + .map(it => (it.default || it)(api, markoOptions)); + traverse( + file.ast, rootTransformers.length ? visitors.merge(rootTransformers.concat(transform)) - : transform + : transform, + file.scope ); - nodePath.traverse(translator.visitor); + traverse(file.ast, translator.visitor, file.scope); } } - return Object.assign({}, hub.file); + file.ast.markoMeta = file._meta; + return t.cloneDeep(file.ast); }, - post(file) { + pre(file) { // Attach marko metadata to babel metadata. file.metadata.marko = file.ast.markoMeta; } diff --git a/packages/compiler/src/babel-plugin/parser.js b/packages/compiler/src/babel-plugin/parser.js index acd639443..1e9696566 100644 --- a/packages/compiler/src/babel-plugin/parser.js +++ b/packages/compiler/src/babel-plugin/parser.js @@ -16,15 +16,14 @@ const htmlTrim = t => htmlTrimStart(htmlTrimEnd(t)); const isAttributeTag = node => t.isStringLiteral(node.name) && node.name.value[0] === "@"; -export function parse(fileNodePath) { - const { hub } = fileNodePath; - const { filename, htmlParseOptions = {} } = hub; - const { preserveWhitespace } = htmlParseOptions; - const code = hub.getCode(); - const getTagBody = () => - currentTag.get(currentTag.isFile() ? "program" : "body"); +export function parse(file) { + const { code } = file; + const { htmlParseOptions = {} } = file._markoOptions; const pushTagBody = node => getTagBody().pushContainer("body", node); - let currentTag = fileNodePath; + const getTagBody = () => + currentTag.isProgram() ? currentTag : currentTag.get("body"); + let { preserveWhitespace } = htmlParseOptions; + let currentTag = file.path; let preservingWhitespaceUntil = preserveWhitespace; let wasSelfClosing = false; let handledTagName = false; @@ -32,27 +31,27 @@ export function parse(fileNodePath) { const handlers = { onDocumentType({ value, pos, endPos }) { - const node = hub.createNode("markoDocumentType", pos, endPos, value); + const node = file.createNode("markoDocumentType", pos, endPos, value); pushTagBody(node); /* istanbul ignore next */ onNext = onNext && onNext(node); }, onDeclaration({ value, pos, endPos }) { - const node = hub.createNode("markoDeclaration", pos, endPos, value); + const node = file.createNode("markoDeclaration", pos, endPos, value); pushTagBody(node); /* istanbul ignore next */ onNext = onNext && onNext(node); }, onComment({ value, pos, endPos }) { - const node = hub.createNode("markoComment", pos, endPos, value); + const node = file.createNode("markoComment", pos, endPos, value); pushTagBody(node); onNext = onNext && onNext(node); }, onCDATA({ value, pos, endPos }) { - const node = hub.createNode("markoCDATA", pos, endPos, value); + const node = file.createNode("markoCDATA", pos, endPos, value); pushTagBody(node); onNext = onNext && onNext(node); }, @@ -99,7 +98,7 @@ export function parse(fileNodePath) { } const endPos = pos + value.length; - const node = hub.createNode("markoText", pos, endPos, value); + const node = file.createNode("markoText", pos, endPos, value); const prevBody = getTagBody().node.body; pushTagBody(node); onNext && onNext(node); @@ -116,11 +115,14 @@ export function parse(fileNodePath) { onPlaceholder({ escape, value, withinBody, pos, endPos }) { if (withinBody) { - const node = hub.createNode( + const node = file.createNode( "markoPlaceholder", pos, endPos, - hub.parseExpression(value, pos + (escape ? 2 /* ${ */ : 3) /* $!{ */), + file.parseExpression( + value, + pos + (escape ? 2 /* ${ */ : 3) /* $!{ */ + ), escape ); @@ -131,7 +133,7 @@ export function parse(fileNodePath) { onScriptlet({ value, line, block, pos, endPos }) { if (!line && !block) { - throw hub.buildError( + throw file.buildCodeFrameError( { start: pos, end: endPos }, "<% scriptlets %> are no longer supported." ); @@ -140,11 +142,11 @@ export function parse(fileNodePath) { pos -= 1; // Include $. // Scriptlets are ignored as content and don't call `onNext`. pushTagBody( - hub.createNode( + file.createNode( "markoScriptlet", pos, endPos, - hub.parse(value, pos + 2 /** Ignores leading `$ ` */).body + file.parse(value, pos + 2 /** Ignores leading `$ ` */).body ) ); }, @@ -154,25 +156,28 @@ export function parse(fileNodePath) { const tagName = event.tagName || "div"; const [, tagNameExpression] = /^\$\{([\s\S]*)\}/.exec(tagName) || EMPTY_ARRAY; - const tagDef = !tagNameExpression && hub.lookup.getTag(tagName); + const tagDef = !tagNameExpression && file._lookup.getTag(tagName); const tagNameStartPos = pos + (event.concise ? 0 : 1); // Account for leading `<`. handledTagName = true; if (tagNameExpression === "") { - throw hub.buildError( + throw file.buildCodeFrameError( { start: tagNameStartPos + 1, end: tagNameStartPos + 3 }, "Missing expression for <${dynamic}> tag." ); } - const node = hub.createNode( + const node = file.createNode( "markoTag", pos, endPos, tagNameExpression - ? hub.parseExpression(tagNameExpression, tagNameStartPos + 2 /* ${ */) - : hub.createNode( + ? file.parseExpression( + tagNameExpression, + tagNameStartPos + 2 /* ${ */ + ) + : file.createNode( "stringLiteral", tagNameStartPos, tagNameStartPos + tagName.length, @@ -189,8 +194,8 @@ export function parse(fileNodePath) { if (parseOptions) { event.setParseOptions(parseOptions); - if (parseOptions.rootOnly && !currentTag.isFile()) { - throw hub.buildError( + if (parseOptions.rootOnly && !currentTag.isProgram()) { + throw file.buildCodeFrameError( { start: pos, end: endPos }, `"${tagName}" tags must be at the root of your Marko template.` ); @@ -233,17 +238,17 @@ export function parse(fileNodePath) { } if (!parseOptions.ignoreAttributes) { - currentTag.set("params", parseParams(hub, event.params)); - currentTag.set("arguments", parseArguments(hub, event.argument)); + currentTag.set("params", parseParams(file, event.params)); + currentTag.set("arguments", parseArguments(file, event.argument)); currentTag.set( "attributes", parseIDShorthand( - hub, + file, event.shorthandId, parseClassnameShorthand( - hub, + file, event.shorthandClassNames, - parseAttributes(hub, event.attributes, tagNameEndPos) + parseAttributes(file, event.attributes, tagNameEndPos) ) ) ); @@ -285,7 +290,7 @@ export function parse(fileNodePath) { code[pos + 1] !== "/" && !currentTag.get("name").isStringLiteral() ) { - throw hub.buildError( + throw file.buildCodeFrameError( { start: pos, end: endPos }, `Invalid ending for dynamic tag, expected "".` ); @@ -297,7 +302,7 @@ export function parse(fileNodePath) { (module.default || module)(tag, t); } - currentTag = currentTag.parentPath.parentPath; + currentTag = currentTag.parentPath.parentPath || file.path; }, onfinish() { @@ -306,17 +311,17 @@ export function parse(fileNodePath) { onError({ message, pos, endPos }) { if (message.includes("EOF")) endPos = pos; - throw hub.buildError({ start: pos, end: endPos }, message); + throw file.buildCodeFrameError({ start: pos, end: endPos }, message); } }; createParser(handlers, { isOpenTagOnly(name) { const { parseOptions = EMPTY_OBJECT } = - hub.lookup.getTag(name) || EMPTY_OBJECT; + file._lookup.getTag(name) || EMPTY_OBJECT; return parseOptions.openTagOnly; }, ignoreNonstandardStringPlaceholders: true, ...htmlParseOptions - }).parse(code, filename); + }).parse(code, file.opts.filename); } diff --git a/packages/compiler/src/babel-plugin/plugins/migrate.js b/packages/compiler/src/babel-plugin/plugins/migrate.js index cc63a661e..904d3954b 100644 --- a/packages/compiler/src/babel-plugin/plugins/migrate.js +++ b/packages/compiler/src/babel-plugin/plugins/migrate.js @@ -28,10 +28,13 @@ export const visitor = { }; function getMigratorsForTag(path) { - const { hub } = path; - const { lookup } = hub; + const { + hub: { file } + } = path; + const { _lookup } = file; const tagName = path.get("name.value").node; - const MIGRATOR_CACHE = (lookup.MIGRATOR_CACHE = lookup.MIGRATOR_CACHE || {}); + const MIGRATOR_CACHE = (_lookup.MIGRATOR_CACHE = + _lookup.MIGRATOR_CACHE || {}); let migrators = MIGRATOR_CACHE[tagName]; @@ -40,7 +43,7 @@ function getMigratorsForTag(path) { migrators = MIGRATOR_CACHE[tagName] = [ ...(tagDef ? tagDef.migratorPaths : []), - ...(lookup.getTag("*") || { migratorPaths: [] }).migratorPaths + ...(_lookup.getTag("*") || { migratorPaths: [] }).migratorPaths ].map(path => markoModules.require(path)); } diff --git a/packages/compiler/src/babel-plugin/plugins/transform.js b/packages/compiler/src/babel-plugin/plugins/transform.js index 09bac05dd..5f53ed59d 100644 --- a/packages/compiler/src/babel-plugin/plugins/transform.js +++ b/packages/compiler/src/babel-plugin/plugins/transform.js @@ -8,7 +8,7 @@ import { enter, exit } from "../util/plugin-hooks"; */ export const visitor = { Program(path) { - path.hub._componentDefIdentifier = path.scope.generateUidIdentifier( + path.hub.file._componentDefIdentifier = path.scope.generateUidIdentifier( "component" ); }, @@ -35,11 +35,13 @@ export const visitor = { }; function getTransformersForTag(path) { - const { hub } = path; - const { lookup } = hub; + const { + hub: { file } + } = path; + const { _lookup } = file; const tagName = path.get("name.value").node || "*"; - const TRANSFORMER_CACHE = (lookup.TRANSFORMER_CACHE = - lookup.TRANSFORMER_CACHE || {}); + const TRANSFORMER_CACHE = (_lookup.TRANSFORMER_CACHE = + _lookup.TRANSFORMER_CACHE || {}); let transformers = TRANSFORMER_CACHE[tagName]; @@ -51,7 +53,9 @@ function getTransformersForTag(path) { : [] ) .concat( - Object.values((lookup.getTag("*") || { transformers: [] }).transformers) + Object.values( + (_lookup.getTag("*") || { transformers: [] }).transformers + ) ) .sort(comparePriority) .map(({ path }) => markoModules.require(path)); diff --git a/packages/compiler/src/babel-plugin/util/code-frame-error.js b/packages/compiler/src/babel-plugin/util/code-frame-error.js deleted file mode 100644 index f88c51cdf..000000000 --- a/packages/compiler/src/babel-plugin/util/code-frame-error.js +++ /dev/null @@ -1,14 +0,0 @@ -import { relative } from "path"; -import { codeFrameColumns } from "@babel/code-frame"; -import { getLoc } from "./get-loc"; -const cwd = process.cwd(); - -export default (filename = "", code, msg, startPos, endPos) => { - const start = getLoc(code, startPos); - const end = endPos != null && getLoc(code, endPos); - const frame = codeFrameColumns(code, { start, end }, { highlightCode: true }); - const position = `(${start.line},${start.column})`; - return new SyntaxError( - `${relative(cwd, filename)}${position}: ${msg}\n${frame}` - ); -}; diff --git a/packages/compiler/src/babel-plugin/util/code-frame-warning.js b/packages/compiler/src/babel-plugin/util/code-frame-warning.js deleted file mode 100644 index b9c436da4..000000000 --- a/packages/compiler/src/babel-plugin/util/code-frame-warning.js +++ /dev/null @@ -1,25 +0,0 @@ -import { relative } from "path"; -import { codeFrameColumns } from "@babel/code-frame"; -import { getLoc } from "./get-loc"; -import complain from "complain"; -const cwd = process.cwd(); - -export default (filename = "", code, msg, node) => { - const start = getLoc(code, node.start); - const end = node.end != null && getLoc(code, node.end); - const frame = codeFrameColumns(code, { start, end }, { highlightCode: true }); - const position = `(${start.line},${start.column})`; - const location = node && node.pos; - const options = { location }; - - if (location != null) { - options.location = position; - } else { - options.location = filename; - } - - return complain( - `${relative(cwd, filename)}${position}: ${msg}\n${frame}`, - options - ); -}; diff --git a/packages/compiler/src/babel-plugin/util/create-file.js b/packages/compiler/src/babel-plugin/util/create-file.js deleted file mode 100644 index 090aecbb0..000000000 --- a/packages/compiler/src/babel-plugin/util/create-file.js +++ /dev/null @@ -1,21 +0,0 @@ -import { getLoc } from "./get-loc"; - -export default (filename, code) => { - const opts = { filename }; - const start = { line: 0, column: 0 }; - const end = getLoc(code, code.length); - const loc = { start, end, loc: { start, end } }; - return { - type: "File", - code, - opts, - ...loc, - program: { - type: "Program", - sourceType: "module", - ...loc, - body: [], - directives: [] - } - }; -}; diff --git a/packages/compiler/src/babel-plugin/util/parse-arguments.js b/packages/compiler/src/babel-plugin/util/parse-arguments.js index b7d7d5dfe..c3c2fc842 100644 --- a/packages/compiler/src/babel-plugin/util/parse-arguments.js +++ b/packages/compiler/src/babel-plugin/util/parse-arguments.js @@ -1,6 +1,6 @@ -export default (hub, details) => { +export default (file, details) => { if (details) { - return hub.parseExpression(`_(${details.value})`, details.pos - 1) + return file.parseExpression(`_(${details.value})`, details.pos - 1) .arguments; } }; diff --git a/packages/compiler/src/babel-plugin/util/parse-attributes.js b/packages/compiler/src/babel-plugin/util/parse-attributes.js index 1e94d61a1..b6564baf8 100644 --- a/packages/compiler/src/babel-plugin/util/parse-attributes.js +++ b/packages/compiler/src/babel-plugin/util/parse-attributes.js @@ -1,8 +1,8 @@ import { types as t } from "@marko/babel-types"; import parseArguments from "./parse-arguments"; -export default (hub, attributes, startPos) => { - const code = hub.getCode(); +export default (file, attributes, startPos) => { + const code = file.code; let attrEndPos = startPos; return attributes.map(attr => { @@ -17,10 +17,10 @@ export default (hub, attributes, startPos) => { attrEndPos = attrStartPos + attrExpression.length; - const value = hub.parseExpression(attrExpression, attrStartPos + 3); + const value = file.parseExpression(attrExpression, attrStartPos + 3); // TODO: Inline merge object literals. - return hub.createNode( + return file.createNode( "markoSpreadAttribute", attrStartPos, attrEndPos, @@ -41,20 +41,20 @@ export default (hub, attributes, startPos) => { attrEndPos = attr.endPos; const valueStart = attr.pos + 1; // Add one to account for "=". const rawValue = code.slice(valueStart, attrEndPos); // We use the raw value to ignore things like non standard placeholders. - value = hub.parseExpression(rawValue, valueStart); + value = file.parseExpression(rawValue, valueStart); } else { attrEndPos = attr.argument ? attr.argument.endPos + 1 : attr.endPos; value = t.booleanLiteral(true); } - return hub.createNode( + return file.createNode( "markoAttribute", attrStartPos, attrEndPos, name, value, modifier, - parseArguments(hub, attr.argument) + parseArguments(file, attr.argument) ); }); }; diff --git a/packages/compiler/src/babel-plugin/util/parse-classname-shorthand.js b/packages/compiler/src/babel-plugin/util/parse-classname-shorthand.js index 0deb1b121..5dc132c9e 100644 --- a/packages/compiler/src/babel-plugin/util/parse-classname-shorthand.js +++ b/packages/compiler/src/babel-plugin/util/parse-classname-shorthand.js @@ -1,6 +1,6 @@ import { types as t } from "@marko/babel-types"; -export default (hub, shorthands, attributes) => { +export default (file, shorthands, attributes) => { if (!shorthands) { return attributes; } @@ -9,8 +9,8 @@ export default (hub, shorthands, attributes) => { const classParts = shorthands.map(({ rawParts }) => { const nodes = rawParts.map(part => part.expression - ? hub.parseExpression(part.expression, part.pos) - : hub.createNode("stringLiteral", part.pos, part.endPos, part.text) + ? file.parseExpression(part.expression, part.pos) + : file.createNode("stringLiteral", part.pos, part.endPos, part.text) ); if (nodes.length === 1) { @@ -27,7 +27,7 @@ export default (hub, shorthands, attributes) => { const combinedStartPos = shorthands[0].rawParts[0].pos; const lastParts = shorthands[shorthands.length - 1].rawParts; const combinedEndPos = lastParts[lastParts.length - 1].endPos; - shorthandNode = hub.createNode( + shorthandNode = file.createNode( "stringLiteral", combinedStartPos, combinedEndPos, diff --git a/packages/compiler/src/babel-plugin/util/parse-id-shorthand.js b/packages/compiler/src/babel-plugin/util/parse-id-shorthand.js index 336ee986d..515d1c825 100644 --- a/packages/compiler/src/babel-plugin/util/parse-id-shorthand.js +++ b/packages/compiler/src/babel-plugin/util/parse-id-shorthand.js @@ -1,19 +1,22 @@ import { types as t } from "@marko/babel-types"; -export default (hub, shorthand, attributes) => { +export default (file, shorthand, attributes) => { if (!shorthand) { return attributes; } const idAttr = attributes.find(({ name }) => name === "id"); if (idAttr) { - throw hub.buildError(idAttr, "Cannot have shorthand id and id attribute."); + throw file.buildCodeFrameError( + idAttr, + "Cannot have shorthand id and id attribute." + ); } const idParts = shorthand.rawParts.map(part => part.expression - ? hub.parseExpression(part.expression, part.pos) - : hub.createNode("stringLiteral", part.pos, part.endPos, part.text) + ? file.parseExpression(part.expression, part.pos) + : file.createNode("stringLiteral", part.pos, part.endPos, part.text) ); attributes.push( diff --git a/packages/compiler/src/babel-plugin/util/parse-params.js b/packages/compiler/src/babel-plugin/util/parse-params.js index 0d480f1b7..1223711a9 100644 --- a/packages/compiler/src/babel-plugin/util/parse-params.js +++ b/packages/compiler/src/babel-plugin/util/parse-params.js @@ -1,5 +1,5 @@ -export default (hub, details) => { +export default (file, details) => { if (details) { - return hub.parseExpression(`(${details.value})=>{}`, details.pos).params; + return file.parseExpression(`(${details.value})=>{}`, details.pos).params; } }; diff --git a/packages/translator-default/src/cdata/index.js b/packages/translator-default/src/cdata/index.js index b13252aa0..eeab011f1 100644 --- a/packages/translator-default/src/cdata/index.js +++ b/packages/translator-default/src/cdata/index.js @@ -3,9 +3,11 @@ import translateVDOM from "./index[vdom]"; export default function(path) { const { - hub: { options } + hub: { + file: { _markoOptions } + } } = path; - if (options.output === "html") { + if (_markoOptions.output === "html") { translateHTML(path); } else { translateVDOM(path); diff --git a/packages/translator-default/src/class.js b/packages/translator-default/src/class.js index d2a48b5b7..22282f0a2 100644 --- a/packages/translator-default/src/class.js +++ b/packages/translator-default/src/class.js @@ -2,7 +2,7 @@ import { types as t } from "@marko/babel-types"; export default function(path) { const { - hub, + hub: { file }, node: { body: { body } } @@ -36,7 +36,10 @@ export default function(path) { return undefined; } - throw hub.buildError(prop, "Unsupported class property on component."); + throw file.buildCodeFrameError( + prop, + "Unsupported class property on component." + ); }) .filter(Boolean); @@ -55,6 +58,6 @@ export default function(path) { onCreateMethod.body.body.unshift(...classProperties); } - hub.inlineComponentClass = t.objectExpression(objectProperties); + file._inlineComponentClass = t.objectExpression(objectProperties); path.remove(); } diff --git a/packages/translator-default/src/comment/index.js b/packages/translator-default/src/comment/index.js index b13252aa0..eeab011f1 100644 --- a/packages/translator-default/src/comment/index.js +++ b/packages/translator-default/src/comment/index.js @@ -3,9 +3,11 @@ import translateVDOM from "./index[vdom]"; export default function(path) { const { - hub: { options } + hub: { + file: { _markoOptions } + } } = path; - if (options.output === "html") { + if (_markoOptions.output === "html") { translateHTML(path); } else { translateVDOM(path); diff --git a/packages/translator-default/src/declaration/index.js b/packages/translator-default/src/declaration/index.js index b13252aa0..eeab011f1 100644 --- a/packages/translator-default/src/declaration/index.js +++ b/packages/translator-default/src/declaration/index.js @@ -3,9 +3,11 @@ import translateVDOM from "./index[vdom]"; export default function(path) { const { - hub: { options } + hub: { + file: { _markoOptions } + } } = path; - if (options.output === "html") { + if (_markoOptions.output === "html") { translateHTML(path); } else { translateVDOM(path); diff --git a/packages/translator-default/src/document-type/index.js b/packages/translator-default/src/document-type/index.js index b13252aa0..eeab011f1 100644 --- a/packages/translator-default/src/document-type/index.js +++ b/packages/translator-default/src/document-type/index.js @@ -3,9 +3,11 @@ import translateVDOM from "./index[vdom]"; export default function(path) { const { - hub: { options } + hub: { + file: { _markoOptions } + } } = path; - if (options.output === "html") { + if (_markoOptions.output === "html") { translateHTML(path); } else { translateVDOM(path); diff --git a/packages/translator-default/src/index.js b/packages/translator-default/src/index.js index ba1a59a29..81fa5f477 100644 --- a/packages/translator-default/src/index.js +++ b/packages/translator-default/src/index.js @@ -26,11 +26,13 @@ export const visitor = { MarkoComment, Program: { enter(path) { - const { hub } = path; + const { + hub: { file } + } = path; - if (hub.moduleCode) { + if (file._moduleCode) { path.get("body").forEach(bodyItemPath => bodyItemPath.remove()); - hub.moduleCode.forEach(node => path.pushContainer("body", node)); + file._moduleCode.forEach(node => path.pushContainer("body", node)); return path.skip(); } @@ -44,55 +46,59 @@ export const visitor = { childPath.remove(); }); - hub._renderBlock = renderBlock; + file._renderBlock = renderBlock; }, exit(path) { - const { hub } = path; - const { options, meta, inlineComponentClass } = hub; + const { + hub: { file } + } = path; + const { _markoOptions, _meta, _inlineComponentClass } = file; const { styleFile, packageFile, componentFile, componentBrowserFile } = getComponentFiles(path); - const isHTML = options.output === "html"; + const isHTML = _markoOptions.output === "html"; let isSplit = false; - let isImplicit = !hub._hasTagParams; + let isImplicit = !file._hasTagParams; if (packageFile) { - meta.deps.unshift(packageFile); + _meta.deps.unshift(packageFile); } if (styleFile) { - meta.deps.unshift(styleFile); + _meta.deps.unshift(styleFile); } - if (componentFile || inlineComponentClass) { + if (componentFile || _inlineComponentClass) { isImplicit = false; - meta.component = hub.filename; + _meta.component = file.opts.filename; } if (componentBrowserFile) { isImplicit = false; isSplit = true; - meta.component = componentBrowserFile; + _meta.component = componentBrowserFile; } - meta.component = - meta.component && hub.resolveRelativePath(meta.component); - meta.deps = meta.deps.map(file => - typeof file === "string" ? hub.resolveRelativePath(file) : file + _meta.component = + _meta.component && file.resolveRelativePath(_meta.component); + _meta.deps = _meta.deps.map(filename => + typeof filename === "string" + ? file.resolveRelativePath(filename) + : filename ); - const renderBlock = hub._renderBlock; + const renderBlock = file._renderBlock; const componentClass = (componentFile && - hub.importDefault( + file.importDefault( path, - hub.resolveRelativePath(componentFile), + file.resolveRelativePath(componentFile), "marko_component" )) || - inlineComponentClass || + _inlineComponentClass || t.objectExpression([]); const componentIdentifier = path.scope.generateUidIdentifier( @@ -104,7 +110,7 @@ export const visitor = { const templateIdentifier = path.scope.generateUidIdentifier( "marko_template" ); - const rendererIdentifier = hub.importDefault( + const rendererIdentifier = file.importDefault( path, "marko/src/runtime/components/renderer", "marko_renderer" @@ -117,9 +123,9 @@ export const visitor = { templateIdentifier, t.identifier("meta") ); - const componentId = meta.id; + const componentId = _meta.id; - if (options.writeVersionComment) { + if (_markoOptions.writeVersionComment) { path.addComment( "leading", ` Compiled using marko@${version} - DO NOT EDIT`, @@ -137,7 +143,11 @@ export const visitor = { t.variableDeclarator( templateIdentifier, t.callExpression( - hub.importNamed(path, `marko/src/runtime/${options.output}`, "t"), + file.importNamed( + path, + `marko/src/runtime/${_markoOptions.output}`, + "t" + ), [t.identifier("__filename")] ) ) @@ -153,7 +163,7 @@ export const visitor = { isHTML ? componentIdString : t.callExpression( - hub.importNamed( + file.importNamed( path, "marko/src/runtime/components/registry-browser", "r", @@ -164,9 +174,9 @@ export const visitor = { t.arrowFunctionExpression( [], isSplit - ? hub.importDefault( + ? file.importDefault( path, - hub.resolveRelativePath(componentBrowserFile), + file.resolveRelativePath(componentBrowserFile), "marko_split_component" ) : templateIdentifier @@ -206,7 +216,7 @@ export const visitor = { [ t.identifier("input"), t.identifier("out"), - hub._componentDefIdentifier, + file._componentDefIdentifier, t.identifier("component"), t.identifier("state") ], @@ -228,7 +238,7 @@ export const visitor = { "=", t.memberExpression(templateIdentifier, t.identifier("Component")), t.callExpression( - hub.importDefault( + file.importDefault( path, "marko/src/runtime/components/defineComponent", "marko_defineComponent" @@ -240,37 +250,34 @@ export const visitor = { ); } - if (options.meta !== false) { + if (_markoOptions.meta !== false) { const metaObject = t.objectExpression([ t.objectProperty(t.identifier("id"), componentTypeIdentifier) ]); - if (meta.component) { + if (_meta.component) { metaObject.properties.push( t.objectProperty( t.identifier("component"), - t.stringLiteral(meta.component) + t.stringLiteral(_meta.component) ) ); } - if (meta.deps.length) { + if (_meta.deps.length) { metaObject.properties.push( t.objectProperty( t.identifier("deps"), - hub.parseExpression( - JSON.stringify(meta.deps), - hub.getCode().length - ) + file.parseExpression(JSON.stringify(_meta.deps), file.code.length) ) ); } - if (meta.tags.length) { + if (_meta.tags.length) { metaObject.properties.push( t.objectProperty( t.identifier("tags"), - t.arrayExpression(meta.tags.map(tag => t.stringLiteral(tag))) + t.arrayExpression(_meta.tags.map(tag => t.stringLiteral(tag))) ) ); } diff --git a/packages/translator-default/src/placeholder/index.js b/packages/translator-default/src/placeholder/index.js index b13252aa0..eeab011f1 100644 --- a/packages/translator-default/src/placeholder/index.js +++ b/packages/translator-default/src/placeholder/index.js @@ -3,9 +3,11 @@ import translateVDOM from "./index[vdom]"; export default function(path) { const { - hub: { options } + hub: { + file: { _markoOptions } + } } = path; - if (options.output === "html") { + if (_markoOptions.output === "html") { translateHTML(path); } else { translateVDOM(path); diff --git a/packages/translator-default/src/placeholder/index[html].js b/packages/translator-default/src/placeholder/index[html].js index 237732791..697296da8 100644 --- a/packages/translator-default/src/placeholder/index[html].js +++ b/packages/translator-default/src/placeholder/index[html].js @@ -27,7 +27,10 @@ const ESCAPE_TYPES = { }; export default function(path) { - const { node, hub } = path; + const { + node, + hub: { file } + } = path; const { confident, value: computed } = path.get("value").evaluate(); let { escape, value } = node; @@ -39,20 +42,20 @@ export default function(path) { ? t.stringLiteral(escapeType.fn(computed)) : t.callExpression( escapeType.name - ? hub.importNamed( + ? file.importNamed( path, escapeType.module, escapeType.name, escapeType.alias ) - : hub.importDefault(path, escapeType.module, escapeType.alias), + : file.importDefault(path, escapeType.module, escapeType.alias), [value] ); } else { value = confident ? t.stringLiteral(toString(computed)) : t.callExpression( - hub.importDefault( + file.importDefault( path, "marko/src/runtime/helpers/to-string", "marko_to_string" diff --git a/packages/translator-default/src/tag/attribute/directives/class.js b/packages/translator-default/src/tag/attribute/directives/class.js index 7b2aae6f4..2541546b8 100644 --- a/packages/translator-default/src/tag/attribute/directives/class.js +++ b/packages/translator-default/src/tag/attribute/directives/class.js @@ -5,7 +5,9 @@ import withPreviousLocation from "../../../util/with-previous-location"; export default { exit(tag, _, value) { - const { hub } = tag; + const { + hub: { file } + } = tag; if (!isNativeTag(tag)) return; if (value.isStringLiteral()) return; @@ -16,7 +18,7 @@ export default { ? t.stringLiteral(classToString(computed) || "") : withPreviousLocation( t.callExpression( - hub.importDefault( + file.importDefault( tag, "marko/src/runtime/helpers/class-value", "marko_class_merge" diff --git a/packages/translator-default/src/tag/attribute/directives/style.js b/packages/translator-default/src/tag/attribute/directives/style.js index f163bde54..1945339cb 100644 --- a/packages/translator-default/src/tag/attribute/directives/style.js +++ b/packages/translator-default/src/tag/attribute/directives/style.js @@ -5,7 +5,9 @@ import withPreviousLocation from "../../../util/with-previous-location"; export default { exit(tag, _, value) { - const { hub } = tag; + const { + hub: { file } + } = tag; if (value.isStringLiteral()) return; if (!isNativeTag(tag)) return; @@ -15,7 +17,7 @@ export default { confident ? t.stringLiteral(styleToString(computed) || "") : t.callExpression( - hub.importDefault( + file.importDefault( tag, "marko/src/runtime/helpers/style-value", "marko_style_merge" diff --git a/packages/translator-default/src/tag/attribute/index.js b/packages/translator-default/src/tag/attribute/index.js index b9093b111..6a1177759 100644 --- a/packages/translator-default/src/tag/attribute/index.js +++ b/packages/translator-default/src/tag/attribute/index.js @@ -8,11 +8,13 @@ const attachedDetachedLoaded = new WeakSet(); export default { enter(attr) { - const { hub } = attr; + const { + hub: { file } + } = attr; const tag = attr.parentPath; const value = attr.get("value"); const { name, arguments: args } = attr.node; - const isVDOM = hub.options.output !== "html"; + const isVDOM = file._markoOptions.output !== "html"; if (execModifiersAndDirectives("enter", tag, attr, value)) { return; @@ -60,10 +62,10 @@ export default { if (isVDOM) { if (eventName === "attach" || eventName === "detach") { - if (!attachedDetachedLoaded.has(hub)) { + if (!attachedDetachedLoaded.has(file)) { // Pull in helper for element attach/detach; - attachedDetachedLoaded.add(hub); - hub.importDefault( + attachedDetachedLoaded.add(file); + file.importDefault( tag, "marko/src/runtime/components/attach-detach" ); diff --git a/packages/translator-default/src/tag/attribute/modifiers/no-update.js b/packages/translator-default/src/tag/attribute/modifiers/no-update.js index 087bfe2b7..4835240b1 100644 --- a/packages/translator-default/src/tag/attribute/modifiers/no-update.js +++ b/packages/translator-default/src/tag/attribute/modifiers/no-update.js @@ -7,18 +7,21 @@ const hasMonkeyPatch = new WeakSet(); */ export default { exit(tag, attr) { - const { node, hub } = tag; + const { + node, + hub: { file } + } = tag; const { properties } = node; - const isVDOM = hub.options.output !== "html"; + const isVDOM = file._markoOptions.output !== "html"; let prop = properties.find(({ key: { name } }) => name === "noupdate"); if (!prop) { prop = t.objectProperty(t.identifier("noupdate"), t.arrayExpression([])); properties.push(prop); - if (isVDOM && !hasMonkeyPatch.has(hub)) { - hasMonkeyPatch.add(hub); - hub.importDefault(tag, "marko/src/runtime/vdom/preserve-attrs"); + if (isVDOM && !hasMonkeyPatch.has(file)) { + hasMonkeyPatch.add(file); + file.importDefault(tag, "marko/src/runtime/vdom/preserve-attrs"); } } diff --git a/packages/translator-default/src/tag/attribute/modifiers/scoped.js b/packages/translator-default/src/tag/attribute/modifiers/scoped.js index ee843c4c5..3e8099528 100644 --- a/packages/translator-default/src/tag/attribute/modifiers/scoped.js +++ b/packages/translator-default/src/tag/attribute/modifiers/scoped.js @@ -3,11 +3,16 @@ import withPreviousLocation from "../../../util/with-previous-location"; export default { exit(tag, _, value) { - const { hub } = tag; + const { + hub: { file } + } = tag; value.replaceWith( withPreviousLocation( t.callExpression( - t.memberExpression(hub._componentDefIdentifier, t.identifier("elId")), + t.memberExpression( + file._componentDefIdentifier, + t.identifier("elId") + ), [value.node] ), value.node diff --git a/packages/translator-default/src/tag/custom-tag.js b/packages/translator-default/src/tag/custom-tag.js index 1b9745d27..079866778 100644 --- a/packages/translator-default/src/tag/custom-tag.js +++ b/packages/translator-default/src/tag/custom-tag.js @@ -8,8 +8,11 @@ import withPreviousLocation from "../util/with-previous-location"; const TAG_FILE_ENTRIES = ["template", "renderer"]; export default function(path) { - const { hub, node } = path; - const { meta, options } = hub; + const { + hub: { file }, + node + } = path; + const { _meta, _markoOptions } = file; const { name, key, isNullable } = node; assertNoArgs(path); @@ -19,10 +22,10 @@ export default function(path) { if (t.isStringLiteral(name)) { const tagDef = getTagDef(path); const tagName = name.value; - const relativePath = tagDef && resolveRelativePath(hub, tagDef); + const relativePath = tagDef && resolveRelativePath(file, tagDef); if (!relativePath) { - if (options.ignoreUnrecognizedTags) { + if (_markoOptions.ignoreUnrecognizedTags) { return nativeTag(path); } @@ -33,10 +36,10 @@ export default function(path) { ); } - tagIdentifier = hub.importDefault(path, relativePath, tagName); + tagIdentifier = file.importDefault(path, relativePath, tagName); - if (!meta.tags.includes(relativePath)) { - meta.tags.push(relativePath); + if (!_meta.tags.includes(relativePath)) { + _meta.tags.push(relativePath); } } else { tagIdentifier = name; @@ -46,7 +49,7 @@ export default function(path) { const customTagRenderCall = withPreviousLocation( t.expressionStatement( t.callExpression( - hub.importDefault( + file.importDefault( path, "marko/src/runtime/helpers/render-tag", "marko_tag" @@ -56,7 +59,7 @@ export default function(path) { // TODO: this could be left as null if we froze input mutations and used a default object in the runtime. t.isNullLiteral(foundAttrs) ? t.objectExpression([]) : foundAttrs, t.identifier("out"), - hub._componentDefIdentifier, + file._componentDefIdentifier, key, ...buildEventHandlerArray(path) ] @@ -99,9 +102,9 @@ export default function(path) { } } -function resolveRelativePath(hub, tagDef) { +function resolveRelativePath(file, tagDef) { for (const entry of TAG_FILE_ENTRIES) { if (!tagDef[entry]) continue; - return hub.resolveRelativePath(tagDef[entry]); + return file.resolveRelativePath(tagDef[entry]); } } diff --git a/packages/translator-default/src/tag/dynamic-tag.js b/packages/translator-default/src/tag/dynamic-tag.js index b49c722f0..c6aa705ad 100644 --- a/packages/translator-default/src/tag/dynamic-tag.js +++ b/packages/translator-default/src/tag/dynamic-tag.js @@ -8,7 +8,10 @@ import customTag from "./custom-tag"; const HANDLE_BINDINGS = ["module", "var", "let", "const"]; export default function(path) { - const { node, hub } = path; + const { + node, + hub: { file } + } = path; const { key, arguments: args, properties: tagProperties } = node; const name = path.get("name"); @@ -59,7 +62,7 @@ export default function(path) { } const dynamicTagRenderCall = t.callExpression( - hub.importDefault( + file.importDefault( path, `marko/src/runtime/helpers/dynamic-tag`, "marko_dynamic_tag" @@ -73,7 +76,7 @@ export default function(path) { tagProperties.length ? t.objectExpression(tagProperties) : t.nullLiteral(), - hub._componentDefIdentifier, + file._componentDefIdentifier, key, ...buildEventHandlerArray(path) ] diff --git a/packages/translator-default/src/tag/index.js b/packages/translator-default/src/tag/index.js index 7356bb29d..50c6aa2d0 100644 --- a/packages/translator-default/src/tag/index.js +++ b/packages/translator-default/src/tag/index.js @@ -45,7 +45,7 @@ export default { } } - if (path.hub.options.ignoreUnrecognizedTags && !tagDef) { + if (path.hub.file._markoOptions.ignoreUnrecognizedTags && !tagDef) { findAttributeTags(path).forEach(child => { child.set( "name", diff --git a/packages/translator-default/src/tag/native-tag.js b/packages/translator-default/src/tag/native-tag.js index 3e79816e1..cf340e87d 100644 --- a/packages/translator-default/src/tag/native-tag.js +++ b/packages/translator-default/src/tag/native-tag.js @@ -7,16 +7,18 @@ import { } from "@marko/babel-utils"; export default function(path) { - const { hub } = path; - const { options } = hub; + const { + hub: { file } + } = path; + const { _markoOptions } = file; - if (!options.ignoreUnrecognizedTags) { + if (!_markoOptions.ignoreUnrecognizedTags) { assertNoArgs(path); assertNoParams(path); assertNoAttributeTags(path); } - if (options.output === "html") { + if (_markoOptions.output === "html") { nativeTagHtml(path); } else { nativeTagVdom(path); diff --git a/packages/translator-default/src/tag/native-tag[html]/attributes.js b/packages/translator-default/src/tag/native-tag[html]/attributes.js index 74422f4c9..30fe32f02 100644 --- a/packages/translator-default/src/tag/native-tag[html]/attributes.js +++ b/packages/translator-default/src/tag/native-tag[html]/attributes.js @@ -18,7 +18,7 @@ export default function(path, attrs) { for (let i = 0; i < attrs.length; i++) { const attr = attrs[i]; const { - hub, + hub: { file }, node: { name, value } } = attr; @@ -56,7 +56,7 @@ export default function(path, attrs) { expressions.push( t.callExpression( - hub.importDefault( + file.importDefault( attr, "marko/src/runtime/html/helpers/attr", "marko_attr" @@ -69,7 +69,7 @@ export default function(path, attrs) { quasis.push(curString); if (hasSpread) { return t.callExpression( - path.hub.importDefault( + path.hub.file.importDefault( path, "marko/src/runtime/html/helpers/attrs", "marko_attrs" diff --git a/packages/translator-default/src/tag/native-tag[html]/index.js b/packages/translator-default/src/tag/native-tag[html]/index.js index 134edf927..16c9cd16a 100644 --- a/packages/translator-default/src/tag/native-tag[html]/index.js +++ b/packages/translator-default/src/tag/native-tag[html]/index.js @@ -14,7 +14,10 @@ const EMPTY_OBJECT = {}; * Translates the html streaming version of a standard html element. */ export default function(path) { - const { hub, node } = path; + const { + hub: { file }, + node + } = path; const { name, body: { body }, @@ -29,7 +32,7 @@ export default function(path) { const { parseOptions = EMPTY_OBJECT } = tagDef; if (parseOptions.import) { // TODO: the taglib should be updated to support this as a top level option. - hub.meta.deps.push(resolve(tagDef.dir, parseOptions.import)); + file._meta.deps.push(resolve(tagDef.dir, parseOptions.import)); } } @@ -51,7 +54,7 @@ export default function(path) { t.stringLiteral(`on${eventName}`), t.callExpression( t.memberExpression( - hub._componentDefIdentifier, + file._componentDefIdentifier, t.identifier("d") ), delegateArgs @@ -62,22 +65,22 @@ export default function(path) { ); } - const isHTML = hub.options.output === "html"; + const isHTML = file._markoOptions.output === "html"; let dataMarko = t.stringLiteral(""); if (isHTML) { const componentFiles = getComponentFiles(path); const isSplit = Boolean(componentFiles.componentBrowserFile); const isImplicit = Boolean( - !hub.inlineComponentClass && + !file._inlineComponentClass && !componentFiles.componentFile && - !hub._hasTagParams + !file._hasTagParams ); const needsDataMarkoAttr = isSplit || isImplicit || isPreserved(path); if (needsDataMarkoAttr) { - const dataMarkoArgs = [t.identifier("out"), hub._componentDefIdentifier]; + const dataMarkoArgs = [t.identifier("out"), file._componentDefIdentifier]; if (tagProperties.length) { // TODO we should pre evaluate this if it is static. @@ -89,12 +92,12 @@ export default function(path) { dataMarkoArgs.push(t.numericLiteral(0)); } - dataMarkoArgs.push(path.get("key").node, hub._componentDefIdentifier); + dataMarkoArgs.push(path.get("key").node, file._componentDefIdentifier); } if (dataMarkoArgs.length > 2) { dataMarko = t.callExpression( - hub.importDefault( + file.importDefault( path, "marko/src/runtime/html/helpers/data-marko", "marko_props" diff --git a/packages/translator-default/src/tag/native-tag[vdom]/index.js b/packages/translator-default/src/tag/native-tag[vdom]/index.js index c7027fa72..af2404b8c 100644 --- a/packages/translator-default/src/tag/native-tag[vdom]/index.js +++ b/packages/translator-default/src/tag/native-tag[vdom]/index.js @@ -19,7 +19,11 @@ const MAYBE_SVG = { * Translates the html streaming version of a standard html element. */ export default function(path) { - const { hub, node, parent } = path; + const { + hub: { file }, + node, + parent + } = path; const { name, key, @@ -51,7 +55,7 @@ export default function(path) { attrsObj.properties.some(t.isSpreadElement) ) { attrsObj = t.callExpression( - hub.importDefault( + file.importDefault( path, "marko/src/runtime/vdom/helpers/attrs", "marko_attrs" @@ -88,7 +92,7 @@ export default function(path) { t.stringLiteral(`on${eventName}`), t.callExpression( t.memberExpression( - hub._componentDefIdentifier, + file._componentDefIdentifier, t.identifier("d") ), delegateArgs @@ -115,7 +119,7 @@ export default function(path) { node.runtimeFlags |= FLAGS.IS_CUSTOM_ELEMENT; if (parseOptions.import) { // TODO: the taglib should be updated to support this as a top level option. - hub.meta.deps.push(resolve(tagDef.dir, parseOptions.import)); + file._meta.deps.push(resolve(tagDef.dir, parseOptions.import)); } } else if ( htmlType === "svg" || diff --git a/packages/translator-default/src/tag/util.js b/packages/translator-default/src/tag/util.js index 4f5dcc8d5..9b7c06084 100644 --- a/packages/translator-default/src/tag/util.js +++ b/packages/translator-default/src/tag/util.js @@ -4,7 +4,10 @@ import { getTagDef } from "@marko/babel-utils"; const EMPTY_ARR = []; export function getAttrs(path, noCamel, skipRenderBody) { - const { node, hub } = path; + const { + node, + hub: { file } + } = path; const { attributes, body: { body }, @@ -66,8 +69,8 @@ export function getAttrs(path, noCamel, skipRenderBody) { path.insertBefore(body); } else { if (node.params) { - if (!hub._hasTagParams && !isIgnoredTagParams(path)) { - hub._hasTagParams = true; + if (!file._hasTagParams && !isIgnoredTagParams(path)) { + file._hasTagParams = true; } } diff --git a/packages/translator-default/src/taglib/core/macro/transform.js b/packages/translator-default/src/taglib/core/macro/transform.js index 9aa3dd6e5..9830fbaeb 100644 --- a/packages/translator-default/src/taglib/core/macro/transform.js +++ b/packages/translator-default/src/taglib/core/macro/transform.js @@ -1,6 +1,8 @@ export function enter(path) { const { - hub: { macros }, + hub: { + file: { _macros } + }, node } = path; const attributes = path.get("attributes"); @@ -28,11 +30,11 @@ export function enter(path) { const name = nameAttrValue.node.value; - if (macros[name]) { + if (_macros[name]) { throw nameAttr.buildCodeFrameError( `A macro with the name "${name}" already exists.` ); } - node._macroId = macros[name] = path.scope.generateUidIdentifier(name); + node._macroId = _macros[name] = path.scope.generateUidIdentifier(name); } diff --git a/packages/translator-default/src/taglib/core/parse-class.js b/packages/translator-default/src/taglib/core/parse-class.js index c53db69e5..b2e6a8115 100644 --- a/packages/translator-default/src/taglib/core/parse-class.js +++ b/packages/translator-default/src/taglib/core/parse-class.js @@ -4,7 +4,10 @@ import getComponentFiles from "../../util/get-component-files"; const SEEN_INLINE_CLASS = new WeakSet(); export default function(path) { - const { node, hub } = path; + const { + node, + hub: { file } + } = path; const { rawValue: code, start } = node; if (getComponentFiles(path).componentFile) { @@ -15,7 +18,7 @@ export default function(path) { ); } - if (SEEN_INLINE_CLASS.has(hub)) { + if (SEEN_INLINE_CLASS.has(file)) { throw path .get("name") .buildCodeFrameError( @@ -23,14 +26,17 @@ export default function(path) { ); } - const parsed = hub.parseExpression(code, start); + const parsed = file.parseExpression(code, start); if (parsed.id) { - throw hub.buildError(parsed.id, "Component class cannot have a name."); + throw file.buildCodeFrameError( + parsed.id, + "Component class cannot have a name." + ); } if (parsed.superClass) { - throw hub.buildError( + throw file.buildCodeFrameError( parsed.superClass, "Component class cannot have a super class." ); @@ -40,12 +46,12 @@ export default function(path) { prop => t.isClassMethod(prop) && prop.kind === "constructor" ); if (constructorProp) { - throw hub.buildError( + throw file.buildCodeFrameError( constructorProp.key, "The constructor method should not be used for a component, use onCreate instead." ); } - SEEN_INLINE_CLASS.add(hub); + SEEN_INLINE_CLASS.add(file); path.replaceWith(t.markoClass(parsed.body)); } diff --git a/packages/translator-default/src/taglib/core/parse-export.js b/packages/translator-default/src/taglib/core/parse-export.js index f045ae301..68148d90b 100644 --- a/packages/translator-default/src/taglib/core/parse-export.js +++ b/packages/translator-default/src/taglib/core/parse-export.js @@ -1,6 +1,9 @@ export default function(path) { - const { node, hub } = path; + const { + node, + hub: { file } + } = path; const { rawValue, start } = node; - const [exportNode] = hub.parse(rawValue, start).body; + const [exportNode] = file.parse(rawValue, start).body; path.replaceWith(exportNode); } diff --git a/packages/translator-default/src/taglib/core/parse-import.js b/packages/translator-default/src/taglib/core/parse-import.js index 6ecd4f234..62754bcd0 100644 --- a/packages/translator-default/src/taglib/core/parse-import.js +++ b/packages/translator-default/src/taglib/core/parse-import.js @@ -1,6 +1,9 @@ export default function(path) { - const { node, hub } = path; + const { + node, + hub: { file } + } = path; const { rawValue, start } = node; - const [importNode] = hub.parse(rawValue, start).body; + const [importNode] = file.parse(rawValue, start).body; path.replaceWith(importNode); } diff --git a/packages/translator-default/src/taglib/core/parse-module-code.js b/packages/translator-default/src/taglib/core/parse-module-code.js index 3383f1ef8..b7df72771 100644 --- a/packages/translator-default/src/taglib/core/parse-module-code.js +++ b/packages/translator-default/src/taglib/core/parse-module-code.js @@ -6,14 +6,14 @@ const startOffset = "module-code".length; export default function parse(path) { const { - hub, + hub: { file }, node: { rawValue, start } } = path; - const dirname = nodePath.dirname(hub.filename); + const dirname = nodePath.dirname(file.opts.filename); const relativeRequire = entry => markoModules.require(resolveFrom(dirname, entry)); const fn = eval(rawValue.slice(startOffset)); const source = fn(relativeRequire); - const program = hub.parse(source, start + startOffset); - hub.moduleCode = program.body; + const program = file.parse(source, start + startOffset); + file._moduleCode = program.body; } diff --git a/packages/translator-default/src/taglib/core/parse-static.js b/packages/translator-default/src/taglib/core/parse-static.js index 874d4fd16..15b7528dd 100644 --- a/packages/translator-default/src/taglib/core/parse-static.js +++ b/packages/translator-default/src/taglib/core/parse-static.js @@ -1,11 +1,14 @@ import { types as t } from "@marko/babel-types"; export default function(path) { - const { node, hub } = path; + const { + node, + hub: { file } + } = path; const { rawValue } = node; const code = rawValue.replace(/^static\s*/, "").trim(); const start = node.start + (rawValue.length - code.length); - let { body } = hub.parse(code, start); + let { body } = file.parse(code, start); if (body.length === 1 && t.isBlockStatement(body[0])) { body = body[0].body; } diff --git a/packages/translator-default/src/taglib/core/transform-await.js b/packages/translator-default/src/taglib/core/transform-await.js index 6535ba2a1..48577f025 100644 --- a/packages/translator-default/src/taglib/core/transform-await.js +++ b/packages/translator-default/src/taglib/core/transform-await.js @@ -12,7 +12,7 @@ export function exit(path) { } else if (args.length > 1) { const { start } = args[1].node; const { end } = args[args.length - 1].node; - throw path.hub.buildError( + throw path.hub.file.buildCodeFrameError( { start, end }, 'You can only pass one argument to the "" tag.' ); diff --git a/packages/translator-default/src/taglib/core/transform-body.js b/packages/translator-default/src/taglib/core/transform-body.js index 9897dbdc0..d5ad5e7a8 100644 --- a/packages/translator-default/src/taglib/core/transform-body.js +++ b/packages/translator-default/src/taglib/core/transform-body.js @@ -1,7 +1,7 @@ import { types as t } from "@marko/babel-types"; export function exit(path) { - if (path.hub.options.output === "html") { + if (path.hub.file._markoOptions.output === "html") { const body = path.get("body"); body.pushContainer("body", [ diff --git a/packages/translator-default/src/taglib/core/transform-server-only.js b/packages/translator-default/src/taglib/core/transform-server-only.js index f09bc2393..67bf88e29 100644 --- a/packages/translator-default/src/taglib/core/transform-server-only.js +++ b/packages/translator-default/src/taglib/core/transform-server-only.js @@ -1,5 +1,5 @@ export function exit(path) { - if (path.hub.options.output !== "html") { + if (path.hub.file._markoOptions.output !== "html") { path.remove(); } } diff --git a/packages/translator-default/src/taglib/core/translate-html-comment.js b/packages/translator-default/src/taglib/core/translate-html-comment.js index 9b7791a15..271f1a869 100644 --- a/packages/translator-default/src/taglib/core/translate-html-comment.js +++ b/packages/translator-default/src/taglib/core/translate-html-comment.js @@ -6,12 +6,11 @@ import { import write from "../../util/html-out-write"; export function enter(path) { - const { hub } = path; assertNoArgs(path); assertNoParams(path); assertNoAttributes(path); - if (hub.options.output === "html") { + if (path.hub.file._markoOptions.output === "html") { path.replaceWithMultiple([write``]); } else { path.remove(); diff --git a/packages/translator-default/src/taglib/core/translate-include-content.js b/packages/translator-default/src/taglib/core/translate-include-content.js index d9a2722ce..91c0add44 100644 --- a/packages/translator-default/src/taglib/core/translate-include-content.js +++ b/packages/translator-default/src/taglib/core/translate-include-content.js @@ -4,7 +4,9 @@ import { types as t } from "@marko/babel-types"; import { assertNoParams, assertNoAttributes } from "@marko/babel-utils"; export function enter(path) { - const { hub } = path; + const { + hub: { file } + } = path; assertNoParams(path); assertNoAttributes(path); @@ -26,7 +28,7 @@ export function enter(path) { ); } - const dir = nodePath.dirname(hub.filename); + const dir = nodePath.dirname(file.opts.filename); const fullPath = nodePath.resolve(dir, content.node.value); try { diff --git a/packages/translator-default/src/taglib/core/translate-style.js b/packages/translator-default/src/taglib/core/translate-style.js index 664c8e807..c78d856a6 100644 --- a/packages/translator-default/src/taglib/core/translate-style.js +++ b/packages/translator-default/src/taglib/core/translate-style.js @@ -1,15 +1,18 @@ import { basename } from "path"; export function exit(path) { - const { hub, node } = path; + const { + hub: { file }, + node + } = path; const { _styleType: type, _styleCode: code } = node; if (!type) { return; } - const base = basename(hub.filename); - hub.meta.deps.push({ + const base = basename(file.opts.filename); + file._meta.deps.push({ type, code: code.trim(), path: `./${base}`, diff --git a/packages/translator-default/src/text/index.js b/packages/translator-default/src/text/index.js index b13252aa0..f19aa4eff 100644 --- a/packages/translator-default/src/text/index.js +++ b/packages/translator-default/src/text/index.js @@ -2,10 +2,7 @@ import translateHTML from "./index[html]"; import translateVDOM from "./index[vdom]"; export default function(path) { - const { - hub: { options } - } = path; - if (options.output === "html") { + if (path.hub.file._markoOptions.output === "html") { translateHTML(path); } else { translateVDOM(path); diff --git a/packages/translator-default/src/util/get-component-files.js b/packages/translator-default/src/util/get-component-files.js index 77d086af8..f4f5ca747 100644 --- a/packages/translator-default/src/util/get-component-files.js +++ b/packages/translator-default/src/util/get-component-files.js @@ -8,7 +8,7 @@ export default function getComponentFiles({ hub }) { return CACHE.get(hub); } - const { filename } = hub; + const { filename } = hub.file.opts; const ext = path.extname(filename); const dirname = path.dirname(filename); const dirFiles = fs.readdirSync(dirname).sort(); diff --git a/packages/translator-default/test/fixtures/error-class-private-properties/generated-error-expected.txt b/packages/translator-default/test/fixtures/error-class-private-properties/generated-error-expected.txt index ea208465c..172b23a0f 100644 --- a/packages/translator-default/test/fixtures/error-class-private-properties/generated-error-expected.txt +++ b/packages/translator-default/test/fixtures/error-class-private-properties/generated-error-expected.txt @@ -1,4 +1,4 @@ -packages/translator-default/test/fixtures/error-class-private-properties/template.marko: packages/translator-default/test/fixtures/error-class-private-properties/template.marko(2,3): Unknown PrivateName "#x" +packages/translator-default/test/fixtures/error-class-private-properties/template.marko: Unknown PrivateName "#x" 1 | class { > 2 | #x = 1; | ^^