Skip to content
This repository has been archived by the owner on Apr 6, 2023. It is now read-only.

Commit

Permalink
fix: sanitize import filenames in generated imports (#2216)
Browse files Browse the repository at this point in the history
  • Loading branch information
danielroe committed Feb 7, 2022
1 parent 614e87e commit 29171bd
Show file tree
Hide file tree
Showing 25 changed files with 118 additions and 94 deletions.
1 change: 1 addition & 0 deletions packages/bridge/package.json
Expand Up @@ -38,6 +38,7 @@
"globby": "^13.1.1",
"h3": "^0.3.9",
"hash-sum": "^2.0.0",
"knitwork": "^0.1.0",
"magic-string": "^0.25.7",
"mlly": "^0.4.1",
"murmurhash-es": "^0.1.1",
Expand Down
13 changes: 5 additions & 8 deletions packages/bridge/src/vite/templates.ts
Expand Up @@ -2,6 +2,7 @@ import hash from 'hash-sum'
import { resolve } from 'pathe'

import type { Nuxt, NuxtApp } from '@nuxt/schema'
import { genImport, genObjectFromRawEntries } from 'knitwork'

type TemplateContext = {
nuxt: Nuxt;
Expand All @@ -24,10 +25,8 @@ export const middlewareTemplate = {
id: m.name || m.src.replace(/[\\/]/g, '/').replace(/\.(js|ts)$/, '')
}
})
return `${_middleware.map(m => `import $${hash(m.id)} from '${m.filePath}'`).join('\n')}
const middleware = {
${_middleware.map(m => ` ['${m.id}']: $${hash(m.id)}`).join(',\n')}
}
return `${_middleware.map(m => genImport(m.filePath, `$${hash(m.id)}`)).join('\n')}
const middleware = ${genObjectFromRawEntries(_middleware.map(m => [m.id, `$${hash(m.id)}`]))}
export default middleware`
}
}
Expand All @@ -49,14 +48,12 @@ export const storeTemplate = {

return `import Vue from 'vue'
import Vuex from 'vuex'
${_storeModules.map(s => `import * as $${hash(s.id)} from '${s.filePath}'`).join('\n')}
${_storeModules.map(s => genImport(s.filePath, { name: '*', as: `$${hash(s.id)}` })).join('\n')}
Vue.use(Vuex)
const VUEX_PROPERTIES = ['state', 'getters', 'actions', 'mutations']
const storeModules = {
${_storeModules.map(m => ` ['${m.id}']: $${hash(m.id)}`).join(',\n')}
}
const storeModules = ${genObjectFromRawEntries(_storeModules.map(m => [m.id, `$${hash(m.id)}`]))}
export function createStore() {
let store = normalizeRoot(storeModules.root || {})
Expand Down
1 change: 1 addition & 0 deletions packages/kit/package.json
Expand Up @@ -20,6 +20,7 @@
"globby": "^13.1.1",
"hash-sum": "^2.0.0",
"jiti": "^1.12.15",
"knitwork": "^0.1.0",
"lodash.template": "^4.5.0",
"mlly": "^0.4.1",
"pathe": "^0.2.0",
Expand Down
5 changes: 3 additions & 2 deletions packages/kit/src/components.ts
@@ -1,5 +1,6 @@
import { pascalCase, kebabCase } from 'scule'
import type { ComponentsDir, Component } from '@nuxt/schema'
import { genDynamicImport } from 'knitwork'
import { useNuxt } from './context'
import { assertNuxtCompatibility } from './compatibility'

Expand Down Expand Up @@ -43,8 +44,8 @@ export async function addComponent (opts: AddComponentOptions) {
shortPath: opts.filePath,
async: false,
level: 0,
asyncImport: `() => import('${opts.filePath}').then(r => r['${opts.export || 'default'}'])`,
import: `require('${opts.filePath}')['${opts.export || 'default'}']`,
asyncImport: `${genDynamicImport(opts.filePath)}.then(r => r['${opts.export || 'default'}'])`,
import: `require(${JSON.stringify(opts.filePath)})['${opts.export || 'default'}']`,

...opts
}
Expand Down
7 changes: 4 additions & 3 deletions packages/kit/src/internal/template.ts
Expand Up @@ -3,6 +3,7 @@ import lodashTemplate from 'lodash.template'
import hash from 'hash-sum'
import { camelCase } from 'scule'
import { basename, extname } from 'pathe'
import { genDynamicImport, genImport } from 'knitwork'

import type { NuxtTemplate } from '@nuxt/schema'

Expand All @@ -23,7 +24,7 @@ export async function compileTemplate (template: NuxtTemplate, ctx: any) {
throw new Error('Invalid template: ' + JSON.stringify(template))
}

const serialize = (data: any) => JSON.stringify(data, null, 2).replace(/"{(.+)}"/g, '$1')
const serialize = (data: any) => JSON.stringify(data, null, 2).replace(/"{(.+)}"(?=,?$)/gm, r => JSON.parse(r).replace(/^{(.*)}$/, '$1'))

const importName = (src: string) => `${camelCase(basename(src, extname(src))).replace(/[^a-zA-Z?\d\s:]/g, '')}_${hash(src)}`

Expand All @@ -33,9 +34,9 @@ const importSources = (sources: string | string[], { lazy = false } = {}) => {
}
return sources.map((src) => {
if (lazy) {
return `const ${importName(src)} = () => import('${src}' /* webpackChunkName: '${src}' */)`
return `const ${importName(src)} = ${genDynamicImport(src, { comment: `webpackChunkName: ${JSON.stringify(src)}` })}`
}
return `import ${importName(src)} from '${src}'`
return genImport(src, importName(src))
}).join('\n')
}

