Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add LoaderContext to types #13164

Merged
merged 32 commits into from May 7, 2021
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
586d013
feat: LoaderContext type
johnnyreilly Apr 16, 2021
a2f8808
apply @sokra's feedback and include runtime type
johnnyreilly Apr 19, 2021
df44d7d
attempt @sokras suggestion
johnnyreilly Apr 20, 2021
79da320
non generics
johnnyreilly Apr 20, 2021
39042a2
Update lib/index.js
johnnyreilly Apr 20, 2021
b967f36
Update declarations/LoaderContext.d.ts
johnnyreilly Apr 20, 2021
5ef8aca
Update declarations/LoaderContext.d.ts
johnnyreilly Apr 20, 2021
3d45e2b
Update declarations/LoaderContext.d.ts
johnnyreilly Apr 20, 2021
1578fd4
schema
johnnyreilly Apr 20, 2021
25c80ea
Merge branch 'master' of https://github.com/johnnyreilly/webpack
johnnyreilly Apr 20, 2021
a679319
bring in suggested types
johnnyreilly Apr 20, 2021
111e95c
Update declarations/LoaderContext.d.ts
johnnyreilly Apr 20, 2021
35eef1e
Update declarations/LoaderContext.d.ts
johnnyreilly Apr 20, 2021
3898b38
Update declarations/LoaderContext.d.ts
johnnyreilly Apr 20, 2021
481832d
Update declarations/LoaderContext.d.ts
johnnyreilly Apr 20, 2021
57e49bc
Update declarations/LoaderContext.d.ts
johnnyreilly Apr 20, 2021
8703248
Update declarations/LoaderContext.d.ts
johnnyreilly Apr 20, 2021
40a5eb1
tried generic workarouuund
johnnyreilly Apr 20, 2021
8cd30eb
revert generic approach
johnnyreilly Apr 20, 2021
ee03137
change import
johnnyreilly Apr 20, 2021
cf1a1fe
fixup some types
sokra Apr 22, 2021
984308a
generate types with yarn special-lint-fix
johnnyreilly Apr 22, 2021
e42915c
clean up types
sokra Apr 22, 2021
7cc4078
fix some internal types
sokra Apr 22, 2021
ea53a23
improve LoaderContext declaration
sokra Apr 22, 2021
4e70b37
test typings and fix type problems in loaders in the test suite
sokra Apr 22, 2021
b71e0ce
Merge branch 'master' into johnnyreilly/master
sokra Apr 22, 2021
5b21dd2
fix import problem
sokra Apr 22, 2021
77f625a
upgrade tooling and update types.d.ts
sokra May 7, 2021
87c0d1c
Merge branch 'master' into johnnyreilly/master
sokra May 7, 2021
b6693fe
getOptions returns OptionsType
sokra May 7, 2021
442a1eb
rename validate function to avoid conflict
sokra May 7, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
172 changes: 172 additions & 0 deletions declarations/LoaderContext.d.ts
@@ -0,0 +1,172 @@
import type { AssetInfo, Configuration } from "../lib";
import Compilation from "../lib/Compilation";
import NormalModule, { InputFileSystem } from "../lib/NormalModule";
import type { Mode } from "./WebpackOptions";

