upgrade webpack-sources

make source maps and source names context independent

add enhanced-resolve declarations
add types to Module.build
fix tooling for import order to support import renaming
add support for concatenated modules in eval source maps
This commit is contained in:
Tobias Koppers 2019-11-11 15:25:03 +01:00
parent 51ae7896e2
commit b90f3e14a1
29 changed files with 771 additions and 298 deletions

41
declarations.d.ts vendored
View File

@ -345,6 +345,47 @@ declare module "webpack-sources" {
}
}
declare module "enhanced-resolve" {
type ResolveFunction = (
path: string,
request: string,
resolveContext: ResolveContext,
callback: (
err?: NodeJS.ErrnoException,
result?: string,
additionalInfo?: Object
) => void
) => void;
export function create(options: any): ResolveFunction;
interface ResolveContext {
log?: (message: string) => void;
fileDependencies?: Set<string>;
contextDependencies?: Set<string>;
missingDependencies?: Set<string>;
stack?: Set<string>;
}
export class Resolver {
resolve(
context: Object,
path: string,
request: string,
resolveContext: ResolveContext,
callback: (
err?: NodeJS.ErrnoException,
result?: string,
additionalInfo?: Object
) => void
): void;
}
export class ResolverFactory {
static createResolver(options: TODO): Resolver;
}
}
// This "hack" is needed because typescript doesn't support recursive type definitions
// It's referenced from "ruleSet-conditions" in schemas/WebpackOptions.json
interface RuleSetConditionsRecursive

View File

@ -22,6 +22,7 @@ const { contextify } = require("./util/identifier");
const makeSerializable = require("./util/makeSerializable");
/** @typedef {import("webpack-sources").Source} Source */
/** @typedef {import("../declarations/WebpackOptions").WebpackOptions} WebpackOptions */
/** @typedef {import("./ChunkGraph")} ChunkGraph */
/** @typedef {import("./ChunkGroup").RawChunkGroupOptions} RawChunkGroupOptions */
/** @typedef {import("./Compilation")} Compilation */
@ -32,8 +33,10 @@ const makeSerializable = require("./util/makeSerializable");
/** @typedef {import("./Module").NeedBuildContext} NeedBuildContext */
/** @typedef {import("./ModuleGraph")} ModuleGraph */
/** @typedef {import("./RequestShortener")} RequestShortener */
/** @typedef {import("./ResolverFactory").ResolverWithOptions} ResolverWithOptions */
/** @typedef {import("./RuntimeTemplate")} RuntimeTemplate */
/** @typedef {import("./dependencies/ContextElementDependency")} ContextElementDependency */
/** @typedef {import("./util/fs").InputFileSystem} InputFileSystem */
/** @typedef {"sync" | "eager" | "weak" | "async-weak" | "lazy" | "lazy-once"} ContextMode Context mode */
@ -309,10 +312,10 @@ class ContextModule extends Module {
}
/**
* @param {TODO} options TODO
* @param {WebpackOptions} options webpack options
* @param {Compilation} compilation the compilation
* @param {TODO} resolver TODO
* @param {TODO} fs the file system
* @param {ResolverWithOptions} resolver the resolver
* @param {InputFileSystem} fs the file system
* @param {function(WebpackError=): void} callback callback function
* @returns {void}
*/

View File

