Skip to content

Commit

Permalink
perf: avoid sourcemap chains during dev (#8796)
Browse files Browse the repository at this point in the history
Co-authored-by: yoho <panyoho@gmail.com>
  • Loading branch information
patak-dev and poyoho committed Jun 26, 2022
1 parent 8bb452d commit 1566f61
Show file tree
Hide file tree
Showing 12 changed files with 378 additions and 505 deletions.
@@ -1,164 +1,44 @@
// Vitest Snapshot v1

exports[`fixture > transform 1`] = `
"import * as __vite_glob_1_0 from \\"./modules/a.ts\\"
import * as __vite_glob_1_1 from \\"./modules/b.ts\\"
import * as __vite_glob_1_2 from \\"./modules/index.ts\\"
import { name as __vite_glob_3_0 } from \\"./modules/a.ts\\"
import { name as __vite_glob_3_1 } from \\"./modules/b.ts\\"
import { name as __vite_glob_3_2 } from \\"./modules/index.ts\\"
import { default as __vite_glob_5_0 } from \\"./modules/a.ts?raw\\"
import { default as __vite_glob_5_1 } from \\"./modules/b.ts?raw\\"
import \\"../../../../../../types/importMeta\\";
export const basic = Object.assign({
\\"./modules/a.ts\\": () => import(\\"./modules/a.ts\\"),
\\"./modules/b.ts\\": () => import(\\"./modules/b.ts\\"),
\\"./modules/index.ts\\": () => import(\\"./modules/index.ts\\")
});
export const basicEager = Object.assign({
\\"./modules/a.ts\\": __vite_glob_1_0,
\\"./modules/b.ts\\": __vite_glob_1_1,
\\"./modules/index.ts\\": __vite_glob_1_2
});
export const ignore = Object.assign({
\\"./modules/a.ts\\": () => import(\\"./modules/a.ts\\"),
\\"./modules/b.ts\\": () => import(\\"./modules/b.ts\\")
});
export const namedEager = Object.assign({
\\"./modules/a.ts\\": __vite_glob_3_0,
\\"./modules/b.ts\\": __vite_glob_3_1,
\\"./modules/index.ts\\": __vite_glob_3_2
});
export const namedDefault = Object.assign({
\\"./modules/a.ts\\": () => import(\\"./modules/a.ts\\").then(m => m[\\"default\\"]),
\\"./modules/b.ts\\": () => import(\\"./modules/b.ts\\").then(m => m[\\"default\\"]),
\\"./modules/index.ts\\": () => import(\\"./modules/index.ts\\").then(m => m[\\"default\\"])
});
export const eagerAs = Object.assign({
\\"./modules/a.ts\\": __vite_glob_5_0,
\\"./modules/b.ts\\": __vite_glob_5_1
});
export const rawImportModule = Object.assign({
\\"./modules/a.ts\\": () => import(\\"./modules/a.ts?raw\\"),
\\"./modules/b.ts\\": () => import(\\"./modules/b.ts?raw\\")
});
export const excludeSelf = Object.assign({
\\"./sibling.ts\\": () => import(\\"./sibling.ts\\")
});
export const customQueryString = Object.assign({
\\"./sibling.ts\\": () => import(\\"./sibling.ts?custom\\")
});
export const customQueryObject = Object.assign({
\\"./sibling.ts\\": () => import(\\"./sibling.ts?foo=bar&raw=true\\")
});
export const parent = Object.assign({
});
export const rootMixedRelative = Object.assign({
\\"/css.spec.ts\\": () => import(\\"../../css.spec.ts?url\\").then(m => m[\\"default\\"]),
\\"/define.spec.ts\\": () => import(\\"../../define.spec.ts?url\\").then(m => m[\\"default\\"]),
\\"/esbuild.spec.ts\\": () => import(\\"../../esbuild.spec.ts?url\\").then(m => m[\\"default\\"]),
\\"/import.spec.ts\\": () => import(\\"../../import.spec.ts?url\\").then(m => m[\\"default\\"]),
\\"/importGlob/fixture-b/a.ts\\": () => import(\\"../fixture-b/a.ts?url\\").then(m => m[\\"default\\"]),
\\"/importGlob/fixture-b/b.ts\\": () => import(\\"../fixture-b/b.ts?url\\").then(m => m[\\"default\\"]),
\\"/importGlob/fixture-b/index.ts\\": () => import(\\"../fixture-b/index.ts?url\\").then(m => m[\\"default\\"])
});
export const cleverCwd1 = Object.assign({
\\"./node_modules/framework/pages/hello.page.js\\": () => import(\\"./node_modules/framework/pages/hello.page.js\\")
});
export const cleverCwd2 = Object.assign({
\\"./modules/a.ts\\": () => import(\\"./modules/a.ts\\"),
\\"./modules/b.ts\\": () => import(\\"./modules/b.ts\\"),
\\"../fixture-b/a.ts\\": () => import(\\"../fixture-b/a.ts\\"),
\\"../fixture-b/b.ts\\": () => import(\\"../fixture-b/b.ts\\")
});
"import * as __vite_glob_1_0 from \\"./modules/a.ts\\";import * as __vite_glob_1_1 from \\"./modules/b.ts\\";import * as __vite_glob_1_2 from \\"./modules/index.ts\\";import { name as __vite_glob_3_0 } from \\"./modules/a.ts\\";import { name as __vite_glob_3_1 } from \\"./modules/b.ts\\";import { name as __vite_glob_3_2 } from \\"./modules/index.ts\\";import { default as __vite_glob_5_0 } from \\"./modules/a.ts?raw\\";import { default as __vite_glob_5_1 } from \\"./modules/b.ts?raw\\";import \\"../../../../../../types/importMeta\\";
export const basic = Object.assign({\\"./modules/a.ts\\": () => import(\\"./modules/a.ts\\"),\\"./modules/b.ts\\": () => import(\\"./modules/b.ts\\"),\\"./modules/index.ts\\": () => import(\\"./modules/index.ts\\")});
export const basicEager = Object.assign({\\"./modules/a.ts\\": __vite_glob_1_0,\\"./modules/b.ts\\": __vite_glob_1_1,\\"./modules/index.ts\\": __vite_glob_1_2});
export const ignore = Object.assign({\\"./modules/a.ts\\": () => import(\\"./modules/a.ts\\"),\\"./modules/b.ts\\": () => import(\\"./modules/b.ts\\")});
export const namedEager = Object.assign({\\"./modules/a.ts\\": __vite_glob_3_0,\\"./modules/b.ts\\": __vite_glob_3_1,\\"./modules/index.ts\\": __vite_glob_3_2});
export const namedDefault = Object.assign({\\"./modules/a.ts\\": () => import(\\"./modules/a.ts\\").then(m => m[\\"default\\"]),\\"./modules/b.ts\\": () => import(\\"./modules/b.ts\\").then(m => m[\\"default\\"]),\\"./modules/index.ts\\": () => import(\\"./modules/index.ts\\").then(m => m[\\"default\\"])});
export const eagerAs = Object.assign({\\"./modules/a.ts\\": __vite_glob_5_0,\\"./modules/b.ts\\": __vite_glob_5_1});
export const rawImportModule = Object.assign({\\"./modules/a.ts\\": () => import(\\"./modules/a.ts?raw\\"),\\"./modules/b.ts\\": () => import(\\"./modules/b.ts?raw\\")});
export const excludeSelf = Object.assign({\\"./sibling.ts\\": () => import(\\"./sibling.ts\\")});
export const customQueryString = Object.assign({\\"./sibling.ts\\": () => import(\\"./sibling.ts?custom\\")});
export const customQueryObject = Object.assign({\\"./sibling.ts\\": () => import(\\"./sibling.ts?foo=bar&raw=true\\")});
export const parent = Object.assign({});
export const rootMixedRelative = Object.assign({\\"/css.spec.ts\\": () => import(\\"../../css.spec.ts?url\\").then(m => m[\\"default\\"]),\\"/define.spec.ts\\": () => import(\\"../../define.spec.ts?url\\").then(m => m[\\"default\\"]),\\"/esbuild.spec.ts\\": () => import(\\"../../esbuild.spec.ts?url\\").then(m => m[\\"default\\"]),\\"/import.spec.ts\\": () => import(\\"../../import.spec.ts?url\\").then(m => m[\\"default\\"]),\\"/importGlob/fixture-b/a.ts\\": () => import(\\"../fixture-b/a.ts?url\\").then(m => m[\\"default\\"]),\\"/importGlob/fixture-b/b.ts\\": () => import(\\"../fixture-b/b.ts?url\\").then(m => m[\\"default\\"]),\\"/importGlob/fixture-b/index.ts\\": () => import(\\"../fixture-b/index.ts?url\\").then(m => m[\\"default\\"])});
export const cleverCwd1 = Object.assign({\\"./node_modules/framework/pages/hello.page.js\\": () => import(\\"./node_modules/framework/pages/hello.page.js\\")});
export const cleverCwd2 = Object.assign({\\"./modules/a.ts\\": () => import(\\"./modules/a.ts\\"),\\"./modules/b.ts\\": () => import(\\"./modules/b.ts\\"),\\"../fixture-b/a.ts\\": () => import(\\"../fixture-b/a.ts\\"),\\"../fixture-b/b.ts\\": () => import(\\"../fixture-b/b.ts\\")});
"
`;

exports[`fixture > transform with restoreQueryExtension 1`] = `
"import * as __vite_glob_1_0 from \\"./modules/a.ts\\"
import * as __vite_glob_1_1 from \\"./modules/b.ts\\"
import * as __vite_glob_1_2 from \\"./modules/index.ts\\"
import { name as __vite_glob_3_0 } from \\"./modules/a.ts\\"
import { name as __vite_glob_3_1 } from \\"./modules/b.ts\\"
import { name as __vite_glob_3_2 } from \\"./modules/index.ts\\"
import { default as __vite_glob_5_0 } from \\"./modules/a.ts?raw\\"
import { default as __vite_glob_5_1 } from \\"./modules/b.ts?raw\\"
import \\"../../../../../../types/importMeta\\";
export const basic = Object.assign({
\\"./modules/a.ts\\": () => import(\\"./modules/a.ts\\"),
\\"./modules/b.ts\\": () => import(\\"./modules/b.ts\\"),
\\"./modules/index.ts\\": () => import(\\"./modules/index.ts\\")
});
export const basicEager = Object.assign({
\\"./modules/a.ts\\": __vite_glob_1_0,
\\"./modules/b.ts\\": __vite_glob_1_1,
\\"./modules/index.ts\\": __vite_glob_1_2
});
export const ignore = Object.assign({
\\"./modules/a.ts\\": () => import(\\"./modules/a.ts\\"),
\\"./modules/b.ts\\": () => import(\\"./modules/b.ts\\")
});
export const namedEager = Object.assign({
\\"./modules/a.ts\\": __vite_glob_3_0,
\\"./modules/b.ts\\": __vite_glob_3_1,
\\"./modules/index.ts\\": __vite_glob_3_2
});
export const namedDefault = Object.assign({
\\"./modules/a.ts\\": () => import(\\"./modules/a.ts\\").then(m => m[\\"default\\"]),
\\"./modules/b.ts\\": () => import(\\"./modules/b.ts\\").then(m => m[\\"default\\"]),
\\"./modules/index.ts\\": () => import(\\"./modules/index.ts\\").then(m => m[\\"default\\"])
});
export const eagerAs = Object.assign({
\\"./modules/a.ts\\": __vite_glob_5_0,
\\"./modules/b.ts\\": __vite_glob_5_1
});
export const rawImportModule = Object.assign({
\\"./modules/a.ts\\": () => import(\\"./modules/a.ts?raw\\"),
\\"./modules/b.ts\\": () => import(\\"./modules/b.ts?raw\\")
});
export const excludeSelf = Object.assign({
\\"./sibling.ts\\": () => import(\\"./sibling.ts\\")
});
export const customQueryString = Object.assign({
\\"./sibling.ts\\": () => import(\\"./sibling.ts?custom&lang.ts\\")
});
export const customQueryObject = Object.assign({
\\"./sibling.ts\\": () => import(\\"./sibling.ts?foo=bar&raw=true&lang.ts\\")
});
export const parent = Object.assign({
});
export const rootMixedRelative = Object.assign({
\\"/css.spec.ts\\": () => import(\\"../../css.spec.ts?url&lang.ts\\").then(m => m[\\"default\\"]),
\\"/define.spec.ts\\": () => import(\\"../../define.spec.ts?url&lang.ts\\").then(m => m[\\"default\\"]),
\\"/esbuild.spec.ts\\": () => import(\\"../../esbuild.spec.ts?url&lang.ts\\").then(m => m[\\"default\\"]),
\\"/import.spec.ts\\": () => import(\\"../../import.spec.ts?url&lang.ts\\").then(m => m[\\"default\\"]),
\\"/importGlob/fixture-b/a.ts\\": () => import(\\"../fixture-b/a.ts?url&lang.ts\\").then(m => m[\\"default\\"]),
\\"/importGlob/fixture-b/b.ts\\": () => import(\\"../fixture-b/b.ts?url&lang.ts\\").then(m => m[\\"default\\"]),
\\"/importGlob/fixture-b/index.ts\\": () => import(\\"../fixture-b/index.ts?url&lang.ts\\").then(m => m[\\"default\\"])
});
export const cleverCwd1 = Object.assign({
\\"./node_modules/framework/pages/hello.page.js\\": () => import(\\"./node_modules/framework/pages/hello.page.js\\")
});
export const cleverCwd2 = Object.assign({
\\"./modules/a.ts\\": () => import(\\"./modules/a.ts\\"),
\\"./modules/b.ts\\": () => import(\\"./modules/b.ts\\"),
\\"../fixture-b/a.ts\\": () => import(\\"../fixture-b/a.ts\\"),
\\"../fixture-b/b.ts\\": () => import(\\"../fixture-b/b.ts\\")
});
"import * as __vite_glob_1_0 from \\"./modules/a.ts\\";import * as __vite_glob_1_1 from \\"./modules/b.ts\\";import * as __vite_glob_1_2 from \\"./modules/index.ts\\";import { name as __vite_glob_3_0 } from \\"./modules/a.ts\\";import { name as __vite_glob_3_1 } from \\"./modules/b.ts\\";import { name as __vite_glob_3_2 } from \\"./modules/index.ts\\";import { default as __vite_glob_5_0 } from \\"./modules/a.ts?raw\\";import { default as __vite_glob_5_1 } from \\"./modules/b.ts?raw\\";import \\"../../../../../../types/importMeta\\";
export const basic = Object.assign({\\"./modules/a.ts\\": () => import(\\"./modules/a.ts\\"),\\"./modules/b.ts\\": () => import(\\"./modules/b.ts\\"),\\"./modules/index.ts\\": () => import(\\"./modules/index.ts\\")});
export const basicEager = Object.assign({\\"./modules/a.ts\\": __vite_glob_1_0,\\"./modules/b.ts\\": __vite_glob_1_1,\\"./modules/index.ts\\": __vite_glob_1_2});
export const ignore = Object.assign({\\"./modules/a.ts\\": () => import(\\"./modules/a.ts\\"),\\"./modules/b.ts\\": () => import(\\"./modules/b.ts\\")});
export const namedEager = Object.assign({\\"./modules/a.ts\\": __vite_glob_3_0,\\"./modules/b.ts\\": __vite_glob_3_1,\\"./modules/index.ts\\": __vite_glob_3_2});
export const namedDefault = Object.assign({\\"./modules/a.ts\\": () => import(\\"./modules/a.ts\\").then(m => m[\\"default\\"]),\\"./modules/b.ts\\": () => import(\\"./modules/b.ts\\").then(m => m[\\"default\\"]),\\"./modules/index.ts\\": () => import(\\"./modules/index.ts\\").then(m => m[\\"default\\"])});
export const eagerAs = Object.assign({\\"./modules/a.ts\\": __vite_glob_5_0,\\"./modules/b.ts\\": __vite_glob_5_1});
export const rawImportModule = Object.assign({\\"./modules/a.ts\\": () => import(\\"./modules/a.ts?raw\\"),\\"./modules/b.ts\\": () => import(\\"./modules/b.ts?raw\\")});
export const excludeSelf = Object.assign({\\"./sibling.ts\\": () => import(\\"./sibling.ts\\")});
export const customQueryString = Object.assign({\\"./sibling.ts\\": () => import(\\"./sibling.ts?custom&lang.ts\\")});
export const customQueryObject = Object.assign({\\"./sibling.ts\\": () => import(\\"./sibling.ts?foo=bar&raw=true&lang.ts\\")});
export const parent = Object.assign({});
export const rootMixedRelative = Object.assign({\\"/css.spec.ts\\": () => import(\\"../../css.spec.ts?url&lang.ts\\").then(m => m[\\"default\\"]),\\"/define.spec.ts\\": () => import(\\"../../define.spec.ts?url&lang.ts\\").then(m => m[\\"default\\"]),\\"/esbuild.spec.ts\\": () => import(\\"../../esbuild.spec.ts?url&lang.ts\\").then(m => m[\\"default\\"]),\\"/import.spec.ts\\": () => import(\\"../../import.spec.ts?url&lang.ts\\").then(m => m[\\"default\\"]),\\"/importGlob/fixture-b/a.ts\\": () => import(\\"../fixture-b/a.ts?url&lang.ts\\").then(m => m[\\"default\\"]),\\"/importGlob/fixture-b/b.ts\\": () => import(\\"../fixture-b/b.ts?url&lang.ts\\").then(m => m[\\"default\\"]),\\"/importGlob/fixture-b/index.ts\\": () => import(\\"../fixture-b/index.ts?url&lang.ts\\").then(m => m[\\"default\\"])});
export const cleverCwd1 = Object.assign({\\"./node_modules/framework/pages/hello.page.js\\": () => import(\\"./node_modules/framework/pages/hello.page.js\\")});
export const cleverCwd2 = Object.assign({\\"./modules/a.ts\\": () => import(\\"./modules/a.ts\\"),\\"./modules/b.ts\\": () => import(\\"./modules/b.ts\\"),\\"../fixture-b/a.ts\\": () => import(\\"../fixture-b/a.ts\\"),\\"../fixture-b/b.ts\\": () => import(\\"../fixture-b/b.ts\\")});
"
`;

exports[`fixture > virtual modules 1`] = `
"Object.assign({
\\"/modules/a.ts\\": () => import(\\"/modules/a.ts\\"),
\\"/modules/b.ts\\": () => import(\\"/modules/b.ts\\"),
\\"/modules/index.ts\\": () => import(\\"/modules/index.ts\\")
})
Object.assign({
\\"/../fixture-b/a.ts\\": () => import(\\"/../fixture-b/a.ts\\"),
\\"/../fixture-b/b.ts\\": () => import(\\"/../fixture-b/b.ts\\"),
\\"/../fixture-b/index.ts\\": () => import(\\"/../fixture-b/index.ts\\")
})"
"Object.assign({\\"/modules/a.ts\\": () => import(\\"/modules/a.ts\\"),\\"/modules/b.ts\\": () => import(\\"/modules/b.ts\\"),\\"/modules/index.ts\\": () => import(\\"/modules/index.ts\\")})
Object.assign({\\"/../fixture-b/a.ts\\": () => import(\\"/../fixture-b/a.ts\\"),\\"/../fixture-b/b.ts\\": () => import(\\"/../fixture-b/b.ts\\"),\\"/../fixture-b/index.ts\\": () => import(\\"/../fixture-b/index.ts\\")})"
`;
4 changes: 2 additions & 2 deletions packages/vite/src/node/plugins/assetImportMetaUrl.ts
Expand Up @@ -3,7 +3,7 @@ import MagicString from 'magic-string'
import { stripLiteral } from 'strip-literal'
import type { Plugin } from '../plugin'
import type { ResolvedConfig } from '../config'
import { transformResult } from '../utils'
import { transformStableResult } from '../utils'
import { fileToUrl } from './asset'
import { preloadHelperId } from './importAnalysisBuild'

Expand Down Expand Up @@ -81,7 +81,7 @@ export function assetImportMetaUrlPlugin(config: ResolvedConfig): Plugin {
)
}
if (s) {
return transformResult(s, id, config)
return transformStableResult(s, id, config)
}
}
return null
Expand Down
8 changes: 2 additions & 6 deletions packages/vite/src/node/plugins/define.ts
@@ -1,7 +1,7 @@
import MagicString from 'magic-string'
import type { TransformResult } from 'rollup'
import type { ResolvedConfig } from '../config'
import type { Plugin } from '../plugin'
import { transformStableResult } from '../utils'
import { isCSSRequest } from './css'
import { isHTMLRequest } from './html'