Expand Down
1 change: 1 addition & 0 deletions packages/nitro/package.json
Expand Up @@ -48,6 +48,7 @@
"http-proxy": "^1.18.1",
"is-primitive": "^3.0.1",
"jiti": "^1.12.15",
"knitwork": "^0.1.0",
"listhen": "^0.2.6",
"mime": "^3.0.0",
"mlly": "^0.4.1",
Expand Down
3 changes: 2 additions & 1 deletion packages/nitro/src/build.ts
Expand Up @@ -2,6 +2,7 @@ import { relative, resolve, join } from 'pathe'
import consola from 'consola'
import * as rollup from 'rollup'
import fse from 'fs-extra'
import { genDynamicImport } from 'knitwork'
import { printFSTree } from './utils/tree'
import { getRollupConfig } from './rollup/config'
import { hl, prettyPath, serializeTemplate, writeFile, isDirectory, replaceAll } from './utils'
Expand Down Expand Up @@ -73,7 +74,7 @@ export async function writeTypes (nitroContext: NitroContext) {
if (typeof mw.handle !== 'string') { continue }
const relativePath = relative(nitroContext._nuxt.buildDir, mw.handle).replace(/\.[a-z]+$/, '')
routeTypes[mw.route] = routeTypes[mw.route] || []
routeTypes[mw.route].push(`Awaited<ReturnType<typeof import('${relativePath}').default>>`)
routeTypes[mw.route].push(`Awaited<ReturnType<typeof ${genDynamicImport(relativePath, { wrapper: false })}.default>>`)
}