export interface LoaderContext {
johnnyreilly marked this conversation as resolved.
Show resolved Hide resolved
version: number;
getOptions(schema: any): any;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could steal the Schema type from schema-utils:

Parameters<typeof import("schema-utils").validate>[0]

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will steal!

emitWarning(warning: Error | string): void;
emitError(error: Error | string): void;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
emitWarning(warning: Error | string): void;
emitError(error: Error | string): void;
emitWarning(warning: Error): void;
emitError(error: Error): void;

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking at usage it seems these can be strings:

if (!(error instanceof Error)) {

			emitError: error => {
				if (!(error instanceof Error)) {
					error = new NonErrorEmittedError(error);
				}
				this.addError(
					new ModuleError(error, {
						from: getCurrentLoaderName()
					})
				);
			},

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, but that's only for backward-compat. The NonErrorEmittedError says that you made an error in error reporting... so it should not be in the typings

getLogger(name: string): Compilation["logger"];
johnnyreilly marked this conversation as resolved.
Show resolved Hide resolved
resolve(context: string, request: string, callback: any): any;
getResolve(
options: Configuration
): (context: string, request: string, callback: any) => Promise<any>;
emitFile(
name: string,
content: string,
sourceMap: string,
assetInfo: AssetInfo
johnnyreilly marked this conversation as resolved.
Show resolved Hide resolved
): void;
addBuildDependency(dep: string): void;
utils: {
absolutify: (context: string, request: string) => string;
contextify: (context: string, request: string) => string;
};
rootContext: string;
webpack: boolean;
sourceMap: boolean;
johnnyreilly marked this conversation as resolved.
Show resolved Hide resolved
mode: Mode;
_module: NormalModule;
_compilation: Compilation;
_compiler: Compilation.Compiler;
johnnyreilly marked this conversation as resolved.
Show resolved Hide resolved
fs: InputFileSystem;
}

/** The types added to LoaderContextBase by https://github.com/webpack/loader-runner */
export interface EmptyContextAdditions {
johnnyreilly marked this conversation as resolved.
Show resolved Hide resolved
/**
* Add a directory as dependency of the loader result.
*/
addContextDependency(context: string): void;

/**
* Adds a file as dependency of the loader result in order to make them watchable.
* For example, html-loader uses this technique as it finds src and src-set attributes.
* Then, it sets the url's for those attributes as dependencies of the html file that is parsed.
*/
addDependency(file: string): void;

addMissingDependency(context: string): void;

/**
* Make this loader async.
*/
async(): (
err: Error | undefined | null,
content?: string | Buffer,
sourceMap?: string | any
johnnyreilly marked this conversation as resolved.
Show resolved Hide resolved
) => void | undefined;

/**
* Make this loader result cacheable. By default it's not cacheable.
johnnyreilly marked this conversation as resolved.
Show resolved Hide resolved
* A cacheable loader must have a deterministic result, when inputs and dependencies haven't changed.
* This means the loader shouldn't have other dependencies than specified with this.addDependency.
* Most loaders are deterministic and cacheable.
*/
cacheable(flag?: boolean): void;

callback(): void;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same arguments as for async() return value


/**
* Remove all dependencies of the loader result. Even initial dependencies and these of other loaders.
*/
clearDependencies(): void;

/**
* The directory of the module. Can be used as context for resolving other stuff.
* eg '/workspaces/ts-loader/examples/vanilla/src'
*/
context: string;

readonly currentRequest: string;

readonly data: any;
/**
* alias of addDependency
* Adds a file as dependency of the loader result in order to make them watchable.
* For example, html-loader uses this technique as it finds src and src-set attributes.
* Then, it sets the url's for those attributes as dependencies of the html file that is parsed.
*/
dependency(file: string): void;

getContextDependencies(): string[];

getDependencies(): string[];

getMissingDependencies(): string[];

/**
* The index in the loaders array of the current loader.
* In the example: in loader1: 0, in loader2: 1
*/
loaderIndex: number;

/**
* Resolves the given request to a module, applies all configured loaders and calls
* back with the generated source, the sourceMap and the module instance (usually an
* instance of NormalModule). Use this function if you need to know the source code
* of another module to generate the result.
*/
loadModule(
johnnyreilly marked this conversation as resolved.
Show resolved Hide resolved
request: string,
callback: (
err: Error | null,
source: string,
sourceMap: any,
module: NormalModule
) => void
): void;

readonly previousRequest: string;

readonly query: any;
sokra marked this conversation as resolved.
Show resolved Hide resolved

readonly remainingRequest: string;

readonly request: string;

/**
* An array of all the loaders. It is writeable in the pitch phase.
* loaders = [{request: string, path: string, query: string, module: function}]
*
* In the example:
* [
* { request: "/abc/loader1.js?xyz",
* path: "/abc/loader1.js",
* query: "?xyz",
* module: [Function]
* },
* { request: "/abc/node_modules/loader2/index.js",
* path: "/abc/node_modules/loader2/index.js",
* query: "",
* module: [Function]
* }
* ]
*/
loaders: {
request: string;
path: string;
query: string;
johnnyreilly marked this conversation as resolved.
Show resolved Hide resolved
fragment: string;
options: any;
sokra marked this conversation as resolved.
Show resolved Hide resolved
ident: string;
normal: any;
pitch: any;
raw: any;
data: any;
sokra marked this conversation as resolved.
Show resolved Hide resolved
pitchExecuted: boolean;
normalExecuted: boolean;
}[];

/**
* The resource file.
* In the example: "/abc/resource.js"
*/
resourcePath: string;
}

johnnyreilly marked this conversation as resolved.
Show resolved Hide resolved
export interface LoaderDefinition<ContextAdditions = EmptyContextAdditions> {
(this: LoaderContext & ContextAdditions, contents: string): string;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
(this: LoaderContext & ContextAdditions, contents: string): string;
(this: LoaderContext & (ContextAdditions extends EmptyContextAdditions ? {} : ContextAdditions), contents: string): string;

The EmptyContextAdditions is a workaround for a typescript bug. Usually you would say LoaderDefinition<ContextAdditions = {}>, but that doesn't work in jsdoc without strict mode, where {} becomes any.

}
6 changes: 5 additions & 1 deletion lib/NormalModule.js
Expand Up @@ -44,8 +44,11 @@ const memoize = require("./util/memoize");

/** @typedef {import("source-map").RawSourceMap} SourceMap */
/** @typedef {import("webpack-sources").Source} Source */
/** @typedef {import("../declarations/LoaderContext").LoaderContext} LoaderContext */
/** @typedef {import("../declarations/WebpackOptions").Mode} Mode */
/** @typedef {import("../declarations/WebpackOptions").WebpackOptionsNormalized} WebpackOptions */
/** @typedef {import("./ChunkGraph")} ChunkGraph */
/** @typedef {import("./Compiler")} Compiler */
/** @typedef {import("./Dependency").UpdateHashContext} UpdateHashContext */
/** @typedef {import("./DependencyTemplates")} DependencyTemplates */
/** @typedef {import("./Generator")} Generator */
Expand All @@ -61,6 +64,7 @@ const memoize = require("./util/memoize");
/** @typedef {import("./RequestShortener")} RequestShortener */
/** @typedef {import("./ResolverFactory").ResolverWithOptions} ResolverWithOptions */
/** @typedef {import("./RuntimeTemplate")} RuntimeTemplate */
/** @typedef {import("./logging/Logger").Logger} WebpackLogger */
/** @typedef {import("./util/Hash")} Hash */
/** @typedef {import("./util/fs").InputFileSystem} InputFileSystem */
/** @typedef {import("./util/runtime").RuntimeSpec} RuntimeSpec */
Expand Down Expand Up @@ -421,7 +425,7 @@ class NormalModule extends Module {
* @param {WebpackOptions} options webpack options
* @param {Compilation} compilation the compilation
* @param {InputFileSystem} fs file system from reading
* @returns {any} loader context
* @returns {LoaderContext} loader context
*/
createLoaderContext(resolver, options, compilation, fs) {
const { requestShortener } = compilation.runtimeTemplate;
Expand Down
3 changes: 3 additions & 0 deletions lib/index.js
Expand Up @@ -8,6 +8,9 @@
const util = require("util");
const memoize = require("./util/memoize");

/** @typedef {import("../declarations/LoaderContext").EmptyContextAdditions} EmptyContextAdditions */
/** @typedef {import("../declarations/LoaderContext").LoaderContext} LoaderContext */
/** @typedef {import("../declarations/LoaderContext").LoaderDefinition} LoaderDefinition */
johnnyreilly marked this conversation as resolved.
Show resolved Hide resolved
/** @typedef {import("../declarations/WebpackOptions").Entry} Entry */
/** @typedef {import("../declarations/WebpackOptions").EntryNormalized} EntryNormalized */
/** @typedef {import("../declarations/WebpackOptions").EntryObject} EntryObject */
Expand Down
1 change: 1 addition & 0 deletions test/cases/errors/load-module-error/error-loader.js
@@ -1,3 +1,4 @@
/** @type {import("../../../../types").LoaderDefinition} */
module.exports = function(source) {
const callback = this.async();
callback(new Error("err: abc"));
Expand Down