Expand Down Expand Up @@ -144,11 +144,7 @@ export function definePlugin(config: ResolvedConfig): Plugin {
return null
}

const result: TransformResult = { code: s.toString() }
if (config.build.sourcemap) {
result.map = s.generateMap({ hires: true })
}
return result
return transformStableResult(s, id, config)
}
}
}
4 changes: 2 additions & 2 deletions packages/vite/src/node/plugins/dynamicImportVars.ts
Expand Up @@ -11,7 +11,7 @@ import {
normalizePath,
parseRequest,
requestQuerySplitRE,
transformResult
transformStableResult
} from '../utils'

export const dynamicImportHelperId = '/@vite/dynamic-import-helper'
Expand Down Expand Up @@ -209,7 +209,7 @@ export function dynamicImportVarsPlugin(config: ResolvedConfig): Plugin {
`import __variableDynamicImportRuntimeHelper from "${dynamicImportHelperId}";`
)
}
return transformResult(s, importer, config)
return transformStableResult(s, importer, config)
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions packages/vite/src/node/plugins/importAnalysis.ts
Expand Up @@ -40,7 +40,7 @@ import {
removeImportQuery,
stripBomTag,
timeFrom,
transformResult,
transformStableResult,
unwrapId
} from '../utils'
import type { ResolvedConfig } from '../config'
Expand Down Expand Up @@ -711,7 +711,7 @@ export function importAnalysisPlugin(config: ResolvedConfig): Plugin {
}