@ -12,6 +12,7 @@ const DelegatedSourceDependency = require("./dependencies/DelegatedSourceDepende
const StaticExportsDependency = require("./dependencies/StaticExportsDependency");
/** @typedef {import("webpack-sources").Source} Source */
/** @typedef {import("../declarations/WebpackOptions").WebpackOptions} WebpackOptions */
/** @typedef {import("./ChunkGraph")} ChunkGraph */
/** @typedef {import("./Compilation")} Compilation */
/** @typedef {import("./DependencyTemplates")} DependencyTemplates */
@ -22,10 +23,12 @@ const StaticExportsDependency = require("./dependencies/StaticExportsDependency"
/** @typedef {import("./Module").NeedBuildContext} NeedBuildContext */
/** @typedef {import("./Module").SourceContext} SourceContext */
/** @typedef {import("./RequestShortener")} RequestShortener */
/** @typedef {import("./ResolverFactory").ResolverWithOptions} ResolverWithOptions */
/** @typedef {import("./RuntimeTemplate")} RuntimeTemplate */
/** @typedef {import("./WebpackError")} WebpackError */
/** @typedef {import("./dependencies/ModuleDependency")} ModuleDependency */
/** @typedef {import("./util/Hash")} Hash */
/** @typedef {import("./util/fs").InputFileSystem} InputFileSystem */
const TYPES = new Set(["javascript"]);
@ -90,10 +93,10 @@ class DelegatedModule extends Module {
}
/**
* @param {TODO} options TODO
* @param {WebpackOptions} options webpack options
* @param {Compilation} compilation the compilation
* @param {TODO} resolver TODO
* @param {TODO} fs the file system
* @param {ResolverWithOptions} resolver the resolver
* @param {InputFileSystem} fs the file system
* @param {function(WebpackError=): void} callback callback function
* @returns {void}
*/

View File

@ -10,6 +10,7 @@ const Module = require("./Module");
const RuntimeGlobals = require("./RuntimeGlobals");
/** @typedef {import("webpack-sources").Source} Source */
/** @typedef {import("../declarations/WebpackOptions").WebpackOptions} WebpackOptions */
/** @typedef {import("./ChunkGraph")} ChunkGraph */
/** @typedef {import("./Compilation")} Compilation */
/** @typedef {import("./DependencyTemplates")} DependencyTemplates */
@ -18,9 +19,11 @@ const RuntimeGlobals = require("./RuntimeGlobals");
/** @typedef {import("./Module").NeedBuildContext} NeedBuildContext */
/** @typedef {import("./Module").SourceContext} SourceContext */
/** @typedef {import("./RequestShortener")} RequestShortener */
/** @typedef {import("./ResolverFactory").ResolverWithOptions} ResolverWithOptions */
/** @typedef {import("./RuntimeTemplate")} RuntimeTemplate */
/** @typedef {import("./WebpackError")} WebpackError */
/** @typedef {import("./util/Hash")} Hash */
/** @typedef {import("./util/fs").InputFileSystem} InputFileSystem */
const TYPES = new Set(["javascript"]);
@ -56,10 +59,10 @@ class DllModule extends Module {
}
/**
* @param {TODO} options TODO
* @param {WebpackOptions} options webpack options
* @param {Compilation} compilation the compilation
* @param {TODO} resolver TODO
* @param {TODO} fs the file system
* @param {ResolverWithOptions} resolver the resolver
* @param {InputFileSystem} fs the file system
* @param {function(WebpackError=): void} callback callback function
* @returns {void}
*/

View File

@ -10,6 +10,8 @@ const ModuleFilenameHelpers = require("./ModuleFilenameHelpers");
const NormalModule = require("./NormalModule");
const SourceMapDevToolModuleOptionsPlugin = require("./SourceMapDevToolModuleOptionsPlugin");
const JavascriptModulesPlugin = require("./javascript/JavascriptModulesPlugin");
const ConcatenatedModule = require("./optimize/ConcatenatedModule");
const { absolutify } = require("./util/identifier");
/** @typedef {import("webpack-sources").Source} Source */
/** @typedef {import("./Compiler")} Compiler */
@ -59,13 +61,23 @@ class EvalSourceMapDevToolPlugin {
return cachedSource;
}
if (!(m instanceof NormalModule)) {
return source;
}
const module = /** @type {NormalModule} */ (m);
if (!matchModule(module.resource)) {
if (m instanceof NormalModule) {
const module = /** @type {NormalModule} */ (m);
if (!matchModule(module.resource)) {
return source;
}
} else if (m instanceof ConcatenatedModule) {
const concatModule = /** @type {ConcatenatedModule} */ (m);
if (concatModule.rootModule instanceof NormalModule) {
const module =
/** @type {NormalModule} */ (concatModule.rootModule);
if (!matchModule(module.resource)) {
return source;
}
} else {
return source;
}
} else {
return source;
}
@ -89,7 +101,11 @@ class EvalSourceMapDevToolPlugin {
obj[key] = sourceMap[key];
return obj;
}, {});
const context = compiler.options.context;
const root = compiler.root;
const modules = sourceMap.sources.map(source => {
if (!source.startsWith("webpack://")) return source;
source = absolutify(context, source.slice(10), root);
const module = compilation.findModule(source);
return module || source;
});
@ -115,7 +131,7 @@ class EvalSourceMapDevToolPlugin {
);
sourceMap.sources = moduleFilenames;
sourceMap.sourceRoot = options.sourceRoot || "";
const moduleId = chunkGraph.getModuleId(module);
const moduleId = chunkGraph.getModuleId(m);
sourceMap.file = `${moduleId}.js`;
const footer =

View File

@ -12,6 +12,7 @@ const Template = require("./Template");
const makeSerializable = require("./util/makeSerializable");
/** @typedef {import("webpack-sources").Source} Source */
/** @typedef {import("../declarations/WebpackOptions").WebpackOptions} WebpackOptions */
/** @typedef {import("./Chunk")} Chunk */
/** @typedef {import("./ChunkGraph")} ChunkGraph */
/** @typedef {import("./Compilation")} Compilation */
@ -21,9 +22,11 @@ const makeSerializable = require("./util/makeSerializable");
/** @typedef {import("./Module").LibIdentOptions} LibIdentOptions */
/** @typedef {import("./Module").NeedBuildContext} NeedBuildContext */
/** @typedef {import("./RequestShortener")} RequestShortener */
/** @typedef {import("./ResolverFactory").ResolverWithOptions} ResolverWithOptions */
/** @typedef {import("./RuntimeTemplate")} RuntimeTemplate */
/** @typedef {import("./WebpackError")} WebpackError */
/** @typedef {import("./util/Hash")} Hash */
/** @typedef {import("./util/fs").InputFileSystem} InputFileSystem */
/**
* @param {string|string[]} variableName the variable name or path
@ -184,10 +187,10 @@ class ExternalModule extends Module {
}
/**
* @param {TODO} options TODO
* @param {WebpackOptions} options webpack options
* @param {Compilation} compilation the compilation
* @param {TODO} resolver TODO
* @param {TODO} fs the file system
* @param {ResolverWithOptions} resolver the resolver
* @param {InputFileSystem} fs the file system
* @param {function(WebpackError=): void} callback callback function
* @returns {void}
*/

View File

@ -5,7 +5,7 @@
"use strict";
const resolve = require("enhanced-resolve");
const { create: createResolver } = require("enhanced-resolve");
const asyncLib = require("neo-async");
const AsyncQueue = require("./util/AsyncQueue");
const createHash = require("./util/createHash");
@ -15,9 +15,12 @@ const { join, dirname, relative } = require("./util/fs");
/** @typedef {import("./logging/Logger").Logger} Logger */
/** @typedef {import("./util/fs").InputFileSystem} InputFileSystem */
const resolveContext = resolve.create({
const resolveContext = createResolver({
resolveToContext: true
});
const resolve = createResolver({
extensions: [".js", ".json", ".node"]
});
let FS_ACCURACY = 2000;
@ -612,14 +615,14 @@ class FileSystemInfo {
const [type, context, path] = key.split("\n");
switch (type) {
case "d":
resolveContext(context, path, (err, result) => {
resolveContext(context, path, {}, (err, result) => {
if (err) return callback(err);
if (result !== expectedResult) return callback(INVALID);
callback();
});
break;
case "f":
resolve(context, path, (err, result) => {
resolve(context, path, {}, (err, result) => {
if (err) return callback(err);
if (result !== expectedResult) return callback(INVALID);
callback();

View File

@ -14,6 +14,7 @@ const { compareChunksById } = require("./util/comparators");
const makeSerializable = require("./util/makeSerializable");
/** @typedef {import("webpack-sources").Source} Source */
/** @typedef {import("../declarations/WebpackOptions").WebpackOptions} WebpackOptions */
/** @typedef {import("./Chunk")} Chunk */
/** @typedef {import("./ChunkGroup")} ChunkGroup */
/** @typedef {import("./Compilation")} Compilation */
@ -22,10 +23,12 @@ const makeSerializable = require("./util/makeSerializable");
/** @typedef {import("./FileSystemInfo")} FileSystemInfo */
/** @typedef {import("./ModuleGraph").UsageStateType} UsageStateType */
/** @typedef {import("./RequestShortener")} RequestShortener */
/** @typedef {import("./ResolverFactory").ResolverWithOptions} ResolverWithOptions */
/** @typedef {import("./RuntimeTemplate")} RuntimeTemplate */
/** @typedef {import("./WebpackError")} WebpackError */
/** @typedef {import("./util/Hash")} Hash */
/** @template T @typedef {import("./util/SortableSet")<T>} SortableSet<T> */
/** @typedef {import("./util/fs").InputFileSystem} InputFileSystem */
/**
* @typedef {Object} SourceContext
@ -599,10 +602,10 @@ class Module extends DependenciesBlock {
/**
* @abstract
* @param {TODO} options TODO
* @param {WebpackOptions} options webpack options
* @param {Compilation} compilation the compilation
* @param {TODO} resolver TODO
* @param {TODO} fs the file system
* @param {ResolverWithOptions} resolver the resolver
* @param {InputFileSystem} fs the file system
* @param {function(WebpackError=): void} callback callback function
* @returns {void}
*/

View File

@ -28,10 +28,12 @@ const {
keepOriginalOrder
} = require("./util/comparators");
const createHash = require("./util/createHash");
const contextify = require("./util/identifier").contextify;
const { contextify } = require("./util/identifier");
const makeSerializable = require("./util/makeSerializable");
/** @typedef {import("source-map").RawSourceMap} SourceMap */
/** @typedef {import("webpack-sources").Source} Source */
/** @typedef {import("../declarations/WebpackOptions").WebpackOptions} WebpackOptions */
/** @typedef {import("./ChunkGraph")} ChunkGraph */
/** @typedef {import("./Compilation")} Compilation */
/** @typedef {import("./DependencyTemplates")} DependencyTemplates */
@ -40,8 +42,10 @@ const makeSerializable = require("./util/makeSerializable");
/** @typedef {import("./Module").LibIdentOptions} LibIdentOptions */
/** @typedef {import("./Module").NeedBuildContext} NeedBuildContext */
/** @typedef {import("./RequestShortener")} RequestShortener */
/** @typedef {import("./ResolverFactory").ResolverWithOptions} ResolverWithOptions */
/** @typedef {import("./RuntimeTemplate")} RuntimeTemplate */
/** @typedef {import("./util/Hash")} Hash */
/** @typedef {import("./util/fs").InputFileSystem} InputFileSystem */
/**
* @typedef {Object} ParserState
@ -51,6 +55,33 @@ const makeSerializable = require("./util/makeSerializable");
* @property {TODO} options
*/
/**
* @param {string} context absolute context path
* @param {string} source a source path
* @param {Object=} associatedObjectForCache an object to which the cache will be attached
* @returns {string} new source path
*/
const contextifySourceUrl = (context, source, associatedObjectForCache) => {
return `webpack://${contextify(context, source, associatedObjectForCache)}`;
};
/**
* @param {string} context absolute context path
* @param {SourceMap} sourceMap a source map
* @param {Object=} associatedObjectForCache an object to which the cache will be attached
* @returns {SourceMap} new source map
*/
const contextifySourceMap = (context, sourceMap, associatedObjectForCache) => {
if (!Array.isArray(sourceMap.sources)) return sourceMap;
const newSources = sourceMap.sources.map(source =>
contextifySourceUrl(context, source, associatedObjectForCache)
);
return {
...sourceMap,
sources: newSources
};
};
/**
* @param {string | Buffer} input the input
* @returns {string} the converted string
@ -229,23 +260,45 @@ class NormalModule extends Module {
}
/**
* @param {string} context the compilation context
* @param {string} name the asset name
* @param {string} content the content
* @param {string | TODO} sourceMap an optional source map
* @param {Object=} associatedObjectForCache object for caching
* @returns {Source} the created source
*/
createSourceForAsset(name, content, sourceMap) {
createSourceForAsset(
context,
name,
content,
sourceMap,
associatedObjectForCache
) {
if (!sourceMap) {
return new RawSource(content);
}
if (typeof sourceMap === "string") {
return new OriginalSource(content, sourceMap);
return new OriginalSource(
content,
contextifySourceUrl(context, sourceMap, associatedObjectForCache)
);
}
return new SourceMapSource(content, name, sourceMap);
return new SourceMapSource(
content,
name,
contextifySourceMap(context, sourceMap, associatedObjectForCache)
);
}
/**
* @param {ResolverWithOptions} resolver a resolver
* @param {WebpackOptions} options webpack options
* @param {Compilation} compilation the compilation
* @param {InputFileSystem} fs file system from reading
* @returns {any} loader context
*/
createLoaderContext(resolver, options, compilation, fs) {
const requestShortener = compilation.runtimeTemplate.requestShortener;
const getCurrentLoaderName = () => {
@ -307,9 +360,11 @@ class NormalModule extends Module {
this.buildInfo.assetsInfo = new Map();
}
this.buildInfo.assets[name] = this.createSourceForAsset(
options.context,
name,
content,
sourceMap
sourceMap,
compilation.compiler.root
);
this.buildInfo.assetsInfo.set(name, assetInfo);
},
@ -349,11 +404,13 @@ class NormalModule extends Module {
}
/**
* @param {string} context the compilation context
* @param {string | Buffer} content the content
* @param {string | TODO} sourceMap an optional source map
* @param {Object=} associatedObjectForCache object for caching
* @returns {Source} the created source
*/
createSource(content, sourceMap) {
createSource(context, content, sourceMap, associatedObjectForCache) {
if (Buffer.isBuffer(content)) {
// @ts-ignore
// TODO We need to fix @types/webpack-sources to allow RawSource to take a Buffer | string
@ -369,12 +426,27 @@ class NormalModule extends Module {
const identifier = this.identifier();
if (this.useSourceMap && sourceMap) {
return new SourceMapSource(content, identifier, sourceMap);
return new SourceMapSource(
content,
contextifySourceUrl(context, identifier, associatedObjectForCache),
contextifySourceMap(context, sourceMap, associatedObjectForCache)
);
}
return new OriginalSource(content, identifier);
return new OriginalSource(
content,
contextifySourceUrl(context, identifier, associatedObjectForCache)
);
}
/**
* @param {WebpackOptions} options webpack options
* @param {Compilation} compilation the compilation
* @param {ResolverWithOptions} resolver the resolver
* @param {InputFileSystem} fs the file system
* @param {function(WebpackError=): void} callback callback function
* @returns {void}
*/
doBuild(options, compilation, resolver, fs, callback) {
const loaderContext = this.createLoaderContext(
resolver,
@ -421,8 +493,10 @@ class NormalModule extends Module {
}
this._source = this.createSource(
options.context,
this.binary ? asBuffer(source) : asString(source),
sourceMap
sourceMap,
compilation.compiler.root
);
if (this._sourceSizes !== undefined) this._sourceSizes.clear();
this._ast =
@ -543,10 +617,10 @@ class NormalModule extends Module {
}
/**
* @param {TODO} options TODO
* @param {WebpackOptions} options webpack options
* @param {Compilation} compilation the compilation
* @param {TODO} resolver TODO
* @param {TODO} fs the file system
* @param {ResolverWithOptions} resolver the resolver
* @param {InputFileSystem} fs the file system
* @param {function(WebpackError=): void} callback callback function
* @returns {void}
*/

View File

@ -10,6 +10,7 @@ const Module = require("./Module");
const makeSerializable = require("./util/makeSerializable");
/** @typedef {import("webpack-sources").Source} Source */
/** @typedef {import("../declarations/WebpackOptions").WebpackOptions} WebpackOptions */
/** @typedef {import("./ChunkGraph")} ChunkGraph */
/** @typedef {import("./Compilation")} Compilation */
/** @typedef {import("./DependencyTemplates")} DependencyTemplates */
@ -17,9 +18,11 @@ const makeSerializable = require("./util/makeSerializable");
/** @typedef {import("./Module").CodeGenerationResult} CodeGenerationResult */
/** @typedef {import("./Module").NeedBuildContext} NeedBuildContext */
/** @typedef {import("./RequestShortener")} RequestShortener */
/** @typedef {import("./ResolverFactory").ResolverWithOptions} ResolverWithOptions */
/** @typedef {import("./RuntimeTemplate")} RuntimeTemplate */
/** @typedef {import("./WebpackError")} WebpackError */
/** @typedef {import("./util/Hash")} Hash */
/** @typedef {import("./util/fs").InputFileSystem} InputFileSystem */
const TYPES = new Set(["javascript"]);
@ -74,10 +77,10 @@ class RawModule extends Module {
}
/**
* @param {TODO} options TODO
* @param {WebpackOptions} options webpack options
* @param {Compilation} compilation the compilation
* @param {TODO} resolver TODO
* @param {TODO} fs the file system
* @param {ResolverWithOptions} resolver the resolver
* @param {InputFileSystem} fs the file system
* @param {function(WebpackError=): void} callback callback function
* @returns {void}
*/

View File

@ -11,12 +11,19 @@ const { cachedCleverMerge } = require("./util/cleverMerge");
/** @typedef {import("enhanced-resolve").Resolver} Resolver */
/**
* @typedef {Object} WithOptions
* @property {function(Object): ResolverWithOptions} withOptions create a resolver with additional/different options
*/
/** @typedef {Resolver & WithOptions} ResolverWithOptions */
const EMTPY_RESOLVE_OPTIONS = {};
/**
* @typedef {Object} ResolverCache
* @property {WeakMap<Object, Resolver>} direct
* @property {Map<string, Resolver>} stringified
* @property {WeakMap<Object, ResolverWithOptions>} direct
* @property {Map<string, ResolverWithOptions>} stringified
*/
module.exports = class ResolverFactory {
@ -38,7 +45,7 @@ module.exports = class ResolverFactory {
/**
* @param {string} type type of resolver
* @param {Object=} resolveOptions options
* @returns {Resolver} the resolver
* @returns {ResolverWithOptions} the resolver
*/
get(type, resolveOptions = EMTPY_RESOLVE_OPTIONS) {
let typedCaches = this.cache.get(type);
@ -68,16 +75,18 @@ module.exports = class ResolverFactory {
/**
* @param {string} type type of resolver
* @param {Object} resolveOptions options
* @returns {Resolver} the resolver
* @returns {ResolverWithOptions} the resolver
*/
_create(type, resolveOptions) {
const originalResolveOptions = { ...resolveOptions };
resolveOptions = this.hooks.resolveOptions.for(type).call(resolveOptions);
const resolver = Factory.createResolver(resolveOptions);
const resolver = /** @type {ResolverWithOptions} */ (Factory.createResolver(
resolveOptions
));
if (!resolver) {
throw new Error("No resolver created");
}
/** @type {Map<Object, Resolver>} */
/** @type {Map<Object, ResolverWithOptions>} */
const childCache = new Map();
resolver.withOptions = options => {
const cacheEntry = childCache.get(options);

View File

@ -10,6 +10,7 @@ const AbstractMethodError = require("./AbstractMethodError");
const Module = require("./Module");
/** @typedef {import("webpack-sources").Source} Source */
/** @typedef {import("../declarations/WebpackOptions").WebpackOptions} WebpackOptions */
/** @typedef {import("./Chunk")} Chunk */
/** @typedef {import("./ChunkGraph")} ChunkGraph */
/** @typedef {import("./Compilation")} Compilation */
@ -17,8 +18,10 @@ const Module = require("./Module");
/** @typedef {import("./Module").CodeGenerationResult} CodeGenerationResult */
/** @typedef {import("./Module").NeedBuildContext} NeedBuildContext */
/** @typedef {import("./RequestShortener")} RequestShortener */
/** @typedef {import("./ResolverFactory").ResolverWithOptions} ResolverWithOptions */
/** @typedef {import("./WebpackError")} WebpackError */
/** @typedef {import("./util/Hash")} Hash */
/** @typedef {import("./util/fs").InputFileSystem} InputFileSystem */
const TYPES = new Set(["runtime"]);
@ -76,10 +79,10 @@ class RuntimeModule extends Module {
}
/**
* @param {TODO} options TODO
* @param {WebpackOptions} options webpack options
* @param {Compilation} compilation the compilation
* @param {TODO} resolver TODO
* @param {TODO} fs the file system
* @param {ResolverWithOptions} resolver the resolver
* @param {InputFileSystem} fs the file system
* @param {function(WebpackError=): void} callback callback function
* @returns {void}
*/

View File

@ -12,6 +12,7 @@ const ProgressPlugin = require("./ProgressPlugin");
const SourceMapDevToolModuleOptionsPlugin = require("./SourceMapDevToolModuleOptionsPlugin");
const createHash = require("./util/createHash");
const { relative, dirname } = require("./util/fs");
const { absolutify } = require("./util/identifier");
const schema = require("../schemas/plugins/SourceMapDevToolPlugin.json");
@ -59,7 +60,11 @@ const getTaskForFile = (file, asset, options, compilation) => {
source = asset.source();
}
if (!sourceMap || typeof source !== "string") return;
const context = compilation.options.context;
const root = compilation.compiler.root;
const modules = sourceMap.sources.map(source => {
if (!source.startsWith("webpack://")) return source;
source = absolutify(context, source.slice(10), root);
const module = compilation.findModule(source);
return module || source;
});

View File

@ -32,6 +32,7 @@ const contextify = require("../util/identifier").contextify;
const propertyAccess = require("../util/propertyAccess");
/** @typedef {import("webpack-sources").Source} Source */
/** @typedef {import("../../declarations/WebpackOptions").WebpackOptions} WebpackOptions */
/** @typedef {import("../ChunkGraph")} ChunkGraph */
/** @typedef {import("../Compilation")} Compilation */
/** @typedef {import("../Dependency")} Dependency */
@ -42,9 +43,11 @@ const propertyAccess = require("../util/propertyAccess");
/** @typedef {import("../Module").LibIdentOptions} LibIdentOptions */
/** @typedef {import("../ModuleGraph")} ModuleGraph */
/** @typedef {import("../RequestShortener")} RequestShortener */
/** @typedef {import("../ResolverFactory").ResolverWithOptions} ResolverWithOptions */
/** @typedef {import("../RuntimeTemplate")} RuntimeTemplate */
/** @typedef {import("../WebpackError")} WebpackError */
/** @typedef {import("../util/Hash")} Hash */
/** @typedef {import("../util/fs").InputFileSystem} InputFileSystem */
/**
* @typedef {Object} ReexportInfo
@ -697,10 +700,10 @@ class ConcatenatedModule extends Module {
}
/**
* @param {TODO} options TODO
* @param {WebpackOptions} options webpack options
* @param {Compilation} compilation the compilation
* @param {TODO} resolver TODO
* @param {TODO} fs the file system
* @param {ResolverWithOptions} resolver the resolver
* @param {InputFileSystem} fs the file system
* @param {function(WebpackError=): void} callback callback function
* @returns {void}
*/

View File

@ -6,7 +6,7 @@
const path = require("path");
const WINDOWS_ABS_PATH_REGEXP = /^[a-zA-Z]:\\/;
const WINDOWS_ABS_PATH_REGEXP = /^[a-zA-Z]:[\\/]/;
const SEGEMENTS_SPLIT_REGEXP = /([|!])/;
const WINDOWS_PATH_SEPARATOR_REGEXP = /\\/g;
@ -67,6 +67,17 @@ const absoluteToRequest = (context, maybeAbsolutePath) => {
return maybeAbsolutePath;
};
/**
* @param {string} context context for relative path
* @param {string} relativePath path
* @returns {string} absolute path
*/
const requestToAbsolute = (context, relativePath) => {
if (relativePath.startsWith("./") || relativePath.startsWith("../"))
return path.join(context, relativePath);
return relativePath;
};
const makeCacheable = fn => {
/** @type {WeakMap<Object, Map<string, Map<string, string>>>} */
const cache = new WeakMap();
@ -133,4 +144,20 @@ const _contextify = (context, request) => {
.join("!");
};
exports.contextify = makeCacheable(_contextify);
const contextify = makeCacheable(_contextify);
exports.contextify = contextify;
/**
* @param {string} context absolute context path
* @param {string} request any request string
* @returns {string} a new request string using absolute paths when possible
*/
const _absolutify = (context, request) => {
return request
.split("!")
.map(r => requestToAbsolute(context, r))
.join("!");
};
const absolutify = makeCacheable(_absolutify);
exports.absolutify = absolutify;

View File

@ -25,12 +25,14 @@
"tapable": "2.0.0-beta.8",
"terser-webpack-plugin": "^2.2.1",
"watchpack": "2.0.0-beta.9",
"webpack-sources": "2.0.0-beta.4"
"webpack-sources": "2.0.0-beta.5"
},
"devDependencies": {
"@babel/core": "^7.7.2",
"@types/estree": "0.0.39",
"@types/node": "^12.6.9",
"@yarnpkg/lockfile": "^1.1.0",
"babel-loader": "^8.0.6",
"benchmark": "^2.1.1",
"bundle-loader": "~0.5.0",
"coffee-loader": "^0.9.0",

View File

@ -145,15 +145,15 @@ describe("NormalModule", () => {
});
describe("given no sourcemap", () => {
it("returns a RawSource", () => {
expect(normalModule.createSourceForAsset(name, content)).toBeInstanceOf(
RawSource
);
expect(
normalModule.createSourceForAsset("/", name, content)
).toBeInstanceOf(RawSource);
});
});
describe("given a string as the sourcemap", () => {
it("returns a OriginalSource", () => {
expect(
normalModule.createSourceForAsset(name, content, sourceMap)
normalModule.createSourceForAsset("/", name, content, sourceMap)
).toBeInstanceOf(OriginalSource);
});
});
@ -163,7 +163,7 @@ describe("NormalModule", () => {
});
it("returns a SourceMapSource", () => {
expect(
normalModule.createSourceForAsset(name, content, sourceMap)
normalModule.createSourceForAsset("/", name, content, sourceMap)
).toBeInstanceOf(SourceMapSource);
});
});

View File

@ -61,6 +61,17 @@ describe("StatsTestCases", () => {
if (fs.existsSync(path.join(base, testName, "webpack.config.js"))) {
options = require(path.join(base, testName, "webpack.config.js"));
}
let testConfig = {};
try {
// try to load a test file
testConfig = Object.assign(
testConfig,
require(path.join(base, testName, "test.config.js"))
);
} catch (e) {
// ignored
}
(Array.isArray(options) ? options : [options]).forEach(options => {
if (!options.context) options.context = path.join(base, testName);
if (!options.output) options.output = options.output || {};
@ -182,6 +193,7 @@ describe("StatsTestCases", () => {
.replace(/(\w)\\(\w)/g, "$1/$2")
.replace(/, additional resolving: Xms/g, "");
expect(actual).toMatchSnapshot();
if (testConfig.validate) testConfig.validate(stats, stderr.toString());
done();
});
});

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,2 @@
import test from "./module";
console.log(test);

View File

@ -0,0 +1,2 @@
console.log("test");
import("./chunk");

View File

@ -0,0 +1 @@
export default 42;

View File

@ -0,0 +1,2 @@
import test from "./module";
console.log(test);

View File

@ -0,0 +1,2 @@
console.log("test");
import("./chunk");

View File

@ -0,0 +1 @@
export default 42;

View File

@ -0,0 +1,10 @@
module.exports = {
validate(stats) {
const a = stats.stats[0].compilation.hash;
const b = stats.stats[1].compilation.hash;
expect(a).toBe(b);
const c = stats.stats[2].compilation.hash;
const d = stats.stats[3].compilation.hash;
expect(c).toBe(d);
}
};

View File

@ -0,0 +1,62 @@
const path = require("path");
const base = {
mode: "production",
devtool: "source-map",
entry: "./index",
module: {
rules: [
{
test: /chunk/,
loader: "babel-loader",
options: {}
}
]
}
};
const base2 = {
...base,
devtool: "eval-source-map"
};
module.exports = [
{
...base,
context: path.resolve(__dirname, "a"),
output: {
path: path.resolve(__dirname, "../../js/stats/context-independence/a"),
filename: "[name]-[chunkhash].js"
}
},
{
...base,
context: path.resolve(__dirname, "b"),
output: {
path: path.resolve(__dirname, "../../js/stats/context-independence/b"),
filename: "[name]-[chunkhash].js"
}
},
{
...base2,
context: path.resolve(__dirname, "a"),
output: {
path: path.resolve(
__dirname,
"../../js/stats/context-independence/eval-a"
),
filename: "[name]-[chunkhash].js"
}
},
{
...base2,
context: path.resolve(__dirname, "b"),
output: {
path: path.resolve(
__dirname,
"../../js/stats/context-independence/eval-b"
),
filename: "[name]-[chunkhash].js"
}
}
];

View File

@ -82,12 +82,12 @@ const schema = [
},
{
title: "imports",
regexp: /(const (\{\s+\w+(,\s+\w+)*\s+\}|\w+) = (\/\*\* @type \{TODO\} \*\/\s\()?require\("[^"]+"\)\)?(\.\w+)*;\n)+\n/g,
regexp: /(const (\{\s+\w+(?::\s+\w+)?(,\s+\w+(?::\s+\w+)?)*\s+\}|\w+) = (\/\*\* @type \{TODO\} \*\/\s\()?require\("[^"]+"\)\)?(\.\w+)*;\n)+\n/g,
updateMessage: "sort imports alphabetically",
update(content) {
const items = execToArray(
content,
/const (?:\{\s+\w+(?:,\s+\w+)*\s+\}|\w+) = (?:\/\*\* @type \{TODO\} \*\/\s\()?require\("([^"]+)"\)\)?((?:\.\w+)*);\n/g
/const (?:\{\s+\w+(?::\s+\w+)?(?:,\s+\w+(?::\s+\w+)?)*\s+\}|\w+) = (?:\/\*\* @type \{TODO\} \*\/\s\()?require\("([^"]+)"\)\)?((?:\.\w+)*);\n/g
);
items.sort(sortImport);
return items.map(item => item.content).join("") + "\n";

136
yarn.lock
View File

@ -29,6 +29,26 @@
semver "^5.4.1"
source-map "^0.5.0"
"@babel/core@^7.7.2":
version "7.7.2"
resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.7.2.tgz#ea5b99693bcfc058116f42fa1dd54da412b29d91"
integrity sha512-eeD7VEZKfhK1KUXGiyPFettgF3m513f8FoBSWiQ1xTvl1RAopLs42Wp9+Ze911I6H0N9lNqJMDgoZT7gHsipeQ==
dependencies:
"@babel/code-frame" "^7.5.5"
"@babel/generator" "^7.7.2"
"@babel/helpers" "^7.7.0"
"@babel/parser" "^7.7.2"
"@babel/template" "^7.7.0"
"@babel/traverse" "^7.7.2"
"@babel/types" "^7.7.2"
convert-source-map "^1.7.0"
debug "^4.1.0"
json5 "^2.1.0"
lodash "^4.17.13"
resolve "^1.3.2"
semver "^5.4.1"
source-map "^0.5.0"
"@babel/generator@^7.4.0", "@babel/generator@^7.6.3", "@babel/generator@^7.6.4":
version "7.6.4"
resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.6.4.tgz#a4f8437287bf9671b07f483b76e3bb731bc97671"
@ -39,6 +59,16 @@
lodash "^4.17.13"
source-map "^0.5.0"
"@babel/generator@^7.7.2":
version "7.7.2"
resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.7.2.tgz#2f4852d04131a5e17ea4f6645488b5da66ebf3af"
integrity sha512-WthSArvAjYLz4TcbKOi88me+KmDJdKSlfwwN8CnUYn9jBkzhq0ZEPuBfkAWIvjJ3AdEV1Cf/+eSQTnp3IDJKlQ==
dependencies:
"@babel/types" "^7.7.2"
jsesc "^2.5.1"
lodash "^4.17.13"
source-map "^0.5.0"
"@babel/helper-function-name@^7.1.0":
version "7.1.0"
resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.1.0.tgz#a0ceb01685f73355d4360c1247f582bfafc8ff53"
@ -48,6 +78,15 @@
"@babel/template" "^7.1.0"
"@babel/types" "^7.0.0"
"@babel/helper-function-name@^7.7.0":
version "7.7.0"
resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.7.0.tgz#44a5ad151cfff8ed2599c91682dda2ec2c8430a3"
integrity sha512-tDsJgMUAP00Ugv8O2aGEua5I2apkaQO7lBGUq1ocwN3G23JE5Dcq0uh3GvFTChPa4b40AWiAsLvCZOA2rdnQ7Q==
dependencies:
"@babel/helper-get-function-arity" "^7.7.0"
"@babel/template" "^7.7.0"
"@babel/types" "^7.7.0"
"@babel/helper-get-function-arity@^7.0.0":
version "7.0.0"
resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0.tgz#83572d4320e2a4657263734113c42868b64e49c3"
@ -55,6 +94,13 @@
dependencies:
"@babel/types" "^7.0.0"
"@babel/helper-get-function-arity@^7.7.0":
version "7.7.0"
resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.7.0.tgz#c604886bc97287a1d1398092bc666bc3d7d7aa2d"
integrity sha512-tLdojOTz4vWcEnHWHCuPN5P85JLZWbm5Fx5ZsMEMPhF3Uoe3O7awrbM2nQ04bDOUToH/2tH/ezKEOR8zEYzqyw==
dependencies:
"@babel/types" "^7.7.0"
"@babel/helper-plugin-utils@^7.0.0":
version "7.0.0"
resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.0.0.tgz#bbb3fbee98661c569034237cc03967ba99b4f250"
@ -67,6 +113,13 @@
dependencies:
"@babel/types" "^7.4.4"
"@babel/helper-split-export-declaration@^7.7.0":
version "7.7.0"
resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.7.0.tgz#1365e74ea6c614deeb56ebffabd71006a0eb2300"
integrity sha512-HgYSI8rH08neWlAH3CcdkFg9qX9YsZysZI5GD8LjhQib/mM0jGOZOVkoUiiV2Hu978fRtjtsGsW6w0pKHUWtqA==
dependencies:
"@babel/types" "^7.7.0"
"@babel/helpers@^7.6.2":
version "7.6.2"
resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.6.2.tgz#681ffe489ea4dcc55f23ce469e58e59c1c045153"
@ -76,6 +129,15 @@
"@babel/traverse" "^7.6.2"
"@babel/types" "^7.6.0"
"@babel/helpers@^7.7.0":
version "7.7.0"
resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.7.0.tgz#359bb5ac3b4726f7c1fde0ec75f64b3f4275d60b"
integrity sha512-VnNwL4YOhbejHb7x/b5F39Zdg5vIQpUUNzJwx0ww1EcVRt41bbGRZWhAURrfY32T5zTT3qwNOQFWpn+P0i0a2g==
dependencies:
"@babel/template" "^7.7.0"
"@babel/traverse" "^7.7.0"
"@babel/types" "^7.7.0"
"@babel/highlight@^7.0.0":
version "7.5.0"
resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.5.0.tgz#56d11312bd9248fa619591d02472be6e8cb32540"
@ -90,6 +152,11 @@
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.6.4.tgz#cb9b36a7482110282d5cb6dd424ec9262b473d81"
integrity sha512-D8RHPW5qd0Vbyo3qb+YjO5nvUVRTXFLQ/FsDxJU2Nqz4uB5EnUN0ZQSEYpvTIbRuttig1XbHWU5oMeQwQSAA+A==
"@babel/parser@^7.7.0", "@babel/parser@^7.7.2":
version "7.7.3"
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.7.3.tgz#5fad457c2529de476a248f75b0f090b3060af043"
integrity sha512-bqv+iCo9i+uLVbI0ILzKkvMorqxouI+GbV13ivcARXn9NNEabi2IEz912IgNpT/60BNXac5dgcfjb94NjsF33A==
"@babel/plugin-syntax-object-rest-spread@^7.0.0":
version "7.2.0"
resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.2.0.tgz#3b7a3e733510c57e820b9142a6579ac8b0dfad2e"
@ -106,6 +173,15 @@
"@babel/parser" "^7.6.0"
"@babel/types" "^7.6.0"
"@babel/template@^7.7.0":
version "7.7.0"
resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.7.0.tgz#4fadc1b8e734d97f56de39c77de76f2562e597d0"
integrity sha512-OKcwSYOW1mhWbnTBgQY5lvg1Fxg+VyfQGjcBduZFljfc044J5iDlnDSfhQ867O17XHiSCxYHUxHg2b7ryitbUQ==
dependencies:
"@babel/code-frame" "^7.0.0"
"@babel/parser" "^7.7.0"
"@babel/types" "^7.7.0"
"@babel/traverse@^7.1.0", "@babel/traverse@^7.4.3", "@babel/traverse@^7.6.2", "@babel/traverse@^7.6.3":
version "7.6.3"
resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.6.3.tgz#66d7dba146b086703c0fb10dd588b7364cec47f9"
@ -121,6 +197,21 @@
globals "^11.1.0"
lodash "^4.17.13"
"@babel/traverse@^7.7.0", "@babel/traverse@^7.7.2":
version "7.7.2"
resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.7.2.tgz#ef0a65e07a2f3c550967366b3d9b62a2dcbeae09"
integrity sha512-TM01cXib2+rgIZrGJOLaHV/iZUAxf4A0dt5auY6KNZ+cm6aschuJGqKJM3ROTt3raPUdIDk9siAufIFEleRwtw==
dependencies:
"@babel/code-frame" "^7.5.5"
"@babel/generator" "^7.7.2"
"@babel/helper-function-name" "^7.7.0"
"@babel/helper-split-export-declaration" "^7.7.0"
"@babel/parser" "^7.7.2"
"@babel/types" "^7.7.2"
debug "^4.1.0"
globals "^11.1.0"
lodash "^4.17.13"
"@babel/types@^7.0.0", "@babel/types@^7.3.0", "@babel/types@^7.4.0", "@babel/types@^7.4.4", "@babel/types@^7.6.0", "@babel/types@^7.6.3":
version "7.6.3"
resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.6.3.tgz#3f07d96f854f98e2fbd45c64b0cb942d11e8ba09"
@ -130,6 +221,15 @@
lodash "^4.17.13"
to-fast-properties "^2.0.0"
"@babel/types@^7.7.0", "@babel/types@^7.7.2":
version "7.7.2"
resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.7.2.tgz#550b82e5571dcd174af576e23f0adba7ffc683f7"
integrity sha512-YTf6PXoh3+eZgRCBzzP25Bugd2ngmpQVrk7kXX0i5N9BO7TFBtIgZYs7WtxtOGs8e6A4ZI7ECkbBCEHeXocvOA==
dependencies:
esutils "^2.0.2"
lodash "^4.17.13"
to-fast-properties "^2.0.0"
"@cnakazawa/watch@^1.0.3":
version "1.0.3"
resolved "https://registry.yarnpkg.com/@cnakazawa/watch/-/watch-1.0.3.tgz#099139eaec7ebf07a27c1786a3ff64f39464d2ef"
@ -926,6 +1026,16 @@ babel-jest@^24.9.0:
chalk "^2.4.2"
slash "^2.0.0"
babel-loader@^8.0.6:
version "8.0.6"
resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-8.0.6.tgz#e33bdb6f362b03f4bb141a0c21ab87c501b70dfb"
integrity sha512-4BmWKtBOBm13uoUwd08UwjZlaw3O9GWf456R9j+5YykFZ6LUIjIKLc0zEZf+hauxPOJs96C8k6FvYD09vWzhYw==
dependencies:
find-cache-dir "^2.0.0"
loader-utils "^1.0.2"
mkdirp "^0.5.1"
pify "^4.0.1"
babel-plugin-istanbul@^5.1.0:
version "5.2.0"
resolved "https://registry.yarnpkg.com/babel-plugin-istanbul/-/babel-plugin-istanbul-5.2.0.tgz#df4ade83d897a92df069c4d9a25cf2671293c854"
@ -1439,6 +1549,13 @@ convert-source-map@^1.1.0, convert-source-map@^1.4.0:
dependencies:
safe-buffer "~5.1.1"
convert-source-map@^1.7.0:
version "1.7.0"
resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.7.0.tgz#17a2cb882d7f77d3490585e2ce6c524424a3a442"
integrity sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==
dependencies:
safe-buffer "~5.1.1"
copy-concurrently@^1.0.0:
version "1.0.5"
resolved "https://registry.yarnpkg.com/copy-concurrently/-/copy-concurrently-1.0.5.tgz#92297398cae34937fcafd6ec8139c18051f0b5e0"
@ -2308,6 +2425,15 @@ fill-range@^7.0.1:
dependencies:
to-regex-range "^5.0.1"
find-cache-dir@^2.0.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-2.1.0.tgz#8d0f94cd13fe43c6c7c261a0d86115ca918c05f7"
integrity sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==
dependencies:
commondir "^1.0.1"
make-dir "^2.0.0"
pkg-dir "^3.0.0"
find-cache-dir@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-3.0.0.tgz#cd4b7dd97b7185b7e17dbfe2d6e4115ee3eeb8fc"
@ -3973,7 +4099,7 @@ lru-queue@0.1:
dependencies:
es5-ext "~0.10.2"
make-dir@^2.1.0:
make-dir@^2.0.0, make-dir@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-2.1.0.tgz#5f0310e18b8be898cc07009295a30ae41e91e6f5"
integrity sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==
@ -6419,10 +6545,10 @@ webidl-conversions@^4.0.2:
resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-4.0.2.tgz#a855980b1f0b6b359ba1d5d9fb39ae941faa63ad"
integrity sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==
webpack-sources@2.0.0-beta.4:
version "2.0.0-beta.4"
resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-2.0.0-beta.4.tgz#b92f912e16e5c49ebd3c268edf83b13972a3c8ef"
integrity sha512-Xa2Ul5hAlMICQsKN1hjoSTSxJ0UmET4gZXR1e/Sfpos0XNSc2K3fhJHz79CxLyYh0KFEaj6NeoMra9Pp66hRBQ==
webpack-sources@2.0.0-beta.5:
version "2.0.0-beta.5"
resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-2.0.0-beta.5.tgz#aac603d9fdf04ce96276cf845cd9bb9afd660c4a"
integrity sha512-Y0NWr3nIeJbHzQciKPjWkERbRrmqZPhE4t8K5qOzl4dhJViIdBnvutCCAQ9PKj6MC8lo4Wytu+SZ9Ct8vhX/cQ==
dependencies:
source-list-map "^2.0.1"
source-map "~0.6.1"