├── .cspell.json
├── .editorconfig
├── .eslintignore
├── .eslintrc.js
├── .gitattributes
├── .github
├── CODEOWNERS
├── CONTRIBUTING.md
├── FUNDING.yml
├── ISSUE_TEMPLATE.md
├── ISSUE_TEMPLATE
│ ├── BUG.md
│ ├── DOCS.md
│ ├── FEATURE.md
│ ├── MODIFICATION.md
│ └── SUPPORT.md
├── PULL_REQUEST_TEMPLATE.md
└── workflows
│ ├── dependency-review.yml
│ └── nodejs.yml
├── .gitignore
├── .husky
├── commit-msg
└── pre-commit
├── .prettierignore
├── CHANGELOG.md
├── LICENSE
├── README.md
├── babel.config.js
├── commitlint.config.js
├── jest.config.js
├── lint-staged.config.js
├── package-lock.json
├── package.json
├── src
├── cjs.js
├── index.js
└── options.json
└── test
├── __snapshots__
├── executableFile.test.js.snap
└── loader.test.js.snap
├── cjs.test.js
├── executableFile.test.js
├── fixtures
├── args.js
├── async-function.js
├── babel.js
├── buffer.js
├── cacheable.js
├── code-commonjs.js
├── code-es.js
├── data.json
├── dependencies-via-context.js
├── dependencies.js
├── error-call-async.js
├── error-call-sync.js
├── error-emitted-with-dependencies.js
├── error-export-null.js
├── error-require.js
├── error-return-async-invalid-code.js
├── error-return-async-wrong-obj.js
├── error-return-sync-invalid-code.js
├── error-return-sync-wrong-obj.js
├── executableFile.js
├── executableFileES.mjs
├── executableFileEntry.js
├── module-parent.js
├── presets
│ ├── figlet.js
│ └── modernizr.js
├── promise-compex.js
├── promise.js
└── simple.js
├── helpers
├── compile.js
├── execute.js
├── getCompiler.js
├── helperLoader.js
├── index.js
├── normalizeErrors.js
└── readAsset.js
├── loader.test.js
└── validate-options.test.js
/.cspell.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": "0.2",
3 | "language": "en,en-gb",
4 | "words": [
5 | "serviceworker",
6 | "flexbox",
7 | "modernizr",
8 | "compex",
9 | "memfs",
10 | "Modernizr",
11 | "serviceworker",
12 | "commitlint",
13 | "modenizr"
14 | ],
15 |
16 | "ignorePaths": [
17 | "CHANGELOG.md",
18 | "package.json",
19 | "dist/**",
20 | "**/__snapshots__/**",
21 | "package-lock.json",
22 | "node_modules",
23 | "coverage",
24 | "*.log"
25 | ]
26 | }
27 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | # editorconfig.org
2 |
3 | [*]
4 | charset = utf-8
5 | indent_style = space
6 | indent_size = 2
7 | end_of_line = lf
8 | insert_final_newline = true
9 | trim_trailing_whitespace = true
10 |
11 | [*.md]
12 | trim_trailing_whitespace = false
--------------------------------------------------------------------------------
/.eslintignore:
--------------------------------------------------------------------------------
1 | /coverage
2 | /dist
3 | /node_modules
4 | /test/fixtures
--------------------------------------------------------------------------------
/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | root: true,
3 | extends: ["@webpack-contrib/eslint-config-webpack", "prettier"],
4 | };
5 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | yarn.lock -diff
2 | * text=auto
3 | bin/* eol=lf
4 | package-lock.json -diff
--------------------------------------------------------------------------------
/.github/CODEOWNERS:
--------------------------------------------------------------------------------
1 | # These are the default owners for everything in
2 | # webpack-contrib
3 | @webpack-contrib/org-maintainers
4 |
5 | # Add repository specific users / groups
6 | # below here for libs that are not maintained by the org.
7 |
--------------------------------------------------------------------------------
/.github/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributing in @webpack-contrib
2 |
3 | We'd always love contributions to further improve the webpack / webpack-contrib ecosystem!
4 | Here are the guidelines we'd like you to follow:
5 |
6 | - [Questions and Problems](#question)
7 | - [Issues and Bugs](#issue)
8 | - [Feature Requests](#feature)
9 | - [Pull Request Submission Guidelines](#submit-pr)
10 | - [Commit Message Conventions](#commit)
11 |
12 | ## Got a Question or Problem?
13 |
14 | Please submit support requests and questions to StackOverflow using the tag [[webpack]](http://stackoverflow.com/tags/webpack).
15 | StackOverflow is better suited for this kind of support though you may also inquire in [Webpack Gitter](https://gitter.im/webpack/webpack).
16 | The issue tracker is for bug reports and feature discussions.
17 |
18 | ## Found an Issue or Bug?
19 |
20 | Before you submit an issue, please search the issue tracker, an issue for your problem may already exist, and the discussion might inform you of workarounds readily available.
21 |
22 | We want to fix all the issues as soon as possible, but before fixing a bug, we need to reproduce and confirm it. In order to reproduce bugs, we ask that you provide a minimal reproduction scenario (GitHub repo or failing test case). Having a live, reproducible scenario gives us a wealth of important information without going back & forth to you with additional questions like:
23 |
24 | - version of Webpack used
25 | - version of the loader / plugin you are creating a bug report for
26 | - the use-case that fails
27 |
28 | A minimal reproduce scenario allows us to quickly confirm a bug (or point out config problems) as well as confirm that we are fixing the right problem.
29 |
30 | We will be insisting on a minimal reproduction scenario in order to save the maintainers' time and ultimately be able to fix more bugs. We understand that sometimes it might be hard to extract essential bits of code from a larger codebase, but we really need to isolate the problem before we can fix it.
31 |
32 | Unfortunately, we are unable to investigate or fix bugs without a minimal reproduction, so if we don't hear back from you, we may have to close an issue that doesn't have enough info to be reproduced.
33 |
34 | ## Feature Requests?
35 |
36 | You can _request_ a new feature by creating an issue on GitHub.
37 |
38 | If you would like to _implement_ a new feature yourself, please **first submit an issue** with a proposal to ensure the idea aligns with the goals of the project.
39 |
40 | ## Pull Request Submission Guidelines
41 |
42 | Before you submit your Pull Request (PR) consider the following guidelines:
43 |
44 | - Search GitHub for an open or closed PR related to your submission to avoid duplicating effort.
45 | - Commit your changes using a descriptive commit message that follows our [commit message conventions](#commit). This is important because release notes are automatically generated from these messages.
46 | - Complete the `Pull Request Template`. Pull requests that ignore the template will not be reviewed.
47 | - Please sign the `Contributor License Agreement (CLA)` when you open your pull request. We cannot accept your contribution without it. Be sure to sign using the primary email address associated with your local and GitHub account.
48 |
49 | ## Webpack Contrib Commit Conventions
50 |
51 | Each commit message consists of a **header**, a **body** and a **footer**. The header has a special
52 | format that includes a **type**, a **scope** and a **subject**:
53 |
54 | ```
55 | ():
56 |
57 |
58 |
59 |
60 | ```
61 |
62 | The **header** is mandatory and the **scope** of the header is optional.
63 |
64 | No line in the commit message should exceed 100 characters! This makes the message easier to read on GitHub as well as in various Git tools.
65 |
66 | The footer should contain a [closing reference to an issue](https://help.github.com/articles/closing-issues-via-commit-messages/) if any.
67 |
68 | Examples:
69 |
70 | ```
71 | docs(readme): update install instructions
72 | ```
73 |
74 | ```
75 | fix: refer to the `entrypoint` instead of the first `module`
76 | ```
77 |
78 | ### Revert
79 |
80 | If the commit reverts a previous commit, it should begin with `revert:`, followed by the header of the reverted commit.
81 | In the body it should say: `This reverts commit .`, where the hash is the SHA of the commit being reverted.
82 |
83 | ### Type
84 |
85 | Must be one of the following commit types:
86 |
87 | - **build**: Changes that affect the build system or external dependencies (example scopes: babel, npm)
88 | - **chore**: Changes that fall outside of build / docs that do not effect source code (example scopes: package, defaults)
89 | - **ci**: Changes to our CI configuration files and scripts (example scopes: circleci, travis)
90 | - **docs**: Documentation only changes (example scopes: readme, changelog)
91 | - **feat**: A new feature
92 | - **fix**: A bug fix
93 | - **perf**: A code change that improves performance
94 | - **refactor**: A code change that neither fixes a bug nor adds a feature
95 | - **revert**: Used when reverting a committed change
96 | - **style**: Changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons)
97 | - **test**: Addition of or updates to Jest tests
98 |
99 | ### Scope
100 |
101 | The scope is subjective & depends on the `type` see above. A good example of a scope would be a change to a particular class or module.
102 |
103 | ### Subject
104 |
105 | The subject contains a succinct description of the change:
106 |
107 | - use the imperative, present tense: "change" not "changed" or "changes"
108 | - don't capitalize the first letter
109 | - no dot (.) at the end
110 |
111 | ### Body
112 |
113 | Just as in the **subject**, use the imperative, present tense: "change" not "changed" or "changes".
114 | The body should include the motivation for the change and contrast it with previous behavior.
115 |
116 | ### Footer
117 |
118 | The footer should include any information about **Breaking Changes** and is also the place to reference GitHub issues that this commit **Closes**.
119 |
120 | **Breaking Changes** must start with the word `BREAKING CHANGE:` followed by a space or two new lines. The rest of the breaking change details should be provided after this.
121 |
122 | Example
123 |
124 | ```
125 | BREAKING CHANGE: Updates to `Chunk.mapModules`.
126 |
127 | This release is not backwards compatible with `Webpack 2.x` due to breaking changes in webpack/webpack#4764
128 | Migration: see webpack/webpack#5225
129 |
130 | ```
131 |
132 | ## Testing Your Pull Request
133 |
134 | You may need to test your changes in a real-world project or a dependent module. Thankfully, GitHub provides a means to do this. To add a dependency to the `package.json` of such a project, use the following syntax:
135 |
136 | ```json
137 | {
138 | "devDependencies": {
139 | "val-loader": "webpack-contrib/val-loader#{id}/head"
140 | }
141 | }
142 | ```
143 |
144 | Where `{id}` is the # ID of your Pull Request.
145 |
146 | ## Contributor License Agreement
147 |
148 | When submitting your contribution, a CLA (Contributor License Agreement) bot will verify whether you have signed the [CLA](https://easycla.lfx.linuxfoundation.org/#/?version=2).
149 | If it is your first time, it will link you to the right place to sign it.
150 | However, if the email used in your commits doesn’t match the email associated with your GitHub account, the CLA bot won’t accept your contribution.
151 |
152 | Run `git config user.email` to see your Git email, and verify it with [your GitHub email](https://github.com/settings/emails).
153 |
154 | ## Thanks
155 |
156 | For your interest, time, understanding, and for following this simple guide.
157 |
--------------------------------------------------------------------------------
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | open_collective: webpack
2 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE.md:
--------------------------------------------------------------------------------
1 |
17 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/BUG.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: 🐛 Bug Report
3 | about: Something went awry and you'd like to tell us about it.
4 | ---
5 |
6 |
7 |
8 |
9 | ### Bug report
10 |
11 |
12 |
13 |
14 |
15 |
16 | ### Actual Behavior
17 |
18 |
19 |
20 | ### Expected Behavior
21 |
22 |
23 |
24 |
25 | ### How Do We Reproduce?
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 | ### Please paste the results of `npx webpack-cli info` here, and mention other relevant information
35 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/DOCS.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: 📚 Documentation
3 | about: Are the docs lacking or missing something? Do they need some new 🔥 hotness? Tell us here.
4 | ---
5 |
6 |
7 |
8 |
9 | Documentation Is:
10 |
11 |
12 |
13 | - [ ] Missing
14 | - [ ] Needed
15 | - [ ] Confusing
16 | - [ ] Not Sure?
17 |
18 | ### Please Explain in Detail...
19 |
20 |
21 |
22 |
23 |
24 |
25 | ### Your Proposal for Changes
26 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/FEATURE.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: ✨ Feature Request
3 | about: Suggest an idea for this project
4 | ---
5 |
6 |
7 |
8 |
9 | ### Feature Proposal
10 |
11 |
12 |
13 |
14 |
15 |
16 | ### Feature Use Case
17 |
18 | ### Please paste the results of `npx webpack-cli info` here, and mention other relevant information
19 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/MODIFICATION.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: 🔧 Modification Request
3 | about: Would you like something work differently? Have an alternative approach? This is the template for you.
4 | ---
5 |
6 |
7 |
8 |
9 | ### Modification Proposal
10 |
11 |
12 |
13 |
14 |
15 |
16 | ### Expected Behavior / Situation
17 |
18 | ### Actual Behavior / Situation
19 |
20 | ### Please paste the results of `npx webpack-cli info` here, and mention other relevant information
21 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/SUPPORT.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: 🆘 Support, Help, and Advice
3 | about: 👉🏽 Need support, help, or advice? Don't open an issue! Head to https://github.com/webpack/webpack/discussions, StackOverflow or https://gitter.im/webpack/webpack.
4 | ---
5 |
6 | Hey there! If you need support, help, or advice then this is not the place to ask.
7 | Please visit [GitHub Discussions](https://github.com/webpack/webpack/discussions) or [StackOverflow](https://stackoverflow.com/questions/tagged/webpack) instead.
8 |
--------------------------------------------------------------------------------
/.github/PULL_REQUEST_TEMPLATE.md:
--------------------------------------------------------------------------------
1 |
10 |
11 | This PR contains a:
12 |
13 | - [ ] **bugfix**
14 | - [ ] new **feature**
15 | - [ ] **code refactor**
16 | - [ ] **test update**
17 | - [ ] **typo fix**
18 | - [ ] **metadata update**
19 |
20 | ### Motivation / Use-Case
21 |
22 |
27 |
28 | ### Breaking Changes
29 |
30 |
34 |
35 | ### Additional Info
36 |
--------------------------------------------------------------------------------
/.github/workflows/dependency-review.yml:
--------------------------------------------------------------------------------
1 | name: "Dependency Review"
2 | on: [pull_request]
3 |
4 | permissions:
5 | contents: read
6 |
7 | jobs:
8 | dependency-review:
9 | runs-on: ubuntu-latest
10 | steps:
11 | - name: "Checkout Repository"
12 | uses: actions/checkout@v4
13 | - name: "Dependency Review"
14 | uses: actions/dependency-review-action@v4
15 |
--------------------------------------------------------------------------------
/.github/workflows/nodejs.yml:
--------------------------------------------------------------------------------
1 | name: val-loader
2 |
3 | on:
4 | push:
5 | branches:
6 | - master
7 | - next
8 | pull_request:
9 | branches:
10 | - master
11 | - next
12 |
13 | permissions:
14 | contents: read
15 |
16 | jobs:
17 | lint:
18 | name: Lint - ${{ matrix.os }} - Node v${{ matrix.node-version }}
19 |
20 | env:
21 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
22 |
23 | strategy:
24 | matrix:
25 | os: [ubuntu-latest]
26 | node-version: [lts/*]
27 |
28 | runs-on: ${{ matrix.os }}
29 |
30 | concurrency:
31 | group: lint-${{ matrix.os }}-v${{ matrix.node-version }}-${{ github.ref }}
32 | cancel-in-progress: true
33 |
34 | steps:
35 | - uses: actions/checkout@v4
36 | with:
37 | fetch-depth: 0
38 |
39 | - name: Use Node.js ${{ matrix.node-version }}
40 | uses: actions/setup-node@v4
41 | with:
42 | node-version: ${{ matrix.node-version }}
43 | cache: "npm"
44 |
45 | - name: Install dependencies
46 | run: npm ci
47 |
48 | - name: Lint
49 | run: npm run lint
50 |
51 | - name: Security audit
52 | run: npm run security
53 |
54 | - name: Validate PR commits with commitlint
55 | if: github.event_name == 'pull_request'
56 | run: npx commitlint --from ${{ github.event.pull_request.head.sha }}~${{ github.event.pull_request.commits }} --to ${{ github.event.pull_request.head.sha }} --verbose
57 |
58 | test:
59 | name: Test - ${{ matrix.os }} - Node v${{ matrix.node-version }}, Webpack ${{ matrix.webpack-version }}
60 |
61 | strategy:
62 | matrix:
63 | os: [ubuntu-latest, windows-latest, macos-latest]
64 | node-version: [18.x, 20.x, 22.x, 24.x]
65 | webpack-version: [latest]
66 |
67 | runs-on: ${{ matrix.os }}
68 |
69 | concurrency:
70 | group: test-${{ matrix.os }}-v${{ matrix.node-version }}-${{ matrix.webpack-version }}-${{ github.ref }}
71 | cancel-in-progress: true
72 |
73 | steps:
74 | - uses: actions/checkout@v4
75 |
76 | - name: Use Node.js ${{ matrix.node-version }}
77 | uses: actions/setup-node@v4
78 | with:
79 | node-version: ${{ matrix.node-version }}
80 | cache: "npm"
81 |
82 | - name: Install dependencies
83 | run: npm ci
84 |
85 | - name: Install webpack ${{ matrix.webpack-version }}
86 | if: matrix.webpack-version != 'latest'
87 | run: npm i webpack@${{ matrix.webpack-version }}
88 |
89 | - name: Run tests for webpack version ${{ matrix.webpack-version }}
90 | run: npm run test:coverage -- --ci
91 |
92 | - name: Submit coverage data to codecov
93 | uses: codecov/codecov-action@v5
94 | with:
95 | token: ${{ secrets.CODECOV_TOKEN }}
96 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | Thumbs.db
3 |
4 | .idea
5 | .vscode
6 | .eslintcache
7 | *.sublime-project
8 | *.sublime-workspace
9 |
10 | /dist
11 | /local
12 | /reports
13 | /coverage
14 | /node_modules
15 | /test/output
16 |
17 | logs
18 | *.log
19 | npm-debug.log*
20 | yarn-debug.log*
21 | *.iml
22 |
--------------------------------------------------------------------------------
/.husky/commit-msg:
--------------------------------------------------------------------------------
1 | commitlint --edit $1
2 |
--------------------------------------------------------------------------------
/.husky/pre-commit:
--------------------------------------------------------------------------------
1 | lint-staged
2 |
--------------------------------------------------------------------------------
/.prettierignore:
--------------------------------------------------------------------------------
1 | /coverage
2 | /dist
3 | /node_modules
4 | /test/fixtures
5 | CHANGELOG.md
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Changelog
2 |
3 | All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
4 |
5 | ## [6.0.0](https://github.com/webpack-contrib/val-loader/compare/v5.0.1...v6.0.0) (2024-01-15)
6 |
7 |
8 | ### ⚠ BREAKING CHANGES
9 |
10 | * minimum supported Node.js version is `18.12.0` ([#151](https://github.com/webpack-contrib/val-loader/issues/151)) ([ed762dc](https://github.com/webpack-contrib/val-loader/commit/ed762dcacd5aec8f462db8a7fa0da3c8d001f4b0))
11 |
12 | ### [5.0.1](https://github.com/webpack-contrib/val-loader/compare/v5.0.0...v5.0.1) (2022-11-29)
13 |
14 |
15 | ### Bug Fixes
16 |
17 | * compatibility with webpack cache ([#122](https://github.com/webpack-contrib/val-loader/issues/122)) ([41c08e3](https://github.com/webpack-contrib/val-loader/commit/41c08e3056741f9e0be1e4e45dc607a83d88b4e7))
18 |
19 | ## [5.0.0](https://github.com/webpack-contrib/val-loader/compare/v4.0.0...v5.0.0) (2022-05-17)
20 |
21 |
22 | ### ⚠ BREAKING CHANGES
23 |
24 | * minimum supported `Node.js` version is `14.15.0`
25 |
26 | ## [4.0.0](https://github.com/webpack-contrib/val-loader/compare/v3.1.0...v4.0.0) (2021-05-14)
27 |
28 |
29 | ### ⚠ BREAKING CHANGES
30 |
31 | * minimum supported `Node.js` version is `12.13.0`
32 |
33 | ## [3.1.0](https://github.com/webpack-contrib/val-loader/compare/v3.0.0...v3.1.0) (2021-03-01)
34 |
35 |
36 | ### Features
37 |
38 | * added the `buildDependensies` option ([#63](https://github.com/webpack-contrib/val-loader/issues/63)) ([04be3eb](https://github.com/webpack-contrib/val-loader/commit/04be3ebd9515358929c661b3c9db98ba3d870ac1))
39 | * added the `executableFile` option ([#65](https://github.com/webpack-contrib/val-loader/issues/65)) ([b46090f](https://github.com/webpack-contrib/val-loader/commit/b46090f323e3d2dcd75cbd552bd9447f98fd63e8))
40 | * support ECMA modules for the `executableFile` option ([#66](https://github.com/webpack-contrib/val-loader/issues/66)) ([1e6675f](https://github.com/webpack-contrib/val-loader/commit/1e6675fdf325c0973b1314fa3ad7984eaba197b9))
41 |
42 | ## [3.0.0](https://github.com/webpack-contrib/val-loader/compare/v2.1.2...v3.0.0) (2020-12-22)
43 |
44 |
45 | ### ⚠ BREAKING CHANGES
46 |
47 | * minimum supported webpack version is `5`
48 |
49 | ### [2.1.2](https://github.com/webpack-contrib/val-loader/compare/v2.1.1...v2.1.2) (2020-10-09)
50 |
51 | ### Chore
52 |
53 | * update `schema-utils`
54 |
55 | ### [2.1.1](https://github.com/webpack-contrib/val-loader/compare/v2.1.0...v2.1.1) (2020-04-09)
56 |
57 | ### Chore
58 |
59 | * update deps
60 |
61 | ## [2.1.0](https://github.com/webpack-contrib/val-loader/compare/v2.0.2...v2.1.0) (2019-12-17)
62 |
63 |
64 | ### Features
65 |
66 | * pass `loaderContext` as 2nd parameter ([#47](https://github.com/webpack-contrib/val-loader/issues/47)) ([cd5dd47](https://github.com/webpack-contrib/val-loader/commit/cd5dd471f41dc5dbb541e09ea8af0f3ed0ad23de))
67 |
68 | ### [2.0.2](https://github.com/webpack-contrib/val-loader/compare/v2.0.1...v2.0.2) (2019-11-25)
69 |
70 |
71 | ### Chore
72 |
73 | * add the `funding` field in `package.json`
74 |
75 |
76 |
77 | ### [2.0.1](https://github.com/webpack-contrib/val-loader/compare/v2.0.0...v2.0.1) (2019-11-19)
78 |
79 |
80 | ### Bug Fixes
81 |
82 | * link on package ([#44](https://github.com/webpack-contrib/val-loader/issues/44)) ([f234364](https://github.com/webpack-contrib/val-loader/commit/f234364a0c98f05fd0c4203c0a3946d6f0075adc))
83 |
84 | ### [2.0.0](https://github.com/webpack-contrib/val-loader/compare/v1.1.1...v2.0.0) (2019-11-14)
85 |
86 |
87 | ### Bug Fixes
88 |
89 | * support `webpack@5`
90 |
91 |
92 | ### Features
93 |
94 | * better handle errors from a module
95 | * pass `module.parent` to a module
96 | * validate loader options
97 |
98 |
99 | ### BREAKING CHANGES
100 |
101 | * minimum supported node version is `10.13.0`
102 | * minimum supported webpack version is `4.0.0`
103 |
104 |
105 |
106 |
107 | ## [1.1.1](https://github.com/webpack-contrib/val-loader/compare/v1.1.0...v1.1.1) (2018-06-21)
108 |
109 |
110 | ### Bug Fixes
111 |
112 | * add support for `webpack@4` ([#30](https://github.com/webpack-contrib/val-loader/issues/30)) ([fea518d](https://github.com/webpack-contrib/val-loader/commit/fea518d))
113 |
114 |
115 |
116 |
117 | # [1.1.0](https://github.com/webpack-contrib/val-loader/compare/v1.0.2...v1.1.0) (2017-11-19)
118 |
119 |
120 | ### Features
121 |
122 | * add support for `contextDependencies` in the `{Object}` interface (`options.contextDependencies`) ([#23](https://github.com/webpack-contrib/val-loader/issues/23)) ([78aa6fe](https://github.com/webpack-contrib/val-loader/commit/78aa6fe))
123 |
124 |
125 |
126 |
127 | ## [1.0.2](https://github.com/webpack-contrib/val-loader/compare/v1.0.1...v1.0.2) (2017-03-21)
128 |
129 |
130 | ### Bug Fixes
131 |
132 | * **.babelrc:** enable modules ([b0b116a](https://github.com/webpack-contrib/val-loader/commit/b0b116a))
133 |
134 |
135 |
136 |
137 | ## [1.0.1](https://github.com/webpack-contrib/val-loader/compare/v1.0.0...v1.0.1) (2017-03-20)
138 |
139 |
140 | ### Bug Fixes
141 |
142 | * **src:** add CJS wrapper ([cd043f5](https://github.com/webpack-contrib/val-loader/commit/cd043f5))
143 |
144 |
145 |
146 |
147 | # [1.0.0](https://github.com/webpack-contrib/val-loader/compare/v0.5.1...v1.0.0) (2017-03-16)
148 |
149 |
150 | ### Features
151 |
152 | * change expected module API ([caf2aab](https://github.com/webpack-contrib/val-loader/commit/caf2aab))
153 |
154 |
155 | ### BREAKING CHANGES
156 |
157 | * this commit introduces a major refactoring of the loader.
158 | * remove node 0.10 and node 0.12 support
159 | * the loaded module must now export a function
160 | * this function will be called with the loader options
161 | * this function must return an object with this structure
162 |
163 | Property | Type | Description
164 | :--------|:-----|:-----------
165 | `code` | `string|Buffer` | **Required**. The code that is passed to the next loader or to webpack.
166 | `sourceMap` | [`SourceMap`](https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit) | **Optional**. Will be pased to the next loader or to webpack.
167 | `ast` | `any` | **Optional**. An [Abstract Syntax Tree](https://en.wikipedia.org/wiki/Abstract_syntax_tree) that will be passed to the next loader. Useful to speed up the build time if the next loader uses the same AST.
168 | `dependencies` | `Array` | **Default: `[]`**. An array of absolute, native paths to file dependencies that need to be watched for changes.
169 | `cacheable` | `boolean` | **Default: `false`**. Flag whether the code can be re-used in watch mode if none of the `dependencies` have changed.
170 |
171 | * the function may also return a promise for async results
172 | * switch tooling to webpack-defaults
173 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright JS Foundation and other contributors
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining
4 | a copy of this software and associated documentation files (the
5 | 'Software'), to deal in the Software without restriction, including
6 | without limitation the rights to use, copy, modify, merge, publish,
7 | distribute, sublicense, and/or sell copies of the Software, and to
8 | permit persons to whom the Software is furnished to do so, subject to
9 | the following conditions:
10 |
11 | The above copyright notice and this permission notice shall be
12 | included in all copies or substantial portions of the Software.
13 |
14 | THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
18 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
19 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
20 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
6 |
7 | [![npm][npm]][npm-url]
8 | [![node][node]][node-url]
9 | [![tests][tests]][tests-url]
10 | [![coverage][cover]][cover-url]
11 | [![discussion][discussion]][discussion-url]
12 | [![size][size]][size-url]
13 |
14 | # val-loader
15 |
16 | A webpack loader that executes a given module and returns the result of the execution at build-time, when the module is required in the bundle. In this way, the loader changes a module from code into a result.
17 |
18 | Another way to view `val-loader` is that it allows users to implement custom loader logic without needing to write a full custom loader.
19 |
20 | The target module is called with two arguments: `(options, loaderContext)`
21 |
22 | - `options`: The loader options (for instance provided in the webpack config. See the [example](#examples) below).
23 | - `loaderContext`: [The loader context](https://webpack.js.org/api/loaders/#the-loader-context).
24 |
25 | ## Getting Started
26 |
27 | To begin, you'll need to install `val-loader`:
28 |
29 | ```console
30 | npm install val-loader --save-dev
31 | ```
32 |
33 | ```console
34 | yarn add -D val-loader
35 | ```
36 |
37 | ```console
38 | pnpm add -D val-loader
39 | ```
40 |
41 | Then, add the loader to your `webpack` configuration. For example:
42 |
43 | **target-file.js**
44 |
45 | ```js
46 | module.exports = (options, loaderContext) => {
47 | return { code: "module.exports = 42;" };
48 | };
49 | ```
50 |
51 | **webpack.config.js**
52 |
53 | ```js
54 | module.exports = {
55 | module: {
56 | rules: [
57 | {
58 | test: /target-file.js$/,
59 | use: [
60 | {
61 | loader: `val-loader`,
62 | },
63 | ],
64 | },
65 | ],
66 | },
67 | };
68 | ```
69 |
70 | **src/entry.js**
71 |
72 | ```js
73 | const answer = require("target-file");
74 | ```
75 |
76 | Finally, run `webpack` using the method you normally use (e.g., via CLI or an npm script).
77 |
78 | ## Options
79 |
80 | - **[`executableFile`](#executableFile)**
81 |
82 | ### `executableFile`
83 |
84 | Type:
85 |
86 | ```ts
87 | type executableFile = string;
88 | ```
89 |
90 | Default: `undefined`
91 |
92 | Allows to specify path to the executable file.
93 |
94 | **data.json**
95 |
96 | ```json
97 | {
98 | "years": "10"
99 | }
100 | ```
101 |
102 | **executable-file.js**
103 |
104 | ```js
105 | module.exports = function yearsInMs(options, loaderContext, content) {
106 | const { years } = JSON.parse(content);
107 | const value = years * 365 * 24 * 60 * 60 * 1000;
108 |
109 | return {
110 | cacheable: true,
111 | code: "module.exports = " + value,
112 | };
113 | };
114 | ```
115 |
116 | **webpack.config.js**
117 |
118 | ```js
119 | module.exports = {
120 | module: {
121 | rules: [
122 | {
123 | test: /\.(json)$/i,
124 | rules: [
125 | {
126 | loader: "val-loader",
127 | options: {
128 | executableFile: path.resolve(
129 | __dirname,
130 | "fixtures",
131 | "executableFile.js",
132 | ),
133 | },
134 | },
135 | ],
136 | },
137 | {
138 | test: /\.json$/i,
139 | type: "asset/resource",
140 | },
141 | ],
142 | },
143 | };
144 | ```
145 |
146 | ## Return Object Properties
147 |
148 | Targeted modules of this loader must export a `function` that returns an object, or a `Promise` resolving to an object (e.g. async function), containing a `code` property at a minimum, but can also include additional properties.
149 |
150 | ### `code`
151 |
152 | Type:
153 |
154 | ```ts
155 | type code = string | Buffer;
156 | ```
157 |
158 | Default: `undefined`
159 | _Required_
160 |
161 | Code passed along to webpack or the next loader that will replace the original module.
162 |
163 | ### `sourceMap`
164 |
165 | Type:
166 |
167 | ```ts
168 | type sourceMap = object;
169 | ```
170 |
171 | Default: `undefined`
172 |
173 | A source map passed along to webpack or the next loader.
174 |
175 | ### `ast`
176 |
177 | Type:
178 |
179 | ```ts
180 | type ast = Array;
181 | ```
182 |
183 | Default: `undefined`
184 |
185 | An [Abstract Syntax Tree (AST)](https://en.wikipedia.org/wiki/Abstract_syntax_tree) that will be passed to the next loader. Useful to speed up the build time if the next loader uses the same AST.
186 |
187 | ### `dependencies`
188 |
189 | Type:
190 |
191 | ```ts
192 | type dependencies = Array;
193 | ```
194 |
195 | Default: `[]`
196 |
197 | An array of absolute, native paths to file dependencies that should be watched by webpack for changes.
198 |
199 | Dependencies can also be added using [`loaderContext.addDependency(file: string)`](https://webpack.js.org/api/loaders/#thisadddependency).
200 |
201 | ### `contextDependencies`
202 |
203 | Type:
204 |
205 | ```ts
206 | type contextDependencies = Array;
207 | ```
208 |
209 | Default: `[]`
210 |
211 | An array of absolute, native paths to directory dependencies that should be watched by webpack for changes.
212 |
213 | Context dependencies can also be added using [`loaderContext.addContextDependency(directory: string)`](https://webpack.js.org/api/loaders/#thisaddcontextdependency).
214 |
215 | ### `buildDependencies`
216 |
217 | Type:
218 |
219 | ```ts
220 | type buildDependencies = Array;
221 | ```
222 |
223 | Default: `[]`
224 |
225 | An array of absolute, native paths to directory dependencies that should be watched by webpack for changes.
226 |
227 | Build dependencies can also be added using `loaderContext.addBuildDependency(file: string)`.
228 |
229 | ### `cacheable`
230 |
231 | Type:
232 |
233 | ```ts
234 | type cacheable = boolean;
235 | ```
236 |
237 | Default: `false`
238 |
239 | If `true`, specifies that the code can be reused in watch mode if none of the `dependencies` have changed.
240 |
241 | ## Examples
242 |
243 | ### Simple
244 |
245 | In this example the loader is configured to operate on a file name of `years-in-ms.js`, execute the code, and store the result in the bundle as the result of the execution.
246 | This example passes `years` as an `option`, which corresponds to the `years` parameter in the target module's exported function:
247 |
248 | **years-in-ms.js**
249 |
250 | ```js
251 | module.exports = function yearsInMs({ years }) {
252 | const value = years * 365 * 24 * 60 * 60 * 1000;
253 |
254 | // NOTE: this return value will replace the module in the bundle
255 | return {
256 | cacheable: true,
257 | code: "module.exports = " + value,
258 | };
259 | };
260 | ```
261 |
262 | **webpack.config.js**
263 |
264 | ```js
265 | module.exports = {
266 | module: {
267 | rules: [
268 | {
269 | test: require.resolve("src/years-in-ms.js"),
270 | use: [
271 | {
272 | loader: "val-loader",
273 | options: {
274 | years: 10,
275 | },
276 | },
277 | ],
278 | },
279 | ],
280 | },
281 | };
282 | ```
283 |
284 | In the bundle, requiring the module then returns:
285 |
286 | ```js
287 | import tenYearsMs from "years-in-ms";
288 |
289 | console.log(tenYearsMs); // 315360000000
290 | ```
291 |
292 | ### Modernizr
293 |
294 | Example shows how to build [`modernizr`](https://www.npmjs.com/package/modernizr).
295 |
296 | **entry.js**
297 |
298 | ```js
299 | import modenizr from "./modernizr.js";
300 | ```
301 |
302 | **modernizr.js**
303 |
304 | ```js
305 | const modernizr = require("modernizr");
306 |
307 | module.exports = function (options) {
308 | return new Promise(function (resolve) {
309 | // It is impossible to throw an error because modernizr causes the process.exit(1)
310 | modernizr.build(options, function (output) {
311 | resolve({
312 | cacheable: true,
313 | code: `var modernizr; var hadGlobal = 'Modernizr' in window; var oldGlobal = window.Modernizr; ${output} modernizr = window.Modernizr; if (hadGlobal) { window.Modernizr = oldGlobal; } else { delete window.Modernizr; } export default modernizr;`,
314 | });
315 | });
316 | });
317 | };
318 | ```
319 |
320 | **webpack.config.js**
321 |
322 | ```js
323 | const path = require("path");
324 | module.exports = {
325 | module: {
326 | rules: [
327 | {
328 | test: path.resolve(__dirname, "src", "modernizr.js"),
329 | use: [
330 | {
331 | loader: "val-loader",
332 | options: {
333 | minify: false,
334 | options: ["setClasses"],
335 | "feature-detects": [
336 | "test/css/flexbox",
337 | "test/es6/promises",
338 | "test/serviceworker",
339 | ],
340 | },
341 | },
342 | ],
343 | },
344 | ],
345 | },
346 | };
347 | ```
348 |
349 | ### Figlet
350 |
351 | Example shows how to build [`figlet`](https://www.npmjs.com/package/figlet).
352 |
353 | **entry.js**
354 |
355 | ```js
356 | import { default as figlet } from "./figlet.js";
357 |
358 | console.log(figlet);
359 | ```
360 |
361 | **figlet.js**
362 |
363 | ```js
364 | const figlet = require("figlet");
365 |
366 | function wrapOutput(output, config) {
367 | let figletOutput = "";
368 |
369 | if (config.textBefore) {
370 | figletOutput += encodeURI(`${config.textBefore}\n`);
371 | }
372 |
373 | output.split("\n").forEach((line) => {
374 | figletOutput += encodeURI(`${line}\n`);
375 | });
376 |
377 | if (config.textAfter) {
378 | figletOutput += encodeURI(`${config.textAfter}\n`);
379 | }
380 |
381 | return `module.exports = decodeURI("${figletOutput}");`;
382 | }
383 |
384 | module.exports = function (options) {
385 | const defaultConfig = {
386 | fontOptions: {
387 | font: "ANSI Shadow",
388 | horizontalLayout: "default",
389 | kerning: "default",
390 | verticalLayout: "default",
391 | },
392 | text: "FIGLET-LOADER",
393 | textAfter: null,
394 | textBefore: null,
395 | };
396 |
397 | const config = Object.assign({}, defaultConfig, options);
398 |
399 | return new Promise(function (resolve, reject) {
400 | figlet.text(config.text, config.fontOptions, (error, output) => {
401 | if (error) {
402 | return reject(error);
403 | }
404 |
405 | resolve({
406 | cacheable: true,
407 | code: "module.exports = " + wrapOutput(output, config),
408 | });
409 | });
410 | });
411 | };
412 | ```
413 |
414 | **webpack.config.js**
415 |
416 | ```js
417 | const path = require("path");
418 | module.exports = {
419 | module: {
420 | rules: [
421 | {
422 | test: path.resolve(__dirname, "src", "figlet.js"),
423 | use: [
424 | {
425 | loader: "val-loader",
426 | options: {
427 | text: "FIGLET",
428 | },
429 | },
430 | ],
431 | },
432 | ],
433 | },
434 | };
435 | ```
436 |
437 | ## Contributing
438 |
439 | We welcome all contributions!
440 | If you're new here, please take a moment to review our contributing guidelines before submitting issues or pull requests.
441 |
442 | [CONTRIBUTING](./.github/CONTRIBUTING.md)
443 |
444 | ## License
445 |
446 | [MIT](./LICENSE)
447 |
448 | [npm]: https://img.shields.io/npm/v/val-loader.svg
449 | [npm-url]: https://npmjs.com/package/val-loader
450 | [node]: https://img.shields.io/node/v/val-loader.svg
451 | [node-url]: https://nodejs.org
452 | [tests]: https://github.com/webpack-contrib/val-loader/workflows/val-loader/badge.svg
453 | [tests-url]: https://github.com/webpack-contrib/val-loader/actions
454 | [cover]: https://codecov.io/gh/webpack-contrib/val-loader/branch/master/graph/badge.svg
455 | [cover-url]: https://codecov.io/gh/webpack-contrib/val-loader
456 | [discussion]: https://img.shields.io/github/discussions/webpack/webpack
457 | [discussion-url]: https://github.com/webpack/webpack/discussions
458 | [size]: https://packagephobia.now.sh/badge?p=val-loader
459 | [size-url]: https://packagephobia.now.sh/result?p=val-loader
460 |
--------------------------------------------------------------------------------
/babel.config.js:
--------------------------------------------------------------------------------
1 | const MIN_BABEL_VERSION = 7;
2 |
3 | module.exports = (api) => {
4 | api.assertVersion(MIN_BABEL_VERSION);
5 | api.cache(true);
6 |
7 | return {
8 | presets: [
9 | [
10 | "@babel/preset-env",
11 | {
12 | targets: {
13 | node: "18.12.0",
14 | },
15 | },
16 | ],
17 | ],
18 | };
19 | };
20 |
--------------------------------------------------------------------------------
/commitlint.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | extends: ["@commitlint/config-conventional"],
3 | rules: {
4 | "header-max-length": [0],
5 | "body-max-line-length": [0],
6 | "footer-max-line-length": [0],
7 | },
8 | };
9 |
--------------------------------------------------------------------------------
/jest.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | transformIgnorePatterns: [
3 | "/node_modules/",
4 | "\\.pnp\\.[^\\/]+$",
5 | "/test/fixtures/",
6 | ],
7 | };
8 |
--------------------------------------------------------------------------------
/lint-staged.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | "*": ["prettier --write --ignore-unknown", "cspell --no-must-find-files"],
3 | "*.js": ["eslint --cache --fix"],
4 | };
5 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "val-loader",
3 | "version": "6.0.0",
4 | "description": "val loader module for webpack",
5 | "license": "MIT",
6 | "repository": "webpack-contrib/val-loader",
7 | "author": "Tobias Koppers @sokra",
8 | "homepage": "https://github.com/webpack-contrib/val-loader",
9 | "bugs": "https://github.com/webpack-contrib/val-loader/issues",
10 | "funding": {
11 | "type": "opencollective",
12 | "url": "https://opencollective.com/webpack"
13 | },
14 | "main": "dist/cjs.js",
15 | "engines": {
16 | "node": ">= 18.12.0"
17 | },
18 | "scripts": {
19 | "start": "npm run build -- -w",
20 | "clean": "del-cli dist",
21 | "prebuild": "npm run clean",
22 | "build": "cross-env NODE_ENV=production babel src -d dist --copy-files",
23 | "commitlint": "commitlint --from=master",
24 | "security": "npm audit --production",
25 | "lint:prettier": "prettier --list-different .",
26 | "lint:js": "eslint --cache .",
27 | "lint:spelling": "cspell --no-must-find-files --cache --quiet \"**/*.*\"",
28 | "lint": "npm-run-all -l -p \"lint:**\"",
29 | "fix:js": "npm run lint:js -- --fix",
30 | "fix:prettier": "npm run lint:prettier -- --write",
31 | "fix": "npm-run-all -l fix:js fix:prettier",
32 | "test:only": "cross-env NODE_ENV=test NODE_OPTIONS=--experimental-vm-modules jest",
33 | "test:watch": "npm run test:only -- --watch",
34 | "test:coverage": "npm run test:only -- --collectCoverageFrom=\"src/**/*.js\" --coverage",
35 | "pretest": "npm run lint",
36 | "test": "npm run test:coverage",
37 | "prepare": "husky && npm run build",
38 | "release": "standard-version"
39 | },
40 | "files": [
41 | "dist"
42 | ],
43 | "peerDependencies": {
44 | "webpack": "^5.0.0"
45 | },
46 | "devDependencies": {
47 | "@babel/cli": "^7.24.6",
48 | "@babel/core": "^7.24.6",
49 | "@babel/preset-env": "^7.24.6",
50 | "@commitlint/cli": "^18.6.1",
51 | "@commitlint/config-conventional": "^18.6.2",
52 | "@webpack-contrib/eslint-config-webpack": "^3.0.0",
53 | "cross-env": "^7.0.3",
54 | "cspell": "^8.8.3",
55 | "del": "^7.1.0",
56 | "del-cli": "^5.1.0",
57 | "eslint": "^8.57.0",
58 | "eslint-config-prettier": "^9.1.0",
59 | "eslint-plugin-import": "^2.29.1",
60 | "figlet": "^1.7.0",
61 | "husky": "^9.1.3",
62 | "jest": "^29.7.0",
63 | "lint-staged": "^15.2.5",
64 | "memfs": "^4.9.2",
65 | "modernizr": "^3.13.0",
66 | "npm-run-all": "^4.1.5",
67 | "prettier": "^3.3.0",
68 | "standard-version": "^9.5.0",
69 | "webpack": "^5.91.0"
70 | },
71 | "keywords": [
72 | "webpack",
73 | "loader",
74 | "execute",
75 | "val"
76 | ]
77 | }
78 |
--------------------------------------------------------------------------------
/src/cjs.js:
--------------------------------------------------------------------------------
1 | const loader = require("./index");
2 |
3 | module.exports = loader.default;
4 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | import Module from "module";
2 | import { pathToFileURL } from "url";
3 |
4 | import schema from "./options.json";
5 |
6 | const parentModule = module;
7 |
8 | function execute(code, loaderContext) {
9 | const module = new Module(loaderContext.resource, parentModule);
10 |
11 | // eslint-disable-next-line no-underscore-dangle
12 | module.paths = Module._nodeModulePaths(loaderContext.context);
13 | // Use the path without webpack-specific parts (`resourceQuery` or `resourceFragment`)
14 | module.filename = loaderContext.resourcePath;
15 |
16 | // eslint-disable-next-line no-underscore-dangle
17 | module._compile(code, loaderContext.resource);
18 |
19 | return module.exports;
20 | }
21 |
22 | function processResult(loaderContext, result) {
23 | if (!result || typeof result !== "object" || "code" in result === false) {
24 | loaderContext.callback(
25 | new Error(
26 | `The returned result of module "${loaderContext.resource}" is not an object with a "code" property`,
27 | ),
28 | );
29 |
30 | return;
31 | }
32 |
33 | if (
34 | typeof result.code !== "string" &&
35 | result.code instanceof Buffer === false
36 | ) {
37 | loaderContext.callback(
38 | new Error(
39 | `The returned code of module "${loaderContext.resource}" is neither a string nor an instance of Buffer`,
40 | ),
41 | );
42 |
43 | return;
44 | }
45 |
46 | (result.dependencies || []).forEach((dep) =>
47 | loaderContext.addDependency(dep),
48 | );
49 |
50 | (result.contextDependencies || []).forEach((dep) =>
51 | loaderContext.addContextDependency(dep),
52 | );
53 |
54 | (result.buildDependencies || []).forEach((dep) =>
55 | loaderContext.addBuildDependency(dep),
56 | );
57 |
58 | // Defaults to false which is a good default here because we assume that
59 | // results tend to be not cacheable when this loader is necessary
60 | loaderContext.cacheable(Boolean(result.cacheable));
61 |
62 | loaderContext.callback(
63 | null,
64 | result.code,
65 | result.sourceMap || null,
66 | result.ast || null,
67 | );
68 | }
69 |
70 | export default async function loader(content) {
71 | const options = this.getOptions(schema);
72 | const { executableFile } = options;
73 | const callback = this.async();
74 |
75 | let exports;
76 |
77 | if (executableFile) {
78 | try {
79 | // eslint-disable-next-line global-require,import/no-dynamic-require
80 | exports = require(executableFile);
81 | } catch (requireError) {
82 | try {
83 | let importESM;
84 |
85 | try {
86 | // eslint-disable-next-line no-new-func
87 | importESM = new Function("id", "return import(id);");
88 | } catch (e) {
89 | importESM = null;
90 | }
91 |
92 | if (
93 | requireError.code === "ERR_REQUIRE_ESM" &&
94 | pathToFileURL &&
95 | importESM
96 | ) {
97 | const urlForConfig = pathToFileURL(executableFile);
98 |
99 | exports = await importESM(urlForConfig);
100 | } else {
101 | throw requireError;
102 | }
103 | } catch (error) {
104 | callback(new Error(`Unable to require "${executableFile}": ${error}`));
105 |
106 | return;
107 | }
108 | }
109 | } else {
110 | try {
111 | exports = execute(content, this);
112 | } catch (error) {
113 | callback(new Error(`Unable to execute "${this.resource}": ${error}`));
114 |
115 | return;
116 | }
117 | }
118 |
119 | const func = exports && exports.default ? exports.default : exports;
120 |
121 | if (typeof func !== "function") {
122 | callback(
123 | new Error(
124 | `Module "${this.resource}" does not export a function as default`,
125 | ),
126 | );
127 | return;
128 | }
129 |
130 | let result;
131 |
132 | try {
133 | result = func(options, this, content);
134 | } catch (error) {
135 | callback(new Error(`Module "${this.resource}" throw error: ${error}`));
136 | return;
137 | }
138 |
139 | if (result && typeof result.then === "function") {
140 | result
141 | .then((res) => processResult(this, res))
142 | .catch((error) => {
143 | callback(new Error(`Module "${this.resource}" throw error: ${error}`));
144 | });
145 |
146 | return;
147 | }
148 |
149 | // No return necessary because processResult calls this.callback()
150 | processResult(this, result);
151 | }
152 |
--------------------------------------------------------------------------------
/src/options.json:
--------------------------------------------------------------------------------
1 | {
2 | "title": "Val Loader options",
3 | "type": "object",
4 | "additionalProperties": true
5 | }
6 |
--------------------------------------------------------------------------------
/test/__snapshots__/executableFile.test.js.snap:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://goo.gl/fbAQLP
2 |
3 | exports[`executableFile option should emit error: errors 1`] = `
4 | [
5 | "ModuleBuildError: Module build failed (from \`replaced original path\`):
6 | Error: Unable to require "/test/fixtures/error-require.js": Error: This is a typical require() error",
7 | ]
8 | `;
9 |
10 | exports[`executableFile option should emit error: warnings 1`] = `[]`;
11 |
12 | exports[`executableFile option should work with commonjs format: errors 1`] = `[]`;
13 |
14 | exports[`executableFile option should work with commonjs format: result 1`] = `
15 | "{
16 | "content": "module.exports = 315360000000",
17 | "map": null,
18 | "meta": null,
19 | "dependencies": [
20 | "test/fixtures/data.json"
21 | ],
22 | "contextDependencies": [],
23 | "buildDependencies": []
24 | }"
25 | `;
26 |
27 | exports[`executableFile option should work with commonjs format: warnings 1`] = `[]`;
28 |
--------------------------------------------------------------------------------
/test/__snapshots__/loader.test.js.snap:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://goo.gl/fbAQLP
2 |
3 | exports[`loader should allow adding dependencies, contextDependencies and buildDependencies via loader context: errors 1`] = `[]`;
4 |
5 | exports[`loader should allow adding dependencies, contextDependencies and buildDependencies via loader context: result 1`] = `
6 | "{
7 | "content": "module.exports = \\"hello world\\";",
8 | "map": null,
9 | "meta": null,
10 | "dependencies": [
11 | "test/fixtures/dependencies-via-context.js",
12 | "test/fixtures/args.js",
13 | "test/fixtures/simple.js"
14 | ],
15 | "contextDependencies": [
16 | "test/fixtures"
17 | ],
18 | "buildDependencies": [
19 | "test/fixtures/args.js",
20 | "test/fixtures/simple.js",
21 | "test/fixtures"
22 | ]
23 | }"
24 | `;
25 |
26 | exports[`loader should allow adding dependencies, contextDependencies and buildDependencies via loader context: warnings 1`] = `[]`;
27 |
28 | exports[`loader should call the function with the loader options: errors 1`] = `[]`;
29 |
30 | exports[`loader should call the function with the loader options: result 1`] = `
31 | "{
32 | "content": "module.exports = \\"hello world\\";",
33 | "map": null,
34 | "meta": [
35 | {
36 | "arg": 123,
37 | "arg2": "string",
38 | "arg3": true,
39 | "arg4": null,
40 | "arg6": {}
41 | }
42 | ],
43 | "dependencies": [
44 | "test/fixtures/args.js"
45 | ],
46 | "contextDependencies": [],
47 | "buildDependencies": []
48 | }"
49 | `;
50 |
51 | exports[`loader should call the function with the loader options: warnings 1`] = `[]`;
52 |
53 | exports[`loader should flag the module as cacheable if requested: errors 1`] = `[]`;
54 |
55 | exports[`loader should flag the module as cacheable if requested: result 1`] = `
56 | "{
57 | "content": "module.exports = \\"hello world\\";",
58 | "map": null,
59 | "meta": null,
60 | "dependencies": [
61 | "test/fixtures/cacheable.js"
62 | ],
63 | "contextDependencies": [],
64 | "buildDependencies": []
65 | }"
66 | `;
67 |
68 | exports[`loader should flag the module as cacheable if requested: warnings 1`] = `[]`;
69 |
70 | exports[`loader should flag the module as not cacheable by default: errors 1`] = `[]`;
71 |
72 | exports[`loader should flag the module as not cacheable by default: result 1`] = `
73 | "{
74 | "content": "module.exports = \\"hello world\\";",
75 | "map": {
76 | "isASourceMap": true
77 | },
78 | "meta": {
79 | "isAnAst": true
80 | },
81 | "dependencies": [
82 | "test/fixtures/simple.js"
83 | ],
84 | "contextDependencies": [],
85 | "buildDependencies": []
86 | }"
87 | `;
88 |
89 | exports[`loader should flag the module as not cacheable by default: warnings 1`] = `[]`;
90 |
91 | exports[`loader should handle dependencies, contextDependencies and buildDependencies of the module: errors 1`] = `[]`;
92 |
93 | exports[`loader should handle dependencies, contextDependencies and buildDependencies of the module: result 1`] = `
94 | "{
95 | "content": "module.exports = \\"hello world\\";",
96 | "map": null,
97 | "meta": null,
98 | "dependencies": [
99 | "test/fixtures/dependencies.js",
100 | "test/fixtures/args.js",
101 | "test/fixtures/simple.js"
102 | ],
103 | "contextDependencies": [
104 | "test/fixtures"
105 | ],
106 | "buildDependencies": [
107 | "test/fixtures/args.js",
108 | "test/fixtures/simple.js"
109 | ]
110 | }"
111 | `;
112 |
113 | exports[`loader should handle dependencies, contextDependencies and buildDependencies of the module: warnings 1`] = `[]`;
114 |
115 | exports[`loader should has module.parent: errors 1`] = `[]`;
116 |
117 | exports[`loader should has module.parent: result 1`] = `
118 | "{
119 | "content": "module.exports = \\"hello world\\";",
120 | "map": {
121 | "isASourceMap": true
122 | },
123 | "meta": {
124 | "isAnAst": true,
125 | "hasParent": true
126 | },
127 | "dependencies": [
128 | "test/fixtures/module-parent.js"
129 | ],
130 | "contextDependencies": [],
131 | "buildDependencies": []
132 | }"
133 | `;
134 |
135 | exports[`loader should has module.parent: warnings 1`] = `[]`;
136 |
137 | exports[`loader should keep dependencies if errors are emitted: errors 1`] = `
138 | [
139 | "ModuleError: Module Error (from \`replaced original path\`):
140 | (Emitted value instead of an instance of Error) Error: Calling the function failed",
141 | ]
142 | `;
143 |
144 | exports[`loader should keep dependencies if errors are emitted: result 1`] = `
145 | "{
146 | "content": "module.exports = \\"hello world\\";",
147 | "map": null,
148 | "meta": null,
149 | "dependencies": [
150 | "test/fixtures/error-emitted-with-dependencies.js",
151 | "test/fixtures/args.js",
152 | "test/fixtures/simple.js"
153 | ],
154 | "contextDependencies": [
155 | "test/fixtures"
156 | ],
157 | "buildDependencies": []
158 | }"
159 | `;
160 |
161 | exports[`loader should keep dependencies if errors are emitted: warnings 1`] = `[]`;
162 |
163 | exports[`loader should not swallow function call errors (async): errors 1`] = `
164 | [
165 | "ModuleBuildError: Module build failed (from \`replaced original path\`):
166 | Error: Module "/test/fixtures/error-call-async.js" throw error: Error: Calling the function failed asynchronously",
167 | ]
168 | `;
169 |
170 | exports[`loader should not swallow function call errors (async): warnings 1`] = `[]`;
171 |
172 | exports[`loader should not swallow function call errors (sync): errors 1`] = `
173 | [
174 | "ModuleBuildError: Module build failed (from \`replaced original path\`):
175 | Error: Module "/test/fixtures/error-call-sync.js" throw error: Error: Calling the function failed",
176 | ]
177 | `;
178 |
179 | exports[`loader should not swallow function call errors (sync): warnings 1`] = `[]`;
180 |
181 | exports[`loader should pass on the code from the buffer fixture: errors 1`] = `[]`;
182 |
183 | exports[`loader should pass on the code from the buffer fixture: result 1`] = `
184 | "{
185 | "content": "module.exports = \\"hello world\\";",
186 | "map": {
187 | "isASourceMap": true
188 | },
189 | "meta": {
190 | "isAnAst": true
191 | },
192 | "dependencies": [
193 | "test/fixtures/buffer.js"
194 | ],
195 | "contextDependencies": [],
196 | "buildDependencies": []
197 | }"
198 | `;
199 |
200 | exports[`loader should pass on the code from the buffer fixture: warnings 1`] = `[]`;
201 |
202 | exports[`loader should pass on the code from the presets/figlet fixture: errors 1`] = `[]`;
203 |
204 | exports[`loader should pass on the code from the presets/figlet fixture: result 1`] = `
205 | "{
206 | "content": "module.exports = module.exports = decodeURI(\\"%E2%96%88%E2%96%88%E2%96%88%E2%96%88%E2%96%88%E2%96%88%E2%96%88%E2%95%97%E2%96%88%E2%96%88%E2%95%97%20%E2%96%88%E2%96%88%E2%96%88%E2%96%88%E2%96%88%E2%96%88%E2%95%97%20%E2%96%88%E2%96%88%E2%95%97%20%20%20%20%20%E2%96%88%E2%96%88%E2%96%88%E2%96%88%E2%96%88%E2%96%88%E2%96%88%E2%95%97%E2%96%88%E2%96%88%E2%96%88%E2%96%88%E2%96%88%E2%96%88%E2%96%88%E2%96%88%E2%95%97%0A%E2%96%88%E2%96%88%E2%95%94%E2%95%90%E2%95%90%E2%95%90%E2%95%90%E2%95%9D%E2%96%88%E2%96%88%E2%95%91%E2%96%88%E2%96%88%E2%95%94%E2%95%90%E2%95%90%E2%95%90%E2%95%90%E2%95%9D%20%E2%96%88%E2%96%88%E2%95%91%20%20%20%20%20%E2%96%88%E2%96%88%E2%95%94%E2%95%90%E2%95%90%E2%95%90%E2%95%90%E2%95%9D%E2%95%9A%E2%95%90%E2%95%90%E2%96%88%E2%96%88%E2%95%94%E2%95%90%E2%95%90%E2%95%9D%0A%E2%96%88%E2%96%88%E2%96%88%E2%96%88%E2%96%88%E2%95%97%20%20%E2%96%88%E2%96%88%E2%95%91%E2%96%88%E2%96%88%E2%95%91%20%20%E2%96%88%E2%96%88%E2%96%88%E2%95%97%E2%96%88%E2%96%88%E2%95%91%20%20%20%20%20%E2%96%88%E2%96%88%E2%96%88%E2%96%88%E2%96%88%E2%95%97%20%20%20%20%20%E2%96%88%E2%96%88%E2%95%91%20%20%20%0A%E2%96%88%E2%96%88%E2%95%94%E2%95%90%E2%95%90%E2%95%9D%20%20%E2%96%88%E2%96%88%E2%95%91%E2%96%88%E2%96%88%E2%95%91%20%20%20%E2%96%88%E2%96%88%E2%95%91%E2%96%88%E2%96%88%E2%95%91%20%20%20%20%20%E2%96%88%E2%96%88%E2%95%94%E2%95%90%E2%95%90%E2%95%9D%20%20%20%20%20%E2%96%88%E2%96%88%E2%95%91%20%20%20%0A%E2%96%88%E2%96%88%E2%95%91%20%20%20%20%20%E2%96%88%E2%96%88%E2%95%91%E2%95%9A%E2%96%88%E2%96%88%E2%96%88%E2%96%88%E2%96%88%E2%96%88%E2%95%94%E2%95%9D%E2%96%88%E2%96%88%E2%96%88%E2%96%88%E2%96%88%E2%96%88%E2%96%88%E2%95%97%E2%96%88%E2%96%88%E2%96%88%E2%96%88%E2%96%88%E2%96%88%E2%96%88%E2%95%97%20%20%20%E2%96%88%E2%96%88%E2%95%91%20%20%20%0A%E2%95%9A%E2%95%90%E2%95%9D%20%20%20%20%20%E2%95%9A%E2%95%90%E2%95%9D%20%E2%95%9A%E2%95%90%E2%95%90%E2%95%90%E2%95%90%E2%95%90%E2%95%9D%20%E2%95%9A%E2%95%90%E2%95%90%E2%95%90%E2%95%90%E2%95%90%E2%95%90%E2%95%9D%E2%95%9A%E2%95%90%E2%95%90%E2%95%90%E2%95%90%E2%95%90%E2%95%90%E2%95%9D%20%20%20%E2%95%9A%E2%95%90%E2%95%9D%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%0A\\");",
207 | "map": null,
208 | "meta": null,
209 | "dependencies": [
210 | "test/fixtures/presets/figlet.js"
211 | ],
212 | "contextDependencies": [],
213 | "buildDependencies": []
214 | }"
215 | `;
216 |
217 | exports[`loader should pass on the code from the presets/figlet fixture: warnings 1`] = `[]`;
218 |
219 | exports[`loader should pass on the code from the presets/modernizr fixture: errors 1`] = `[]`;
220 |
221 | exports[`loader should pass on the code from the presets/modernizr fixture: result 1`] = `
222 | "{
223 | "content": "var modernizr; var hadGlobal = 'Modernizr' in window; var oldGlobal = window.Modernizr; /*!\\n * modernizr v3.13.0\\n * Build https://modernizr.com/download?-flexbox-promises-serviceworker-setclasses-dontmin\\n *\\n * Copyright (c)\\n * Faruk Ates\\n * Paul Irish\\n * Alex Sexton\\n * Ryan Seddon\\n * Patrick Kettner\\n * Stu Cox\\n * Richard Herrera\\n * Veeck\\n\\n * MIT License\\n */\\n\\n/*\\n * Modernizr tests which native CSS3 and HTML5 features are available in the\\n * current UA and makes the results available to you in two ways: as properties on\\n * a global \`Modernizr\` object, and as classes on the \`\` element. This\\n * information allows you to progressively enhance your pages with a granular level\\n * of control over the experience.\\n*/\\n\\n;(function(scriptGlobalObject, window, document, undefined){\\n\\n var tests = [];\\n \\n\\n /**\\n * ModernizrProto is the constructor for Modernizr\\n *\\n * @class\\n * @access public\\n */\\n var ModernizrProto = {\\n _version: '3.13.0',\\n\\n // Any settings that don't work as separate modules\\n // can go in here as configuration.\\n _config: {\\n 'classPrefix': '',\\n 'enableClasses': true,\\n 'enableJSClass': true,\\n 'usePrefixes': true\\n },\\n\\n // Queue of tests\\n _q: [],\\n\\n // Stub these for people who are listening\\n on: function(test, cb) {\\n // I don't really think people should do this, but we can\\n // safe guard it a bit.\\n // -- NOTE:: this gets WAY overridden in src/addTest for actual async tests.\\n // This is in case people listen to synchronous tests. I would leave it out,\\n // but the code to *disallow* sync tests in the real version of this\\n // function is actually larger than this.\\n var self = this;\\n setTimeout(function() {\\n cb(self[test]);\\n }, 0);\\n },\\n\\n addTest: function(name, fn, options) {\\n tests.push({name: name, fn: fn, options: options});\\n },\\n\\n addAsyncTest: function(fn) {\\n tests.push({name: null, fn: fn});\\n }\\n };\\n\\n \\n\\n // Fake some of Object.create so we can force non test results to be non \\"own\\" properties.\\n var Modernizr = function() {};\\n Modernizr.prototype = ModernizrProto;\\n\\n // Leak modernizr globally when you \`require\` it rather than force it here.\\n // Overwrite name so constructor name is nicer :D\\n Modernizr = new Modernizr();\\n\\n \\n\\n var classes = [];\\n \\n\\n /**\\n * is returns a boolean if the typeof an obj is exactly type.\\n *\\n * @access private\\n * @function is\\n * @param {*} obj - A thing we want to check the type of\\n * @param {string} type - A string to compare the typeof against\\n * @returns {boolean} true if the typeof the first parameter is exactly the specified type, false otherwise\\n */\\n function is(obj, type) {\\n return typeof obj === type;\\n }\\n\\n ;\\n\\n /**\\n * Run through all tests and detect their support in the current UA.\\n *\\n * @access private\\n * @returns {void}\\n */\\n function testRunner() {\\n var featureNames;\\n var feature;\\n var aliasIdx;\\n var result;\\n var nameIdx;\\n var featureName;\\n var featureNameSplit;\\n\\n for (var featureIdx in tests) {\\n if (tests.hasOwnProperty(featureIdx)) {\\n featureNames = [];\\n feature = tests[featureIdx];\\n // run the test, throw the return value into the Modernizr,\\n // then based on that boolean, define an appropriate className\\n // and push it into an array of classes we'll join later.\\n //\\n // If there is no name, it's an 'async' test that is run,\\n // but not directly added to the object. That should\\n // be done with a post-run addTest call.\\n if (feature.name) {\\n featureNames.push(feature.name.toLowerCase());\\n\\n if (feature.options && feature.options.aliases && feature.options.aliases.length) {\\n // Add all the aliases into the names list\\n for (aliasIdx = 0; aliasIdx < feature.options.aliases.length; aliasIdx++) {\\n featureNames.push(feature.options.aliases[aliasIdx].toLowerCase());\\n }\\n }\\n }\\n\\n // Run the test, or use the raw value if it's not a function\\n result = is(feature.fn, 'function') ? feature.fn() : feature.fn;\\n\\n // Set each of the names on the Modernizr object\\n for (nameIdx = 0; nameIdx < featureNames.length; nameIdx++) {\\n featureName = featureNames[nameIdx];\\n // Support dot properties as sub tests. We don't do checking to make sure\\n // that the implied parent tests have been added. You must call them in\\n // order (either in the test, or make the parent test a dependency).\\n //\\n // Cap it to TWO to make the logic simple and because who needs that kind of subtesting\\n // hashtag famous last words\\n featureNameSplit = featureName.split('.');\\n\\n if (featureNameSplit.length === 1) {\\n Modernizr[featureNameSplit[0]] = result;\\n } else {\\n // cast to a Boolean, if not one already or if it doesnt exist yet (like inputtypes)\\n if (!Modernizr[featureNameSplit[0]] || Modernizr[featureNameSplit[0]] && !(Modernizr[featureNameSplit[0]] instanceof Boolean)) {\\n Modernizr[featureNameSplit[0]] = new Boolean(Modernizr[featureNameSplit[0]]);\\n }\\n\\n Modernizr[featureNameSplit[0]][featureNameSplit[1]] = result;\\n }\\n\\n classes.push((result ? '' : 'no-') + featureNameSplit.join('-'));\\n }\\n }\\n }\\n }\\n ;\\n\\n /**\\n * docElement is a convenience wrapper to grab the root element of the document\\n *\\n * @access private\\n * @returns {HTMLElement|SVGElement} The root element of the document\\n */\\n var docElement = document.documentElement;\\n \\n\\n /**\\n * A convenience helper to check if the document we are running in is an SVG document\\n *\\n * @access private\\n * @returns {boolean}\\n */\\n var isSVG = docElement.nodeName.toLowerCase() === 'svg';\\n\\n \\n\\n /**\\n * setClasses takes an array of class names and adds them to the root element\\n *\\n * @access private\\n * @function setClasses\\n * @param {string[]} classes - Array of class names\\n */\\n // Pass in an and array of class names, e.g.:\\n // ['no-webp', 'borderradius', ...]\\n function setClasses(classes) {\\n var className = docElement.className;\\n var classPrefix = Modernizr._config.classPrefix || '';\\n\\n if (isSVG) {\\n className = className.baseVal;\\n }\\n\\n // Change \`no-js\` to \`js\` (independently of the \`enableClasses\` option)\\n // Handle classPrefix on this too\\n if (Modernizr._config.enableJSClass) {\\n var reJS = new RegExp('(^|\\\\\\\\s)' + classPrefix + 'no-js(\\\\\\\\s|$)');\\n className = className.replace(reJS, '$1' + classPrefix + 'js$2');\\n }\\n\\n if (Modernizr._config.enableClasses) {\\n // Add the new classes\\n if (classes.length > 0) {\\n className += ' ' + classPrefix + classes.join(' ' + classPrefix);\\n }\\n if (isSVG) {\\n docElement.className.baseVal = className;\\n } else {\\n docElement.className = className;\\n }\\n }\\n }\\n\\n ;\\n\\n /**\\n * If the browsers follow the spec, then they would expose vendor-specific styles as:\\n * elem.style.WebkitBorderRadius\\n * instead of something like the following (which is technically incorrect):\\n * elem.style.webkitBorderRadius\\n *\\n * WebKit ghosts their properties in lowercase but Opera & Moz do not.\\n * Microsoft uses a lowercase \`ms\` instead of the correct \`Ms\` in IE8+\\n * erik.eae.net/archives/2008/03/10/21.48.10/\\n *\\n * More here: github.com/Modernizr/Modernizr/issues/issue/21\\n *\\n * @access private\\n * @returns {string} The string representing the vendor-specific style properties\\n */\\n var omPrefixes = 'Moz O ms Webkit';\\n \\n\\n var cssomPrefixes = (ModernizrProto._config.usePrefixes ? omPrefixes.split(' ') : []);\\n ModernizrProto._cssomPrefixes = cssomPrefixes;\\n \\n\\n /**\\n * contains checks to see if a string contains another string\\n *\\n * @access private\\n * @function contains\\n * @param {string} str - The string we want to check for substrings\\n * @param {string} substr - The substring we want to search the first string for\\n * @returns {boolean} true if and only if the first string 'str' contains the second string 'substr'\\n */\\n function contains(str, substr) {\\n return !!~('' + str).indexOf(substr);\\n }\\n\\n ;\\n\\n /**\\n * createElement is a convenience wrapper around document.createElement. Since we\\n * use createElement all over the place, this allows for (slightly) smaller code\\n * as well as abstracting away issues with creating elements in contexts other than\\n * HTML documents (e.g. SVG documents).\\n *\\n * @access private\\n * @function createElement\\n * @returns {HTMLElement|SVGElement} An HTML or SVG element\\n */\\n function createElement() {\\n if (typeof document.createElement !== 'function') {\\n // This is the case in IE7, where the type of createElement is \\"object\\".\\n // For this reason, we cannot call apply() as Object is not a Function.\\n return document.createElement(arguments[0]);\\n } else if (isSVG) {\\n return document.createElementNS.call(document, 'http://www.w3.org/2000/svg', arguments[0]);\\n } else {\\n return document.createElement.apply(document, arguments);\\n }\\n }\\n\\n ;\\n\\n /**\\n * Create our \\"modernizr\\" element that we do most feature tests on.\\n *\\n * @access private\\n */\\n var modElem = {\\n elem: createElement('modernizr')\\n };\\n\\n // Clean up this element\\n Modernizr._q.push(function() {\\n delete modElem.elem;\\n });\\n\\n \\n\\n var mStyle = {\\n style: modElem.elem.style\\n };\\n\\n // kill ref for gc, must happen before mod.elem is removed, so we unshift on to\\n // the front of the queue.\\n Modernizr._q.unshift(function() {\\n delete mStyle.style;\\n });\\n\\n \\n\\n /**\\n * getBody returns the body of a document, or an element that can stand in for\\n * the body if a real body does not exist\\n *\\n * @access private\\n * @function getBody\\n * @returns {HTMLElement|SVGElement} Returns the real body of a document, or an\\n * artificially created element that stands in for the body\\n */\\n function getBody() {\\n // After page load injecting a fake body doesn't work so check if body exists\\n var body = document.body;\\n\\n if (!body) {\\n // Can't use the real body create a fake one.\\n body = createElement(isSVG ? 'svg' : 'body');\\n body.fake = true;\\n }\\n\\n return body;\\n }\\n\\n ;\\n\\n /**\\n * injectElementWithStyles injects an element with style element and some CSS rules\\n *\\n * @access private\\n * @function injectElementWithStyles\\n * @param {string} rule - String representing a css rule\\n * @param {Function} callback - A function that is used to test the injected element\\n * @param {number} [nodes] - An integer representing the number of additional nodes you want injected\\n * @param {string[]} [testnames] - An array of strings that are used as ids for the additional nodes\\n * @returns {boolean} the result of the specified callback test\\n */\\n function injectElementWithStyles(rule, callback, nodes, testnames) {\\n var mod = 'modernizr';\\n var style;\\n var ret;\\n var node;\\n var docOverflow;\\n var div = createElement('div');\\n var body = getBody();\\n\\n if (parseInt(nodes, 10)) {\\n // In order not to give false positives we create a node for each test\\n // This also allows the method to scale for unspecified uses\\n while (nodes--) {\\n node = createElement('div');\\n node.id = testnames ? testnames[nodes] : mod + (nodes + 1);\\n div.appendChild(node);\\n }\\n }\\n\\n style = createElement('style');\\n style.type = 'text/css';\\n style.id = 's' + mod;\\n\\n // IE6 will false positive on some tests due to the style element inside the test div somehow interfering offsetHeight, so insert it into body or fakebody.\\n // Opera will act all quirky when injecting elements in documentElement when page is served as xml, needs fakebody too. #270\\n (!body.fake ? div : body).appendChild(style);\\n body.appendChild(div);\\n\\n if (style.styleSheet) {\\n style.styleSheet.cssText = rule;\\n } else {\\n style.appendChild(document.createTextNode(rule));\\n }\\n div.id = mod;\\n\\n if (body.fake) {\\n //avoid crashing IE8, if background image is used\\n body.style.background = '';\\n //Safari 5.13/5.1.4 OSX stops loading if ::-webkit-scrollbar is used and scrollbars are visible\\n body.style.overflow = 'hidden';\\n docOverflow = docElement.style.overflow;\\n docElement.style.overflow = 'hidden';\\n docElement.appendChild(body);\\n }\\n\\n ret = callback(div, rule);\\n // If this is done after page load we don't want to remove the body so check if body exists\\n if (body.fake && body.parentNode) {\\n body.parentNode.removeChild(body);\\n docElement.style.overflow = docOverflow;\\n // Trigger layout so kinetic scrolling isn't disabled in iOS6+\\n // eslint-disable-next-line\\n docElement.offsetHeight;\\n } else {\\n div.parentNode.removeChild(div);\\n }\\n\\n return !!ret;\\n }\\n\\n ;\\n\\n /**\\n * domToCSS takes a camelCase string and converts it to hyphen-case\\n * e.g. boxSizing -> box-sizing\\n *\\n * @access private\\n * @function domToCSS\\n * @param {string} name - String name of camelCase prop we want to convert\\n * @returns {string} The hyphen-case version of the supplied name\\n */\\n function domToCSS(name) {\\n return name.replace(/([A-Z])/g, function(str, m1) {\\n return '-' + m1.toLowerCase();\\n }).replace(/^ms-/, '-ms-');\\n }\\n\\n ;\\n\\n\\n /**\\n * wrapper around getComputedStyle, to fix issues with Firefox returning null when\\n * called inside of a hidden iframe\\n *\\n * @access private\\n * @function computedStyle\\n * @param {HTMLElement|SVGElement} elem - The element we want to find the computed styles of\\n * @param {string|null} [pseudo] - An optional pseudo element selector (e.g. :before), of null if none\\n * @param {string} prop - A CSS property\\n * @returns {CSSStyleDeclaration} the value of the specified CSS property\\n */\\n function computedStyle(elem, pseudo, prop) {\\n var result;\\n\\n if ('getComputedStyle' in window) {\\n result = getComputedStyle.call(window, elem, pseudo);\\n var console = window.console;\\n\\n if (result !== null) {\\n if (prop) {\\n result = result.getPropertyValue(prop);\\n }\\n } else {\\n if (console) {\\n var method = console.error ? 'error' : 'log';\\n console[method].call(console, 'getComputedStyle returning null, its possible modernizr test results are inaccurate');\\n }\\n }\\n } else {\\n result = !pseudo && elem.currentStyle && elem.currentStyle[prop];\\n }\\n\\n return result;\\n }\\n\\n ;\\n\\n /**\\n * nativeTestProps allows for us to use native feature detection functionality if available.\\n * some prefixed form, or false, in the case of an unsupported rule\\n *\\n * @access private\\n * @function nativeTestProps\\n * @param {Array} props - An array of property names\\n * @param {string} value - A string representing the value we want to check via @supports\\n * @returns {boolean|undefined} A boolean when @supports exists, undefined otherwise\\n */\\n // Accepts a list of property names and a single value\\n // Returns \`undefined\` if native detection not available\\n function nativeTestProps(props, value) {\\n var i = props.length;\\n // Start with the JS API: https://www.w3.org/TR/css3-conditional/#the-css-interface\\n if ('CSS' in window && 'supports' in window.CSS) {\\n // Try every prefixed variant of the property\\n while (i--) {\\n if (window.CSS.supports(domToCSS(props[i]), value)) {\\n return true;\\n }\\n }\\n return false;\\n }\\n // Otherwise fall back to at-rule (for Opera 12.x)\\n else if ('CSSSupportsRule' in window) {\\n // Build a condition string for every prefixed variant\\n var conditionText = [];\\n while (i--) {\\n conditionText.push('(' + domToCSS(props[i]) + ':' + value + ')');\\n }\\n conditionText = conditionText.join(' or ');\\n return injectElementWithStyles('@supports (' + conditionText + ') { #modernizr { position: absolute; } }', function(node) {\\n return computedStyle(node, null, 'position') === 'absolute';\\n });\\n }\\n return undefined;\\n }\\n ;\\n\\n /**\\n * cssToDOM takes a hyphen-case string and converts it to camelCase\\n * e.g. box-sizing -> boxSizing\\n *\\n * @access private\\n * @function cssToDOM\\n * @param {string} name - String name of hyphen-case prop we want to convert\\n * @returns {string} The camelCase version of the supplied name\\n */\\n function cssToDOM(name) {\\n return name.replace(/([a-z])-([a-z])/g, function(str, m1, m2) {\\n return m1 + m2.toUpperCase();\\n }).replace(/^-/, '');\\n }\\n\\n ;\\n\\n // testProps is a generic CSS / DOM property test.\\n\\n // In testing support for a given CSS property, it's legit to test:\\n // \`elem.style[styleName] !== undefined\`\\n // If the property is supported it will return an empty string,\\n // if unsupported it will return undefined.\\n\\n // We'll take advantage of this quick test and skip setting a style\\n // on our modernizr element, but instead just testing undefined vs\\n // empty string.\\n\\n // Property names can be provided in either camelCase or hyphen-case.\\n\\n function testProps(props, prefixed, value, skipValueTest) {\\n skipValueTest = is(skipValueTest, 'undefined') ? false : skipValueTest;\\n\\n // Try native detect first\\n if (!is(value, 'undefined')) {\\n var result = nativeTestProps(props, value);\\n if (!is(result, 'undefined')) {\\n return result;\\n }\\n }\\n\\n // Otherwise do it properly\\n var afterInit, i, propsLength, prop, before;\\n\\n // If we don't have a style element, that means we're running async or after\\n // the core tests, so we'll need to create our own elements to use.\\n\\n // Inside of an SVG element, in certain browsers, the \`style\` element is only\\n // defined for valid tags. Therefore, if \`modernizr\` does not have one, we\\n // fall back to a less used element and hope for the best.\\n // For strict XHTML browsers the hardly used samp element is used.\\n var elems = ['modernizr', 'tspan', 'samp'];\\n while (!mStyle.style && elems.length) {\\n afterInit = true;\\n mStyle.modElem = createElement(elems.shift());\\n mStyle.style = mStyle.modElem.style;\\n }\\n\\n // Delete the objects if we created them.\\n function cleanElems() {\\n if (afterInit) {\\n delete mStyle.style;\\n delete mStyle.modElem;\\n }\\n }\\n\\n propsLength = props.length;\\n for (i = 0; i < propsLength; i++) {\\n prop = props[i];\\n before = mStyle.style[prop];\\n\\n if (contains(prop, '-')) {\\n prop = cssToDOM(prop);\\n }\\n\\n if (mStyle.style[prop] !== undefined) {\\n\\n // If value to test has been passed in, do a set-and-check test.\\n // 0 (integer) is a valid property value, so check that \`value\` isn't\\n // undefined, rather than just checking it's truthy.\\n if (!skipValueTest && !is(value, 'undefined')) {\\n\\n // Needs a try catch block because of old IE. This is slow, but will\\n // be avoided in most cases because \`skipValueTest\` will be used.\\n try {\\n mStyle.style[prop] = value;\\n } catch (e) {}\\n\\n // If the property value has changed, we assume the value used is\\n // supported. If \`value\` is empty string, it'll fail here (because\\n // it hasn't changed), which matches how browsers have implemented\\n // CSS.supports()\\n if (mStyle.style[prop] !== before) {\\n cleanElems();\\n return prefixed === 'pfx' ? prop : true;\\n }\\n }\\n // Otherwise just return true, or the property name if this is a\\n // \`prefixed()\` call\\n else {\\n cleanElems();\\n return prefixed === 'pfx' ? prop : true;\\n }\\n }\\n }\\n cleanElems();\\n return false;\\n }\\n\\n ;\\n\\n /**\\n * List of JavaScript DOM values used for tests\\n *\\n * @memberOf Modernizr\\n * @name Modernizr._domPrefixes\\n * @optionName Modernizr._domPrefixes\\n * @optionProp domPrefixes\\n * @access public\\n * @example\\n *\\n * Modernizr._domPrefixes is exactly the same as [_prefixes](#modernizr-_prefixes), but rather\\n * than hyphen-case properties, all properties are their Capitalized variant\\n *\\n * \`\`\`js\\n * Modernizr._domPrefixes === [ \\"Moz\\", \\"O\\", \\"ms\\", \\"Webkit\\" ];\\n * \`\`\`\\n */\\n var domPrefixes = (ModernizrProto._config.usePrefixes ? omPrefixes.toLowerCase().split(' ') : []);\\n ModernizrProto._domPrefixes = domPrefixes;\\n \\n\\n /**\\n * fnBind is a super small [bind](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind) polyfill.\\n *\\n * @access private\\n * @function fnBind\\n * @param {Function} fn - a function you want to change \`this\` reference to\\n * @param {object} that - the \`this\` you want to call the function with\\n * @returns {Function} The wrapped version of the supplied function\\n */\\n function fnBind(fn, that) {\\n return function() {\\n return fn.apply(that, arguments);\\n };\\n }\\n\\n ;\\n\\n /**\\n * testDOMProps is a generic DOM property test; if a browser supports\\n * a certain property, it won't return undefined for it.\\n *\\n * @access private\\n * @function testDOMProps\\n * @param {Array} props - An array of properties to test for\\n * @param {object} obj - An object or Element you want to use to test the parameters again\\n * @param {boolean|object} elem - An Element to bind the property lookup again. Use \`false\` to prevent the check\\n * @returns {boolean|*} returns \`false\` if the prop is unsupported, otherwise the value that is supported\\n */\\n function testDOMProps(props, obj, elem) {\\n var item;\\n\\n for (var i in props) {\\n if (props[i] in obj) {\\n\\n // return the property name as a string\\n if (elem === false) {\\n return props[i];\\n }\\n\\n item = obj[props[i]];\\n\\n // let's bind a function\\n if (is(item, 'function')) {\\n // bind to obj unless overridden\\n return fnBind(item, elem || obj);\\n }\\n\\n // return the unbound function or obj or value\\n return item;\\n }\\n }\\n return false;\\n }\\n\\n ;\\n\\n /**\\n * testPropsAll tests a list of DOM properties we want to check against.\\n * We specify literally ALL possible (known and/or likely) properties on\\n * the element including the non-vendor prefixed one, for forward-\\n * compatibility.\\n *\\n * @access private\\n * @function testPropsAll\\n * @param {string} prop - A string of the property to test for\\n * @param {string|object} [prefixed] - An object to check the prefixed properties on. Use a string to skip\\n * @param {HTMLElement|SVGElement} [elem] - An element used to test the property and value against\\n * @param {string} [value] - A string of a css value\\n * @param {boolean} [skipValueTest] - An boolean representing if you want to test if value sticks when set\\n * @returns {string|boolean} returns the string version of the property, or \`false\` if it is unsupported\\n */\\n function testPropsAll(prop, prefixed, elem, value, skipValueTest) {\\n\\n var ucProp = prop.charAt(0).toUpperCase() + prop.slice(1),\\n props = (prop + ' ' + cssomPrefixes.join(ucProp + ' ') + ucProp).split(' ');\\n\\n // did they call .prefixed('boxSizing') or are we just testing a prop?\\n if (is(prefixed, 'string') || is(prefixed, 'undefined')) {\\n return testProps(props, prefixed, value, skipValueTest);\\n\\n // otherwise, they called .prefixed('requestAnimationFrame', window[, elem])\\n } else {\\n props = (prop + ' ' + (domPrefixes).join(ucProp + ' ') + ucProp).split(' ');\\n return testDOMProps(props, prefixed, elem);\\n }\\n }\\n\\n // Modernizr.testAllProps() investigates whether a given style property,\\n // or any of its vendor-prefixed variants, is recognized\\n //\\n // Note that the property names must be provided in the camelCase variant.\\n // Modernizr.testAllProps('boxSizing')\\n ModernizrProto.testAllProps = testPropsAll;\\n\\n \\n\\n /**\\n * testAllProps determines whether a given CSS property is supported in the browser\\n *\\n * @memberOf Modernizr\\n * @name Modernizr.testAllProps\\n * @optionName Modernizr.testAllProps()\\n * @optionProp testAllProps\\n * @access public\\n * @function testAllProps\\n * @param {string} prop - String naming the property to test (either camelCase or hyphen-case)\\n * @param {string} [value] - String of the value to test\\n * @param {boolean} [skipValueTest=false] - Whether to skip testing that the value is supported when using non-native detection\\n * @returns {string|boolean} returns the string version of the property, or \`false\` if it is unsupported\\n * @example\\n *\\n * testAllProps determines whether a given CSS property, in some prefixed form,\\n * is supported by the browser.\\n *\\n * \`\`\`js\\n * testAllProps('boxSizing') // true\\n * \`\`\`\\n *\\n * It can optionally be given a CSS value in string form to test if a property\\n * value is valid\\n *\\n * \`\`\`js\\n * testAllProps('display', 'block') // true\\n * testAllProps('display', 'penguin') // false\\n * \`\`\`\\n *\\n * A boolean can be passed as a third parameter to skip the value check when\\n * native detection (@supports) isn't available.\\n *\\n * \`\`\`js\\n * testAllProps('shapeOutside', 'content-box', true);\\n * \`\`\`\\n */\\n function testAllProps(prop, value, skipValueTest) {\\n return testPropsAll(prop, undefined, undefined, value, skipValueTest);\\n }\\n\\n ModernizrProto.testAllProps = testAllProps;\\n\\n \\n/*!\\n{\\n \\"name\\": \\"Flexbox\\",\\n \\"property\\": \\"flexbox\\",\\n \\"caniuse\\": \\"flexbox\\",\\n \\"tags\\": [\\"css\\"],\\n \\"notes\\": [{\\n \\"name\\": \\"The _new_ flexbox\\",\\n \\"href\\": \\"https://www.w3.org/TR/css-flexbox-1/\\"\\n }],\\n \\"warnings\\": [\\n \\"A \`true\` result for this detect does not imply that the \`flex-wrap\` property is supported; see the \`flexwrap\` detect.\\"\\n ]\\n}\\n!*/\\n/* DOC\\nDetects support for the Flexible Box Layout model, a.k.a. Flexbox, which allows easy manipulation of layout order and sizing within a container.\\n*/\\n\\n Modernizr.addTest('flexbox', testAllProps('flexBasis', '1px', true));\\n\\n/*!\\n{\\n \\"name\\": \\"ES6 Promises\\",\\n \\"property\\": \\"promises\\",\\n \\"caniuse\\": \\"promises\\",\\n \\"polyfills\\": [\\"es6promises\\"],\\n \\"authors\\": [\\"Krister Kari\\", \\"Jake Archibald\\"],\\n \\"tags\\": [\\"es6\\"],\\n \\"notes\\": [{\\n \\"name\\": \\"The ES6 promises spec\\",\\n \\"href\\": \\"https://github.com/domenic/promises-unwrapping\\"\\n }, {\\n \\"name\\": \\"Chromium dashboard - ES6 Promises\\",\\n \\"href\\": \\"https://www.chromestatus.com/features/5681726336532480\\"\\n }, {\\n \\"name\\": \\"JavaScript Promises: an Introduction\\",\\n \\"href\\": \\"https://developers.google.com/web/fundamentals/primers/promises/\\"\\n }]\\n}\\n!*/\\n/* DOC\\nCheck if browser implements ECMAScript 6 Promises per specification.\\n*/\\n\\n Modernizr.addTest('promises', function() {\\n return 'Promise' in window &&\\n // Some of these methods are missing from\\n // Firefox/Chrome experimental implementations\\n 'resolve' in window.Promise &&\\n 'reject' in window.Promise &&\\n 'all' in window.Promise &&\\n 'race' in window.Promise &&\\n // Older version of the spec had a resolver object\\n // as the arg rather than a function\\n (function() {\\n var resolve;\\n new window.Promise(function(r) { resolve = r; });\\n return typeof resolve === 'function';\\n }());\\n });\\n\\n/*!\\n{\\n \\"name\\": \\"ServiceWorker API\\",\\n \\"property\\": \\"serviceworker\\",\\n \\"caniuse\\": \\"serviceworkers\\",\\n \\"notes\\": [{\\n \\"name\\": \\"ServiceWorkers Explained\\",\\n \\"href\\": \\"https://github.com/slightlyoff/ServiceWorker/blob/master/explainer.md\\"\\n }]\\n}\\n!*/\\n/* DOC\\nServiceWorkers (formerly Navigation Controllers) are a way to persistently cache resources to built apps that work better offline.\\n*/\\n\\n Modernizr.addTest('serviceworker', 'serviceWorker' in navigator);\\n\\n\\n // Run each test\\n testRunner();\\n\\n // Remove the \\"no-js\\" class if it exists\\n setClasses(classes);\\n\\n delete ModernizrProto.addTest;\\n delete ModernizrProto.addAsyncTest;\\n\\n // Run the things that are supposed to run after the tests\\n for (var i = 0; i < Modernizr._q.length; i++) {\\n Modernizr._q[i]();\\n }\\n\\n // Leak Modernizr namespace\\n scriptGlobalObject.Modernizr = Modernizr;\\n\\n\\n;\\n\\n})(window, window, document);\\n modernizr = window.Modernizr; if (hadGlobal) { window.Modernizr = oldGlobal; } else { delete window.Modernizr; } export default modernizr;",
224 | "map": null,
225 | "meta": null,
226 | "dependencies": [
227 | "test/fixtures/presets/modernizr.js"
228 | ],
229 | "contextDependencies": [],
230 | "buildDependencies": []
231 | }"
232 | `;
233 |
234 | exports[`loader should pass on the code from the presets/modernizr fixture: warnings 1`] = `[]`;
235 |
236 | exports[`loader should pass on the code from the simple fixture without options: errors 1`] = `[]`;
237 |
238 | exports[`loader should pass on the code from the simple fixture without options: result 1`] = `
239 | "{
240 | "content": "module.exports = \\"hello world\\";",
241 | "map": {
242 | "isASourceMap": true
243 | },
244 | "meta": {
245 | "isAnAst": true
246 | },
247 | "dependencies": [
248 | "test/fixtures/simple.js"
249 | ],
250 | "contextDependencies": [],
251 | "buildDependencies": []
252 | }"
253 | `;
254 |
255 | exports[`loader should pass on the code from the simple fixture without options: warnings 1`] = `[]`;
256 |
257 | exports[`loader should pass on the code from the simple fixture: errors 1`] = `[]`;
258 |
259 | exports[`loader should pass on the code from the simple fixture: result 1`] = `
260 | "{
261 | "content": "module.exports = \\"hello world\\";",
262 | "map": {
263 | "isASourceMap": true
264 | },
265 | "meta": {
266 | "isAnAst": true
267 | },
268 | "dependencies": [
269 | "test/fixtures/simple.js"
270 | ],
271 | "contextDependencies": [],
272 | "buildDependencies": []
273 | }"
274 | `;
275 |
276 | exports[`loader should pass on the code from the simple fixture: warnings 1`] = `[]`;
277 |
278 | exports[`loader should recognize modules produced by babel: errors 1`] = `[]`;
279 |
280 | exports[`loader should recognize modules produced by babel: result 1`] = `
281 | "{
282 | "content": "module.exports = \\"hello world\\";",
283 | "map": null,
284 | "meta": null,
285 | "dependencies": [
286 | "test/fixtures/babel.js"
287 | ],
288 | "contextDependencies": [],
289 | "buildDependencies": []
290 | }"
291 | `;
292 |
293 | exports[`loader should recognize modules produced by babel: warnings 1`] = `[]`;
294 |
295 | exports[`loader should report require() errors with a useful stacktrace: errors 1`] = `
296 | [
297 | "ModuleBuildError: Module build failed (from \`replaced original path\`):
298 | Error: Unable to execute "/test/fixtures/error-require.js": Error: This is a typical require() error",
299 | ]
300 | `;
301 |
302 | exports[`loader should report require() errors with a useful stacktrace: warnings 1`] = `[]`;
303 |
304 | exports[`loader should throw a useful error message if the exported function returns a wrong object (async): errors 1`] = `
305 | [
306 | "ModuleBuildError: Module build failed (from \`replaced original path\`):
307 | Error: The returned result of module "/test/fixtures/error-return-async-wrong-obj.js" is not an object with a "code" property",
308 | ]
309 | `;
310 |
311 | exports[`loader should throw a useful error message if the exported function returns a wrong object (async): warnings 1`] = `[]`;
312 |
313 | exports[`loader should throw a useful error message if the exported function returns a wrong object (sync): errors 1`] = `
314 | [
315 | "ModuleBuildError: Module build failed (from \`replaced original path\`):
316 | Error: The returned result of module "/test/fixtures/error-return-sync-wrong-obj.js" is not an object with a "code" property",
317 | ]
318 | `;
319 |
320 | exports[`loader should throw a useful error message if the exported function returns a wrong object (sync): warnings 1`] = `[]`;
321 |
322 | exports[`loader should throw a useful error message if the exported function returns code that is neither a string nor an instanceof Buffer (async): errors 1`] = `
323 | [
324 | "ModuleBuildError: Module build failed (from \`replaced original path\`):
325 | Error: The returned code of module "/test/fixtures/error-return-async-invalid-code.js" is neither a string nor an instance of Buffer",
326 | ]
327 | `;
328 |
329 | exports[`loader should throw a useful error message if the exported function returns code that is neither a string nor an instanceof Buffer (async): warnings 1`] = `[]`;
330 |
331 | exports[`loader should throw a useful error message if the exported function returns code that is neither a string nor an instanceof Buffer (sync): errors 1`] = `
332 | [
333 | "ModuleBuildError: Module build failed (from \`replaced original path\`):
334 | Error: The returned code of module "/test/fixtures/error-return-sync-invalid-code.js" is neither a string nor an instance of Buffer",
335 | ]
336 | `;
337 |
338 | exports[`loader should throw a useful error message if the exported function returns code that is neither a string nor an instanceof Buffer (sync): warnings 1`] = `[]`;
339 |
340 | exports[`loader should throw a useful error message if the module exports not a function: errors 1`] = `
341 | [
342 | "ModuleBuildError: Module build failed (from \`replaced original path\`):
343 | Error: Module "/test/fixtures/error-export-null.js" does not export a function as default",
344 | ]
345 | `;
346 |
347 | exports[`loader should throw a useful error message if the module exports not a function: warnings 1`] = `[]`;
348 |
349 | exports[`loader should work the same if a promise is returned #2: errors 1`] = `[]`;
350 |
351 | exports[`loader should work the same if a promise is returned #2: result 1`] = `
352 | "{
353 | "content": "module.exports = \\"hello world\\";",
354 | "map": {
355 | "isASourceMap": true
356 | },
357 | "meta": {
358 | "isAnAst": true
359 | },
360 | "dependencies": [
361 | "test/fixtures/promise-compex.js"
362 | ],
363 | "contextDependencies": [],
364 | "buildDependencies": []
365 | }"
366 | `;
367 |
368 | exports[`loader should work the same if a promise is returned #2: warnings 1`] = `[]`;
369 |
370 | exports[`loader should work the same if a promise is returned: errors 1`] = `[]`;
371 |
372 | exports[`loader should work the same if a promise is returned: result 1`] = `
373 | "{
374 | "content": "module.exports = \\"hello world\\";",
375 | "map": {
376 | "isASourceMap": true
377 | },
378 | "meta": {
379 | "isAnAst": true
380 | },
381 | "dependencies": [
382 | "test/fixtures/promise.js"
383 | ],
384 | "contextDependencies": [],
385 | "buildDependencies": []
386 | }"
387 | `;
388 |
389 | exports[`loader should work the same if a promise is returned: warnings 1`] = `[]`;
390 |
391 | exports[`loader should work with ES modules code: errors 1`] = `[]`;
392 |
393 | exports[`loader should work with ES modules code: result 1`] = `
394 | "{
395 | "content": "module.exports = \\"hello world\\";",
396 | "map": {
397 | "isASourceMap": true
398 | },
399 | "meta": {
400 | "isAnAst": true
401 | },
402 | "dependencies": [
403 | "test/fixtures/code-commonjs.js"
404 | ],
405 | "contextDependencies": [],
406 | "buildDependencies": []
407 | }"
408 | `;
409 |
410 | exports[`loader should work with ES modules code: warnings 1`] = `[]`;
411 |
412 | exports[`loader should work with async function: errors 1`] = `[]`;
413 |
414 | exports[`loader should work with async function: result 1`] = `
415 | "{
416 | "content": "module.exports = \\"hello world\\";",
417 | "map": {
418 | "isASourceMap": true
419 | },
420 | "meta": {
421 | "isAnAst": true
422 | },
423 | "dependencies": [
424 | "test/fixtures/async-function.js"
425 | ],
426 | "contextDependencies": [],
427 | "buildDependencies": []
428 | }"
429 | `;
430 |
431 | exports[`loader should work with async function: warnings 1`] = `[]`;
432 |
433 | exports[`loader should work with commonjs code: errors 1`] = `[]`;
434 |
435 | exports[`loader should work with commonjs code: result 1`] = `
436 | "{
437 | "content": "export default \\"hello world\\";",
438 | "map": {
439 | "isASourceMap": true
440 | },
441 | "meta": {
442 | "isAnAst": true
443 | },
444 | "dependencies": [
445 | "test/fixtures/code-es.js"
446 | ],
447 | "contextDependencies": [],
448 | "buildDependencies": []
449 | }"
450 | `;
451 |
452 | exports[`loader should work with commonjs code: warnings 1`] = `[]`;
453 |
--------------------------------------------------------------------------------
/test/cjs.test.js:
--------------------------------------------------------------------------------
1 | import src from "../src";
2 | import cjs from "../src/cjs";
3 |
4 | describe("CJS", () => {
5 | it("should export loader", () => {
6 | expect(cjs).toEqual(src);
7 | });
8 |
9 | it('should export "raw" flag', () => {
10 | expect(cjs.raw).toBeUndefined();
11 | });
12 | });
13 |
--------------------------------------------------------------------------------
/test/executableFile.test.js:
--------------------------------------------------------------------------------
1 | import path from "path";
2 |
3 | import { getCompiler, compile, readAsset, normalizeErrors } from "./helpers";
4 |
5 | describe("executableFile option", () => {
6 | it("should work with commonjs format", async () => {
7 | const compiler = getCompiler(
8 | "executableFileEntry.js",
9 | {},
10 | {
11 | module: {
12 | rules: [
13 | {
14 | test: /\.(json)$/i,
15 | rules: [
16 | {
17 | loader: require.resolve("./helpers/helperLoader.js"),
18 | },
19 | {
20 | loader: require.resolve("../src"),
21 | options: {
22 | executableFile: path.resolve(
23 | __dirname,
24 | "fixtures",
25 | "executableFile.js",
26 | ),
27 | },
28 | },
29 | ],
30 | },
31 | {
32 | test: /\.json$/i,
33 | type: "asset/resource",
34 | },
35 | ],
36 | },
37 | },
38 | );
39 | const stats = await compile(compiler);
40 |
41 | expect(readAsset("val-loader.js", compiler, stats)).toMatchSnapshot(
42 | "result",
43 | );
44 | expect(normalizeErrors(stats.compilation.warnings)).toMatchSnapshot(
45 | "warnings",
46 | );
47 | expect(normalizeErrors(stats.compilation.errors)).toMatchSnapshot("errors");
48 | });
49 |
50 | // TODO jest have not good support for ES modules for testing it, tested manually
51 | it.skip("should work with ES modules format", async () => {
52 | const compiler = getCompiler(
53 | "executableFileEntry.js",
54 | {},
55 | {
56 | module: {
57 | rules: [
58 | {
59 | test: /\.(json)$/i,
60 | rules: [
61 | {
62 | loader: require.resolve("./helpers/helperLoader.js"),
63 | },
64 | {
65 | loader: require.resolve("../src"),
66 | options: {
67 | executableFile: path.resolve(
68 | __dirname,
69 | "fixtures",
70 | "executableFileES.mjs",
71 | ),
72 | },
73 | },
74 | ],
75 | },
76 | {
77 | test: /\.json$/i,
78 | type: "asset/resource",
79 | },
80 | ],
81 | },
82 | },
83 | );
84 | const stats = await compile(compiler);
85 |
86 | expect(readAsset("val-loader.js", compiler, stats)).toMatchSnapshot(
87 | "result",
88 | );
89 | expect(normalizeErrors(stats.compilation.warnings)).toMatchSnapshot(
90 | "warnings",
91 | );
92 | expect(normalizeErrors(stats.compilation.errors)).toMatchSnapshot("errors");
93 | });
94 |
95 | it("should emit error", async () => {
96 | const compiler = getCompiler(
97 | "executableFileEntry.js",
98 | {},
99 | {
100 | module: {
101 | rules: [
102 | {
103 | test: /\.(json)$/i,
104 | rules: [
105 | {
106 | loader: require.resolve("./helpers/helperLoader.js"),
107 | },
108 | {
109 | loader: require.resolve("../src"),
110 | options: {
111 | executableFile: path.resolve(
112 | __dirname,
113 | "fixtures",
114 | "error-require.js",
115 | ),
116 | },
117 | },
118 | ],
119 | },
120 | {
121 | test: /\.json$/i,
122 | type: "asset/resource",
123 | },
124 | ],
125 | },
126 | },
127 | );
128 | const stats = await compile(compiler);
129 |
130 | expect(normalizeErrors(stats.compilation.warnings)).toMatchSnapshot(
131 | "warnings",
132 | );
133 | expect(normalizeErrors(stats.compilation.errors)).toMatchSnapshot("errors");
134 | });
135 | });
136 |
--------------------------------------------------------------------------------
/test/fixtures/args.js:
--------------------------------------------------------------------------------
1 | function args(options) {
2 | return {
3 | code: 'module.exports = "hello world";',
4 | // We use the ast property because it is not validated
5 | ast: [options],
6 | };
7 | }
8 |
9 | module.exports = args;
10 |
--------------------------------------------------------------------------------
/test/fixtures/async-function.js:
--------------------------------------------------------------------------------
1 | async function simple() {
2 | return {
3 | code: 'module.exports = "hello world";',
4 | sourceMap: { isASourceMap: true },
5 | ast: { isAnAst: true },
6 | };
7 | }
8 |
9 | module.exports = simple;
10 |
--------------------------------------------------------------------------------
/test/fixtures/babel.js:
--------------------------------------------------------------------------------
1 | function babel() {
2 | return {
3 | code: 'module.exports = "hello world";',
4 | };
5 | }
6 |
7 | module.exports = {
8 | default: babel,
9 | };
10 |
--------------------------------------------------------------------------------
/test/fixtures/buffer.js:
--------------------------------------------------------------------------------
1 | function buffer() {
2 | return {
3 | code: Buffer.from('module.exports = "hello world";'),
4 | sourceMap: { isASourceMap: true },
5 | ast: { isAnAst: true },
6 | };
7 | }
8 |
9 | module.exports = buffer;
10 |
--------------------------------------------------------------------------------
/test/fixtures/cacheable.js:
--------------------------------------------------------------------------------
1 | function cacheable() {
2 | return {
3 | cacheable: true,
4 | code: 'module.exports = "hello world";',
5 | };
6 | }
7 |
8 | module.exports = cacheable;
9 |
--------------------------------------------------------------------------------
/test/fixtures/code-commonjs.js:
--------------------------------------------------------------------------------
1 | function codeES() {
2 | return {
3 | code: 'module.exports = "hello world";',
4 | sourceMap: { isASourceMap: true },
5 | ast: { isAnAst: true },
6 | };
7 | }
8 |
9 | module.exports = codeES;
10 |
--------------------------------------------------------------------------------
/test/fixtures/code-es.js:
--------------------------------------------------------------------------------
1 | function codeES() {
2 | return {
3 | code: 'export default "hello world";',
4 | sourceMap: { isASourceMap: true },
5 | ast: { isAnAst: true },
6 | };
7 | }
8 |
9 | module.exports = codeES;
10 |
--------------------------------------------------------------------------------
/test/fixtures/data.json:
--------------------------------------------------------------------------------
1 | {
2 | "years": "10"
3 | }
4 |
--------------------------------------------------------------------------------
/test/fixtures/dependencies-via-context.js:
--------------------------------------------------------------------------------
1 | function dependencies(options, loaderContext) {
2 | loaderContext.addDependency(require.resolve('./args.js'));
3 | loaderContext.addDependency(require.resolve('./simple.js'));
4 | loaderContext.addBuildDependency(require.resolve('./args.js'));
5 | loaderContext.addBuildDependency(require.resolve('./simple.js'));
6 | loaderContext.addBuildDependency(__dirname);
7 | loaderContext.addContextDependency(__dirname);
8 |
9 | return {
10 | code: 'module.exports = "hello world";',
11 | };
12 | }
13 |
14 | module.exports = dependencies;
15 |
--------------------------------------------------------------------------------
/test/fixtures/dependencies.js:
--------------------------------------------------------------------------------
1 | function dependencies() {
2 | return {
3 | dependencies: [
4 | require.resolve('./args.js'),
5 | require.resolve('./simple.js'),
6 | ],
7 | buildDependencies: [
8 | require.resolve('./args.js'),
9 | require.resolve('./simple.js'),
10 | ],
11 | contextDependencies: [__dirname],
12 | code: 'module.exports = "hello world";',
13 | };
14 | }
15 |
16 | module.exports = dependencies;
17 |
--------------------------------------------------------------------------------
/test/fixtures/error-call-async.js:
--------------------------------------------------------------------------------
1 | function errorCallAsync() {
2 | return Promise.reject(
3 | new Error('Calling the function failed asynchronously')
4 | );
5 | }
6 |
7 | module.exports = errorCallAsync;
8 |
--------------------------------------------------------------------------------
/test/fixtures/error-call-sync.js:
--------------------------------------------------------------------------------
1 | function errorCallSync() {
2 | throw new Error('Calling the function failed');
3 | }
4 |
5 | module.exports = errorCallSync;
6 |
--------------------------------------------------------------------------------
/test/fixtures/error-emitted-with-dependencies.js:
--------------------------------------------------------------------------------
1 | function errorEmittedWithDependencies(options, loaderOptions) {
2 | loaderOptions.emitError(new Error('Calling the function failed'));
3 |
4 | return {
5 | dependencies: [
6 | require.resolve('./args.js'),
7 | require.resolve('./simple.js'),
8 | ],
9 | contextDependencies: [__dirname],
10 | code: 'module.exports = "hello world";',
11 | };
12 | }
13 |
14 | module.exports = errorEmittedWithDependencies;
15 |
--------------------------------------------------------------------------------
/test/fixtures/error-export-null.js:
--------------------------------------------------------------------------------
1 | module.exports = null;
2 |
--------------------------------------------------------------------------------
/test/fixtures/error-require.js:
--------------------------------------------------------------------------------
1 | throw new Error('This is a typical require() error');
2 |
--------------------------------------------------------------------------------
/test/fixtures/error-return-async-invalid-code.js:
--------------------------------------------------------------------------------
1 | function errorReturnInvalidCode() {
2 | return Promise.resolve({
3 | code: null,
4 | });
5 | }
6 |
7 | module.exports = errorReturnInvalidCode;
8 |
--------------------------------------------------------------------------------
/test/fixtures/error-return-async-wrong-obj.js:
--------------------------------------------------------------------------------
1 | function errorReturnWrongObj() {
2 | return Promise.resolve(null);
3 | }
4 |
5 | module.exports = errorReturnWrongObj;
6 |
--------------------------------------------------------------------------------
/test/fixtures/error-return-sync-invalid-code.js:
--------------------------------------------------------------------------------
1 | function errorReturnInvalidCode() {
2 | return {
3 | code: null,
4 | };
5 | }
6 |
7 | module.exports = errorReturnInvalidCode;
8 |
--------------------------------------------------------------------------------
/test/fixtures/error-return-sync-wrong-obj.js:
--------------------------------------------------------------------------------
1 | function errorReturnWrongObj() {
2 | return null;
3 | }
4 |
5 | module.exports = errorReturnWrongObj;
6 |
--------------------------------------------------------------------------------
/test/fixtures/executableFile.js:
--------------------------------------------------------------------------------
1 | module.exports = function yearsInMs(options, loaderContext, content) {
2 | const {years} = JSON.parse(content);
3 | const value = years * 365 * 24 * 60 * 60 * 1000;
4 |
5 | return {
6 | cacheable: true,
7 | code: "module.exports = " + value,
8 | };
9 | };
10 |
--------------------------------------------------------------------------------
/test/fixtures/executableFileES.mjs:
--------------------------------------------------------------------------------
1 | export default function yearsInMs(options, loaderContext, content) {
2 | const {years} = JSON.parse(content);
3 | const value = years * 365 * 24 * 60 * 60 * 1000;
4 |
5 | return {
6 | cacheable: true,
7 | code: "export default " + value,
8 | };
9 | };
10 |
--------------------------------------------------------------------------------
/test/fixtures/executableFileEntry.js:
--------------------------------------------------------------------------------
1 | const data = require('./data.json');
2 |
3 | module.exports = {data};
4 |
--------------------------------------------------------------------------------
/test/fixtures/module-parent.js:
--------------------------------------------------------------------------------
1 | function simple() {
2 | return {
3 | code: 'module.exports = "hello world";',
4 | sourceMap: { isASourceMap: true },
5 | ast: {
6 | isAnAst: true,
7 | hasParent: Boolean(module.parent)
8 | },
9 | };
10 | }
11 |
12 | module.exports = simple;
13 |
--------------------------------------------------------------------------------
/test/fixtures/presets/figlet.js:
--------------------------------------------------------------------------------
1 | const figlet = require("figlet");
2 |
3 | function wrapOutput(output, config) {
4 | let figletOutput = "";
5 |
6 | if (config.textBefore) {
7 | figletOutput += encodeURI(`${config.textBefore}\n`);
8 | }
9 |
10 | output.split("\n").forEach(line => {
11 | figletOutput += encodeURI(`${line}\n`);
12 | });
13 |
14 | if (config.textAfter) {
15 | figletOutput += encodeURI(`${config.textAfter}\n`);
16 | }
17 |
18 | return `module.exports = decodeURI("${figletOutput}");`;
19 | }
20 |
21 | module.exports = function (options) {
22 | const defaultConfig = {
23 | fontOptions: {
24 | font: "ANSI Shadow",
25 | horizontalLayout: "default",
26 | kerning: "default",
27 | verticalLayout: "default"
28 | },
29 | text: "FIGLET-LOADER",
30 | textAfter: null,
31 | textBefore: null
32 | };
33 |
34 | const config = Object.assign({}, defaultConfig, options);
35 |
36 | return new Promise(function(resolve, reject) {
37 | figlet.text(config.text, config.fontOptions, (error, output) => {
38 | if (error) {
39 | return reject(error)
40 | }
41 |
42 | resolve({
43 | code: 'module.exports = ' + wrapOutput(output, config)
44 | });
45 | });
46 | });
47 | }
48 |
--------------------------------------------------------------------------------
/test/fixtures/presets/modernizr.js:
--------------------------------------------------------------------------------
1 | const modernizr = require("modernizr");
2 |
3 | module.exports = function(options) {
4 | return new Promise(function(resolve) {
5 | // It is impossible to throw an error because modernizr causes the process.exit(1)
6 | modernizr.build(options, function(output) {
7 | resolve({
8 | cacheable: true,
9 | code: `var modernizr; var hadGlobal = 'Modernizr' in window; var oldGlobal = window.Modernizr; ${output} modernizr = window.Modernizr; if (hadGlobal) { window.Modernizr = oldGlobal; } else { delete window.Modernizr; } export default modernizr;`
10 | });
11 | });
12 | });
13 | };
14 |
--------------------------------------------------------------------------------
/test/fixtures/promise-compex.js:
--------------------------------------------------------------------------------
1 | function promise() {
2 | return new Promise((resolve) => {
3 | setTimeout(() => {
4 | resolve({
5 | code: 'module.exports = "hello world";',
6 | sourceMap: { isASourceMap: true },
7 | ast: { isAnAst: true },
8 | })
9 | }, 100)
10 | });
11 | }
12 |
13 | module.exports = promise;
14 |
--------------------------------------------------------------------------------
/test/fixtures/promise.js:
--------------------------------------------------------------------------------
1 | function promise() {
2 | return Promise.resolve({
3 | cacheable: true,
4 | code: 'module.exports = "hello world";',
5 | sourceMap: { isASourceMap: true },
6 | ast: { isAnAst: true },
7 | });
8 | }
9 |
10 | module.exports = promise;
11 |
--------------------------------------------------------------------------------
/test/fixtures/simple.js:
--------------------------------------------------------------------------------
1 | function simple() {
2 | return {
3 | code: 'module.exports = "hello world";',
4 | sourceMap: { isASourceMap: true },
5 | ast: { isAnAst: true },
6 | };
7 | }
8 |
9 | module.exports = simple;
10 |
--------------------------------------------------------------------------------
/test/helpers/compile.js:
--------------------------------------------------------------------------------
1 | export default (compiler) =>
2 | new Promise((resolve, reject) => {
3 | compiler.run((error, stats) => {
4 | if (error) {
5 | return reject(error);
6 | }
7 |
8 | return resolve(stats);
9 | });
10 | });
11 |
--------------------------------------------------------------------------------
/test/helpers/execute.js:
--------------------------------------------------------------------------------
1 | import Module from "module";
2 | import path from "path";
3 |
4 | const parentModule = module;
5 |
6 | export default (code) => {
7 | const resource = "test.js";
8 | const module = new Module(resource, parentModule);
9 | // eslint-disable-next-line no-underscore-dangle
10 | module.paths = Module._nodeModulePaths(
11 | path.resolve(__dirname, "../fixtures"),
12 | );
13 | module.filename = resource;
14 |
15 | // eslint-disable-next-line no-underscore-dangle
16 | module._compile(
17 | `let __export__;${code};module.exports = __export__;`,
18 | resource,
19 | );
20 |
21 | return module.exports;
22 | };
23 |
--------------------------------------------------------------------------------
/test/helpers/getCompiler.js:
--------------------------------------------------------------------------------
1 | import path from "path";
2 |
3 | import webpack from "webpack";
4 | import { createFsFromVolume, Volume } from "memfs";
5 |
6 | export default (fixture, loaderOptions = {}, config = {}) => {
7 | const fullConfig = {
8 | mode: "development",
9 | devtool: config.devtool || false,
10 | context: path.resolve(__dirname, "../fixtures"),
11 | entry: path.resolve(__dirname, "../fixtures", fixture),
12 | output: {
13 | path: path.resolve(__dirname, "../outputs/"),
14 | filename: "[name].bundle.js",
15 | },
16 | module: {
17 | rules: [
18 | {
19 | test: /\.js$/i,
20 | rules: [
21 | {
22 | loader: require.resolve("./helperLoader.js"),
23 | },
24 | {
25 | loader: require.resolve("../../src"),
26 | options: loaderOptions,
27 | },
28 | ],
29 | },
30 | ],
31 | },
32 | plugins: [],
33 | ...config,
34 | };
35 |
36 | const compiler = webpack(fullConfig);
37 |
38 | if (!config.outputFileSystem) {
39 | compiler.outputFileSystem = createFsFromVolume(new Volume());
40 | }
41 |
42 | return compiler;
43 | };
44 |
--------------------------------------------------------------------------------
/test/helpers/helperLoader.js:
--------------------------------------------------------------------------------
1 | import path from "path";
2 |
3 | function rel(p) {
4 | return path.relative(process.cwd(), p);
5 | }
6 |
7 | export default function helperLoader(content, map, meta) {
8 | const dependencies = this.getDependencies().map((dependency) =>
9 | rel(dependency).replace(/\\/g, "/"),
10 | );
11 | const contextDependencies = this.getContextDependencies().map((dependency) =>
12 | rel(dependency).replace(/\\/g, "/"),
13 | );
14 |
15 | const buildDependencies = Array.from(
16 | this._module.buildInfo.buildDependencies || [],
17 | ).map((dependency) => rel(dependency).replace(/\\/g, "/"));
18 | const json = JSON.stringify(
19 | {
20 | content,
21 | map,
22 | meta,
23 | dependencies,
24 | contextDependencies,
25 | buildDependencies,
26 | },
27 | null,
28 | " ",
29 | )
30 | .replace(/\u2028/g, "\\u2028")
31 | .replace(/\u2029/g, "\\u2029");
32 |
33 | this.emitFile("val-loader.js", json, false);
34 |
35 | return ``;
36 | }
37 |
--------------------------------------------------------------------------------
/test/helpers/index.js:
--------------------------------------------------------------------------------
1 | import compile from "./compile";
2 | import execute from "./execute";
3 | import getCompiler from "./getCompiler";
4 | import helperLoader from "./helperLoader";
5 | import normalizeErrors from "./normalizeErrors";
6 | import readAsset from "./readAsset";
7 |
8 | export {
9 | compile,
10 | execute,
11 | getCompiler,
12 | helperLoader,
13 | normalizeErrors,
14 | readAsset,
15 | };
16 |
--------------------------------------------------------------------------------
/test/helpers/normalizeErrors.js:
--------------------------------------------------------------------------------
1 | function removeCWD(str) {
2 | const isWin = process.platform === "win32";
3 | let cwd = process.cwd();
4 |
5 | if (isWin) {
6 | // eslint-disable-next-line no-param-reassign
7 | str = str.replace(/\\/g, "/");
8 | // eslint-disable-next-line no-param-reassign
9 | cwd = cwd.replace(/\\/g, "/");
10 | }
11 |
12 | return str
13 | .replace(/\(from .*?\)/, "(from `replaced original path`)")
14 | .replace(new RegExp(cwd, "g"), "")
15 | .replace(
16 | /Cannot read property 'get' of undefined/,
17 | "Cannot read properties of undefined (reading 'get')",
18 | );
19 | }
20 |
21 | export default (errors) =>
22 | errors.map((error) =>
23 | removeCWD(error.toString().split("\n").slice(0, 2).join("\n")),
24 | );
25 |
--------------------------------------------------------------------------------
/test/helpers/readAsset.js:
--------------------------------------------------------------------------------
1 | import path from "path";
2 |
3 | export default (asset, compiler, stats) => {
4 | const usedFs = compiler.outputFileSystem;
5 | const outputPath = stats.compilation.outputOptions.path;
6 | let data = "";
7 |
8 | try {
9 | data = usedFs.readFileSync(path.join(outputPath, asset)).toString();
10 | } catch (error) {
11 | data = error.toString();
12 | }
13 |
14 | return data;
15 | };
16 |
--------------------------------------------------------------------------------
/test/loader.test.js:
--------------------------------------------------------------------------------
1 | import { getCompiler, compile, readAsset, normalizeErrors } from "./helpers";
2 |
3 | describe("loader", () => {
4 | it("should pass on the code from the simple fixture", async () => {
5 | const compiler = getCompiler("simple.js");
6 | const stats = await compile(compiler);
7 |
8 | expect(readAsset("val-loader.js", compiler, stats)).toMatchSnapshot(
9 | "result",
10 | );
11 | expect(normalizeErrors(stats.compilation.warnings)).toMatchSnapshot(
12 | "warnings",
13 | );
14 | expect(normalizeErrors(stats.compilation.errors)).toMatchSnapshot("errors");
15 | });
16 |
17 | it("should pass on the code from the simple fixture without options", async () => {
18 | // eslint-disable-next-line no-undefined
19 | const compiler = getCompiler("simple.js", undefined);
20 | const stats = await compile(compiler);
21 |
22 | expect(readAsset("val-loader.js", compiler, stats)).toMatchSnapshot(
23 | "result",
24 | );
25 | expect(normalizeErrors(stats.compilation.warnings)).toMatchSnapshot(
26 | "warnings",
27 | );
28 | expect(normalizeErrors(stats.compilation.errors)).toMatchSnapshot("errors");
29 | });
30 |
31 | it("should pass on the code from the buffer fixture", async () => {
32 | const compiler = getCompiler("buffer.js");
33 | const stats = await compile(compiler);
34 |
35 | expect(readAsset("val-loader.js", compiler, stats)).toMatchSnapshot(
36 | "result",
37 | );
38 | expect(normalizeErrors(stats.compilation.warnings)).toMatchSnapshot(
39 | "warnings",
40 | );
41 | expect(normalizeErrors(stats.compilation.errors)).toMatchSnapshot("errors");
42 | });
43 |
44 | it("should recognize modules produced by babel", async () => {
45 | const compiler = getCompiler("babel.js");
46 | const stats = await compile(compiler);
47 |
48 | expect(readAsset("val-loader.js", compiler, stats)).toMatchSnapshot(
49 | "result",
50 | );
51 | expect(normalizeErrors(stats.compilation.warnings)).toMatchSnapshot(
52 | "warnings",
53 | );
54 | expect(normalizeErrors(stats.compilation.errors)).toMatchSnapshot("errors");
55 | });
56 |
57 | it("should call the function with the loader options", async () => {
58 | const compiler = getCompiler("args.js", {
59 | arg: 123,
60 | arg2: "string",
61 | arg3: true,
62 | arg4: null,
63 | // eslint-disable-next-line no-undefined
64 | arg5: undefined,
65 | arg6: {},
66 | arg7: Symbol("id"),
67 | });
68 | const stats = await compile(compiler);
69 |
70 | expect(readAsset("val-loader.js", compiler, stats)).toMatchSnapshot(
71 | "result",
72 | );
73 | expect(normalizeErrors(stats.compilation.warnings)).toMatchSnapshot(
74 | "warnings",
75 | );
76 | expect(normalizeErrors(stats.compilation.errors)).toMatchSnapshot("errors");
77 | });
78 |
79 | it("should flag the module as not cacheable by default", async () => {
80 | const compiler = getCompiler("simple.js");
81 | const stats = await compile(compiler);
82 |
83 | expect(readAsset("val-loader.js", compiler, stats)).toMatchSnapshot(
84 | "result",
85 | );
86 | // In webpack@5 modules is Set
87 | expect([...stats.compilation.modules][0].buildInfo.cacheable).toBe(false);
88 | expect(normalizeErrors(stats.compilation.warnings)).toMatchSnapshot(
89 | "warnings",
90 | );
91 | expect(normalizeErrors(stats.compilation.errors)).toMatchSnapshot("errors");
92 | });
93 |
94 | it("should flag the module as cacheable if requested", async () => {
95 | const compiler = getCompiler("cacheable.js");
96 | const stats = await compile(compiler);
97 |
98 | expect(readAsset("val-loader.js", compiler, stats)).toMatchSnapshot(
99 | "result",
100 | );
101 | // In webpack@5 modules is Set
102 | expect([...stats.compilation.modules][0].buildInfo.cacheable).toBe(true);
103 | expect(normalizeErrors(stats.compilation.warnings)).toMatchSnapshot(
104 | "warnings",
105 | );
106 | expect(normalizeErrors(stats.compilation.errors)).toMatchSnapshot("errors");
107 | });
108 |
109 | it("should handle dependencies, contextDependencies and buildDependencies of the module", async () => {
110 | const compiler = getCompiler("dependencies.js");
111 | const stats = await compile(compiler);
112 |
113 | expect(readAsset("val-loader.js", compiler, stats)).toMatchSnapshot(
114 | "result",
115 | );
116 | expect(normalizeErrors(stats.compilation.warnings)).toMatchSnapshot(
117 | "warnings",
118 | );
119 | expect(normalizeErrors(stats.compilation.errors)).toMatchSnapshot("errors");
120 | });
121 |
122 | it("should allow adding dependencies, contextDependencies and buildDependencies via loader context", async () => {
123 | const compiler = getCompiler("dependencies-via-context.js");
124 | const stats = await compile(compiler);
125 |
126 | expect(readAsset("val-loader.js", compiler, stats)).toMatchSnapshot(
127 | "result",
128 | );
129 | expect(normalizeErrors(stats.compilation.warnings)).toMatchSnapshot(
130 | "warnings",
131 | );
132 | expect(normalizeErrors(stats.compilation.errors)).toMatchSnapshot("errors");
133 | });
134 |
135 | it("should work the same if a promise is returned", async () => {
136 | const compiler = getCompiler("promise.js");
137 | const stats = await compile(compiler);
138 |
139 | expect(readAsset("val-loader.js", compiler, stats)).toMatchSnapshot(
140 | "result",
141 | );
142 | expect(normalizeErrors(stats.compilation.warnings)).toMatchSnapshot(
143 | "warnings",
144 | );
145 | expect(normalizeErrors(stats.compilation.errors)).toMatchSnapshot("errors");
146 | });
147 |
148 | it("should work the same if a promise is returned #2", async () => {
149 | const compiler = getCompiler("promise-compex.js");
150 | const stats = await compile(compiler);
151 |
152 | expect(readAsset("val-loader.js", compiler, stats)).toMatchSnapshot(
153 | "result",
154 | );
155 | expect(normalizeErrors(stats.compilation.warnings)).toMatchSnapshot(
156 | "warnings",
157 | );
158 | expect(normalizeErrors(stats.compilation.errors)).toMatchSnapshot("errors");
159 | });
160 |
161 | it("should work with async function", async () => {
162 | const compiler = getCompiler("async-function.js");
163 | const stats = await compile(compiler);
164 |
165 | expect(readAsset("val-loader.js", compiler, stats)).toMatchSnapshot(
166 | "result",
167 | );
168 | expect(normalizeErrors(stats.compilation.warnings)).toMatchSnapshot(
169 | "warnings",
170 | );
171 | expect(normalizeErrors(stats.compilation.errors)).toMatchSnapshot("errors");
172 | });
173 |
174 | it("should has module.parent", async () => {
175 | const compiler = getCompiler("module-parent.js");
176 | const stats = await compile(compiler);
177 |
178 | expect(readAsset("val-loader.js", compiler, stats)).toMatchSnapshot(
179 | "result",
180 | );
181 | expect(normalizeErrors(stats.compilation.warnings)).toMatchSnapshot(
182 | "warnings",
183 | );
184 | expect(normalizeErrors(stats.compilation.errors)).toMatchSnapshot("errors");
185 | });
186 |
187 | it("should keep dependencies if errors are emitted", async () => {
188 | const compiler = getCompiler("error-emitted-with-dependencies.js");
189 | const stats = await compile(compiler);
190 |
191 | expect(readAsset("val-loader.js", compiler, stats)).toMatchSnapshot(
192 | "result",
193 | );
194 | expect(normalizeErrors(stats.compilation.warnings)).toMatchSnapshot(
195 | "warnings",
196 | );
197 | expect(normalizeErrors(stats.compilation.errors)).toMatchSnapshot("errors");
198 | });
199 |
200 | it("should report require() errors with a useful stacktrace", async () => {
201 | const compiler = getCompiler("error-require.js");
202 | const stats = await compile(compiler);
203 |
204 | expect(normalizeErrors(stats.compilation.warnings)).toMatchSnapshot(
205 | "warnings",
206 | );
207 | expect(normalizeErrors(stats.compilation.errors)).toMatchSnapshot("errors");
208 | });
209 |
210 | it("should throw a useful error message if the module exports not a function", async () => {
211 | const compiler = getCompiler("error-export-null.js");
212 | const stats = await compile(compiler);
213 |
214 | expect(normalizeErrors(stats.compilation.warnings)).toMatchSnapshot(
215 | "warnings",
216 | );
217 | expect(normalizeErrors(stats.compilation.errors)).toMatchSnapshot("errors");
218 | });
219 |
220 | it("should throw a useful error message if the exported function returns a wrong object (sync)", async () => {
221 | const compiler = getCompiler("error-return-sync-wrong-obj.js");
222 | const stats = await compile(compiler);
223 |
224 | expect(normalizeErrors(stats.compilation.warnings)).toMatchSnapshot(
225 | "warnings",
226 | );
227 | expect(normalizeErrors(stats.compilation.errors)).toMatchSnapshot("errors");
228 | });
229 |
230 | it("should throw a useful error message if the exported function returns a wrong object (async)", async () => {
231 | const compiler = getCompiler("error-return-async-wrong-obj.js");
232 | const stats = await compile(compiler);
233 |
234 | expect(normalizeErrors(stats.compilation.warnings)).toMatchSnapshot(
235 | "warnings",
236 | );
237 | expect(normalizeErrors(stats.compilation.errors)).toMatchSnapshot("errors");
238 | });
239 |
240 | it("should throw a useful error message if the exported function returns code that is neither a string nor an instanceof Buffer (sync)", async () => {
241 | const compiler = getCompiler("error-return-sync-invalid-code.js");
242 | const stats = await compile(compiler);
243 |
244 | expect(normalizeErrors(stats.compilation.warnings)).toMatchSnapshot(
245 | "warnings",
246 | );
247 | expect(normalizeErrors(stats.compilation.errors)).toMatchSnapshot("errors");
248 | });
249 |
250 | it("should throw a useful error message if the exported function returns code that is neither a string nor an instanceof Buffer (async)", async () => {
251 | const compiler = getCompiler("error-return-async-invalid-code.js");
252 | const stats = await compile(compiler);
253 |
254 | expect(normalizeErrors(stats.compilation.warnings)).toMatchSnapshot(
255 | "warnings",
256 | );
257 | expect(normalizeErrors(stats.compilation.errors)).toMatchSnapshot("errors");
258 | });
259 |
260 | it("should not swallow function call errors (sync)", async () => {
261 | const compiler = getCompiler("error-call-sync.js");
262 | const stats = await compile(compiler);
263 |
264 | expect(normalizeErrors(stats.compilation.warnings)).toMatchSnapshot(
265 | "warnings",
266 | );
267 | expect(normalizeErrors(stats.compilation.errors)).toMatchSnapshot("errors");
268 | });
269 |
270 | it("should not swallow function call errors (async)", async () => {
271 | const compiler = getCompiler("error-call-async.js");
272 | const stats = await compile(compiler);
273 |
274 | expect(normalizeErrors(stats.compilation.warnings)).toMatchSnapshot(
275 | "warnings",
276 | );
277 | expect(normalizeErrors(stats.compilation.errors)).toMatchSnapshot("errors");
278 | });
279 |
280 | it("should pass on the code from the presets/modernizr fixture", async () => {
281 | const compiler = getCompiler("presets/modernizr.js", {
282 | minify: false,
283 | options: ["setClasses"],
284 | "feature-detects": [
285 | "test/css/flexbox",
286 | "test/es6/promises",
287 | "test/serviceworker",
288 | ],
289 | });
290 | const stats = await compile(compiler);
291 |
292 | expect(readAsset("val-loader.js", compiler, stats)).toMatchSnapshot(
293 | "result",
294 | );
295 | expect(normalizeErrors(stats.compilation.warnings)).toMatchSnapshot(
296 | "warnings",
297 | );
298 | expect(normalizeErrors(stats.compilation.errors)).toMatchSnapshot("errors");
299 | });
300 |
301 | it("should pass on the code from the presets/figlet fixture", async () => {
302 | const compiler = getCompiler("presets/figlet.js", {
303 | text: "FIGLET",
304 | });
305 | const stats = await compile(compiler);
306 |
307 | expect(readAsset("val-loader.js", compiler, stats)).toMatchSnapshot(
308 | "result",
309 | );
310 | expect(normalizeErrors(stats.compilation.warnings)).toMatchSnapshot(
311 | "warnings",
312 | );
313 | expect(normalizeErrors(stats.compilation.errors)).toMatchSnapshot("errors");
314 | });
315 |
316 | it("should work with commonjs code", async () => {
317 | const compiler = getCompiler("code-es.js");
318 | const stats = await compile(compiler);
319 |
320 | expect(readAsset("val-loader.js", compiler, stats)).toMatchSnapshot(
321 | "result",
322 | );
323 | expect(normalizeErrors(stats.compilation.warnings)).toMatchSnapshot(
324 | "warnings",
325 | );
326 | expect(normalizeErrors(stats.compilation.errors)).toMatchSnapshot("errors");
327 | });
328 |
329 | it("should work with ES modules code", async () => {
330 | const compiler = getCompiler("code-commonjs.js");
331 | const stats = await compile(compiler);
332 |
333 | expect(readAsset("val-loader.js", compiler, stats)).toMatchSnapshot(
334 | "result",
335 | );
336 | expect(normalizeErrors(stats.compilation.warnings)).toMatchSnapshot(
337 | "warnings",
338 | );
339 | expect(normalizeErrors(stats.compilation.errors)).toMatchSnapshot("errors");
340 | });
341 | });
342 |
--------------------------------------------------------------------------------
/test/validate-options.test.js:
--------------------------------------------------------------------------------
1 | import { getCompiler, compile } from "./helpers";
2 |
3 | describe("validate options", () => {
4 | const tests = {
5 | unknown: {
6 | success: [1, true, false, "test", /test/, [], {}, { foo: "bar" }],
7 | failure: [],
8 | },
9 | };
10 |
11 | function stringifyValue(value) {
12 | if (
13 | Array.isArray(value) ||
14 | (value && typeof value === "object" && value.constructor === Object)
15 | ) {
16 | return JSON.stringify(value);
17 | }
18 |
19 | return value;
20 | }
21 |
22 | async function createTestCase(key, value, type) {
23 | it(`should ${
24 | type === "success" ? "successfully validate" : "throw an error on"
25 | } the "${key}" option with "${stringifyValue(value)}" value`, async () => {
26 | const compiler = getCompiler("simple.js", { [key]: value });
27 |
28 | let stats;
29 |
30 | try {
31 | stats = await compile(compiler);
32 | } finally {
33 | if (type === "success") {
34 | expect(stats.hasErrors()).toBe(false);
35 | } else if (type === "failure") {
36 | const {
37 | compilation: { errors },
38 | } = stats;
39 |
40 | expect(errors).toHaveLength(1);
41 | expect(() => {
42 | throw new Error(errors[0].error.message);
43 | }).toThrowErrorMatchingSnapshot();
44 | }
45 | }
46 | });
47 | }
48 |
49 | for (const [key, values] of Object.entries(tests)) {
50 | for (const type of Object.keys(values)) {
51 | for (const value of values[type]) {
52 | createTestCase(key, value, type);
53 | }
54 | }
55 | }
56 | });
57 |
--------------------------------------------------------------------------------