if (s) {
return transformResult(s, importer, config)
return transformStableResult(s, importer, config)
} else {
return source
}
Expand Down
8 changes: 4 additions & 4 deletions packages/vite/src/node/plugins/importMetaGlob.ts
Expand Up @@ -17,7 +17,7 @@ import type { Plugin } from '../plugin'
import type { ViteDevServer } from '../server'
import type { ModuleNode } from '../server/moduleGraph'
import type { ResolvedConfig } from '../config'
import { normalizePath, slash, transformResult } from '../utils'
import { normalizePath, slash, transformStableResult } from '../utils'

const { isMatch, scan } = micromatch

Expand Down Expand Up @@ -75,7 +75,7 @@ export function importGlobPlugin(config: ResolvedConfig): Plugin {
server!.watcher.add(dirname(file))
})
}
return transformResult(result.s, id, config)
return transformStableResult(result.s, id, config)
}
}
}
Expand Down Expand Up @@ -426,7 +426,7 @@ export async function transformGlobImport(

files.forEach((i) => matchedFiles.add(i))

const replacement = `Object.assign({\n${objectProps.join(',\n')}\n})`
const replacement = `Object.assign({${objectProps.join(',')}})`
s.overwrite(start, end, replacement)

return staticImports
Expand All @@ -435,7 +435,7 @@ export async function transformGlobImport(
)
).flat()