const lines = [
Expand Down
7 changes: 4 additions & 3 deletions packages/nitro/src/presets/browser.ts
Expand Up @@ -2,6 +2,7 @@ import { existsSync, promises as fsp } from 'fs'
import { resolve } from 'pathe'
import consola from 'consola'
import { joinURL } from 'ufo'
import { genString } from 'knitwork'
import { extendPreset, prettyPath } from '../utils'
import { NitroPreset, NitroContext, NitroInput } from '../context'
import { worker } from './worker'
Expand All @@ -13,7 +14,7 @@ export const browser: NitroPreset = extendPreset(worker, (input: NitroInput) =>
const script = `<script>
if ('serviceWorker' in navigator) {
window.addEventListener('load', function () {
navigator.serviceWorker.register('${joinURL(baseURL, 'sw.js')}');
navigator.serviceWorker.register(${genString(joinURL(baseURL, 'sw.js'))});
});
}
</script>`
Expand All @@ -27,7 +28,7 @@ if ('serviceWorker' in navigator) {
<link rel="prefetch" href="${joinURL(baseURL, '_server/index.mjs')}">
<script>
async function register () {
const registration = await navigator.serviceWorker.register('${joinURL(baseURL, 'sw.js')}')
const registration = await navigator.serviceWorker.register(${genString(joinURL(baseURL, 'sw.js'))})
await navigator.serviceWorker.ready
registration.active.addEventListener('statechange', (event) => {
if (event.target.state === 'activated') {
Expand Down Expand Up @@ -64,7 +65,7 @@ if ('serviceWorker' in navigator) {
tmpl.contents = tmpl.contents.replace('</body>', script + '</body>')
},
async 'nitro:compiled' ({ output }: NitroContext) {
await fsp.writeFile(resolve(output.publicDir, 'sw.js'), `self.importScripts('${joinURL(baseURL, '_server/index.mjs')}');`, 'utf8')
await fsp.writeFile(resolve(output.publicDir, 'sw.js'), `self.importScripts(${genString(joinURL(baseURL, '_server/index.mjs'))});`, 'utf8')

// Temp fix
if (!existsSync(resolve(output.publicDir, 'index.html'))) {
Expand Down
3 changes: 2 additions & 1 deletion packages/nitro/src/rollup/config.ts
Expand Up @@ -18,6 +18,7 @@ import devalue from '@nuxt/devalue'

import type { Preset } from 'unenv'
import { sanitizeFilePath } from 'mlly'
import { genImport } from 'knitwork'
import { NitroContext } from '../context'
import { resolvePath } from '../utils'
import { pkgDir } from '../dirs'
Expand Down Expand Up @@ -215,7 +216,7 @@ export const getRollupConfig = (nitroContext: NitroContext) => {

// Polyfill
rollupConfig.plugins.push(virtual({
'#polyfill': env.polyfill.map(p => `import '${p}';`).join('\n')
'#polyfill': env.polyfill.map(p => genImport(p)).join('\n')
}))

// https://github.com/rollup/plugins/tree/master/packages/alias
Expand Down
10 changes: 7 additions & 3 deletions packages/nitro/src/rollup/plugins/assets.ts
Expand Up @@ -4,6 +4,7 @@ import createEtag from 'etag'
import mime from 'mime'
import { resolve } from 'pathe'
import { globby } from 'globby'
import { genDynamicImport, genObjectFromRawEntries } from 'knitwork'
import virtual from './virtual'

export interface AssetOptions {
Expand Down Expand Up @@ -81,9 +82,12 @@ function normalizeKey (key) {

function getAssetProd (assets: Record<string, Asset>) {
return `
const _assets = {\n${Object.entries(assets).map(([id, asset]) =>
` ['${normalizeKey(id)}']: {\n import: () => import('${asset.fsPath}').then(r => r.default || r),\n meta: ${JSON.stringify(asset.meta)}\n }`
).join(',\n')}\n}
const _assets = ${genObjectFromRawEntries(
Object.entries(assets).map(([id, asset]) => [normalizeKey(id), {
import: genDynamicImport(asset.fsPath, { interopDefault: true }),
meta: asset.meta
}])
)}
${normalizeKey.toString()}
Expand Down
13 changes: 5 additions & 8 deletions packages/nitro/src/rollup/plugins/dynamic-require.ts
Expand Up @@ -2,6 +2,7 @@ import { pathToFileURL } from 'url'
import { resolve } from 'pathe'
import { globby } from 'globby'
import type { Plugin } from 'rollup'
import { genDynamicImport, genObjectFromRawEntries, genImport } from 'knitwork'
import { serializeImportName } from '../../utils'

const PLUGIN_NAME = 'dynamic-require'
Expand Down Expand Up @@ -36,7 +37,7 @@ export function dynamicRequire ({ dir, ignore, inline }: Options): Plugin {
name: PLUGIN_NAME,
transform (code: string, _id: string) {
return {
code: code.replace(DYNAMIC_REQUIRE_RE, `import('${HELPER_DYNAMIC}').then(r => r.default || r).then(dynamicRequire => dynamicRequire($1)).then`),
code: code.replace(DYNAMIC_REQUIRE_RE, `${genDynamicImport(HELPER_DYNAMIC, { wrapper: false, interopDefault: true })}.then(dynamicRequire => dynamicRequire($1)).then`),
map: null
}
},
Expand Down Expand Up @@ -89,10 +90,8 @@ async function getWebpackChunkMeta (src: string) {
}

function TMPL_INLINE ({ chunks }: TemplateContext) {
return `${chunks.map(i => `import * as ${i.name} from '${i.src}'`).join('\n')}
const dynamicChunks = {
${chunks.map(i => ` ['${i.id}']: ${i.name}`).join(',\n')}
};
return `${chunks.map(i => genImport(i.src, { name: '*', as: i.name })).join('\n')}
const dynamicChunks = ${genObjectFromRawEntries(chunks.map(i => [i.id, i.name]))};
export default function dynamicRequire(id) {
return Promise.resolve(dynamicChunks[id]);
Expand All @@ -101,9 +100,7 @@ export default function dynamicRequire(id) {

function TMPL_LAZY ({ chunks }: TemplateContext) {
return `
const dynamicChunks = {
${chunks.map(i => ` ['${i.id}']: () => import('${i.src}')`).join(',\n')}
};
const dynamicChunks = ${genObjectFromRawEntries(chunks.map(i => [i.id, genDynamicImport(i.src)]))};
export default function dynamicRequire(id) {
return dynamicChunks[id]();
Expand Down
16 changes: 10 additions & 6 deletions packages/nitro/src/rollup/plugins/middleware.ts
Expand Up @@ -3,6 +3,7 @@ import { relative } from 'pathe'
import table from 'table'
import isPrimitive from 'is-primitive'
import { isDebug } from 'std-env'
import { genArrayFromRaw, genDynamicImport, genImport } from 'knitwork'
import type { ServerMiddleware } from '../../server/middleware'
import virtual from './virtual'

Expand Down Expand Up @@ -35,15 +36,18 @@ export function middleware (getMiddleware: () => ServerMiddleware[]) {
const lazyImports = unique(middleware.filter(m => m.lazy !== false && !imports.includes(m.handle)).map(m => m.handle))

return `
${imports.map(handle => `import ${getImportId(handle)} from '${handle}';`).join('\n')}
${imports.map(handle => `${genImport(handle, getImportId(handle))};`).join('\n')}
${lazyImports.map(handle => `const ${getImportId(handle)} = () => import('${handle}');`).join('\n')}
${lazyImports.map(handle => `const ${getImportId(handle)} = ${genDynamicImport(handle)};`).join('\n')}
const middleware = [
${middleware.map(m => `{ route: '${m.route}', handle: ${getImportId(m.handle)}, lazy: ${m.lazy || true}, promisify: ${m.promisify !== undefined ? m.promisify : true} }`).join(',\n')}
];
const middleware = ${genArrayFromRaw(middleware.map(m => ({
route: JSON.stringify(m.route),
handle: getImportId(m.handle),
lazy: m.lazy || true,
promisify: m.promisify !== undefined ? m.promisify : true
})))};
export default middleware
export default middleware
`
}
}
Expand Down
5 changes: 3 additions & 2 deletions packages/nitro/src/rollup/plugins/storage.ts
@@ -1,4 +1,5 @@
import virtual from '@rollup/plugin-virtual'
import { genImport, genString } from 'knitwork'
import { serializeImportName } from '../../utils'

export interface StorageOptions {
Expand Down Expand Up @@ -35,13 +36,13 @@ export function storage (opts: StorageOptions) {
import { createStorage } from 'unstorage'
import { assets } from '#assets'
${driverImports.map(i => `import ${serializeImportName(i)} from '${i}'`).join('\n')}
${driverImports.map(i => genImport(i, serializeImportName(i))).join('\n')}
export const storage = createStorage({})
storage.mount('/assets', assets)
${mounts.map(m => `storage.mount('${m.path}', ${serializeImportName(m.driver)}(${JSON.stringify(m.opts)}))`).join('\n')}
${mounts.map(m => `storage.mount(${genString(m.path)}, ${serializeImportName(m.driver)}(${JSON.stringify(m.opts)}))`).join('\n')}
`
})
}
1 change: 1 addition & 0 deletions packages/nuxt3/package.json
Expand Up @@ -39,6 +39,7 @@
"hash-sum": "^2.0.0",
"hookable": "^5.1.1",
"ignore": "^5.2.0",
"knitwork": "^0.1.0",
"mlly": "^0.4.1",
"murmurhash-es": "^0.1.1",
"nuxi": "3.0.0",
Expand Down
3 changes: 2 additions & 1 deletion packages/nuxt3/src/auto-imports/module.ts
@@ -1,6 +1,7 @@
import { addVitePlugin, addWebpackPlugin, defineNuxtModule, addTemplate, resolveAlias, addPluginTemplate, useNuxt } from '@nuxt/kit'
import type { AutoImportsOptions } from '@nuxt/schema'
import { isAbsolute, join, relative, resolve, normalize } from 'pathe'
import { genDynamicImport } from 'knitwork'
import { TransformPlugin } from './transform'
import { Nuxt3AutoImports } from './imports'
import { scanForComposables } from './composables'
Expand Down Expand Up @@ -132,7 +133,7 @@ function generateDts (ctx: AutoImportContext) {
write: true,
getContents: () => `// Generated by auto imports
declare global {
${ctx.autoImports.map(i => ` const ${i.as}: typeof import('${r(i.from)}')['${i.name}']`).join('\n')}
${ctx.autoImports.map(i => ` const ${i.as}: typeof ${genDynamicImport(r(i.from), { wrapper: false })}['${i.name}']`).join('\n')}
}
export {}
Expand Down
7 changes: 4 additions & 3 deletions packages/nuxt3/src/auto-imports/utils.ts
@@ -1,4 +1,5 @@
import type { AutoImport } from '@nuxt/schema'
import { genExport, genImport, genString } from 'knitwork'

export function toImportModuleMap (autoImports: AutoImport[], isCJS = false) {
const aliasKeyword = isCJS ? ' : ' : ' as '
Expand All @@ -20,19 +21,19 @@ export function toImports (autoImports: AutoImport[], isCJS = false) {
const map = toImportModuleMap(autoImports, isCJS)
if (isCJS) {
return Object.entries(map)
.map(([name, imports]) => `const { ${Array.from(imports).join(', ')} } = require('${name}');`)
.map(([name, imports]) => `const { ${Array.from(imports).join(', ')} } = require(${genString(name)});`)
.join('\n')
} else {
return Object.entries(map)
.map(([name, imports]) => `import { ${Array.from(imports).join(', ')} } from '${name}';`)
.map(([name, imports]) => genImport(name, Array.from(imports)))
.join('\n')
}
}

export function toExports (autoImports: AutoImport[]) {
const map = toImportModuleMap(autoImports, false)
return Object.entries(map)
.map(([name, imports]) => `export { ${Array.from(imports).join(', ')} } from '${name}';`)
.map(([name, imports]) => genExport(name, Array.from(imports)))
.join('\n')
}

Expand Down
3 changes: 2 additions & 1 deletion packages/nuxt3/src/components/loader.ts
@@ -1,6 +1,7 @@
import { createUnplugin } from 'unplugin'
import { parseQuery, parseURL } from 'ufo'
import { Component } from '@nuxt/schema'
import { genImport } from 'knitwork'

interface LoaderOptions {
getComponents(): Component[]
Expand Down Expand Up @@ -36,7 +37,7 @@ function transform (content: string, components: Component[]) {
if (component) {
const identifier = map.get(component) || `__nuxt_component_${num++}`
map.set(component, identifier)
imports += `import ${identifier} from "${component.filePath}";`
imports += genImport(component.filePath, identifier)
return ` ${identifier}`
}
// no matched
Expand Down

0 comments on commit 29171bd

Please sign in to comment.