if (staticImports.length) s.prepend(`${staticImports.join('\n')}\n`)
if (staticImports.length) s.prepend(`${staticImports.join(';')};`)

return {
s,
Expand Down
4 changes: 2 additions & 2 deletions packages/vite/src/node/plugins/workerImportMetaUrl.ts
Expand Up @@ -10,7 +10,7 @@ import {
injectQuery,
normalizePath,
parseRequest,
transformResult
transformStableResult
} from '../utils'
import { getDepsOptimizer } from '../optimizer'
import type { WorkerType } from './worker'
Expand Down Expand Up @@ -136,7 +136,7 @@ export function workerImportMetaUrlPlugin(config: ResolvedConfig): Plugin {
}

if (s) {
return transformResult(s, id, config)
return transformStableResult(s, id, config)
}

return null
Expand Down
13 changes: 9 additions & 4 deletions packages/vite/src/node/utils.ts
Expand Up @@ -1028,16 +1028,21 @@ function normalizeSingleAlias({
return alias
}

export function transformResult(
/**
* Transforms transpiled code result where line numbers aren't altered,
* so we can skip sourcemap generation during dev
*/
export function transformStableResult(
s: MagicString,
id: string,
config: ResolvedConfig
): TransformResult {
const isBuild = config.command === 'build'
const needSourceMap = !isBuild || config.build.sourcemap
return {
code: s.toString(),
map: needSourceMap ? s.generateMap({ hires: true, source: id }) : null
map:
config.command === 'build' && config.build.sourcemap
? s.generateMap({ hires: true, source: id })
: null
}
}

Expand Down

0 comments on commit 1566f61

Please sign in to comment.