├── .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
├── lint-staged.config.js
├── package-lock.json
├── package.json
├── src
├── cjs.js
├── index.js
├── labels-to-names.js
├── options.json
├── parse-data-url.js
└── utils.js
└── test
├── __snapshots__
├── filterSourceMappingUrl.test.js.snap
├── loader.test.js.snap
├── parseDataUrl.test.js.snap
├── sourceMapperRegexp.test.js.snap
└── validate-options.test.js.snap
├── cjs.test.js
├── filterSourceMappingUrl.test.js
├── fixtures
├── .gitignore
├── absolute-source-root.js
├── absolute-source-root.js.map
├── absolute-sourceRoot-source-map.js
├── absolute-sourceRoot-source-map.txt
├── app.css
├── app.css.map
├── charset-inline-source-map.js
├── charset-inline-source-map.txt
├── data
│ ├── external-source-map2.map
│ └── relative-sourceRoot-source-map.txt
├── dependencies.js
├── dependencies.js.map
├── dependencies2.js
├── dependencies2.js.map
├── external-by-webpack.js.map
├── external-source-map.js
├── external-source-map.map
├── external-source-map2.js
├── external-source-map2.txt
├── file-broken-protocol-path.js
├── file-broken-protocol-path.js.map
├── file-source-map-windows.js
├── file-source-map.js
├── http-source-map.js
├── indexed-sourcemap
│ ├── file.js
│ ├── file.js.map
│ ├── file2.js
│ ├── file2.js.map
│ ├── nested1.js
│ └── nested2.js
├── inline-source-map.js
├── inline-sources.js
├── inline-sources.js.map
├── invalid-inline-source-map.js
├── invalid-inline-source-map2.js
├── invalid-source-map.js
├── invalid-source-map.map
├── missing-source-map.js
├── missing-source-map2.js
├── missing-source-map2.map
├── multi-source-map.js
├── normal-file.js
├── normal-file2.js
├── null-in-sources-content.js
├── null-in-sources-content.js.map
├── null-in-sources-content.txt
├── protocol-relative-url-path.js
├── relative-sourceRoot-source-map.js
├── relative-sourceRoot-source-map.map
├── server-relative-url-path.js
├── skip-sourcesContent.js
├── skip-sourcesContent.js.map
├── unSupport-file-source-map.js
├── unresolved-server-relative-url-path.js
├── webpack
│ ├── main.js
│ └── main.js.map
├── {percent}.js
└── {percent}.js.map
├── helpers
├── compile.js
├── execute.js
├── getCodeFromBundle.js
├── getCompiler.js
├── getErrors.js
├── getWarnings.js
├── index.js
├── normalizeErrors.js
├── normalizeMap.js
├── readAsset.js
├── readAssets.js
└── testLoader.js
├── loader.test.js
├── parseDataUrl.test.js
├── sourceMapperRegexp.test.js
└── validate-options.test.js
/.cspell.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": "0.2",
3 | "language": "en,en-gb",
4 | "words": [
5 | "sampledomain",
6 | "Fdvcmxk",
7 | "Привет",
8 | "Bbase",
9 | "Rlbn",
10 | "Nvbn",
11 | "OAAOA",
12 | "SAAUA",
13 | "IAAM",
14 | "IAAI",
15 | "CAAC",
16 | "normilized",
17 | "memfs",
18 | "commitlint",
19 | "Koppers",
20 | "sokra",
21 | "soley",
22 | "Bpercent"
23 | ],
24 |
25 | "ignorePaths": [
26 | "CHANGELOG.md",
27 | "package.json",
28 | "dist/**",
29 | "**/__snapshots__/**",
30 | "package-lock.json",
31 | "test/fixtures/file-protocol-path.js",
32 | "test/fixtures/absolute-path.js",
33 | "node_modules",
34 | "coverage",
35 | "*.log"
36 | ]
37 | }
38 |
--------------------------------------------------------------------------------
/.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.
--------------------------------------------------------------------------------
/.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 | "source-map-loader": "webpack-contrib/source-map-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 |
16 |
--------------------------------------------------------------------------------
/.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 | ### Please paste the results of `npx webpack-cli info` here, and mention other relevant information.
34 |
--------------------------------------------------------------------------------
/.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 |
19 |
20 | ### Please paste the results of `npx webpack-cli info` here, and mention other relevant information.
21 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/MODIFICATION.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: 🔧 Modification Request
3 | about: Want something to 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 |
17 | ### Expected Behavior / Situation
18 |
19 |
20 |
21 | ### Actual Behavior / Situation
22 |
23 |
24 |
25 | ### Please paste the results of `npx webpack-cli info` here, and mention other relevant information.
26 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/SUPPORT.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: 🆘 Support, Help, and Advice
3 | about: 👉🏽 Need support, help, or advice? Don't open an issue - visit "GitHub Discussions" or "Stack Overflow" instead.
4 | ---
5 |
6 | Hey there! 👋
7 |
8 | If you need support, help, or advice then this is not the right place to ask.
9 |
10 | Please visit one of the following instead:
11 |
12 | - [GitHub Discussions](https://github.com/webpack/webpack/discussions)
13 | - [Stack Overflow](https://stackoverflow.com/questions/tagged/webpack)
14 |
15 | Thanks for understanding!
16 |
--------------------------------------------------------------------------------
/.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: source-map-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 | - name: Setup Git
75 | if: matrix.os == 'windows-latest'
76 | run: git config --global core.autocrlf input
77 |
78 | - uses: actions/checkout@v4
79 |
80 | - name: Use Node.js ${{ matrix.node-version }}
81 | uses: actions/setup-node@v4
82 | with:
83 | node-version: ${{ matrix.node-version }}
84 | cache: "npm"
85 |
86 | - name: Install dependencies
87 | run: npm ci
88 |
89 | - name: Install webpack ${{ matrix.webpack-version }}
90 | if: matrix.webpack-version != 'latest'
91 | run: npm i webpack@${{ matrix.webpack-version }}
92 |
93 | - name: Run tests for webpack version ${{ matrix.webpack-version }}
94 | run: npm run test:coverage -- --ci
95 |
96 | - name: Submit coverage data to codecov
97 | uses: codecov/codecov-action@v5
98 | with:
99 | token: ${{ secrets.CODECOV_TOKEN }}
100 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | /node_modules
2 | test/output/*
3 | test/fixtures/absolute-path.js
4 | test/fixtures/absolute-sourceRoot-source-map.map
5 | test/fixtures/file-protocol-path.js
6 | test/fixtures/file-protocol-path.js.map
7 | test/fixtures/map-with-sourceroot.js.map
8 | test/fixtures/map-without-sourceroot.js.map
9 | test/fixtures/normal-map.js.map
10 | /test/fixtures/server-relative-url-path.js.map
11 | logs
12 | *.log
13 | npm-debug.log*
14 | .eslintcache
15 | /coverage
16 | /dist
17 | /local
18 | /reports
19 | .DS_Store
20 | Thumbs.db
21 | .idea
22 | *.iml
23 | .vscode
24 | *.sublime-project
25 | *.sublime-workspace
26 |
--------------------------------------------------------------------------------
/.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 | ## [5.0.0](https://github.com/webpack-contrib/source-map-loader/compare/v4.0.2...v5.0.0) (2024-01-15)
6 |
7 |
8 | ### ⚠ BREAKING CHANGES
9 |
10 | * minimum supported Node.js version is `18.12.0` ([#230](https://github.com/webpack-contrib/source-map-loader/issues/230)) ([7fcab17](https://github.com/webpack-contrib/source-map-loader/commit/7fcab17805723d5c93eeb0703448b1722cbc93d5))
11 |
12 | ### [4.0.2](https://github.com/webpack-contrib/source-map-loader/compare/v4.0.1...v4.0.2) (2023-12-27)
13 |
14 |
15 | ### Bug Fixes
16 |
17 | * avoid deprecation message of `abab` package ([#228](https://github.com/webpack-contrib/source-map-loader/issues/228)) ([9daafb3](https://github.com/webpack-contrib/source-map-loader/commit/9daafb3662f32c30dc84d068c86085dfad025563))
18 |
19 | ### [4.0.1](https://github.com/webpack-contrib/source-map-loader/compare/v4.0.0...v4.0.1) (2022-10-07)
20 |
21 |
22 | ### Bug Fixes
23 |
24 | * logic when sourceRoot contains absolute URL ([e724a1f](https://github.com/webpack-contrib/source-map-loader/commit/e724a1ffbfd57ec111e406274b76df5ab85d74e1))
25 |
26 | ## [4.0.0](https://github.com/webpack-contrib/source-map-loader/compare/v3.0.1...v4.0.0) (2022-06-13)
27 |
28 |
29 | ### ⚠ BREAKING CHANGES
30 |
31 | * minimum supported `Node.js` version is `14.15.0`
32 |
33 | ### [3.0.1](https://github.com/webpack-contrib/source-map-loader/compare/v3.0.0...v3.0.1) (2022-01-03)
34 |
35 | ### Chore
36 |
37 | * update `source-map-js`
38 |
39 | ## [3.0.0](https://github.com/webpack-contrib/source-map-loader/compare/v2.0.2...v3.0.0) (2021-05-21)
40 |
41 |
42 | ### ⚠ BREAKING CHANGES
43 |
44 | * minimum supported `Node.js` version is `12.13.0`
45 |
46 | ### [2.0.2](https://github.com/webpack-contrib/source-map-loader/compare/v2.0.1...v2.0.2) (2021-05-17)
47 |
48 |
49 | ### Bug Fixes
50 |
51 | * don't ignore source file when `sourceContent` contains `null` ([#148](https://github.com/webpack-contrib/source-map-loader/issues/148)) ([8ec2b86](https://github.com/webpack-contrib/source-map-loader/commit/8ec2b86286e938b484b7c13a790192148842002e))
52 |
53 | ### [2.0.1](https://github.com/webpack-contrib/source-map-loader/compare/v2.0.0...v2.0.1) (2021-02-10)
54 |
55 | ### Bug Fixes
56 |
57 | * switch from `source-map` to `source-map-js` package (perf increase)
58 | * fix watch with invalid `sourceURL`
59 |
60 | ## [2.0.0](https://github.com/webpack-contrib/source-map-loader/compare/v1.1.3...v2.0.0) (2020-12-24)
61 |
62 |
63 | ### ⚠ BREAKING CHANGES
64 |
65 | * minimum supported `webpack` version is `5`
66 |
67 | ### [1.1.3](https://github.com/webpack-contrib/source-map-loader/compare/v1.1.2...v1.1.3) (2020-12-04)
68 |
69 |
70 | ### Bug Fixes
71 |
72 | * parse percent-encoding url ([#136](https://github.com/webpack-contrib/source-map-loader/issues/136)) ([80dbf18](https://github.com/webpack-contrib/source-map-loader/commit/80dbf18f240dd40437492414687c04db7825515f))
73 |
74 | ### [1.1.2](https://github.com/webpack-contrib/source-map-loader/compare/v1.1.1...v1.1.2) (2020-10-27)
75 |
76 |
77 | ### Bug Fixes
78 |
79 | * do not watch unnecessary `sources` ([23768df](https://github.com/webpack-contrib/source-map-loader/commit/23768df65e1ea4773114ec004a29d1271e9ab02d))
80 |
81 | ### [1.1.1](https://github.com/webpack-contrib/source-map-loader/compare/v1.1.0...v1.1.1) (2020-10-09)
82 |
83 | ### Chore
84 |
85 | * update `schema-utils`
86 |
87 | ## [1.1.0](https://github.com/webpack-contrib/source-map-loader/compare/v1.0.2...v1.1.0) (2020-08-29)
88 |
89 |
90 | ### Features
91 |
92 | * filter source mapping url ([5cc3dfd](https://github.com/webpack-contrib/source-map-loader/commit/5cc3dfde50e9f1df95e21a8fdbc697ae36cd6897))
93 |
94 |
95 | ### Bug Fixes
96 |
97 | * update anchor ([#126](https://github.com/webpack-contrib/source-map-loader/issues/126)) ([78effee](https://github.com/webpack-contrib/source-map-loader/commit/78effeee8eead75081d3ebc71567f408aa2f6ce2))
98 |
99 | ### [1.0.2](https://github.com/webpack-contrib/source-map-loader/compare/v1.0.1...v1.0.2) (2020-08-19)
100 |
101 |
102 | ### Bug Fixes
103 |
104 | * resolve server-relative url ([30317f8](https://github.com/webpack-contrib/source-map-loader/commit/30317f8aefa6d25c07a02a12850017a76d58f3a5))
105 |
106 | ### [1.0.1](https://github.com/webpack-contrib/source-map-loader/compare/v1.0.0...v1.0.1) (2020-06-30)
107 |
108 |
109 | ### Bug Fixes
110 |
111 | * webpack protocol ([a2e4cd6](https://github.com/webpack-contrib/source-map-loader/commit/a2e4cd6be7f9ff9024c201093f1410431f7a48e9))
112 |
113 | ## [1.0.0](https://github.com/webpack-contrib/source-map-loader/compare/v0.2.4...v1.0.0) (2020-05-26)
114 |
115 |
116 | ### ⚠ BREAKING CHANGES
117 |
118 | * minimum supported Node.js version is `10.13`
119 | * minimum supported `webpack` version is `4`
120 |
121 | ### Features
122 |
123 | * support indexed source maps ([c18d1f9](https://github.com/webpack-contrib/source-map-loader/commit/c18d1f9495fce229d21993aba1d215cc75986d84))
124 | * support `charsert` for Data URLs
125 |
126 | ### Bug Fixes
127 |
128 | * absolute path for sources ([b64f7d8](https://github.com/webpack-contrib/source-map-loader/commit/b64f7d82de27769c8bbd2be280faf4f9f97492d5))
129 | * avoid crash on big data URL source maps ([7f769aa](https://github.com/webpack-contrib/source-map-loader/commit/7f769aa5a09d362cf29eeb52f4c8155360e1afad))
130 | * improve performance ([#101](https://github.com/webpack-contrib/source-map-loader/issues/101)) ([4c39c22](https://github.com/webpack-contrib/source-map-loader/commit/4c39c228ae215b43d6c90fd1727d572dfd3d5929))
131 | * use webpack fs ([#105](https://github.com/webpack-contrib/source-map-loader/issues/105)) ([1e785a1](https://github.com/webpack-contrib/source-map-loader/commit/1e785a1114afe2f40a9f2361d8a326a99b5050e6))
132 | * support `file` protocol
133 | * improve error messages
134 | * avoid conflicts with other source maps
135 | * fix compatibility with `5` version of `webpack`
136 |
137 |
138 | ## [0.2.4](https://github.com/webpack-contrib/source-map-loader/compare/v0.2.3...v0.2.4) (2018-08-14)
139 |
140 |
141 | ### Bug Fixes
142 |
143 | * **index:** handle exception on loading invalid source maps ([#67](https://github.com/webpack-contrib/source-map-loader/issues/67)) ([78ad469](https://github.com/webpack-contrib/source-map-loader/commit/78ad469))
144 | * **index:** resolve source maps with root-relative paths correctly ([#68](https://github.com/webpack-contrib/source-map-loader/issues/68)) ([e2fdbfd](https://github.com/webpack-contrib/source-map-loader/commit/e2fdbfd))
145 | * **package:** 5 low severity vulnerabilities ([#72](https://github.com/webpack-contrib/source-map-loader/issues/72)) ([8262587](https://github.com/webpack-contrib/source-map-loader/commit/8262587))
146 |
147 |
148 |
149 |
150 | ## [0.2.3](https://github.com/webpack/source-map-loader/compare/v0.2.2...v0.2.3) (2017-10-23)
151 |
152 |
153 | ### Chores
154 |
155 | * Increase minimum version of source-map dependency for bug fix https://github.com/mozilla/source-map/issues/247 ([#56](https://github.com/webpack-contrib/source-map-loader/issues/56)) ([f6cf53c](https://github.com/webpack/source-map-loader/commit/f6cf53c))
156 |
157 |
158 |
159 |
160 | ## [0.2.2](https://github.com/webpack/source-map-loader/compare/v0.2.1...v0.2.2) (2017-09-30)
161 |
162 |
163 | ### Bug Fixes
164 |
165 | * Handle exception on loading invalid base64 source maps ([#53](https://github.com/webpack/source-map-loader/issues/53)) ([38da2eb](https://github.com/webpack/source-map-loader/commit/38da2eb))
166 |
167 |
168 |
169 |
170 | ## [0.2.1](https://github.com/webpack/source-map-loader/compare/v0.2.0...v0.2.1) (2017-03-30)
171 |
172 |
173 | ### Bug Fixes
174 |
175 | * Regex does not work for minified artifact of style-loader ([#39](https://github.com/webpack/source-map-loader/issues/39)) ([582f8dc](https://github.com/webpack/source-map-loader/commit/582f8dc))
176 |
177 |
178 |
179 |
180 | # [0.2.0](https://github.com/webpack/source-map-loader/compare/v0.1.6...v0.2.0) (2017-03-10)
181 |
182 |
183 | ### Bug Fixes
184 |
185 | * Load source map only from last directive ([#31](https://github.com/webpack/source-map-loader/issues/31)) ([eabfc7e](https://github.com/webpack/source-map-loader/commit/eabfc7e))
186 |
187 |
188 | ### Features
189 |
190 | * allow charset in inline-source-map support ([#21](https://github.com/webpack/source-map-loader/issues/21)) ([2730ccb](https://github.com/webpack/source-map-loader/commit/2730ccb))
191 |
--------------------------------------------------------------------------------
/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 | # source-map-loader
15 |
16 | Extracts source maps from existing source files (from their `sourceMappingURL
`).
17 |
18 | ## Getting Started
19 |
20 | To begin, you'll need to install `source-map-loader`:
21 |
22 | ```console
23 | npm i -D source-map-loader
24 | ```
25 |
26 | or
27 |
28 | ```console
29 | yarn add -D source-map-loader
30 | ```
31 |
32 | or
33 |
34 | ```console
35 | pnpm add -D source-map-loader
36 | ```
37 |
38 | Then add the loader to your `webpack` configuration. For example:
39 |
40 | **file.js**
41 |
42 | ```js
43 | import css from "file.css";
44 | ```
45 |
46 | **webpack.config.js**
47 |
48 | ```js
49 | module.exports = {
50 | module: {
51 | rules: [
52 | {
53 | test: /\.js$/,
54 | enforce: "pre",
55 | use: ["source-map-loader"],
56 | },
57 | ],
58 | },
59 | };
60 | ```
61 |
62 | The `source-map-loader` extracts existing source maps from all JavaScript entries.
63 | This includes both inline source maps as well as those linked via a `sourceMappingURL`.
64 |
65 | All source map data is passed to webpack for processing as per a chosen [source map style](https://webpack.js.org/configuration/devtool/) specified by the `devtool` option in [webpack.config.js](https://webpack.js.org/configuration/).
66 |
67 | This loader is especially useful when using third-party libraries having their own source maps.
68 | If not extracted and processed into the source map of the webpack bundle, browsers may misinterpret or ignore source map data.
69 |
70 | The `source-map-loader` allows webpack to maintain source map data continuity across libraries so ease of debugging is preserved.
71 |
72 | The `source-map-loader` will extract from any JavaScript file, including those in the `node_modules` directory.
73 |
74 | Be mindful in setting [include](https://webpack.js.org/configuration/module/#ruleinclude) and [exclude](https://webpack.js.org/configuration/module/#ruleexclude) rule conditions to maximize bundling performance.
75 |
76 | Finally, run `webpack` using the method you normally use (e.g., via CLI or an npm script).
77 |
78 | ## Options
79 |
80 | | Name | Type | Default | Description |
81 | | :-----------------------------------------------------: | :----------: | :---------: | :--------------------------------------------- |
82 | | **[`filterSourceMappingUrl`](#filtersourcemappingurl)** | `{Function}` | `undefined` | Allows to control `SourceMappingURL` behaviour |
83 |
84 | ### filterSourceMappingUrl
85 |
86 | Type: `Function`
87 | Default: `undefined`
88 |
89 | Allows you to specify the behavior of the loader for `SourceMappingURL` comment.
90 |
91 | The function must return one of the following values:
92 |
93 | - `true` or `'consume'` - consume the source map and remove `SourceMappingURL` comment (default behavior)
94 | - `false` or `'remove'` - do not consume the source map and remove `SourceMappingURL` comment
95 | - `skip` - do not consume the source map and do not remove `SourceMappingURL` comment
96 |
97 | Example configuration:
98 |
99 | **webpack.config.js**
100 |
101 | ```js
102 | module.exports = {
103 | module: {
104 | rules: [
105 | {
106 | test: /\.js$/,
107 | enforce: "pre",
108 | use: [
109 | {
110 | loader: "source-map-loader",
111 | options: {
112 | filterSourceMappingUrl: (url, resourcePath) => {
113 | if (/broker-source-map-url\.js$/i.test(url)) {
114 | return false;
115 | }
116 |
117 | if (/keep-source-mapping-url\.js$/i.test(resourcePath)) {
118 | return "skip";
119 | }
120 |
121 | return true;
122 | },
123 | },
124 | },
125 | ],
126 | },
127 | ],
128 | },
129 | };
130 | ```
131 |
132 | ## Examples
133 |
134 | ### Ignoring Warnings
135 |
136 | To ignore warnings, you can use the following configuration:
137 |
138 | **webpack.config.js**
139 |
140 | ```js
141 | module.exports = {
142 | module: {
143 | rules: [
144 | {
145 | test: /\.js$/,
146 | enforce: "pre",
147 | use: ["source-map-loader"],
148 | },
149 | ],
150 | },
151 | ignoreWarnings: [/Failed to parse source map/],
152 | };
153 | ```
154 |
155 | More information about the `ignoreWarnings` option can be found [here](https://webpack.js.org/configuration/other-options/#ignorewarnings)
156 |
157 | ## Contributing
158 |
159 | We welcome all contributions!
160 | If you're new here, please take a moment to review our contributing guidelines before submitting issues or pull requests.
161 |
162 | [CONTRIBUTING](./.github/CONTRIBUTING.md)
163 |
164 | ## License
165 |
166 | [MIT](./LICENSE)
167 |
168 | [npm]: https://img.shields.io/npm/v/source-map-loader.svg
169 | [npm-url]: https://npmjs.com/package/source-map-loader
170 | [node]: https://img.shields.io/node/v/source-map-loader.svg
171 | [node-url]: https://nodejs.org
172 | [tests]: https://github.com/webpack-contrib/source-map-loader/workflows/source-map-loader/badge.svg
173 | [tests-url]: https://github.com/webpack-contrib/source-map-loader/actions
174 | [cover]: https://codecov.io/gh/webpack-contrib/source-map-loader/branch/master/graph/badge.svg
175 | [cover-url]: https://codecov.io/gh/webpack-contrib/source-map-loader
176 | [discussion]: https://img.shields.io/github/discussions/webpack/webpack
177 | [discussion-url]: https://github.com/webpack/webpack/discussions
178 | [size]: https://packagephobia.now.sh/badge?p=source-map-loader
179 | [size-url]: https://packagephobia.now.sh/result?p=source-map-loader
180 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/lint-staged.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | "*.js": ["eslint --fix", "prettier --write", "cspell"],
3 | "*.{json,md,yml,css,ts}": ["prettier --write"],
4 | };
5 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "source-map-loader",
3 | "version": "5.0.0",
4 | "description": "extracts inlined source map and offers it to webpack",
5 | "license": "MIT",
6 | "repository": "webpack-contrib/source-map-loader",
7 | "author": "Tobias Koppers @sokra",
8 | "homepage": "https://github.com/webpack-contrib/source-map-loader",
9 | "bugs": "https://github.com/webpack-contrib/source-map-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",
25 | "lint:prettier": "prettier --list-different .",
26 | "lint:js": "eslint --cache .",
27 | "lint:spelling": "cspell \"**/*.*\"",
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 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.72.1"
45 | },
46 | "dependencies": {
47 | "iconv-lite": "^0.6.3",
48 | "source-map-js": "^1.2.0"
49 | },
50 | "devDependencies": {
51 | "@babel/cli": "^7.24.7",
52 | "@babel/core": "^7.24.7",
53 | "@babel/preset-env": "^7.24.7",
54 | "@commitlint/cli": "^19.7.1",
55 | "@commitlint/config-conventional": "^19.7.1",
56 | "@webpack-contrib/eslint-config-webpack": "^3.0.0",
57 | "babel-jest": "^29.7.0",
58 | "cross-env": "^7.0.3",
59 | "cspell": "^8.10.0",
60 | "del-cli": "^6.0.0",
61 | "eslint": "^8.50.0",
62 | "eslint-config-prettier": "^9.1.0",
63 | "eslint-plugin-import": "^2.28.1",
64 | "husky": "^9.1.3",
65 | "jest": "^29.7.0",
66 | "lint-staged": "^15.2.7",
67 | "memfs": "^4.9.3",
68 | "npm-run-all": "^4.1.5",
69 | "prettier": "^3.3.2",
70 | "standard-version": "^9.5.0",
71 | "webpack": "^5.92.1"
72 | },
73 | "keywords": [
74 | "webpack"
75 | ]
76 | }
77 |
--------------------------------------------------------------------------------
/src/cjs.js:
--------------------------------------------------------------------------------
1 | const loader = require("./index");
2 |
3 | module.exports = loader.default;
4 | module.exports.raw = loader.raw;
5 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | /*
2 | MIT License http://www.opensource.org/licenses/mit-license.php
3 | Author Tobias Koppers @sokra
4 | */
5 | import path from "path";
6 |
7 | import schema from "./options.json";
8 | import {
9 | getSourceMappingURL,
10 | fetchFromURL,
11 | flattenSourceMap,
12 | isURL,
13 | } from "./utils";
14 |
15 | export default async function loader(input, inputMap) {
16 | const options = this.getOptions(schema);
17 | const { sourceMappingURL, replacementString } = getSourceMappingURL(input);
18 | const callback = this.async();
19 |
20 | if (!sourceMappingURL) {
21 | callback(null, input, inputMap);
22 |
23 | return;
24 | }
25 |
26 | let behaviourSourceMappingUrl;
27 |
28 | try {
29 | behaviourSourceMappingUrl =
30 | typeof options.filterSourceMappingUrl !== "undefined"
31 | ? options.filterSourceMappingUrl(sourceMappingURL, this.resourcePath)
32 | : "consume";
33 | } catch (error) {
34 | callback(error);
35 |
36 | return;
37 | }
38 |
39 | // eslint-disable-next-line default-case
40 | switch (behaviourSourceMappingUrl) {
41 | case "skip":
42 | callback(null, input, inputMap);
43 | return;
44 | case false:
45 | case "remove":
46 | callback(null, input.replace(replacementString, ""), inputMap);
47 | return;
48 | }
49 |
50 | let sourceURL;
51 | let sourceContent;
52 |
53 | try {
54 | ({ sourceURL, sourceContent } = await fetchFromURL(
55 | this,
56 | this.context,
57 | sourceMappingURL,
58 | ));
59 | } catch (error) {
60 | this.emitWarning(error);
61 |
62 | callback(null, input, inputMap);
63 |
64 | return;
65 | }
66 |
67 | if (sourceURL) {
68 | this.addDependency(sourceURL);
69 | }
70 |
71 | let map;
72 |
73 | try {
74 | map = JSON.parse(sourceContent.replace(/^\)\]\}'/, ""));
75 | } catch (parseError) {
76 | this.emitWarning(
77 | new Error(
78 | `Failed to parse source map from '${sourceMappingURL}': ${parseError}`,
79 | ),
80 | );
81 |
82 | callback(null, input, inputMap);
83 |
84 | return;
85 | }
86 |
87 | const context = sourceURL ? path.dirname(sourceURL) : this.context;
88 |
89 | if (map.sections) {
90 | // eslint-disable-next-line no-param-reassign
91 | map = await flattenSourceMap(map);
92 | }
93 |
94 | const resolvedSources = await Promise.all(
95 | map.sources.map(async (source, i) => {
96 | // eslint-disable-next-line no-shadow
97 | let sourceURL;
98 | // eslint-disable-next-line no-shadow
99 | let sourceContent;
100 |
101 | const originalSourceContent =
102 | map.sourcesContent &&
103 | typeof map.sourcesContent[i] !== "undefined" &&
104 | map.sourcesContent[i] !== null
105 | ? map.sourcesContent[i]
106 | : // eslint-disable-next-line no-undefined
107 | undefined;
108 | const skipReading = typeof originalSourceContent !== "undefined";
109 | let errored = false;
110 |
111 | // We do not skipReading here, because we need absolute paths in sources.
112 | // This is necessary so that for sourceMaps with the same file structure in sources, name collisions do not occur.
113 | // https://github.com/webpack-contrib/source-map-loader/issues/51
114 | try {
115 | ({ sourceURL, sourceContent } = await fetchFromURL(
116 | this,
117 | context,
118 | source,
119 | map.sourceRoot,
120 | skipReading,
121 | ));
122 | } catch (error) {
123 | errored = true;
124 |
125 | this.emitWarning(error);
126 | }
127 |
128 | if (skipReading) {
129 | sourceContent = originalSourceContent;
130 | } else if (!errored && sourceURL && !isURL(sourceURL)) {
131 | this.addDependency(sourceURL);
132 | }
133 |
134 | // Return original value of `source` when error happens
135 | return { sourceURL: errored ? source : sourceURL, sourceContent };
136 | }),
137 | );
138 |
139 | const newMap = { ...map };
140 |
141 | newMap.sources = [];
142 | newMap.sourcesContent = [];
143 |
144 | delete newMap.sourceRoot;
145 |
146 | resolvedSources.forEach((source) => {
147 | // eslint-disable-next-line no-shadow
148 | const { sourceURL, sourceContent } = source;
149 |
150 | newMap.sources.push(sourceURL || "");
151 | newMap.sourcesContent.push(sourceContent || "");
152 | });
153 |
154 | const sourcesContentIsEmpty =
155 | newMap.sourcesContent.filter((entry) => Boolean(entry)).length === 0;
156 |
157 | if (sourcesContentIsEmpty) {
158 | delete newMap.sourcesContent;
159 | }
160 |
161 | callback(null, input.replace(replacementString, ""), newMap);
162 | }
163 |
--------------------------------------------------------------------------------
/src/labels-to-names.js:
--------------------------------------------------------------------------------
1 | const labelToNames = {
2 | 866: "IBM866",
3 | "unicode-1-1-utf-8": "UTF-8",
4 | "utf-8": "UTF-8",
5 | utf8: "UTF-8",
6 | cp866: "IBM866",
7 | csibm866: "IBM866",
8 | ibm866: "IBM866",
9 | csisolatin2: "ISO-8859-2",
10 | "iso-8859-2": "ISO-8859-2",
11 | "iso-ir-101": "ISO-8859-2",
12 | "iso8859-2": "ISO-8859-2",
13 | iso88592: "ISO-8859-2",
14 | "iso_8859-2": "ISO-8859-2",
15 | "iso_8859-2:1987": "ISO-8859-2",
16 | l2: "ISO-8859-2",
17 | latin2: "ISO-8859-2",
18 | csisolatin3: "ISO-8859-3",
19 | "iso-8859-3": "ISO-8859-3",
20 | "iso-ir-109": "ISO-8859-3",
21 | "iso8859-3": "ISO-8859-3",
22 | iso88593: "ISO-8859-3",
23 | "iso_8859-3": "ISO-8859-3",
24 | "iso_8859-3:1988": "ISO-8859-3",
25 | l3: "ISO-8859-3",
26 | latin3: "ISO-8859-3",
27 | csisolatin4: "ISO-8859-4",
28 | "iso-8859-4": "ISO-8859-4",
29 | "iso-ir-110": "ISO-8859-4",
30 | "iso8859-4": "ISO-8859-4",
31 | iso88594: "ISO-8859-4",
32 | "iso_8859-4": "ISO-8859-4",
33 | "iso_8859-4:1988": "ISO-8859-4",
34 | l4: "ISO-8859-4",
35 | latin4: "ISO-8859-4",
36 | csisolatincyrillic: "ISO-8859-5",
37 | cyrillic: "ISO-8859-5",
38 | "iso-8859-5": "ISO-8859-5",
39 | "iso-ir-144": "ISO-8859-5",
40 | "iso8859-5": "ISO-8859-5",
41 | iso88595: "ISO-8859-5",
42 | "iso_8859-5": "ISO-8859-5",
43 | "iso_8859-5:1988": "ISO-8859-5",
44 | arabic: "ISO-8859-6",
45 | "asmo-708": "ISO-8859-6",
46 | csiso88596e: "ISO-8859-6",
47 | csiso88596i: "ISO-8859-6",
48 | csisolatinarabic: "ISO-8859-6",
49 | "ecma-114": "ISO-8859-6",
50 | "iso-8859-6": "ISO-8859-6",
51 | "iso-8859-6-e": "ISO-8859-6",
52 | "iso-8859-6-i": "ISO-8859-6",
53 | "iso-ir-127": "ISO-8859-6",
54 | "iso8859-6": "ISO-8859-6",
55 | iso88596: "ISO-8859-6",
56 | "iso_8859-6": "ISO-8859-6",
57 | "iso_8859-6:1987": "ISO-8859-6",
58 | csisolatingreek: "ISO-8859-7",
59 | "ecma-118": "ISO-8859-7",
60 | elot_928: "ISO-8859-7",
61 | greek: "ISO-8859-7",
62 | greek8: "ISO-8859-7",
63 | "iso-8859-7": "ISO-8859-7",
64 | "iso-ir-126": "ISO-8859-7",
65 | "iso8859-7": "ISO-8859-7",
66 | iso88597: "ISO-8859-7",
67 | "iso_8859-7": "ISO-8859-7",
68 | "iso_8859-7:1987": "ISO-8859-7",
69 | sun_eu_greek: "ISO-8859-7",
70 | csiso88598e: "ISO-8859-8",
71 | csisolatinhebrew: "ISO-8859-8",
72 | hebrew: "ISO-8859-8",
73 | "iso-8859-8": "ISO-8859-8",
74 | "iso-8859-8-e": "ISO-8859-8",
75 | "iso-ir-138": "ISO-8859-8",
76 | "iso8859-8": "ISO-8859-8",
77 | iso88598: "ISO-8859-8",
78 | "iso_8859-8": "ISO-8859-8",
79 | "iso_8859-8:1988": "ISO-8859-8",
80 | visual: "ISO-8859-8",
81 | csisolatin6: "ISO-8859-10",
82 | "iso-8859-10": "ISO-8859-10",
83 | "iso-ir-157": "ISO-8859-10",
84 | "iso8859-10": "ISO-8859-10",
85 | iso885910: "ISO-8859-10",
86 | l6: "ISO-8859-10",
87 | latin6: "ISO-8859-10",
88 | "iso-8859-13": "ISO-8859-13",
89 | "iso8859-13": "ISO-8859-13",
90 | iso885913: "ISO-8859-13",
91 | "iso-8859-14": "ISO-8859-14",
92 | "iso8859-14": "ISO-8859-14",
93 | iso885914: "ISO-8859-14",
94 | csisolatin9: "ISO-8859-15",
95 | "iso-8859-15": "ISO-8859-15",
96 | "iso8859-15": "ISO-8859-15",
97 | iso885915: "ISO-8859-15",
98 | "iso_8859-15": "ISO-8859-15",
99 | l9: "ISO-8859-15",
100 | "iso-8859-16": "ISO-8859-16",
101 | cskoi8r: "KOI8-R",
102 | koi: "KOI8-R",
103 | koi8: "KOI8-R",
104 | "koi8-r": "KOI8-R",
105 | koi8_r: "KOI8-R",
106 | "koi8-ru": "KOI8-U",
107 | "koi8-u": "KOI8-U",
108 | csmacintosh: "macintosh",
109 | mac: "macintosh",
110 | macintosh: "macintosh",
111 | "x-mac-roman": "macintosh",
112 | "dos-874": "windows-874",
113 | "iso-8859-11": "windows-874",
114 | "iso8859-11": "windows-874",
115 | iso885911: "windows-874",
116 | "tis-620": "windows-874",
117 | "windows-874": "windows-874",
118 | cp1250: "windows-1250",
119 | "windows-1250": "windows-1250",
120 | "x-cp1250": "windows-1250",
121 | cp1251: "windows-1251",
122 | "windows-1251": "windows-1251",
123 | "x-cp1251": "windows-1251",
124 | "ansi_x3.4-1968": "windows-1252",
125 | ascii: "windows-1252",
126 | cp1252: "windows-1252",
127 | cp819: "windows-1252",
128 | csisolatin1: "windows-1252",
129 | ibm819: "windows-1252",
130 | "iso-8859-1": "windows-1252",
131 | "iso-ir-100": "windows-1252",
132 | "iso8859-1": "windows-1252",
133 | iso88591: "windows-1252",
134 | "iso_8859-1": "windows-1252",
135 | "iso_8859-1:1987": "windows-1252",
136 | l1: "windows-1252",
137 | latin1: "windows-1252",
138 | "us-ascii": "windows-1252",
139 | "windows-1252": "windows-1252",
140 | "x-cp1252": "windows-1252",
141 | cp1253: "windows-1253",
142 | "windows-1253": "windows-1253",
143 | "x-cp1253": "windows-1253",
144 | cp1254: "windows-1254",
145 | csisolatin5: "windows-1254",
146 | "iso-8859-9": "windows-1254",
147 | "iso-ir-148": "windows-1254",
148 | "iso8859-9": "windows-1254",
149 | iso88599: "windows-1254",
150 | "iso_8859-9": "windows-1254",
151 | "iso_8859-9:1989": "windows-1254",
152 | l5: "windows-1254",
153 | latin5: "windows-1254",
154 | "windows-1254": "windows-1254",
155 | "x-cp1254": "windows-1254",
156 | cp1255: "windows-1255",
157 | "windows-1255": "windows-1255",
158 | "x-cp1255": "windows-1255",
159 | cp1256: "windows-1256",
160 | "windows-1256": "windows-1256",
161 | "x-cp1256": "windows-1256",
162 | cp1257: "windows-1257",
163 | "windows-1257": "windows-1257",
164 | "x-cp1257": "windows-1257",
165 | cp1258: "windows-1258",
166 | "windows-1258": "windows-1258",
167 | "x-cp1258": "windows-1258",
168 | chinese: "GBK",
169 | csgb2312: "GBK",
170 | csiso58gb231280: "GBK",
171 | gb2312: "GBK",
172 | gb_2312: "GBK",
173 | "gb_2312-80": "GBK",
174 | gbk: "GBK",
175 | "iso-ir-58": "GBK",
176 | "x-gbk": "GBK",
177 | gb18030: "gb18030",
178 | big5: "Big5",
179 | "big5-hkscs": "Big5",
180 | "cn-big5": "Big5",
181 | csbig5: "Big5",
182 | "x-x-big5": "Big5",
183 | cseucpkdfmtjapanese: "EUC-JP",
184 | "euc-jp": "EUC-JP",
185 | "x-euc-jp": "EUC-JP",
186 | csshiftjis: "Shift_JIS",
187 | ms932: "Shift_JIS",
188 | ms_kanji: "Shift_JIS",
189 | "shift-jis": "Shift_JIS",
190 | shift_jis: "Shift_JIS",
191 | sjis: "Shift_JIS",
192 | "windows-31j": "Shift_JIS",
193 | "x-sjis": "Shift_JIS",
194 | cseuckr: "EUC-KR",
195 | csksc56011987: "EUC-KR",
196 | "euc-kr": "EUC-KR",
197 | "iso-ir-149": "EUC-KR",
198 | korean: "EUC-KR",
199 | "ks_c_5601-1987": "EUC-KR",
200 | "ks_c_5601-1989": "EUC-KR",
201 | ksc5601: "EUC-KR",
202 | ksc_5601: "EUC-KR",
203 | "windows-949": "EUC-KR",
204 | "utf-16be": "UTF-16BE",
205 | "utf-16": "UTF-16LE",
206 | "utf-16le": "UTF-16LE",
207 | };
208 |
209 | export default labelToNames;
210 |
--------------------------------------------------------------------------------
/src/options.json:
--------------------------------------------------------------------------------
1 | {
2 | "title": "Source Map Loader options",
3 | "type": "object",
4 | "additionalProperties": false,
5 | "properties": {
6 | "filterSourceMappingUrl": {
7 | "instanceof": "Function"
8 | }
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/src/parse-data-url.js:
--------------------------------------------------------------------------------
1 | const removeLeadingAndTrailingHTTPWhitespace = (string) =>
2 | string.replace(/^[ \t\n\r]+/, "").replace(/[ \t\n\r]+$/, "");
3 |
4 | const removeTrailingHTTPWhitespace = (string) =>
5 | string.replace(/[ \t\n\r]+$/, "");
6 |
7 | const isHTTPWhitespaceChar = (char) =>
8 | char === " " || char === "\t" || char === "\n" || char === "\r";
9 |
10 | const solelyContainsHTTPTokenCodePoints = (string) =>
11 | /^[-!#$%&'*+.^_`|~A-Za-z0-9]*$/.test(string);
12 |
13 | const soleyContainsHTTPQuotedStringTokenCodePoints = (string) =>
14 | /^[\t\u0020-\u007E\u0080-\u00FF]*$/.test(string);
15 |
16 | const asciiLowercase = (string) =>
17 | string.replace(/[A-Z]/g, (l) => l.toLowerCase());
18 |
19 | const collectAnHTTPQuotedString = (input, position) => {
20 | let value = "";
21 |
22 | // eslint-disable-next-line no-param-reassign
23 | position += 1;
24 |
25 | // eslint-disable-next-line no-constant-condition
26 | while (true) {
27 | while (
28 | position < input.length &&
29 | input[position] !== '"' &&
30 | input[position] !== "\\"
31 | ) {
32 | value += input[position];
33 | // eslint-disable-next-line no-param-reassign
34 | position += 1;
35 | }
36 |
37 | if (position >= input.length) {
38 | break;
39 | }
40 |
41 | const quoteOrBackslash = input[position];
42 |
43 | // eslint-disable-next-line no-param-reassign
44 | position += 1;
45 |
46 | if (quoteOrBackslash === "\\") {
47 | if (position >= input.length) {
48 | value += "\\";
49 | break;
50 | }
51 |
52 | value += input[position];
53 | // eslint-disable-next-line no-param-reassign
54 | position += 1;
55 | } else {
56 | break;
57 | }
58 | }
59 |
60 | return [value, position];
61 | };
62 |
63 | function isASCIIHex(c) {
64 | return (
65 | (c >= 0x30 && c <= 0x39) ||
66 | (c >= 0x41 && c <= 0x46) ||
67 | (c >= 0x61 && c <= 0x66)
68 | );
69 | }
70 |
71 | function percentDecodeBytes(input) {
72 | const output = new Uint8Array(input.byteLength);
73 | let outputIndex = 0;
74 |
75 | for (let i = 0; i < input.byteLength; ++i) {
76 | const byte = input[i];
77 |
78 | if (byte !== 0x25) {
79 | output[outputIndex] = byte;
80 | } else if (
81 | byte === 0x25 &&
82 | (!isASCIIHex(input[i + 1]) || !isASCIIHex(input[i + 2]))
83 | ) {
84 | output[outputIndex] = byte;
85 | } else {
86 | output[outputIndex] = parseInt(
87 | String.fromCodePoint(input[i + 1], input[i + 2]),
88 | 16,
89 | );
90 | i += 2;
91 | }
92 |
93 | outputIndex += 1;
94 | }
95 |
96 | return output.slice(0, outputIndex);
97 | }
98 |
99 | /**
100 | * A lookup table for atob(), which converts an ASCII character to the
101 | * corresponding six-bit number.
102 | */
103 |
104 | const characters =
105 | "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
106 |
107 | function atobLookup(chr) {
108 | const index = characters.indexOf(chr);
109 | // Throw exception if character is not in the lookup string; should not be hit in tests
110 | // eslint-disable-next-line no-undefined
111 | return index < 0 ? undefined : index;
112 | }
113 |
114 | /**
115 | * Implementation of atob() according to the HTML and Infra specs, except that
116 | * instead of throwing INVALID_CHARACTER_ERR we return null.
117 | */
118 | function atob(input) {
119 | /* eslint-disable no-bitwise */
120 | // Web IDL requires DOMStrings to just be converted using ECMAScript
121 | // ToString, which in our case amounts to using a template literal.
122 | let data = `${input}`;
123 |
124 | // "Remove all ASCII whitespace from data."
125 | data = data.replace(/[ \t\n\f\r]/g, "");
126 |
127 | // "If data's length divides by 4 leaving no remainder, then: if data ends
128 | // with one or two U+003D (=) code points, then remove them from data."
129 | if (data.length % 4 === 0) {
130 | data = data.replace(/==?$/, "");
131 | }
132 |
133 | // "If data's length divides by 4 leaving a remainder of 1, then return
134 | // failure."
135 | //
136 | // "If data contains a code point that is not one of
137 | //
138 | // U+002B (+)
139 | // U+002F (/)
140 | // ASCII alphanumeric
141 | //
142 | // then return failure."
143 | if (data.length % 4 === 1 || /[^+/0-9A-Za-z]/.test(data)) {
144 | return null;
145 | }
146 |
147 | // "Let output be an empty byte sequence."
148 | let output = "";
149 |
150 | // "Let buffer be an empty buffer that can have bits appended to it."
151 | //
152 | // We append bits via left-shift and or. accumulatedBits is used to track
153 | // when we've gotten to 24 bits.
154 | let buffer = 0;
155 | let accumulatedBits = 0;
156 |
157 | // "Let position be a position variable for data, initially pointing at the
158 | // start of data."
159 | //
160 | // "While position does not point past the end of data:"
161 | for (let i = 0; i < data.length; i++) {
162 | // "Find the code point pointed to by position in the second column of
163 | // Table 1: The Base 64 Alphabet of RFC 4648. Let n be the number given in
164 | // the first cell of the same row.
165 | //
166 | // "Append to buffer the six bits corresponding to n, most significant bit
167 | // first."
168 | //
169 | // atobLookup() implements the table from RFC 4648.
170 | // eslint-disable-next-line no-bitwise
171 | buffer <<= 6;
172 |
173 | // eslint-disable-next-line no-bitwise
174 | buffer |= atobLookup(data[i]);
175 | accumulatedBits += 6;
176 |
177 | // "If buffer has accumulated 24 bits, interpret them as three 8-bit
178 | // big-endian numbers. Append three bytes with values equal to those
179 | // numbers to output, in the same order, and then empty buffer."
180 | if (accumulatedBits === 24) {
181 | output += String.fromCharCode((buffer & 0xff0000) >> 16);
182 | output += String.fromCharCode((buffer & 0xff00) >> 8);
183 | output += String.fromCharCode(buffer & 0xff);
184 | accumulatedBits = 0;
185 | buffer = 0;
186 | }
187 | // "Advance position by 1."
188 | }
189 |
190 | // "If buffer is not empty, it contains either 12 or 18 bits. If it contains
191 | // 12 bits, then discard the last four and interpret the remaining eight as
192 | // an 8-bit big-endian number. If it contains 18 bits, then discard the last
193 | // two and interpret the remaining 16 as two 8-bit big-endian numbers. Append
194 | // the one or two bytes with values equal to those one or two numbers to
195 | // output, in the same order."
196 | if (accumulatedBits === 12) {
197 | buffer >>= 4;
198 | output += String.fromCharCode(buffer);
199 | } else if (accumulatedBits === 18) {
200 | buffer >>= 2;
201 | output += String.fromCharCode((buffer & 0xff00) >> 8);
202 | output += String.fromCharCode(buffer & 0xff);
203 | }
204 | /* eslint-enable no-bitwise */
205 |
206 | // "Return output."
207 | return output;
208 | }
209 |
210 | export default function parseDataUrl(stringInput) {
211 | let parsedUrl;
212 |
213 | try {
214 | parsedUrl = new URL(stringInput);
215 | } catch (error) {
216 | return null;
217 | }
218 |
219 | if (parsedUrl.protocol !== "data:") {
220 | return null;
221 | }
222 |
223 | parsedUrl.hash = "";
224 |
225 | // `5` is value of `'data:'.length`
226 | const input = parsedUrl.toString().substring(5);
227 |
228 | let position = 0;
229 | let mediaType = "";
230 |
231 | while (position < input.length && input[position] !== ",") {
232 | mediaType += input[position];
233 | position += 1;
234 | }
235 |
236 | mediaType = mediaType
237 | .replace(/^[ \t\n\f\r]+/, "")
238 | .replace(/[ \t\n\f\r]+$/, "");
239 |
240 | if (position === input.length) {
241 | return null;
242 | }
243 |
244 | position += 1;
245 |
246 | const encodedBody = input.substring(position);
247 |
248 | let body = Buffer.from(percentDecodeBytes(Buffer.from(encodedBody, "utf-8")));
249 |
250 | // Can't use /i regexp flag because it isn't restricted to ASCII.
251 | const mimeTypeBase64MatchResult = /(.*); *[Bb][Aa][Ss][Ee]64$/.exec(
252 | mediaType,
253 | );
254 |
255 | if (mimeTypeBase64MatchResult) {
256 | const stringBody = body.toString("binary");
257 | const asString = atob(stringBody);
258 |
259 | if (asString === null) {
260 | return null;
261 | }
262 |
263 | body = Buffer.from(asString, "binary");
264 |
265 | [, mediaType] = mimeTypeBase64MatchResult;
266 | }
267 |
268 | if (mediaType.startsWith(";")) {
269 | mediaType = `text/plain ${mediaType}`;
270 | }
271 |
272 | const result = {
273 | // eslint-disable-next-line no-undefined
274 | type: undefined,
275 | // eslint-disable-next-line no-undefined
276 | subtype: undefined,
277 | parameters: new Map(),
278 | isBase64: Boolean(mimeTypeBase64MatchResult),
279 | body,
280 | };
281 |
282 | if (!mediaType) {
283 | return result;
284 | }
285 |
286 | const inputMediaType = removeLeadingAndTrailingHTTPWhitespace(mediaType);
287 |
288 | let positionMediaType = 0;
289 | let type = "";
290 |
291 | while (
292 | positionMediaType < inputMediaType.length &&
293 | inputMediaType[positionMediaType] !== "/"
294 | ) {
295 | type += inputMediaType[positionMediaType];
296 | positionMediaType += 1;
297 | }
298 |
299 | if (type.length === 0 || !solelyContainsHTTPTokenCodePoints(type)) {
300 | return result;
301 | }
302 |
303 | if (positionMediaType >= inputMediaType.length) {
304 | return result;
305 | }
306 |
307 | // Skips past "/"
308 | positionMediaType += 1;
309 |
310 | let subtype = "";
311 |
312 | while (
313 | positionMediaType < inputMediaType.length &&
314 | inputMediaType[positionMediaType] !== ";"
315 | ) {
316 | subtype += inputMediaType[positionMediaType];
317 | positionMediaType += 1;
318 | }
319 |
320 | subtype = removeTrailingHTTPWhitespace(subtype);
321 |
322 | if (subtype.length === 0 || !solelyContainsHTTPTokenCodePoints(subtype)) {
323 | return result;
324 | }
325 |
326 | result.type = asciiLowercase(type);
327 | result.subtype = asciiLowercase(subtype);
328 |
329 | while (positionMediaType < inputMediaType.length) {
330 | // Skip past ";"
331 | positionMediaType += 1;
332 |
333 | while (isHTTPWhitespaceChar(inputMediaType[positionMediaType])) {
334 | positionMediaType += 1;
335 | }
336 |
337 | let parameterName = "";
338 |
339 | while (
340 | positionMediaType < inputMediaType.length &&
341 | inputMediaType[positionMediaType] !== ";" &&
342 | inputMediaType[positionMediaType] !== "="
343 | ) {
344 | parameterName += inputMediaType[positionMediaType];
345 | positionMediaType += 1;
346 | }
347 |
348 | parameterName = asciiLowercase(parameterName);
349 |
350 | if (positionMediaType < inputMediaType.length) {
351 | if (inputMediaType[positionMediaType] === ";") {
352 | // eslint-disable-next-line no-continue
353 | continue;
354 | }
355 |
356 | // Skip past "="
357 | positionMediaType += 1;
358 | }
359 |
360 | let parameterValue = "";
361 |
362 | if (inputMediaType[positionMediaType] === '"') {
363 | [parameterValue, positionMediaType] = collectAnHTTPQuotedString(
364 | inputMediaType,
365 | positionMediaType,
366 | );
367 |
368 | while (
369 | positionMediaType < inputMediaType.length &&
370 | inputMediaType[positionMediaType] !== ";"
371 | ) {
372 | positionMediaType += 1;
373 | }
374 | } else {
375 | while (
376 | positionMediaType < inputMediaType.length &&
377 | inputMediaType[positionMediaType] !== ";"
378 | ) {
379 | parameterValue += inputMediaType[positionMediaType];
380 | positionMediaType += 1;
381 | }
382 |
383 | parameterValue = removeTrailingHTTPWhitespace(parameterValue);
384 |
385 | if (parameterValue === "") {
386 | // eslint-disable-next-line no-continue
387 | continue;
388 | }
389 | }
390 |
391 | if (
392 | parameterName.length > 0 &&
393 | solelyContainsHTTPTokenCodePoints(parameterName) &&
394 | soleyContainsHTTPQuotedStringTokenCodePoints(parameterValue) &&
395 | !result.parameters.has(parameterName)
396 | ) {
397 | result.parameters.set(parameterName, parameterValue);
398 | }
399 | }
400 |
401 | return result;
402 | }
403 |
--------------------------------------------------------------------------------
/src/utils.js:
--------------------------------------------------------------------------------
1 | import path from "path";
2 | import urlUtils from "url";
3 |
4 | import sourceMap from "source-map-js";
5 | import { decode } from "iconv-lite";
6 |
7 | import parseDataURL from "./parse-data-url";
8 | import labelsToNames from "./labels-to-names";
9 |
10 | // Matches only the last occurrence of sourceMappingURL
11 | const innerRegex = /\s*[#@]\s*sourceMappingURL\s*=\s*([^\s'"]*)\s*/;
12 |
13 | /* eslint-disable prefer-template */
14 | const sourceMappingURLRegex = RegExp(
15 | "(?:" +
16 | "/\\*" +
17 | "(?:\\s*\r?\n(?://)?)?" +
18 | "(?:" +
19 | innerRegex.source +
20 | ")" +
21 | "\\s*" +
22 | "\\*/" +
23 | "|" +
24 | "//(?:" +
25 | innerRegex.source +
26 | ")" +
27 | ")" +
28 | "\\s*",
29 | );
30 | /* eslint-enable prefer-template */
31 |
32 | function labelToName(label) {
33 | const labelLowercase = String(label).trim().toLowerCase();
34 |
35 | return labelsToNames[labelLowercase] || null;
36 | }
37 |
38 | async function flattenSourceMap(map) {
39 | const consumer = await new sourceMap.SourceMapConsumer(map);
40 | const generatedMap = map.file
41 | ? new sourceMap.SourceMapGenerator({
42 | file: map.file,
43 | })
44 | : new sourceMap.SourceMapGenerator();
45 |
46 | consumer.sources.forEach((sourceFile) => {
47 | const sourceContent = consumer.sourceContentFor(sourceFile, true);
48 | generatedMap.setSourceContent(sourceFile, sourceContent);
49 | });
50 |
51 | consumer.eachMapping((mapping) => {
52 | const { source } = consumer.originalPositionFor({
53 | line: mapping.generatedLine,
54 | column: mapping.generatedColumn,
55 | });
56 |
57 | const mappings = {
58 | source,
59 | original: {
60 | line: mapping.originalLine,
61 | column: mapping.originalColumn,
62 | },
63 | generated: {
64 | line: mapping.generatedLine,
65 | column: mapping.generatedColumn,
66 | },
67 | };
68 |
69 | if (source) {
70 | generatedMap.addMapping(mappings);
71 | }
72 | });
73 |
74 | return generatedMap.toJSON();
75 | }
76 |
77 | function getSourceMappingURL(code) {
78 | const lines = code.split(/^/m);
79 | let match;
80 |
81 | for (let i = lines.length - 1; i >= 0; i--) {
82 | match = lines[i].match(sourceMappingURLRegex);
83 | if (match) {
84 | break;
85 | }
86 | }
87 |
88 | const sourceMappingURL = match ? match[1] || match[2] || "" : null;
89 |
90 | return {
91 | sourceMappingURL: sourceMappingURL
92 | ? decodeURI(sourceMappingURL)
93 | : sourceMappingURL,
94 | replacementString: match ? match[0] : null,
95 | };
96 | }
97 |
98 | function getAbsolutePath(context, request, sourceRoot) {
99 | if (isURL(sourceRoot)) {
100 | return new URL(request, sourceRoot).toString();
101 | }
102 |
103 | if (sourceRoot) {
104 | if (path.isAbsolute(sourceRoot)) {
105 | return path.join(sourceRoot, request);
106 | }
107 |
108 | return path.join(context, sourceRoot, request);
109 | }
110 |
111 | return path.join(context, request);
112 | }
113 |
114 | function fetchFromDataURL(loaderContext, sourceURL) {
115 | const dataURL = parseDataURL(sourceURL);
116 |
117 | if (dataURL) {
118 | // https://tools.ietf.org/html/rfc4627
119 | // JSON text SHALL be encoded in Unicode. The default encoding is UTF-8.
120 | const encodingName =
121 | labelToName(dataURL.parameters.get("charset")) || "UTF-8";
122 |
123 | return decode(dataURL.body, encodingName);
124 | }
125 |
126 | throw new Error(`Failed to parse source map from "data" URL: ${sourceURL}`);
127 | }
128 |
129 | async function fetchFromFilesystem(loaderContext, sourceURL) {
130 | let buffer;
131 |
132 | if (isURL(sourceURL)) {
133 | return { path: sourceURL };
134 | }
135 |
136 | try {
137 | buffer = await new Promise((resolve, reject) => {
138 | loaderContext.fs.readFile(sourceURL, (error, data) => {
139 | if (error) {
140 | return reject(error);
141 | }
142 |
143 | return resolve(data);
144 | });
145 | });
146 | } catch (error) {
147 | throw new Error(
148 | `Failed to parse source map from '${sourceURL}' file: ${error}`,
149 | );
150 | }
151 |
152 | return { path: sourceURL, data: buffer.toString() };
153 | }
154 |
155 | async function fetchPathsFromFilesystem(
156 | loaderContext,
157 | possibleRequests,
158 | errorsAccumulator = "",
159 | ) {
160 | let result;
161 |
162 | try {
163 | result = await fetchFromFilesystem(
164 | loaderContext,
165 | possibleRequests[0],
166 | errorsAccumulator,
167 | );
168 | } catch (error) {
169 | // eslint-disable-next-line no-param-reassign
170 | errorsAccumulator += `${error.message}\n\n`;
171 |
172 | const [, ...tailPossibleRequests] = possibleRequests;
173 |
174 | if (tailPossibleRequests.length === 0) {
175 | error.message = errorsAccumulator;
176 |
177 | throw error;
178 | }
179 |
180 | return fetchPathsFromFilesystem(
181 | loaderContext,
182 | tailPossibleRequests,
183 | errorsAccumulator,
184 | );
185 | }
186 |
187 | return result;
188 | }
189 |
190 | function isURL(value) {
191 | return /^[a-z][a-z0-9+.-]*:/i.test(value) && !path.win32.isAbsolute(value);
192 | }
193 |
194 | async function fetchFromURL(
195 | loaderContext,
196 | context,
197 | url,
198 | sourceRoot,
199 | skipReading = false,
200 | ) {
201 | // 1. It's an absolute url and it is not `windows` path like `C:\dir\file`
202 | if (isURL(url)) {
203 | const { protocol } = urlUtils.parse(url);
204 |
205 | if (protocol === "data:") {
206 | if (skipReading) {
207 | return { sourceURL: "" };
208 | }
209 |
210 | const sourceContent = fetchFromDataURL(loaderContext, url);
211 |
212 | return { sourceURL: "", sourceContent };
213 | }
214 |
215 | if (skipReading) {
216 | return { sourceURL: url };
217 | }
218 |
219 | if (protocol === "file:") {
220 | const pathFromURL = urlUtils.fileURLToPath(url);
221 | const sourceURL = path.normalize(pathFromURL);
222 | const { data: sourceContent } = await fetchFromFilesystem(
223 | loaderContext,
224 | sourceURL,
225 | );
226 |
227 | return { sourceURL, sourceContent };
228 | }
229 |
230 | throw new Error(
231 | `Failed to parse source map: '${url}' URL is not supported`,
232 | );
233 | }
234 |
235 | // 2. It's a scheme-relative
236 | if (/^\/\//.test(url)) {
237 | throw new Error(
238 | `Failed to parse source map: '${url}' URL is not supported`,
239 | );
240 | }
241 |
242 | // 3. Absolute path
243 | if (path.isAbsolute(url)) {
244 | let sourceURL = path.normalize(url);
245 |
246 | let sourceContent;
247 |
248 | if (!skipReading) {
249 | const possibleRequests = [sourceURL];
250 |
251 | if (url.startsWith("/")) {
252 | possibleRequests.push(
253 | getAbsolutePath(context, sourceURL.slice(1), sourceRoot),
254 | );
255 | }
256 |
257 | const result = await fetchPathsFromFilesystem(
258 | loaderContext,
259 | possibleRequests,
260 | );
261 |
262 | sourceURL = result.path;
263 | sourceContent = result.data;
264 | }
265 |
266 | return { sourceURL, sourceContent };
267 | }
268 |
269 | // 4. Relative path
270 | const sourceURL = getAbsolutePath(context, url, sourceRoot);
271 |
272 | let sourceContent;
273 |
274 | if (!skipReading) {
275 | const { data } = await fetchFromFilesystem(loaderContext, sourceURL);
276 |
277 | sourceContent = data;
278 | }
279 |
280 | return { sourceURL, sourceContent };
281 | }
282 |
283 | export { getSourceMappingURL, fetchFromURL, flattenSourceMap, isURL };
284 |
--------------------------------------------------------------------------------
/test/__snapshots__/filterSourceMappingUrl.test.js.snap:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://goo.gl/fbAQLP
2 |
3 | exports[`filterSourceMappingUrl option should emit error: errors 1`] = `
4 | [
5 | "ModuleBuildError: Module build failed (from \`replaced original path\`):
6 | Error: error",
7 | ]
8 | `;
9 |
10 | exports[`filterSourceMappingUrl option should emit error: warnings 1`] = `[]`;
11 |
12 | exports[`filterSourceMappingUrl option should work with "remove" value: code 1`] = `
13 | "with SourceMap
14 | // comment
15 | "
16 | `;
17 |
18 | exports[`filterSourceMappingUrl option should work with "remove" value: errors 1`] = `[]`;
19 |
20 | exports[`filterSourceMappingUrl option should work with "remove" value: warnings 1`] = `[]`;
21 |
22 | exports[`filterSourceMappingUrl option should work with "skip" value: code 1`] = `
23 | "with SourceMap
24 | //#sourceMappingURL=http://sampledomain.com/external-source-map2.map
25 | // comment
26 | "
27 | `;
28 |
29 | exports[`filterSourceMappingUrl option should work with "skip" value: errors 1`] = `[]`;
30 |
31 | exports[`filterSourceMappingUrl option should work with "skip" value: warnings 1`] = `[]`;
32 |
33 | exports[`filterSourceMappingUrl option should work with false value: code 1`] = `
34 | "with SourceMap
35 | // comment
36 | "
37 | `;
38 |
39 | exports[`filterSourceMappingUrl option should work with false value: errors 1`] = `[]`;
40 |
41 | exports[`filterSourceMappingUrl option should work with false value: warnings 1`] = `[]`;
42 |
43 | exports[`filterSourceMappingUrl option should work with true value: code 1`] = `
44 | "with SourceMap
45 | // comment"
46 | `;
47 |
48 | exports[`filterSourceMappingUrl option should work with true value: errors 1`] = `[]`;
49 |
50 | exports[`filterSourceMappingUrl option should work with true value: map 1`] = `
51 | {
52 | "file": "external-source-map.js",
53 | "mappings": "AAAA",
54 | "sources": [
55 | "/test/fixtures/external-source-map.txt - (normalized for test)",
56 | ],
57 | "sourcesContent": [
58 | "with SourceMap",
59 | ],
60 | "version": 3,
61 | }
62 | `;
63 |
64 | exports[`filterSourceMappingUrl option should work with true value: warnings 1`] = `[]`;
65 |
66 | exports[`filterSourceMappingUrl option should work: code 1`] = `
67 | "with SourceMap
68 | // comment"
69 | `;
70 |
71 | exports[`filterSourceMappingUrl option should work: errors 1`] = `[]`;
72 |
73 | exports[`filterSourceMappingUrl option should work: map 1`] = `
74 | {
75 | "file": "external-source-map.js",
76 | "mappings": "AAAA",
77 | "sources": [
78 | "/test/fixtures/external-source-map.txt - (normalized for test)",
79 | ],
80 | "sourcesContent": [
81 | "with SourceMap",
82 | ],
83 | "version": 3,
84 | }
85 | `;
86 |
87 | exports[`filterSourceMappingUrl option should work: warnings 1`] = `[]`;
88 |
--------------------------------------------------------------------------------
/test/__snapshots__/loader.test.js.snap:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://goo.gl/fbAQLP
2 |
3 | exports[`source-map-loader should add only valid \`sources\` to dependencies: code 1`] = `
4 | "// Dependencies
5 | "
6 | `;
7 |
8 | exports[`source-map-loader should add only valid \`sources\` to dependencies: errors 1`] = `[]`;
9 |
10 | exports[`source-map-loader should add only valid \`sources\` to dependencies: map 1`] = `
11 | {
12 | "file": "inline-sources.js",
13 | "mappings": "AAAA",
14 | "sources": [
15 | "/test/fixtures/data/relative-sourceRoot-source-map.txt - (normalized for test)",
16 | "./data/not-found.txt",
17 | "",
18 | "data:invalid;A;a",
19 | ],
20 | "sourcesContent": [
21 | "with SourceMap
22 | // comment",
23 | "",
24 | "some kind content",
25 | "",
26 | ],
27 | "version": 3,
28 | }
29 | `;
30 |
31 | exports[`source-map-loader should add only valid \`sources\` to dependencies: warnings 1`] = `
32 | [
33 | "ModuleWarning: Module Warning (from \`replaced original path\`):
34 | Failed to parse source map from "data" URL: data:invalid;A;a",
35 | "ModuleWarning: Module Warning (from \`replaced original path\`):
36 | Failed to parse source map from '/test/fixtures/data/not-found.txt' file: Error: ENOENT: no such file or directory, open '/test/fixtures/data/not-found.txt'",
37 | ]
38 | `;
39 |
40 | exports[`source-map-loader should add only valid \`sources\` with \`sourceContent\` to dependencies: code 1`] = `
41 | "// Dependencies
42 | "
43 | `;
44 |
45 | exports[`source-map-loader should add only valid \`sources\` with \`sourceContent\` to dependencies: errors 1`] = `[]`;
46 |
47 | exports[`source-map-loader should add only valid \`sources\` with \`sourceContent\` to dependencies: map 1`] = `
48 | {
49 | "file": "inline-sources.js",
50 | "mappings": "AAAA",
51 | "sources": [
52 | "/test/fixtures/data/relative-sourceRoot-source-map.txt - (normalized for test)",
53 | "/test/fixtures/data/not-found.txt - (normalized for test)",
54 | "",
55 | "",
56 | ],
57 | "sourcesContent": [
58 | "foo",
59 | "bar",
60 | "",
61 | "baz",
62 | ],
63 | "version": 3,
64 | }
65 | `;
66 |
67 | exports[`source-map-loader should add only valid \`sources\` with \`sourceContent\` to dependencies: warnings 1`] = `[]`;
68 |
69 | exports[`source-map-loader should allow to filter warnings: code 1`] = `
70 | "without SourceMap
71 | // @sourceMappingURL=data:application/source-map;base64,invalid/base64=
72 | // comment"
73 | `;
74 |
75 | exports[`source-map-loader should allow to filter warnings: errors 1`] = `[]`;
76 |
77 | exports[`source-map-loader should allow to filter warnings: warnings 1`] = `
78 | [
79 | "ModuleWarning: Module Warning (from \`replaced original path\`):
80 | Failed to parse source map from "data" URL: data:application/source-map;base64,invalid/base64=",
81 | ]
82 | `;
83 |
84 | exports[`source-map-loader should emit warning when unresolved server-relative-url-path: code 1`] = `
85 | "with SourceMap
86 | // #sourceMappingURL=/unresolved-server-relative-url-path.js.map
87 | // comment
88 | "
89 | `;
90 |
91 | exports[`source-map-loader should emit warning when unresolved server-relative-url-path: errors 1`] = `[]`;
92 |
93 | exports[`source-map-loader should emit warning when unresolved server-relative-url-path: warnings 1`] = `
94 | [
95 | "ModuleWarning: Module Warning (from \`replaced original path\`):",
96 | ]
97 | `;
98 |
99 | exports[`source-map-loader should leave normal files untouched: code 1`] = `"without SourceMap"`;
100 |
101 | exports[`source-map-loader should leave normal files untouched: errors 1`] = `[]`;
102 |
103 | exports[`source-map-loader should leave normal files untouched: warnings 1`] = `[]`;
104 |
105 | exports[`source-map-loader should leave normal files with fake source-map untouched: code 1`] = `
106 | "// without SourceMap
107 | anInvalidDirective = "\\n/*# sourceMappingURL=data:application/json;base64,"+btoa(unescape(encodeURIComponent(JSON.stringify(sourceMap))))+" */";
108 | // comment
109 | "
110 | `;
111 |
112 | exports[`source-map-loader should leave normal files with fake source-map untouched: errors 1`] = `[]`;
113 |
114 | exports[`source-map-loader should leave normal files with fake source-map untouched: warnings 1`] = `[]`;
115 |
116 | exports[`source-map-loader should process absolute URL in sourceRoot: code 1`] = `
117 | "const foo = "test";
118 | "
119 | `;
120 |
121 | exports[`source-map-loader should process absolute URL in sourceRoot: errors 1`] = `[]`;
122 |
123 | exports[`source-map-loader should process absolute URL in sourceRoot: map 1`] = `
124 | {
125 | "file": "index.d.ts",
126 | "mappings": "AAAA,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,EAAE,MAAM,EAAE,KAAK,aAAa,EAAE,CAAC;AAEtC,OAAO,EACH,UAAU,EACV,iBAAiB,EACjB,SAAS,EACT,OAAO,EACP,QAAQ,EACX,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,UAAU,EAAE,KAAK,iBAAiB,EAAE,CAAC;AAE9C,aAAK,OAAO,GAAG,aAAa,GAAG,iBAAiB,CAAC;AAIjD;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,GAAG,QAAQ,CAIvE;AACD;;;;;;;;;GASG;AACH,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,GAAG,SAAS,EAAE,CAErE;AACD;;;;;;GAMG;AACH,wBAAgB,eAAe,CAC3B,EAAE,EAAE,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI,EAAE,GAAG,EAAE,SAAS,EAAE,KAAK,IAAI,EACnD,OAAO,CAAC,EAAE,OAAO,EACjB,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,GACvC,MAAM,CAGR;AAED,OAAO,EACH,OAAO,IAAI,SAAS,EACpB,KAAK,SAAS,IAAI,kBAAkB,GACvC,MAAM,gBAAgB,CAAC;AAMxB,OAAO,KAAK,WAAW,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,CAAC;AAEvB,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AAEzC,OAAO,EAAE,OAAO,EAAE,CAAC;AAEnB;;;;;GAKG;AACH,wBAAgB,SAAS,CACrB,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE,aAAa,GAAG,iBAAqC,GAC/D,IAAI,GAAG,IAAI,CAEb;AAED,OAAO,KAAK,QAAQ,MAAM,UAAU,CAAC;AAGrC,OAAO,EAAE,UAAU,IAAI,cAAc,EAAE,CAAC",
127 | "names": [],
128 | "sources": [
129 | "https://raw.githubusercontent.com/fb55/htmlparser2/4763205746cd80120b5d2b69041197a394d24ba9/src/index.ts",
130 | ],
131 | "version": 3,
132 | }
133 | `;
134 |
135 | exports[`source-map-loader should process absolute URL in sourceRoot: warnings 1`] = `[]`;
136 |
137 | exports[`source-map-loader should process css sourceMap: code 1`] = `
138 | "* {
139 | box-sizing: border-box; }
140 |
141 | .row {
142 | display: flex;
143 | margin-right: -15px;
144 | margin-left: -15px; }
145 |
146 | .col-inner {
147 | display: flex;
148 | align-items: center;
149 | justify-content: center;
150 | color: #fff;
151 | height: 50px;
152 | background: coral; }
153 |
154 | .col-s3 {
155 | flex: 0 1 25%;
156 | padding: 0 15px; }
157 |
158 |
159 | "
160 | `;
161 |
162 | exports[`source-map-loader should process css sourceMap: code 2`] = `
163 | "// Skip SourcesContent in SourceMap
164 | // comment
165 | "
166 | `;
167 |
168 | exports[`source-map-loader should process css sourceMap: errors 1`] = `[]`;
169 |
170 | exports[`source-map-loader should process css sourceMap: errors 2`] = `[]`;
171 |
172 | exports[`source-map-loader should process css sourceMap: map 1`] = `
173 | {
174 | "file": "app.css",
175 | "mappings": "AAAA;EACE,sBAAsB;;AAGxB;EACE,aAAa;EACb,mBAAmB;EACnB,kBAAkB;;AAIlB;EACE,aAAa;EACb,mBAAmB;EACnB,uBAAuB;EACvB,WAAW;EACX,YAAY;EACZ,iBAAiB;;AAInB;EACE,aAAa;EACb,eAAe",
176 | "names": [],
177 | "sources": [
178 | "webpack:///./src/app/app.scss",
179 | ],
180 | "sourcesContent": [
181 | "* {
182 | box-sizing: border-box;
183 | }
184 |
185 | .row {
186 | display: flex;
187 | margin-right: -15px;
188 | margin-left: -15px;
189 | }
190 |
191 | .col {
192 | &-inner {
193 | display: flex;
194 | align-items: center;
195 | justify-content: center;
196 | color: #fff;
197 | height: 50px;
198 | background: coral;
199 | //background: red;
200 | }
201 |
202 | &-s3 {
203 | flex: 0 1 25%;
204 | padding: 0 15px;
205 | }
206 | }
207 | ",
208 | ],
209 | "version": 3,
210 | }
211 | `;
212 |
213 | exports[`source-map-loader should process css sourceMap: map 2`] = `
214 | {
215 | "mappings": "AAAA",
216 | "sources": [
217 | "/test/fixtures/normal-file.js - (normalized for test)",
218 | "unresolved-file.js",
219 | "/test/fixtures/normal-file2.js - (normalized for test)",
220 | ],
221 | "sourcesContent": [
222 | "without SourceMap",
223 | "",
224 | "// without SourceMap
225 | anInvalidDirective = "\\n/*# sourceMappingURL=data:application/json;base64,"+btoa(unescape(encodeURIComponent(JSON.stringify(sourceMap))))+" */";
226 | // comment
227 | ",
228 | ],
229 | "version": 3,
230 | }
231 | `;
232 |
233 | exports[`source-map-loader should process css sourceMap: warnings 1`] = `[]`;
234 |
235 | exports[`source-map-loader should process css sourceMap: warnings 2`] = `
236 | [
237 | "ModuleWarning: Module Warning (from \`replaced original path\`):
238 | Failed to parse source map from '/test/fixtures/unresolved-file.js' file: Error: ENOENT: no such file or directory, open '/test/fixtures/unresolved-file.js'",
239 | ]
240 | `;
241 |
242 | exports[`source-map-loader should process external SourceMaps (external sources): code 1`] = `
243 | "with SourceMap
244 | // comment"
245 | `;
246 |
247 | exports[`source-map-loader should process external SourceMaps (external sources): errors 1`] = `[]`;
248 |
249 | exports[`source-map-loader should process external SourceMaps (external sources): map 1`] = `
250 | {
251 | "file": "external-source-map2.js",
252 | "mappings": "AAAA",
253 | "sources": [
254 | "/test/fixtures/external-source-map2.txt - (normalized for test)",
255 | ],
256 | "sourcesContent": [
257 | "with SourceMap",
258 | ],
259 | "version": 3,
260 | }
261 | `;
262 |
263 | exports[`source-map-loader should process external SourceMaps (external sources): warnings 1`] = `[]`;
264 |
265 | exports[`source-map-loader should process external SourceMaps: code 1`] = `
266 | "with SourceMap
267 | // comment"
268 | `;
269 |
270 | exports[`source-map-loader should process external SourceMaps: errors 1`] = `[]`;
271 |
272 | exports[`source-map-loader should process external SourceMaps: map 1`] = `
273 | {
274 | "file": "external-source-map.js",
275 | "mappings": "AAAA",
276 | "sources": [
277 | "/test/fixtures/external-source-map.txt - (normalized for test)",
278 | ],
279 | "sourcesContent": [
280 | "with SourceMap",
281 | ],
282 | "version": 3,
283 | }
284 | `;
285 |
286 | exports[`source-map-loader should process external SourceMaps: warnings 1`] = `[]`;
287 |
288 | exports[`source-map-loader should process inlined SourceMaps with charset: code 1`] = `
289 | "with SourceMap
290 | // comment"
291 | `;
292 |
293 | exports[`source-map-loader should process inlined SourceMaps with charset: errors 1`] = `[]`;
294 |
295 | exports[`source-map-loader should process inlined SourceMaps with charset: map 1`] = `
296 | {
297 | "file": "charset-inline-source-map.js",
298 | "mappings": "AAAA",
299 | "sources": [
300 | "/test/fixtures/charset-inline-source-map.txt - (normalized for test)",
301 | ],
302 | "sourcesContent": [
303 | "with SourceMap",
304 | ],
305 | "version": 3,
306 | }
307 | `;
308 |
309 | exports[`source-map-loader should process inlined SourceMaps with charset: warnings 1`] = `[]`;
310 |
311 | exports[`source-map-loader should process inlined SourceMaps: code 1`] = `
312 | "with SourceMap
313 | // comment"
314 | `;
315 |
316 | exports[`source-map-loader should process inlined SourceMaps: errors 1`] = `[]`;
317 |
318 | exports[`source-map-loader should process inlined SourceMaps: map 1`] = `
319 | {
320 | "file": "inline-source-map.js",
321 | "mappings": "AAAA",
322 | "sources": [
323 | "/test/fixtures/inline-source-map.txt - (normalized for test)",
324 | ],
325 | "sourcesContent": [
326 | "with SourceMap",
327 | ],
328 | "version": 3,
329 | }
330 | `;
331 |
332 | exports[`source-map-loader should process inlined SourceMaps: warnings 1`] = `[]`;
333 |
334 | exports[`source-map-loader should process inlined sources: code 1`] = `
335 | "// Inline Sources in SourceMap
336 | // comment
337 | "
338 | `;
339 |
340 | exports[`source-map-loader should process inlined sources: errors 1`] = `[]`;
341 |
342 | exports[`source-map-loader should process inlined sources: map 1`] = `
343 | {
344 | "file": "inline-sources.js",
345 | "mappings": "AAAA",
346 | "sources": [
347 | "",
348 | ],
349 | "sourcesContent": [
350 | "some kind content",
351 | ],
352 | "version": 3,
353 | }
354 | `;
355 |
356 | exports[`source-map-loader should process inlined sources: warnings 1`] = `[]`;
357 |
358 | exports[`source-map-loader should process null in sources content: code 1`] = `
359 | "with SourceMap
360 | // comment
361 | "
362 | `;
363 |
364 | exports[`source-map-loader should process null in sources content: errors 1`] = `[]`;
365 |
366 | exports[`source-map-loader should process null in sources content: map 1`] = `
367 | {
368 | "file": "null-in-sources-content.js",
369 | "mappings": "AAAA",
370 | "sources": [
371 | "/test/fixtures/null-in-sources-content.txt - (normalized for test)",
372 | ],
373 | "sourcesContent": [
374 | "with SourceMap
375 | // comment
376 | ",
377 | ],
378 | "version": 3,
379 | }
380 | `;
381 |
382 | exports[`source-map-loader should process null in sources content: warnings 1`] = `[]`;
383 |
384 | exports[`source-map-loader should process percent-encoding path: code 1`] = `
385 | "with SourceMap
386 | // comment
387 | "
388 | `;
389 |
390 | exports[`source-map-loader should process percent-encoding path: errors 1`] = `[]`;
391 |
392 | exports[`source-map-loader should process percent-encoding path: warnings 1`] = `[]`;
393 |
394 | exports[`source-map-loader should process protocol-relative-url-path: code 1`] = `
395 | "// Some content
396 | // # sourceMappingURL=//sampledomain.com/external-source-map2.map
397 | // comment
398 | "
399 | `;
400 |
401 | exports[`source-map-loader should process protocol-relative-url-path: errors 1`] = `[]`;
402 |
403 | exports[`source-map-loader should process protocol-relative-url-path: warnings 1`] = `
404 | [
405 | "ModuleWarning: Module Warning (from \`replaced original path\`):
406 | Failed to parse source map: '//sampledomain.com/external-source-map2.map' URL is not supported",
407 | ]
408 | `;
409 |
410 | exports[`source-map-loader should process server-relative-url-path: code 1`] = `
411 | "with SourceMap
412 | // comment
413 | "
414 | `;
415 |
416 | exports[`source-map-loader should process server-relative-url-path: errors 1`] = `[]`;
417 |
418 | exports[`source-map-loader should process server-relative-url-path: map 1`] = `
419 | {
420 | "file": "server-relative-url-path.js",
421 | "mappings": "AAAA",
422 | "sources": [
423 | "/test/fixtures/server-relative-url-path.js - (normalized for test)",
424 | ],
425 | "sourcesContent": [
426 | "with SourceMap
427 | // #sourceMappingURL=/server-relative-url-path.js.map
428 | // comment
429 | ",
430 | ],
431 | "version": 3,
432 | }
433 | `;
434 |
435 | exports[`source-map-loader should process server-relative-url-path: warnings 1`] = `[]`;
436 |
437 | exports[`source-map-loader should reject http SourceMaps: code 1`] = `
438 | "with SourceMap
439 | //#sourceMappingURL=http://sampledomain.com/external-source-map2.map
440 | // comment
441 | "
442 | `;
443 |
444 | exports[`source-map-loader should reject http SourceMaps: errors 1`] = `[]`;
445 |
446 | exports[`source-map-loader should reject http SourceMaps: warnings 1`] = `
447 | [
448 | "ModuleWarning: Module Warning (from \`replaced original path\`):
449 | Failed to parse source map: 'http://sampledomain.com/external-source-map2.map' URL is not supported",
450 | ]
451 | `;
452 |
453 | exports[`source-map-loader should reject not exist file: SourceMaps: errors 1`] = `[]`;
454 |
455 | exports[`source-map-loader should reject not exist file: SourceMaps: warnings 1`] = `"TypeError [ERR_INVALID_FILE"`;
456 |
457 | exports[`source-map-loader should reject not support url: code 1`] = `
458 | "// with SourceMap
459 | //#sourceMappingURL=ftp://exampleurl.com
460 | // comment
461 | "
462 | `;
463 |
464 | exports[`source-map-loader should reject not support url: errors 1`] = `[]`;
465 |
466 | exports[`source-map-loader should reject not support url: warnings 1`] = `
467 | [
468 | "ModuleWarning: Module Warning (from \`replaced original path\`):
469 | Failed to parse source map: 'ftp://exampleurl.com' URL is not supported",
470 | ]
471 | `;
472 |
473 | exports[`source-map-loader should skip file protocol path if sourcesContent is set: code 1`] = `
474 | "// Some content
475 | "
476 | `;
477 |
478 | exports[`source-map-loader should skip file protocol path if sourcesContent is set: errors 1`] = `[]`;
479 |
480 | exports[`source-map-loader should skip file protocol path if sourcesContent is set: map 1`] = `
481 | {
482 | "mappings": "CAAC,IAAI,IAAM,SAAUA,GAClB,OAAOA",
483 | "sources": [
484 | "file:///external normal-file2.js",
485 | ],
486 | "sourcesContent": [
487 | "export default 3;",
488 | ],
489 | "version": 3,
490 | }
491 | `;
492 |
493 | exports[`source-map-loader should skip file protocol path if sourcesContent is set: warnings 1`] = `[]`;
494 |
495 | exports[`source-map-loader should skip invalid base64 SourceMap: code 1`] = `
496 | "without SourceMap
497 | // @sourceMappingURL=data:application/source-map;base64,"something invalid"
498 | // comment"
499 | `;
500 |
501 | exports[`source-map-loader should skip invalid base64 SourceMap: errors 1`] = `[]`;
502 |
503 | exports[`source-map-loader should skip invalid base64 SourceMap: warnings 1`] = `
504 | [
505 | "ModuleWarning: Module Warning (from \`replaced original path\`):
506 | Failed to parse source map from 'data:application/source-map;base64,': SyntaxError: Unexpected end of JSON input",
507 | ]
508 | `;
509 |
510 | exports[`source-map-loader should skip webpack protocol path if sourcesContent is set: code 1`] = `
511 | "!function(e){var t={};function r(n){if(t[n])return t[n].exports;var o=t[n]={i:n,l:!1,exports:{}};return e[n].call(o.exports,o,o.exports,r),o.l=!0,o.exports}r.m=e,r.c=t,r.d=function(e,t,n){r.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:n})},r.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},r.t=function(e,t){if(1&t&&(e=r(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(r.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)r.d(n,o,function(t){return e[t]}.bind(null,o));return n},r.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return r.d(t,"a",t),t},r.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},r.p="",r(r.s=0)}([function(e,t,r){"use strict";r.r(t),t.default=3}]);
512 | "
513 | `;
514 |
515 | exports[`source-map-loader should skip webpack protocol path if sourcesContent is set: errors 1`] = `[]`;
516 |
517 | exports[`source-map-loader should skip webpack protocol path if sourcesContent is set: map 1`] = `
518 | {
519 | "file": "main.js",
520 | "mappings": "aACE,IAAIA,EAAmB,GAGvB,SAASC,EAAoBC,GAG5B,GAAGF,EAAiBE,GACnB,OAAOF,EAAiBE,GAAUC,QAGnC,IAAIC,EAASJ,EAAiBE,GAAY,CACzCG,EAAGH,EACHI,GAAG,EACHH,QAAS,IAUV,OANAI,EAAQL,GAAUM,KAAKJ,EAAOD,QAASC,EAAQA,EAAOD,QAASF,GAG/DG,EAAOE,GAAI,EAGJF,EAAOD,QAKfF,EAAoBQ,EAAIF,EAGxBN,EAAoBS,EAAIV,EAGxBC,EAAoBU,EAAI,SAASR,EAASS,EAAMC,GAC3CZ,EAAoBa,EAAEX,EAASS,IAClCG,OAAOC,eAAeb,EAASS,EAAM,CAAEK,YAAY,EAAMC,IAAKL,KAKhEZ,EAAoBkB,EAAI,SAAShB,GACX,oBAAXiB,QAA0BA,OAAOC,aAC1CN,OAAOC,eAAeb,EAASiB,OAAOC,YAAa,CAAEC,MAAO,WAE7DP,OAAOC,eAAeb,EAAS,aAAc,CAAEmB,OAAO,KAQvDrB,EAAoBsB,EAAI,SAASD,EAAOE,GAEvC,GADU,EAAPA,IAAUF,EAAQrB,EAAoBqB,IAC/B,EAAPE,EAAU,OAAOF,EACpB,GAAW,EAAPE,GAA8B,iBAAVF,GAAsBA,GAASA,EAAMG,WAAY,OAAOH,EAChF,IAAII,EAAKX,OAAOY,OAAO,MAGvB,GAFA1B,EAAoBkB,EAAEO,GACtBX,OAAOC,eAAeU,EAAI,UAAW,CAAET,YAAY,EAAMK,MAAOA,IACtD,EAAPE,GAA4B,iBAATF,EAAmB,IAAI,IAAIM,KAAON,EAAOrB,EAAoBU,EAAEe,EAAIE,EAAK,SAASA,GAAO,OAAON,EAAMM,IAAQC,KAAK,KAAMD,IAC9I,OAAOF,GAIRzB,EAAoB6B,EAAI,SAAS1B,GAChC,IAAIS,EAAST,GAAUA,EAAOqB,WAC7B,WAAwB,OAAOrB,EAAgB,SAC/C,WAA8B,OAAOA,GAEtC,OADAH,EAAoBU,EAAEE,EAAQ,IAAKA,GAC5BA,GAIRZ,EAAoBa,EAAI,SAASiB,EAAQC,GAAY,OAAOjB,OAAOkB,UAAUC,eAAe1B,KAAKuB,EAAQC,IAGzG/B,EAAoBkC,EAAI,GAIjBlC,EAAoBA,EAAoBmC,EAAI,G,+BClFrD,OAAe",
521 | "names": [],
522 | "sources": [
523 | "webpack:///webpack/bootstrap",
524 | "webpack:///./src/index.js",
525 | "webpack:///external "$"",
526 | "/test/fixtures/external {"commonjs":"react","commonjs2":"react","amd":"react","root":"React"} - (normalized for test)",
527 | "/test/fixtures/external {"commonjs":"react-dom","commonjs2":"react-dom","amd":"react-dom","root":"ReactDOM"} - (normalized for test)",
528 | ],
529 | "sourcesContent": [
530 | " //webpack bootstrap;",
531 | "export default 3;",
532 | "module.exports = $;",
533 | "module.exports = __WEBPACK_EXTERNAL_MODULE__5__;",
534 | "module.exports = __WEBPACK_EXTERNAL_MODULE__6__;",
535 | ],
536 | "version": 3,
537 | }
538 | `;
539 |
540 | exports[`source-map-loader should skip webpack protocol path if sourcesContent is set: warnings 1`] = `[]`;
541 |
542 | exports[`source-map-loader should support absolute paths to sourcemaps: code 1`] = `
543 | "// Some content
544 | "
545 | `;
546 |
547 | exports[`source-map-loader should support absolute paths to sourcemaps: errors 1`] = `[]`;
548 |
549 | exports[`source-map-loader should support absolute paths to sourcemaps: map 1`] = `
550 | {
551 | "mappings": "CAAC,IAAI,IAAM,SAAUA,GAClB,OAAOA",
552 | "sources": [
553 | "/test/fixtures/normal-file.js - (normalized for test)",
554 | "/test/fixtures/normal-file2.js - (normalized for test)",
555 | ],
556 | "sourcesContent": [
557 | "without SourceMap",
558 | "// without SourceMap
559 | anInvalidDirective = "\\n/*# sourceMappingURL=data:application/json;base64,"+btoa(unescape(encodeURIComponent(JSON.stringify(sourceMap))))+" */";
560 | // comment
561 | ",
562 | ],
563 | "version": 3,
564 | }
565 | `;
566 |
567 | exports[`source-map-loader should support absolute paths to sourcemaps: warnings 1`] = `[]`;
568 |
569 | exports[`source-map-loader should support absolute sourceRoot paths in sourcemaps: code 1`] = `
570 | "with SourceMap
571 | // comment"
572 | `;
573 |
574 | exports[`source-map-loader should support absolute sourceRoot paths in sourcemaps: errors 1`] = `[]`;
575 |
576 | exports[`source-map-loader should support absolute sourceRoot paths in sourcemaps: map 1`] = `
577 | {
578 | "file": "absolute-sourceRoot-source-map.js",
579 | "mappings": "AAAA",
580 | "sources": [
581 | "/test/fixtures/absolute-sourceRoot-source-map.txt - (normalized for test)",
582 | ],
583 | "sourcesContent": [
584 | "with SourceMap
585 | // comment",
586 | ],
587 | "version": 3,
588 | }
589 | `;
590 |
591 | exports[`source-map-loader should support absolute sourceRoot paths in sourcemaps: warnings 1`] = `[]`;
592 |
593 | exports[`source-map-loader should support file protocol path: code 1`] = `
594 | "// Some content
595 | "
596 | `;
597 |
598 | exports[`source-map-loader should support file protocol path: errors 1`] = `[]`;
599 |
600 | exports[`source-map-loader should support file protocol path: map 1`] = `
601 | {
602 | "mappings": "CAAC,IAAI,IAAM,SAAUA,GAClB,OAAOA",
603 | "sources": [
604 | "/test/fixtures/normal-file.js - (normalized for test)",
605 | "/test/fixtures/normal-file2.js - (normalized for test)",
606 | ],
607 | "sourcesContent": [
608 | "without SourceMap",
609 | "// without SourceMap
610 | anInvalidDirective = "\\n/*# sourceMappingURL=data:application/json;base64,"+btoa(unescape(encodeURIComponent(JSON.stringify(sourceMap))))+" */";
611 | // comment
612 | ",
613 | ],
614 | "version": 3,
615 | }
616 | `;
617 |
618 | exports[`source-map-loader should support file protocol path: warnings 1`] = `[]`;
619 |
620 | exports[`source-map-loader should support indexed sourcemaps 2: code 1`] = `
621 | "console.log('with SourceMap')
622 | "
623 | `;
624 |
625 | exports[`source-map-loader should support indexed sourcemaps 2: errors 1`] = `[]`;
626 |
627 | exports[`source-map-loader should support indexed sourcemaps 2: map 1`] = `
628 | {
629 | "mappings": "CAAC,IAAI,IAAM,SAAU,GAClB,OAAO,IAAI;CCDb,IAAI,IAAM,SAAU,GAClB,OAAO",
630 | "names": [],
631 | "sources": [
632 | "/test/fixtures/indexed-sourcemap/nested1.js - (normalized for test)",
633 | "/different/root/nested2.js",
634 | ],
635 | "sourcesContent": [
636 | " ONE.foo = function (bar) {
637 | return baz(bar);
638 | };",
639 | " TWO.inc = function (n) {
640 | return n + 1;
641 | };",
642 | ],
643 | "version": 3,
644 | }
645 | `;
646 |
647 | exports[`source-map-loader should support indexed sourcemaps 2: warnings 1`] = `[]`;
648 |
649 | exports[`source-map-loader should support indexed sourcemaps: code 1`] = `
650 | "console.log('with SourceMap')
651 | // Map taken from here
652 | // https://github.com/mozilla/source-map/blob/master/test/util.js - indexedTestMapDifferentSourceRoots
653 | "
654 | `;
655 |
656 | exports[`source-map-loader should support indexed sourcemaps: errors 1`] = `[]`;
657 |
658 | exports[`source-map-loader should support indexed sourcemaps: map 1`] = `
659 | {
660 | "file": "file.js",
661 | "mappings": "CAAC,IAAI,IAAM,SAAU,GAClB,OAAO,IAAI;CCDb,IAAI,IAAM,SAAU,GAClB,OAAO",
662 | "names": [],
663 | "sources": [
664 | "/test/fixtures/indexed-sourcemap/nested1.js - (normalized for test)",
665 | "/different/root/nested2.js",
666 | ],
667 | "sourcesContent": [
668 | " ONE.foo = function (bar) {
669 | return baz(bar);
670 | };",
671 | " TWO.inc = function (n) {
672 | return n + 1;
673 | };",
674 | ],
675 | "version": 3,
676 | }
677 | `;
678 |
679 | exports[`source-map-loader should support indexed sourcemaps: warnings 1`] = `[]`;
680 |
681 | exports[`source-map-loader should support mixed paths in sources with sourceRoot: code 1`] = `
682 | "// Some content
683 | "
684 | `;
685 |
686 | exports[`source-map-loader should support mixed paths in sources with sourceRoot: errors 1`] = `[]`;
687 |
688 | exports[`source-map-loader should support mixed paths in sources with sourceRoot: map 1`] = `
689 | {
690 | "mappings": "CAAC,IAAI,IAAM,SAAUA,GAClB,OAAOA",
691 | "sources": [
692 | "/test/fixtures/normal-file.js - (normalized for test)",
693 | "/test/fixtures/normal-file2.js - (normalized for test)",
694 | "http://path-to-map.com",
695 | "ftp://path-to-map.com",
696 | ],
697 | "sourcesContent": [
698 | "without SourceMap",
699 | "// without SourceMap
700 | anInvalidDirective = "\\n/*# sourceMappingURL=data:application/json;base64,"+btoa(unescape(encodeURIComponent(JSON.stringify(sourceMap))))+" */";
701 | // comment
702 | ",
703 | "",
704 | "",
705 | ],
706 | "version": 3,
707 | }
708 | `;
709 |
710 | exports[`source-map-loader should support mixed paths in sources with sourceRoot: warnings 1`] = `
711 | [
712 | "ModuleWarning: Module Warning (from \`replaced original path\`):
713 | Failed to parse source map: 'ftp://path-to-map.com' URL is not supported",
714 | "ModuleWarning: Module Warning (from \`replaced original path\`):
715 | Failed to parse source map: 'http://path-to-map.com' URL is not supported",
716 | ]
717 | `;
718 |
719 | exports[`source-map-loader should support mixed paths in sources without sourceRoot: code 1`] = `
720 | "// Some content
721 | "
722 | `;
723 |
724 | exports[`source-map-loader should support mixed paths in sources without sourceRoot: errors 1`] = `[]`;
725 |
726 | exports[`source-map-loader should support mixed paths in sources without sourceRoot: map 1`] = `
727 | {
728 | "mappings": "CAAC,IAAI,IAAM,SAAUA,GAClB,OAAOA",
729 | "sources": [
730 | "/test/fixtures/normal-file.js - (normalized for test)",
731 | "/test/fixtures/normal-file2.js - (normalized for test)",
732 | "http://path-to-map.com",
733 | "ftp://path-to-map.com",
734 | ],
735 | "sourcesContent": [
736 | "without SourceMap",
737 | "// without SourceMap
738 | anInvalidDirective = "\\n/*# sourceMappingURL=data:application/json;base64,"+btoa(unescape(encodeURIComponent(JSON.stringify(sourceMap))))+" */";
739 | // comment
740 | ",
741 | "",
742 | "",
743 | ],
744 | "version": 3,
745 | }
746 | `;
747 |
748 | exports[`source-map-loader should support mixed paths in sources without sourceRoot: warnings 1`] = `
749 | [
750 | "ModuleWarning: Module Warning (from \`replaced original path\`):
751 | Failed to parse source map: 'ftp://path-to-map.com' URL is not supported",
752 | "ModuleWarning: Module Warning (from \`replaced original path\`):
753 | Failed to parse source map: 'http://path-to-map.com' URL is not supported",
754 | ]
755 | `;
756 |
757 | exports[`source-map-loader should support relative sourceRoot paths in sourcemaps: code 1`] = `
758 | "with SourceMap
759 | // comment"
760 | `;
761 |
762 | exports[`source-map-loader should support relative sourceRoot paths in sourcemaps: errors 1`] = `[]`;
763 |
764 | exports[`source-map-loader should support relative sourceRoot paths in sourcemaps: map 1`] = `
765 | {
766 | "file": "relative-sourceRoot-source-map.js",
767 | "mappings": "AAAA",
768 | "sources": [
769 | "/test/fixtures/data/relative-sourceRoot-source-map.txt - (normalized for test)",
770 | ],
771 | "sourcesContent": [
772 | "with SourceMap
773 | // comment",
774 | ],
775 | "version": 3,
776 | }
777 | `;
778 |
779 | exports[`source-map-loader should support relative sourceRoot paths in sourcemaps: warnings 1`] = `[]`;
780 |
781 | exports[`source-map-loader should use last SourceMap directive: code 1`] = `
782 | "with SourceMap
783 | anInvalidDirective = "\\n/*# sourceMappingURL=data:application/json;base64,"+btoa(unescape(encodeURIComponent(JSON.stringify(sourceMap))))+" */";
784 | // comment"
785 | `;
786 |
787 | exports[`source-map-loader should use last SourceMap directive: errors 1`] = `[]`;
788 |
789 | exports[`source-map-loader should use last SourceMap directive: map 1`] = `
790 | {
791 | "file": "inline-source-map.js",
792 | "mappings": "AAAA",
793 | "sources": [
794 | "/test/fixtures/inline-source-map.txt - (normalized for test)",
795 | ],
796 | "sourcesContent": [
797 | "with SourceMap",
798 | ],
799 | "version": 3,
800 | }
801 | `;
802 |
803 | exports[`source-map-loader should use last SourceMap directive: warnings 1`] = `[]`;
804 |
805 | exports[`source-map-loader should warn on invalid SourceMap: code 1`] = `
806 | "with SourceMap
807 | //#sourceMappingURL=invalid-source-map.map
808 | // comment"
809 | `;
810 |
811 | exports[`source-map-loader should warn on invalid SourceMap: errors 1`] = `[]`;
812 |
813 | exports[`source-map-loader should warn on invalid base64 SourceMap: code 1`] = `
814 | "without SourceMap
815 | // @sourceMappingURL=data:application/source-map;base64,invalid/base64=
816 | // comment"
817 | `;
818 |
819 | exports[`source-map-loader should warn on invalid base64 SourceMap: errors 1`] = `[]`;
820 |
821 | exports[`source-map-loader should warn on invalid base64 SourceMap: warnings 1`] = `
822 | [
823 | "ModuleWarning: Module Warning (from \`replaced original path\`):
824 | Failed to parse source map from "data" URL: data:application/source-map;base64,invalid/base64=",
825 | ]
826 | `;
827 |
828 | exports[`source-map-loader should warn on missing SourceMap: code 1`] = `
829 | "with SourceMap
830 | //#sourceMappingURL=missing-source-map.map
831 | // comment"
832 | `;
833 |
834 | exports[`source-map-loader should warn on missing SourceMap: errors 1`] = `[]`;
835 |
836 | exports[`source-map-loader should warn on missing SourceMap: warnings 1`] = `
837 | [
838 | "ModuleWarning: Module Warning (from \`replaced original path\`):
839 | Failed to parse source map from '/test/fixtures/missing-source-map.map' file: Error: ENOENT: no such file or directory, open '/test/fixtures/missing-source-map.map'",
840 | ]
841 | `;
842 |
843 | exports[`source-map-loader should warn on missing source file: code 1`] = `
844 | "with SourceMap
845 | // comment"
846 | `;
847 |
848 | exports[`source-map-loader should warn on missing source file: errors 1`] = `[]`;
849 |
850 | exports[`source-map-loader should warn on missing source file: map 1`] = `
851 | {
852 | "file": "missing-source-map2.js",
853 | "mappings": "AAAA",
854 | "sources": [
855 | "missing-source-map2.txt",
856 | ],
857 | "version": 3,
858 | }
859 | `;
860 |
861 | exports[`source-map-loader should warn on missing source file: warnings 1`] = `
862 | [
863 | "ModuleWarning: Module Warning (from \`replaced original path\`):
864 | Failed to parse source map from '/test/fixtures/missing-source-map2.txt' file: Error: ENOENT: no such file or directory, open '/test/fixtures/missing-source-map2.txt'",
865 | ]
866 | `;
867 |
--------------------------------------------------------------------------------
/test/__snapshots__/sourceMapperRegexp.test.js.snap:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://goo.gl/fbAQLP
2 |
3 | exports[`source-map-loader should work with "
4 | with SourceMap
5 |
6 | // #sourceMappingURL = /sample-source-map.map
7 | // comment
8 | " url: result 1`] = `"/sample-source-map.map"`;
9 |
10 | exports[`source-map-loader should work with "
11 | with SourceMap
12 | // #sourceMappingURL = /sample-source-map-1.map
13 | // #sourceMappingURL = /sample-source-map-2.map
14 | // #sourceMappingURL = /sample-source-map-last.map
15 | // comment
16 | " url: result 1`] = `"/sample-source-map-last.map"`;
17 |
18 | exports[`source-map-loader should work with " // # sourceMappingURL = absolute-sourceRoot-source-map.map " url: result 1`] = `"absolute-sourceRoot-source-map.map"`;
19 |
20 | exports[`source-map-loader should work with " // #sourceMappingURL=absolute-sourceRoot-source-map.map" url: result 1`] = `"absolute-sourceRoot-source-map.map"`;
21 |
22 | exports[`source-map-loader should work with ""
23 | /*# sourceMappingURL=data:application/json;base64,"+btoa(unescape(encodeURIComponent(JSON.stringify(sourceMap))))+" */";" url: result 1`] = `null`;
24 |
25 | exports[`source-map-loader should work with "/* #sourceMappingURL=absolute-sourceRoot-source-map.map */" url: result 1`] = `"absolute-sourceRoot-source-map.map"`;
26 |
27 | exports[`source-map-loader should work with "/*#sourceMappingURL=absolute-sourceRoot-source-map.map*/" url: result 1`] = `"absolute-sourceRoot-source-map.map"`;
28 |
29 | exports[`source-map-loader should work with "// # sourceMappingURL=data:application/json;base64,"+btoa(unescape(encodeURIComponent(JSON.stringify(sourceMap))))+"" url: result 1`] = `"data:application/json;base64,"`;
30 |
31 | exports[`source-map-loader should work with "// #sourceMappingURL = //sampledomain.com/external-source-map2.map" url: result 1`] = `"//sampledomain.com/external-source-map2.map"`;
32 |
33 | exports[`source-map-loader should work with "// #sourceMappingURL = http://sampledomain.com/external-source-map2.map" url: result 1`] = `"http://sampledomain.com/external-source-map2.map"`;
34 |
35 | exports[`source-map-loader should work with "// @sourceMappingURL=data:application/source-map;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5saW5lLXNvdXJjZS1tYXAuanMiLCJzb3VyY2VzIjpbImlubGluZS1zb3VyY2UtbWFwLnR4dCJdLCJzb3VyY2VzQ29udGVudCI6WyJ3aXRoIFNvdXJjZU1hcCJdLCJtYXBwaW5ncyI6IkFBQUEifQ==" url: result 1`] = `"data:application/source-map;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5saW5lLXNvdXJjZS1tYXAuanMiLCJzb3VyY2VzIjpbImlubGluZS1zb3VyY2UtbWFwLnR4dCJdLCJzb3VyY2VzQ29udGVudCI6WyJ3aXRoIFNvdXJjZU1hcCJdLCJtYXBwaW5ncyI6IkFBQUEifQ=="`;
36 |
37 | exports[`source-map-loader should work with "//#sourceMappingURL=absolute-sourceRoot-source-map.map" url: result 1`] = `"absolute-sourceRoot-source-map.map"`;
38 |
39 | exports[`source-map-loader should work with "//@sourceMappingURL=absolute-sourceRoot-source-map.map" url: result 1`] = `"absolute-sourceRoot-source-map.map"`;
40 |
41 | exports[`source-map-loader should work with "anInvalidDirective = "\\n/*# sourceMappingURL=data:application/json;base64,"+btoa(unescape(encodeURIComponent(JSON.stringify(sourceMap))))+" */";" url: result 1`] = `null`;
42 |
--------------------------------------------------------------------------------
/test/__snapshots__/validate-options.test.js.snap:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://goo.gl/fbAQLP
2 |
3 | exports[`validate options should throw an error on the "filterSourceMappingUrl" option with "/test/" value 1`] = `
4 | "Invalid options object. Source Map Loader has been initialized using an options object that does not match the API schema.
5 | - options.filterSourceMappingUrl should be an instance of function."
6 | `;
7 |
8 | exports[`validate options should throw an error on the "filterSourceMappingUrl" option with "[]" value 1`] = `
9 | "Invalid options object. Source Map Loader has been initialized using an options object that does not match the API schema.
10 | - options.filterSourceMappingUrl should be an instance of function."
11 | `;
12 |
13 | exports[`validate options should throw an error on the "filterSourceMappingUrl" option with "{"foo":"bar"}" value 1`] = `
14 | "Invalid options object. Source Map Loader has been initialized using an options object that does not match the API schema.
15 | - options.filterSourceMappingUrl should be an instance of function."
16 | `;
17 |
18 | exports[`validate options should throw an error on the "filterSourceMappingUrl" option with "{}" value 1`] = `
19 | "Invalid options object. Source Map Loader has been initialized using an options object that does not match the API schema.
20 | - options.filterSourceMappingUrl should be an instance of function."
21 | `;
22 |
23 | exports[`validate options should throw an error on the "filterSourceMappingUrl" option with "1" value 1`] = `
24 | "Invalid options object. Source Map Loader has been initialized using an options object that does not match the API schema.
25 | - options.filterSourceMappingUrl should be an instance of function."
26 | `;
27 |
28 | exports[`validate options should throw an error on the "filterSourceMappingUrl" option with "false" value 1`] = `
29 | "Invalid options object. Source Map Loader has been initialized using an options object that does not match the API schema.
30 | - options.filterSourceMappingUrl should be an instance of function."
31 | `;
32 |
33 | exports[`validate options should throw an error on the "filterSourceMappingUrl" option with "test" value 1`] = `
34 | "Invalid options object. Source Map Loader has been initialized using an options object that does not match the API schema.
35 | - options.filterSourceMappingUrl should be an instance of function."
36 | `;
37 |
38 | exports[`validate options should throw an error on the "filterSourceMappingUrl" option with "true" value 1`] = `
39 | "Invalid options object. Source Map Loader has been initialized using an options object that does not match the API schema.
40 | - options.filterSourceMappingUrl should be an instance of function."
41 | `;
42 |
43 | exports[`validate options should throw an error on the "unknown" option with "/test/" value 1`] = `
44 | "Invalid options object. Source Map Loader has been initialized using an options object that does not match the API schema.
45 | - options has an unknown property 'unknown'. These properties are valid:
46 | object { filterSourceMappingUrl? }"
47 | `;
48 |
49 | exports[`validate options should throw an error on the "unknown" option with "[]" value 1`] = `
50 | "Invalid options object. Source Map Loader has been initialized using an options object that does not match the API schema.
51 | - options has an unknown property 'unknown'. These properties are valid:
52 | object { filterSourceMappingUrl? }"
53 | `;
54 |
55 | exports[`validate options should throw an error on the "unknown" option with "{"foo":"bar"}" value 1`] = `
56 | "Invalid options object. Source Map Loader has been initialized using an options object that does not match the API schema.
57 | - options has an unknown property 'unknown'. These properties are valid:
58 | object { filterSourceMappingUrl? }"
59 | `;
60 |
61 | exports[`validate options should throw an error on the "unknown" option with "{}" value 1`] = `
62 | "Invalid options object. Source Map Loader has been initialized using an options object that does not match the API schema.
63 | - options has an unknown property 'unknown'. These properties are valid:
64 | object { filterSourceMappingUrl? }"
65 | `;
66 |
67 | exports[`validate options should throw an error on the "unknown" option with "1" value 1`] = `
68 | "Invalid options object. Source Map Loader has been initialized using an options object that does not match the API schema.
69 | - options has an unknown property 'unknown'. These properties are valid:
70 | object { filterSourceMappingUrl? }"
71 | `;
72 |
73 | exports[`validate options should throw an error on the "unknown" option with "false" value 1`] = `
74 | "Invalid options object. Source Map Loader has been initialized using an options object that does not match the API schema.
75 | - options has an unknown property 'unknown'. These properties are valid:
76 | object { filterSourceMappingUrl? }"
77 | `;
78 |
79 | exports[`validate options should throw an error on the "unknown" option with "test" value 1`] = `
80 | "Invalid options object. Source Map Loader has been initialized using an options object that does not match the API schema.
81 | - options has an unknown property 'unknown'. These properties are valid:
82 | object { filterSourceMappingUrl? }"
83 | `;
84 |
85 | exports[`validate options should throw an error on the "unknown" option with "true" value 1`] = `
86 | "Invalid options object. Source Map Loader has been initialized using an options object that does not match the API schema.
87 | - options has an unknown property 'unknown'. These properties are valid:
88 | object { filterSourceMappingUrl? }"
89 | `;
90 |
--------------------------------------------------------------------------------
/test/cjs.test.js:
--------------------------------------------------------------------------------
1 | import src from "../src";
2 | import cjs from "../src/cjs";
3 |
4 | describe("cjs", () => {
5 | it("should exported", () => {
6 | expect(cjs).toEqual(src);
7 | });
8 | });
9 |
--------------------------------------------------------------------------------
/test/filterSourceMappingUrl.test.js:
--------------------------------------------------------------------------------
1 | import {
2 | compile,
3 | getCodeFromBundle,
4 | getCompiler,
5 | getErrors,
6 | normalizeMap,
7 | getWarnings,
8 | } from "./helpers";
9 |
10 | describe("filterSourceMappingUrl option", () => {
11 | it("should work", async () => {
12 | expect.assertions(6);
13 |
14 | const testId = "external-source-map.js";
15 | const compiler = getCompiler(testId, {
16 | filterSourceMappingUrl: (sourceMappingURL, resourcePath) => {
17 | expect(sourceMappingURL).toBeDefined();
18 | expect(resourcePath).toBeDefined();
19 |
20 | return true;
21 | },
22 | });
23 | const stats = await compile(compiler);
24 | const codeFromBundle = getCodeFromBundle(stats, compiler);
25 |
26 | expect(codeFromBundle.code).toMatchSnapshot("code");
27 | expect(normalizeMap(codeFromBundle.map)).toMatchSnapshot("map");
28 | expect(getWarnings(stats)).toMatchSnapshot("warnings");
29 | expect(getErrors(stats)).toMatchSnapshot("errors");
30 | });
31 |
32 | it("should work with true value", async () => {
33 | const testId = "external-source-map.js";
34 | const compiler = getCompiler(testId, {
35 | filterSourceMappingUrl: () => true,
36 | });
37 | const stats = await compile(compiler);
38 | const codeFromBundle = getCodeFromBundle(stats, compiler);
39 |
40 | expect(codeFromBundle.code).toMatchSnapshot("code");
41 | expect(normalizeMap(codeFromBundle.map)).toMatchSnapshot("map");
42 | expect(getWarnings(stats)).toMatchSnapshot("warnings");
43 | expect(getErrors(stats)).toMatchSnapshot("errors");
44 | });
45 |
46 | it('should work with "skip" value', async () => {
47 | const testId = "http-source-map.js";
48 | const compiler = getCompiler(testId, {
49 | filterSourceMappingUrl: () => "skip",
50 | });
51 | const stats = await compile(compiler);
52 | const codeFromBundle = getCodeFromBundle(stats, compiler);
53 |
54 | expect(codeFromBundle.map).toBeUndefined();
55 | expect(codeFromBundle.code).toMatchSnapshot("code");
56 | expect(getWarnings(stats)).toMatchSnapshot("warnings");
57 | expect(getErrors(stats)).toMatchSnapshot("errors");
58 | });
59 |
60 | it('should work with "remove" value', async () => {
61 | const testId = "http-source-map.js";
62 | const compiler = getCompiler(testId, {
63 | filterSourceMappingUrl: () => "remove",
64 | });
65 | const stats = await compile(compiler);
66 | const codeFromBundle = getCodeFromBundle(stats, compiler);
67 |
68 | expect(codeFromBundle.map).toBeUndefined();
69 | expect(codeFromBundle.code).toMatchSnapshot("code");
70 | expect(getWarnings(stats)).toMatchSnapshot("warnings");
71 | expect(getErrors(stats)).toMatchSnapshot("errors");
72 | });
73 |
74 | it("should work with false value", async () => {
75 | const testId = "http-source-map.js";
76 | const compiler = getCompiler(testId, {
77 | filterSourceMappingUrl: () => false,
78 | });
79 | const stats = await compile(compiler);
80 | const codeFromBundle = getCodeFromBundle(stats, compiler);
81 |
82 | expect(codeFromBundle.map).toBeUndefined();
83 | expect(codeFromBundle.code).toMatchSnapshot("code");
84 | expect(getWarnings(stats)).toMatchSnapshot("warnings");
85 | expect(getErrors(stats)).toMatchSnapshot("errors");
86 | });
87 |
88 | it("should emit error", async () => {
89 | const testId = "external-source-map.js";
90 | const compiler = getCompiler(testId, {
91 | filterSourceMappingUrl: () => {
92 | throw new Error("error");
93 | },
94 | });
95 | const stats = await compile(compiler);
96 |
97 | expect(getWarnings(stats)).toMatchSnapshot("warnings");
98 | expect(getErrors(stats)).toMatchSnapshot("errors");
99 | });
100 | });
101 |
--------------------------------------------------------------------------------
/test/fixtures/.gitignore:
--------------------------------------------------------------------------------
1 | absolute-path.js
2 | absolute-sourceRoot-source-map.map
3 | map-with-sourceroot.js.map
4 | normal-map.js.map
5 |
--------------------------------------------------------------------------------
/test/fixtures/absolute-source-root.js:
--------------------------------------------------------------------------------
1 | const foo = "test";
2 | //# sourceMappingURL=absolute-source-root.js.map
3 |
--------------------------------------------------------------------------------
/test/fixtures/absolute-source-root.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"file":"index.d.ts","sourceRoot":"https://raw.githubusercontent.com/fb55/htmlparser2/4763205746cd80120b5d2b69041197a394d24ba9/src/","sources":["index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,EAAE,MAAM,EAAE,KAAK,aAAa,EAAE,CAAC;AAEtC,OAAO,EACH,UAAU,EACV,iBAAiB,EACjB,SAAS,EACT,OAAO,EACP,QAAQ,EACX,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,UAAU,EAAE,KAAK,iBAAiB,EAAE,CAAC;AAE9C,aAAK,OAAO,GAAG,aAAa,GAAG,iBAAiB,CAAC;AAIjD;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,GAAG,QAAQ,CAIvE;AACD;;;;;;;;;GASG;AACH,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,GAAG,SAAS,EAAE,CAErE;AACD;;;;;;GAMG;AACH,wBAAgB,eAAe,CAC3B,EAAE,EAAE,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI,EAAE,GAAG,EAAE,SAAS,EAAE,KAAK,IAAI,EACnD,OAAO,CAAC,EAAE,OAAO,EACjB,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,GACvC,MAAM,CAGR;AAED,OAAO,EACH,OAAO,IAAI,SAAS,EACpB,KAAK,SAAS,IAAI,kBAAkB,GACvC,MAAM,gBAAgB,CAAC;AAMxB,OAAO,KAAK,WAAW,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,CAAC;AAEvB,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AAEzC,OAAO,EAAE,OAAO,EAAE,CAAC;AAEnB;;;;;GAKG;AACH,wBAAgB,SAAS,CACrB,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE,aAAa,GAAG,iBAAqC,GAC/D,IAAI,GAAG,IAAI,CAEb;AAED,OAAO,KAAK,QAAQ,MAAM,UAAU,CAAC;AAGrC,OAAO,EAAE,UAAU,IAAI,cAAc,EAAE,CAAC"}
--------------------------------------------------------------------------------
/test/fixtures/absolute-sourceRoot-source-map.js:
--------------------------------------------------------------------------------
1 | with SourceMap
2 | //#sourceMappingURL=absolute-sourceRoot-source-map.map
3 | // comment
--------------------------------------------------------------------------------
/test/fixtures/absolute-sourceRoot-source-map.txt:
--------------------------------------------------------------------------------
1 | with SourceMap
2 | // comment
--------------------------------------------------------------------------------
/test/fixtures/app.css:
--------------------------------------------------------------------------------
1 | * {
2 | box-sizing: border-box; }
3 |
4 | .row {
5 | display: flex;
6 | margin-right: -15px;
7 | margin-left: -15px; }
8 |
9 | .col-inner {
10 | display: flex;
11 | align-items: center;
12 | justify-content: center;
13 | color: #fff;
14 | height: 50px;
15 | background: coral; }
16 |
17 | .col-s3 {
18 | flex: 0 1 25%;
19 | padding: 0 15px; }
20 |
21 |
22 | /*# sourceMappingURL=app.css.map*/
--------------------------------------------------------------------------------
/test/fixtures/app.css.map:
--------------------------------------------------------------------------------
1 | {"version":3,"sources":["webpack:///./src/app/app.scss"],"names":[],"mappings":"AAAA;EACE,sBAAsB;;AAGxB;EACE,aAAa;EACb,mBAAmB;EACnB,kBAAkB;;AAIlB;EACE,aAAa;EACb,mBAAmB;EACnB,uBAAuB;EACvB,WAAW;EACX,YAAY;EACZ,iBAAiB;;AAInB;EACE,aAAa;EACb,eAAe","file":"app.css","sourcesContent":["* {\n box-sizing: border-box;\n}\n\n.row {\n display: flex;\n margin-right: -15px;\n margin-left: -15px;\n}\n\n.col {\n &-inner {\n display: flex;\n align-items: center;\n justify-content: center;\n color: #fff;\n height: 50px;\n background: coral;\n //background: red;\n }\n\n &-s3 {\n flex: 0 1 25%;\n padding: 0 15px;\n }\n}\n"],"sourceRoot":""}
--------------------------------------------------------------------------------
/test/fixtures/charset-inline-source-map.js:
--------------------------------------------------------------------------------
1 | with SourceMap
2 | // @ sourceMappingURL = data:application/source-map;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2hhcnNldC1pbmxpbmUtc291cmNlLW1hcC5qcyIsInNvdXJjZXMiOlsiY2hhcnNldC1pbmxpbmUtc291cmNlLW1hcC50eHQiXSwic291cmNlc0NvbnRlbnQiOlsid2l0aCBTb3VyY2VNYXAiXSwibWFwcGluZ3MiOiJBQUFBIn0=
3 | // comment
--------------------------------------------------------------------------------
/test/fixtures/charset-inline-source-map.txt:
--------------------------------------------------------------------------------
1 | // Content
2 |
--------------------------------------------------------------------------------
/test/fixtures/data/external-source-map2.map:
--------------------------------------------------------------------------------
1 | {"version":3,"file":"external-source-map2.js","sources":["../external-source-map2.txt"],"mappings":"AAAA"}
--------------------------------------------------------------------------------
/test/fixtures/data/relative-sourceRoot-source-map.txt:
--------------------------------------------------------------------------------
1 | with SourceMap
2 | // comment
--------------------------------------------------------------------------------
/test/fixtures/dependencies.js:
--------------------------------------------------------------------------------
1 | // Dependencies
2 | //#sourceMappingURL=dependencies.js.map
3 |
--------------------------------------------------------------------------------
/test/fixtures/dependencies.js.map:
--------------------------------------------------------------------------------
1 | {
2 | "version":3,
3 | "file":"inline-sources.js",
4 | "sources":[
5 | "./data/relative-sourceRoot-source-map.txt",
6 | "./data/not-found.txt",
7 | "data:application/json;base64,c29tZSBraW5kIGNvbnRlbnQ=",
8 | "data:invalid;A;a"
9 | ],
10 | "mappings":"AAAA"
11 | }
12 |
--------------------------------------------------------------------------------
/test/fixtures/dependencies2.js:
--------------------------------------------------------------------------------
1 | // Dependencies
2 | //#sourceMappingURL=dependencies2.js.map
3 |
--------------------------------------------------------------------------------
/test/fixtures/dependencies2.js.map:
--------------------------------------------------------------------------------
1 | {
2 | "version":3,
3 | "file":"inline-sources.js",
4 | "sources":[
5 | "./data/relative-sourceRoot-source-map.txt",
6 | "./data/not-found.txt",
7 | "data:application/json;base64,c29tZSBraW5kIGNvbnRlbnQ=",
8 | "data:invalid;A;a"
9 | ],
10 | "sourcesContent": [
11 | "foo",
12 | "bar",
13 | "",
14 | "baz"
15 | ],
16 | "mappings":"AAAA"
17 | }
18 |
--------------------------------------------------------------------------------
/test/fixtures/external-by-webpack.js.map:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/webpack-contrib/source-map-loader/2f67eead9f9eb9a0755e89f05f2683240d3be3d7/test/fixtures/external-by-webpack.js.map
--------------------------------------------------------------------------------
/test/fixtures/external-source-map.js:
--------------------------------------------------------------------------------
1 | with SourceMap
2 | //#sourceMappingURL=external-source-map.map
3 | // comment
--------------------------------------------------------------------------------
/test/fixtures/external-source-map.map:
--------------------------------------------------------------------------------
1 | {"version":3,"file":"external-source-map.js","sources":["external-source-map.txt"],"sourcesContent":["with SourceMap"],"mappings":"AAAA"}
--------------------------------------------------------------------------------
/test/fixtures/external-source-map2.js:
--------------------------------------------------------------------------------
1 | with SourceMap
2 | //#sourceMappingURL=data/external-source-map2.map
3 | // comment
--------------------------------------------------------------------------------
/test/fixtures/external-source-map2.txt:
--------------------------------------------------------------------------------
1 | with SourceMap
--------------------------------------------------------------------------------
/test/fixtures/file-broken-protocol-path.js:
--------------------------------------------------------------------------------
1 | // Some content
2 | // # sourceMappingURL=file-broken-protocol-path.js.map
3 |
--------------------------------------------------------------------------------
/test/fixtures/file-broken-protocol-path.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"sources":["file:///external normal-file2.js"],"sourcesContent":["export default 3;"],"mappings":"CAAC,IAAI,IAAM,SAAUA,GAClB,OAAOA"}
2 |
--------------------------------------------------------------------------------
/test/fixtures/file-source-map-windows.js:
--------------------------------------------------------------------------------
1 | with SourceMap
2 | // #sourceMappingURL=file:///unresolvedPath/map.map
3 | // comment
4 |
--------------------------------------------------------------------------------
/test/fixtures/file-source-map.js:
--------------------------------------------------------------------------------
1 | with SourceMap
2 | // #sourceMappingURL=file://relative-sourceRoot-source-map.map
3 | // comment
4 |
--------------------------------------------------------------------------------
/test/fixtures/http-source-map.js:
--------------------------------------------------------------------------------
1 | with SourceMap
2 | //#sourceMappingURL=http://sampledomain.com/external-source-map2.map
3 | // comment
4 |
--------------------------------------------------------------------------------
/test/fixtures/indexed-sourcemap/file.js:
--------------------------------------------------------------------------------
1 | console.log('with SourceMap')
2 | //#sourceMappingURL=file.js.map
3 | // Map taken from here
4 | // https://github.com/mozilla/source-map/blob/master/test/util.js - indexedTestMapDifferentSourceRoots
5 |
--------------------------------------------------------------------------------
/test/fixtures/indexed-sourcemap/file.js.map:
--------------------------------------------------------------------------------
1 | {
2 | "version": 3,
3 | "file": "file.js",
4 | "sections": [
5 | {
6 | "offset": {
7 | "line": 0,
8 | "column": 0
9 | },
10 | "map": {
11 | "version": 3,
12 | "sources": ["nested1.js"],
13 | "sourcesContent": [
14 | " ONE.foo = function (bar) {\n return baz(bar);\n };"
15 | ],
16 | "names": ["bar", "baz"],
17 | "mappings": "CAAC,IAAI,IAAM,SAAUA,GAClB,OAAOC,IAAID",
18 | "file": "file.js"
19 | }
20 | },
21 | {
22 | "offset": {
23 | "line": 1,
24 | "column": 0
25 | },
26 | "map": {
27 | "version": 3,
28 | "sources": ["nested2.js"],
29 | "sourcesContent": [" TWO.inc = function (n) {\n return n + 1;\n };"],
30 | "names": ["n"],
31 | "mappings": "CAAC,IAAI,IAAM,SAAUA,GAClB,OAAOA",
32 | "file": "file.js",
33 | "sourceRoot": "/different/root"
34 | }
35 | }
36 | ]
37 | }
38 |
--------------------------------------------------------------------------------
/test/fixtures/indexed-sourcemap/file2.js:
--------------------------------------------------------------------------------
1 | console.log('with SourceMap')
2 | //#sourceMappingURL=file2.js.map
3 |
--------------------------------------------------------------------------------
/test/fixtures/indexed-sourcemap/file2.js.map:
--------------------------------------------------------------------------------
1 | {
2 | "version": 3,
3 | "sections": [
4 | {
5 | "offset": {
6 | "line": 0,
7 | "column": 0
8 | },
9 | "map": {
10 | "version": 3,
11 | "sources": ["nested1.js"],
12 | "sourcesContent": [
13 | " ONE.foo = function (bar) {\n return baz(bar);\n };"
14 | ],
15 | "names": ["bar", "baz"],
16 | "mappings": "CAAC,IAAI,IAAM,SAAUA,GAClB,OAAOC,IAAID"
17 | }
18 | },
19 | {
20 | "offset": {
21 | "line": 1,
22 | "column": 0
23 | },
24 | "map": {
25 | "version": 3,
26 | "sources": ["nested2.js"],
27 | "sourcesContent": [" TWO.inc = function (n) {\n return n + 1;\n };"],
28 | "names": ["n"],
29 | "mappings": "CAAC,IAAI,IAAM,SAAUA,GAClB,OAAOA",
30 | "sourceRoot": "/different/root"
31 | }
32 | }
33 | ]
34 | }
35 |
--------------------------------------------------------------------------------
/test/fixtures/indexed-sourcemap/nested1.js:
--------------------------------------------------------------------------------
1 | ONE.foo = function (bar) {
2 | return baz(bar);
3 | };
4 |
--------------------------------------------------------------------------------
/test/fixtures/indexed-sourcemap/nested2.js:
--------------------------------------------------------------------------------
1 | TWO.inc = function (n) {
2 | return n + 1;
3 | };
4 |
--------------------------------------------------------------------------------
/test/fixtures/inline-source-map.js:
--------------------------------------------------------------------------------
1 | with SourceMap
2 | // @ sourceMappingURL = data:application/source-map;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5saW5lLXNvdXJjZS1tYXAuanMiLCJzb3VyY2VzIjpbImlubGluZS1zb3VyY2UtbWFwLnR4dCJdLCJzb3VyY2VzQ29udGVudCI6WyJ3aXRoIFNvdXJjZU1hcCJdLCJtYXBwaW5ncyI6IkFBQUEifQ==
3 | // comment
--------------------------------------------------------------------------------
/test/fixtures/inline-sources.js:
--------------------------------------------------------------------------------
1 | // Inline Sources in SourceMap
2 | //#sourceMappingURL=inline-sources.js.map
3 | // comment
4 |
--------------------------------------------------------------------------------
/test/fixtures/inline-sources.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"file":"inline-sources.js","sources":["data:application/json;base64,c29tZSBraW5kIGNvbnRlbnQ="],"mappings":"AAAA"}
2 |
--------------------------------------------------------------------------------
/test/fixtures/invalid-inline-source-map.js:
--------------------------------------------------------------------------------
1 | without SourceMap
2 | // @sourceMappingURL=data:application/source-map;base64,"something invalid"
3 | // comment
--------------------------------------------------------------------------------
/test/fixtures/invalid-inline-source-map2.js:
--------------------------------------------------------------------------------
1 | without SourceMap
2 | // @sourceMappingURL=data:application/source-map;base64,invalid/base64=
3 | // comment
--------------------------------------------------------------------------------
/test/fixtures/invalid-source-map.js:
--------------------------------------------------------------------------------
1 | with SourceMap
2 | //#sourceMappingURL=invalid-source-map.map
3 | // comment
--------------------------------------------------------------------------------
/test/fixtures/invalid-source-map.map:
--------------------------------------------------------------------------------
1 | {"version":3,"file":"invalid-source-map.js","sources":["../invalid-source-map.txt"],"mappings":"AAAA"}"}
--------------------------------------------------------------------------------
/test/fixtures/missing-source-map.js:
--------------------------------------------------------------------------------
1 | with SourceMap
2 | //#sourceMappingURL=missing-source-map.map
3 | // comment
--------------------------------------------------------------------------------
/test/fixtures/missing-source-map2.js:
--------------------------------------------------------------------------------
1 | with SourceMap
2 | //#sourceMappingURL=missing-source-map2.map
3 | // comment
--------------------------------------------------------------------------------
/test/fixtures/missing-source-map2.map:
--------------------------------------------------------------------------------
1 | {"version":3,"file":"missing-source-map2.js","sources":["missing-source-map2.txt"],"mappings":"AAAA"}
--------------------------------------------------------------------------------
/test/fixtures/multi-source-map.js:
--------------------------------------------------------------------------------
1 | with SourceMap
2 | anInvalidDirective = "\n/*# sourceMappingURL=data:application/json;base64,"+btoa(unescape(encodeURIComponent(JSON.stringify(sourceMap))))+" */";
3 | // @ sourceMappingURL = data:application/source-map;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5saW5lLXNvdXJjZS1tYXAuanMiLCJzb3VyY2VzIjpbImlubGluZS1zb3VyY2UtbWFwLnR4dCJdLCJzb3VyY2VzQ29udGVudCI6WyJ3aXRoIFNvdXJjZU1hcCJdLCJtYXBwaW5ncyI6IkFBQUEifQ==
4 | // comment
--------------------------------------------------------------------------------
/test/fixtures/normal-file.js:
--------------------------------------------------------------------------------
1 | without SourceMap
--------------------------------------------------------------------------------
/test/fixtures/normal-file2.js:
--------------------------------------------------------------------------------
1 | // without SourceMap
2 | anInvalidDirective = "\n/*# sourceMappingURL=data:application/json;base64,"+btoa(unescape(encodeURIComponent(JSON.stringify(sourceMap))))+" */";
3 | // comment
4 |
--------------------------------------------------------------------------------
/test/fixtures/null-in-sources-content.js:
--------------------------------------------------------------------------------
1 | with SourceMap
2 | // #sourceMappingURL=null-in-sources-content.js.map
3 | // comment
4 |
--------------------------------------------------------------------------------
/test/fixtures/null-in-sources-content.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"file":"null-in-sources-content.js","sources":["null-in-sources-content.txt"],"sourcesContent":[null],"mappings":"AAAA"}
2 |
--------------------------------------------------------------------------------
/test/fixtures/null-in-sources-content.txt:
--------------------------------------------------------------------------------
1 | with SourceMap
2 | // comment
3 |
--------------------------------------------------------------------------------
/test/fixtures/protocol-relative-url-path.js:
--------------------------------------------------------------------------------
1 | // Some content
2 | // # sourceMappingURL=//sampledomain.com/external-source-map2.map
3 | // comment
4 |
--------------------------------------------------------------------------------
/test/fixtures/relative-sourceRoot-source-map.js:
--------------------------------------------------------------------------------
1 | with SourceMap
2 | //#sourceMappingURL=relative-sourceRoot-source-map.map
3 | // comment
--------------------------------------------------------------------------------
/test/fixtures/relative-sourceRoot-source-map.map:
--------------------------------------------------------------------------------
1 | {"version":3,"file":"relative-sourceRoot-source-map.js","sourceRoot":"../fixtures/data/","sources":["relative-sourceRoot-source-map.txt"],"mappings":"AAAA"}
--------------------------------------------------------------------------------
/test/fixtures/server-relative-url-path.js:
--------------------------------------------------------------------------------
1 | with SourceMap
2 | // #sourceMappingURL=/server-relative-url-path.js.map
3 | // comment
4 |
--------------------------------------------------------------------------------
/test/fixtures/skip-sourcesContent.js:
--------------------------------------------------------------------------------
1 | // Skip SourcesContent in SourceMap
2 | // # sourceMappingURL=skip-sourcesContent.js.map
3 | // comment
4 |
--------------------------------------------------------------------------------
/test/fixtures/skip-sourcesContent.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"sources":["normal-file.js","unresolved-file.js","normal-file2.js"],"mappings":"AAAA"}
2 |
--------------------------------------------------------------------------------
/test/fixtures/unSupport-file-source-map.js:
--------------------------------------------------------------------------------
1 | // with SourceMap
2 | //#sourceMappingURL=ftp://exampleurl.com
3 | // comment
4 |
--------------------------------------------------------------------------------
/test/fixtures/unresolved-server-relative-url-path.js:
--------------------------------------------------------------------------------
1 | with SourceMap
2 | // #sourceMappingURL=/unresolved-server-relative-url-path.js.map
3 | // comment
4 |
--------------------------------------------------------------------------------
/test/fixtures/webpack/main.js:
--------------------------------------------------------------------------------
1 | !function(e){var t={};function r(n){if(t[n])return t[n].exports;var o=t[n]={i:n,l:!1,exports:{}};return e[n].call(o.exports,o,o.exports,r),o.l=!0,o.exports}r.m=e,r.c=t,r.d=function(e,t,n){r.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:n})},r.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},r.t=function(e,t){if(1&t&&(e=r(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(r.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)r.d(n,o,function(t){return e[t]}.bind(null,o));return n},r.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return r.d(t,"a",t),t},r.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},r.p="",r(r.s=0)}([function(e,t,r){"use strict";r.r(t),t.default=3}]);
2 | //# sourceMappingURL=main.js.map
3 |
--------------------------------------------------------------------------------
/test/fixtures/webpack/main.js.map:
--------------------------------------------------------------------------------
1 | {
2 | "version": 3,
3 | "sources": [
4 | "webpack:///webpack/bootstrap",
5 | "webpack:///./src/index.js",
6 | "webpack:///external \"$\"",
7 | "../external {\"commonjs\":\"react\",\"commonjs2\":\"react\",\"amd\":\"react\",\"root\":\"React\"}",
8 | "../external {\"commonjs\":\"react-dom\",\"commonjs2\":\"react-dom\",\"amd\":\"react-dom\",\"root\":\"ReactDOM\"}"
9 | ],
10 | "names": [],
11 | "mappings": "aACE,IAAIA,EAAmB,GAGvB,SAASC,EAAoBC,GAG5B,GAAGF,EAAiBE,GACnB,OAAOF,EAAiBE,GAAUC,QAGnC,IAAIC,EAASJ,EAAiBE,GAAY,CACzCG,EAAGH,EACHI,GAAG,EACHH,QAAS,IAUV,OANAI,EAAQL,GAAUM,KAAKJ,EAAOD,QAASC,EAAQA,EAAOD,QAASF,GAG/DG,EAAOE,GAAI,EAGJF,EAAOD,QAKfF,EAAoBQ,EAAIF,EAGxBN,EAAoBS,EAAIV,EAGxBC,EAAoBU,EAAI,SAASR,EAASS,EAAMC,GAC3CZ,EAAoBa,EAAEX,EAASS,IAClCG,OAAOC,eAAeb,EAASS,EAAM,CAAEK,YAAY,EAAMC,IAAKL,KAKhEZ,EAAoBkB,EAAI,SAAShB,GACX,oBAAXiB,QAA0BA,OAAOC,aAC1CN,OAAOC,eAAeb,EAASiB,OAAOC,YAAa,CAAEC,MAAO,WAE7DP,OAAOC,eAAeb,EAAS,aAAc,CAAEmB,OAAO,KAQvDrB,EAAoBsB,EAAI,SAASD,EAAOE,GAEvC,GADU,EAAPA,IAAUF,EAAQrB,EAAoBqB,IAC/B,EAAPE,EAAU,OAAOF,EACpB,GAAW,EAAPE,GAA8B,iBAAVF,GAAsBA,GAASA,EAAMG,WAAY,OAAOH,EAChF,IAAII,EAAKX,OAAOY,OAAO,MAGvB,GAFA1B,EAAoBkB,EAAEO,GACtBX,OAAOC,eAAeU,EAAI,UAAW,CAAET,YAAY,EAAMK,MAAOA,IACtD,EAAPE,GAA4B,iBAATF,EAAmB,IAAI,IAAIM,KAAON,EAAOrB,EAAoBU,EAAEe,EAAIE,EAAK,SAASA,GAAO,OAAON,EAAMM,IAAQC,KAAK,KAAMD,IAC9I,OAAOF,GAIRzB,EAAoB6B,EAAI,SAAS1B,GAChC,IAAIS,EAAST,GAAUA,EAAOqB,WAC7B,WAAwB,OAAOrB,EAAgB,SAC/C,WAA8B,OAAOA,GAEtC,OADAH,EAAoBU,EAAEE,EAAQ,IAAKA,GAC5BA,GAIRZ,EAAoBa,EAAI,SAASiB,EAAQC,GAAY,OAAOjB,OAAOkB,UAAUC,eAAe1B,KAAKuB,EAAQC,IAGzG/B,EAAoBkC,EAAI,GAIjBlC,EAAoBA,EAAoBmC,EAAI,G,+BClFrD,OAAe",
12 | "file": "main.js",
13 | "sourcesContent": [
14 | " //webpack bootstrap;",
15 | "export default 3;",
16 | "module.exports = $;",
17 | "module.exports = __WEBPACK_EXTERNAL_MODULE__5__;",
18 | "module.exports = __WEBPACK_EXTERNAL_MODULE__6__;"
19 | ],
20 | "sourceRoot": ""
21 | }
22 |
--------------------------------------------------------------------------------
/test/fixtures/{percent}.js:
--------------------------------------------------------------------------------
1 | with SourceMap
2 | // #sourceMappingURL=%7Bpercent%7D.js.map
3 | // comment
4 |
--------------------------------------------------------------------------------
/test/fixtures/{percent}.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"file":"{percent}.js","sources":["{percent}.js"],"mappings":"AAAA"}
2 |
--------------------------------------------------------------------------------
/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(code, resource);
17 |
18 | return module.exports;
19 | };
20 |
--------------------------------------------------------------------------------
/test/helpers/getCodeFromBundle.js:
--------------------------------------------------------------------------------
1 | import vm from "vm";
2 |
3 | import readAsset from "./readAsset";
4 |
5 | function getCodeFromBundle(stats, compiler, asset) {
6 | let code = null;
7 |
8 | if (
9 | stats &&
10 | stats.compilation &&
11 | stats.compilation.assets &&
12 | stats.compilation.assets[asset || "main.bundle.js"]
13 | ) {
14 | code = readAsset(asset || "main.bundle.js", compiler, stats);
15 | }
16 |
17 | if (!code) {
18 | throw new Error("Can't find compiled code");
19 | }
20 |
21 | const result = vm.runInNewContext(
22 | `${code};\nmodule.exports = sourceMapLoaderExport;`,
23 | {
24 | module: {},
25 | },
26 | );
27 |
28 | // eslint-disable-next-line no-underscore-dangle
29 | return result.__esModule ? result.default : result;
30 | }
31 |
32 | export default getCodeFromBundle;
33 |
--------------------------------------------------------------------------------
/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 (
7 | fixture,
8 | loaderOptions = {},
9 | config = {},
10 | skipTestLoader = false,
11 | ) => {
12 | const loaders = [
13 | {
14 | loader: path.resolve(__dirname, "../../src"),
15 | options: loaderOptions || {},
16 | },
17 | ];
18 |
19 | if (!skipTestLoader) {
20 | loaders.unshift({
21 | loader: require.resolve("./testLoader"),
22 | });
23 | }
24 |
25 | const fullConfig = {
26 | mode: "development",
27 | devtool: config.devtool || "source-map",
28 | context: path.resolve(__dirname, "../fixtures"),
29 | entry: path.resolve(__dirname, "../fixtures", fixture),
30 | output: {
31 | path: path.resolve(__dirname, "../outputs"),
32 | filename: "[name].bundle.js",
33 | chunkFilename: "[name].chunk.js",
34 | library: "sourceMapLoaderExport",
35 | // devtoolModuleFilenameTemplate: "[absolute-resource-path]"
36 | },
37 | module: {
38 | rules: [
39 | {
40 | test: /\.js/i,
41 | use: loaders,
42 | },
43 |
44 | {
45 | test: /\.css/i,
46 | use: loaders,
47 | },
48 | ],
49 | },
50 | plugins: [],
51 | ...config,
52 | };
53 |
54 | const compiler = webpack(fullConfig);
55 |
56 | if (!config.outputFileSystem) {
57 | compiler.outputFileSystem = createFsFromVolume(new Volume());
58 | }
59 |
60 | return compiler;
61 | };
62 |
--------------------------------------------------------------------------------
/test/helpers/getErrors.js:
--------------------------------------------------------------------------------
1 | import normalizeErrors from "./normalizeErrors";
2 |
3 | export default (stats) => normalizeErrors(stats.compilation.errors.sort());
4 |
--------------------------------------------------------------------------------
/test/helpers/getWarnings.js:
--------------------------------------------------------------------------------
1 | import normalizeErrors from "./normalizeErrors";
2 |
3 | export default (stats, shortError) =>
4 | normalizeErrors(stats.compilation.warnings.sort(), shortError);
5 |
--------------------------------------------------------------------------------
/test/helpers/index.js:
--------------------------------------------------------------------------------
1 | import compile from "./compile";
2 | import execute from "./execute";
3 | import getCodeFromBundle from "./getCodeFromBundle";
4 | import getCompiler from "./getCompiler";
5 | import getErrors from "./getErrors";
6 | import normalizeMap from "./normalizeMap";
7 | import getWarnings from "./getWarnings";
8 | import normalizeErrors from "./normalizeErrors";
9 | import readAsset from "./readAsset";
10 | import readsAssets from "./readAssets";
11 |
12 | export {
13 | compile,
14 | execute,
15 | getCodeFromBundle,
16 | getCompiler,
17 | getErrors,
18 | normalizeMap,
19 | getWarnings,
20 | normalizeErrors,
21 | readAsset,
22 | readsAssets,
23 | };
24 |
--------------------------------------------------------------------------------
/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 | }
16 |
17 | export default (errors, shortError) =>
18 | errors.map((error) => {
19 | let errorMessage = error.toString();
20 |
21 | if (shortError) {
22 | errorMessage = errorMessage.split("\n").slice(0, 1).join("\n");
23 | }
24 |
25 | return removeCWD(errorMessage.split("\n").slice(0, 2).join("\n"));
26 | });
27 |
--------------------------------------------------------------------------------
/test/helpers/normalizeMap.js:
--------------------------------------------------------------------------------
1 | export default (map) => {
2 | const result = map;
3 |
4 | if (result.sources) {
5 | result.sources = normalizeArr(result.sources);
6 | }
7 |
8 | if (result.file) {
9 | [result.file] = normalizeArr([result.file]);
10 | }
11 |
12 | if (result.sourceRoot) {
13 | [result.sourceRoot] = normalizeArr([result.sourceRoot]);
14 | }
15 |
16 | return result;
17 | };
18 |
19 | function normalizeArr(arr) {
20 | return arr.map((str) => {
21 | const normilized = removeCWD(str);
22 |
23 | if (str === normilized) {
24 | return str;
25 | }
26 |
27 | if (str.replace(/\\/g, "/") === normilized) {
28 | return normilized;
29 | }
30 |
31 | return `${normilized} - (normalized for test)`;
32 | });
33 | }
34 |
35 | function removeCWD(str) {
36 | const isWin = process.platform === "win32";
37 | let cwd = process.cwd();
38 |
39 | if (isWin) {
40 | // eslint-disable-next-line no-param-reassign
41 | str = str.replace(/\\/g, "/");
42 | cwd = cwd.replace(/\\/g, "/");
43 | }
44 |
45 | return str.replace(new RegExp(cwd, "g"), "");
46 | }
47 |
--------------------------------------------------------------------------------
/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 |
7 | let data = "";
8 | let targetFile = asset;
9 |
10 | const queryStringIdx = targetFile.indexOf("?");
11 |
12 | if (queryStringIdx >= 0) {
13 | targetFile = targetFile.slice(0, queryStringIdx);
14 | }
15 |
16 | try {
17 | data = usedFs.readFileSync(path.join(outputPath, targetFile)).toString();
18 | } catch (error) {
19 | data = error.toString();
20 | }
21 |
22 | return data;
23 | };
24 |
--------------------------------------------------------------------------------
/test/helpers/readAssets.js:
--------------------------------------------------------------------------------
1 | import readAsset from "./readAsset";
2 |
3 | export default function readAssets(compiler, stats) {
4 | const assets = {};
5 |
6 | Object.keys(stats.compilation.assets).forEach((asset) => {
7 | assets[asset] = readAsset(asset, compiler, stats);
8 | });
9 |
10 | return assets;
11 | }
12 |
--------------------------------------------------------------------------------
/test/helpers/testLoader.js:
--------------------------------------------------------------------------------
1 | function testLoader(content, sourceMap) {
2 | const result = { code: content };
3 |
4 | if (sourceMap) {
5 | result.map = sourceMap;
6 | }
7 |
8 | return `export default ${JSON.stringify(result)}`;
9 | }
10 |
11 | module.exports = testLoader;
12 |
--------------------------------------------------------------------------------
/test/loader.test.js:
--------------------------------------------------------------------------------
1 | import path from "path";
2 | import fs from "fs";
3 |
4 | import {
5 | compile,
6 | getCodeFromBundle,
7 | getCompiler,
8 | getErrors,
9 | normalizeMap,
10 | getWarnings,
11 | readAsset,
12 | } from "./helpers";
13 |
14 | const isWin = process.platform === "win32";
15 |
16 | describe("source-map-loader", () => {
17 | it("should leave normal files untouched", async () => {
18 | const testId = "normal-file.js";
19 | const compiler = getCompiler(testId);
20 | const stats = await compile(compiler);
21 | const codeFromBundle = getCodeFromBundle(stats, compiler);
22 |
23 | expect(codeFromBundle.map).toBeUndefined();
24 | expect(codeFromBundle.code).toMatchSnapshot("code");
25 | expect(getWarnings(stats)).toMatchSnapshot("warnings");
26 | expect(getErrors(stats)).toMatchSnapshot("errors");
27 | });
28 |
29 | it("should leave normal files with fake source-map untouched", async () => {
30 | const testId = "normal-file2.js";
31 | const compiler = getCompiler(testId);
32 | const stats = await compile(compiler);
33 | const codeFromBundle = getCodeFromBundle(stats, compiler);
34 |
35 | expect(codeFromBundle.map).toBeUndefined();
36 | expect(codeFromBundle.code).toMatchSnapshot("code");
37 | expect(getWarnings(stats)).toMatchSnapshot("warnings");
38 | expect(getErrors(stats)).toMatchSnapshot("errors");
39 | });
40 |
41 | it("should process inlined SourceMaps", async () => {
42 | const testId = "inline-source-map.js";
43 | const compiler = getCompiler(testId);
44 | const stats = await compile(compiler);
45 | const codeFromBundle = getCodeFromBundle(stats, compiler);
46 |
47 | expect(codeFromBundle.map).toBeDefined();
48 | expect(normalizeMap(codeFromBundle.map)).toMatchSnapshot("map");
49 | expect(codeFromBundle.code).toMatchSnapshot("code");
50 | expect(getWarnings(stats)).toMatchSnapshot("warnings");
51 | expect(getErrors(stats)).toMatchSnapshot("errors");
52 | });
53 |
54 | it("should process percent-encoding path", async () => {
55 | const testId = "{percent}.js";
56 | const compiler = getCompiler(testId);
57 | const stats = await compile(compiler);
58 | const codeFromBundle = getCodeFromBundle(stats, compiler);
59 |
60 | expect(codeFromBundle.map).toBeDefined();
61 | expect(codeFromBundle.code).toMatchSnapshot("code");
62 | expect(getWarnings(stats)).toMatchSnapshot("warnings");
63 | expect(getErrors(stats)).toMatchSnapshot("errors");
64 | });
65 |
66 | it("should process external SourceMaps", async () => {
67 | const testId = "external-source-map.js";
68 | const compiler = getCompiler(testId);
69 | const stats = await compile(compiler);
70 | const codeFromBundle = getCodeFromBundle(stats, compiler);
71 | const deps = stats.compilation.fileDependencies;
72 |
73 | const dependencies = [
74 | path.resolve(__dirname, "fixtures", "external-source-map.map"),
75 | ];
76 |
77 | dependencies.forEach((fixture) => {
78 | expect(deps.has(fixture)).toBe(true);
79 | });
80 | expect(codeFromBundle.map).toBeDefined();
81 | expect(normalizeMap(codeFromBundle.map)).toMatchSnapshot("map");
82 | expect(codeFromBundle.code).toMatchSnapshot("code");
83 | expect(getWarnings(stats)).toMatchSnapshot("warnings");
84 | expect(getErrors(stats)).toMatchSnapshot("errors");
85 | });
86 |
87 | it("should process external SourceMaps (external sources)", async () => {
88 | const testId = "external-source-map2.js";
89 | const compiler = getCompiler(testId);
90 | const stats = await compile(compiler);
91 | const codeFromBundle = getCodeFromBundle(stats, compiler);
92 | const deps = stats.compilation.fileDependencies;
93 |
94 | const dependencies = [
95 | path.resolve(__dirname, "fixtures", "data", "external-source-map2.map"),
96 | path.resolve(__dirname, "fixtures", "external-source-map2.js"),
97 | path.resolve(__dirname, "fixtures", "external-source-map2.txt"),
98 | ];
99 |
100 | dependencies.forEach((fixture) => {
101 | expect(deps.has(fixture)).toBe(true);
102 | });
103 | expect(codeFromBundle.map).toBeDefined();
104 | expect(normalizeMap(codeFromBundle.map)).toMatchSnapshot("map");
105 | expect(codeFromBundle.code).toMatchSnapshot("code");
106 | expect(getWarnings(stats)).toMatchSnapshot("warnings");
107 | expect(getErrors(stats)).toMatchSnapshot("errors");
108 | });
109 |
110 | it("should process null in sources content", async () => {
111 | const testId = "null-in-sources-content.js";
112 | const compiler = getCompiler(testId);
113 | const stats = await compile(compiler);
114 | const codeFromBundle = getCodeFromBundle(stats, compiler);
115 | const deps = stats.compilation.fileDependencies;
116 |
117 | const dependencies = [
118 | path.resolve(__dirname, "fixtures", "null-in-sources-content.js.map"),
119 | ];
120 |
121 | dependencies.forEach((fixture) => {
122 | expect(deps.has(fixture)).toBe(true);
123 | });
124 | expect(codeFromBundle.map).toBeDefined();
125 | expect(normalizeMap(codeFromBundle.map)).toMatchSnapshot("map");
126 | expect(codeFromBundle.code).toMatchSnapshot("code");
127 | expect(getWarnings(stats)).toMatchSnapshot("warnings");
128 | expect(getErrors(stats)).toMatchSnapshot("errors");
129 | });
130 |
131 | it("should reject http SourceMaps", async () => {
132 | const testId = "http-source-map.js";
133 | const compiler = getCompiler(testId);
134 | const stats = await compile(compiler);
135 | const codeFromBundle = getCodeFromBundle(stats, compiler);
136 |
137 | expect(codeFromBundle.code).toMatchSnapshot("code");
138 | expect(getWarnings(stats)).toMatchSnapshot("warnings");
139 | expect(getErrors(stats)).toMatchSnapshot("errors");
140 | });
141 |
142 | it("should reject not exist file: SourceMaps", async () => {
143 | const testId = isWin ? "file-source-map-windows.js" : "file-source-map.js";
144 | const compiler = getCompiler(testId);
145 | const stats = await compile(compiler);
146 | const errorString = getWarnings(stats).join("");
147 | const warning = errorString.match(/TypeError \[ERR_INVALID_FILE/gi);
148 |
149 | expect(...warning).toMatchSnapshot("warnings");
150 | expect(getErrors(stats)).toMatchSnapshot("errors");
151 | });
152 |
153 | it("should support file protocol path", async () => {
154 | const sourceRoot = path.resolve(__dirname, "fixtures");
155 | const javaScriptFilename = "file-protocol-path.js";
156 | const entryFileAbsolutePath = path.join(sourceRoot, javaScriptFilename);
157 | const sourceMapPath = path.join(sourceRoot, "file-protocol-path.js.map");
158 |
159 | // Create the sourcemap file
160 | const rawSourceMap = {
161 | version: 3,
162 | sources: [
163 | "normal-file.js",
164 | `file://${path
165 | .resolve(__dirname, "fixtures", "normal-file2.js")
166 | .replace(/\\/g, "/")}`,
167 | ],
168 | mappings: "CAAC,IAAI,IAAM,SAAUA,GAClB,OAAOA",
169 | };
170 | fs.writeFileSync(sourceMapPath, JSON.stringify(rawSourceMap));
171 |
172 | // Create the entryPointFile file
173 | const entryFileContent = `// Some content \r\n // # sourceMappingURL=file://${sourceMapPath.replace(
174 | /\\/g,
175 | "/",
176 | )}`;
177 | fs.writeFileSync(entryFileAbsolutePath, entryFileContent);
178 |
179 | const compiler = getCompiler(javaScriptFilename);
180 | const stats = await compile(compiler);
181 | const codeFromBundle = getCodeFromBundle(stats, compiler);
182 |
183 | expect(codeFromBundle.map).toBeDefined();
184 | expect(normalizeMap(codeFromBundle.map)).toMatchSnapshot("map");
185 | expect(codeFromBundle.code).toMatchSnapshot("code");
186 | expect(getWarnings(stats)).toMatchSnapshot("warnings");
187 | expect(getErrors(stats)).toMatchSnapshot("errors");
188 | });
189 |
190 | it("should skip file protocol path if sourcesContent is set", async () => {
191 | const testId = "file-broken-protocol-path.js";
192 | const compiler = getCompiler(testId);
193 | const stats = await compile(compiler);
194 | const codeFromBundle = getCodeFromBundle(stats, compiler);
195 |
196 | expect(codeFromBundle.map).toBeDefined();
197 | expect(normalizeMap(codeFromBundle.map)).toMatchSnapshot("map");
198 | expect(codeFromBundle.code).toMatchSnapshot("code");
199 | expect(getWarnings(stats)).toMatchSnapshot("warnings");
200 | expect(getErrors(stats)).toMatchSnapshot("errors");
201 | });
202 |
203 | it("should skip webpack protocol path if sourcesContent is set", async () => {
204 | const testId = "webpack/main.js";
205 | const compiler = getCompiler(testId);
206 | const stats = await compile(compiler);
207 | const codeFromBundle = getCodeFromBundle(stats, compiler);
208 |
209 | expect(codeFromBundle.map).toBeDefined();
210 | expect(normalizeMap(codeFromBundle.map)).toMatchSnapshot("map");
211 | expect(codeFromBundle.code).toMatchSnapshot("code");
212 | expect(getWarnings(stats)).toMatchSnapshot("warnings");
213 | expect(getErrors(stats)).toMatchSnapshot("errors");
214 | });
215 |
216 | it("should use last SourceMap directive", async () => {
217 | const testId = "multi-source-map.js";
218 | const compiler = getCompiler(testId);
219 | const stats = await compile(compiler);
220 | const codeFromBundle = getCodeFromBundle(stats, compiler);
221 |
222 | expect(codeFromBundle.map).toBeDefined();
223 | expect(normalizeMap(codeFromBundle.map)).toMatchSnapshot("map");
224 | expect(codeFromBundle.code).toMatchSnapshot("code");
225 | expect(getWarnings(stats)).toMatchSnapshot("warnings");
226 | expect(getErrors(stats)).toMatchSnapshot("errors");
227 | });
228 |
229 | it("should skip invalid base64 SourceMap", async () => {
230 | const testId = "invalid-inline-source-map.js";
231 | const compiler = getCompiler(testId);
232 | const stats = await compile(compiler);
233 | const codeFromBundle = getCodeFromBundle(stats, compiler);
234 |
235 | expect(codeFromBundle.map).toBeUndefined();
236 | expect(codeFromBundle.code).toMatchSnapshot("code");
237 | expect(getWarnings(stats)).toMatchSnapshot("warnings");
238 | expect(getErrors(stats)).toMatchSnapshot("errors");
239 | });
240 |
241 | it("should warn on invalid base64 SourceMap", async () => {
242 | const testId = "invalid-inline-source-map2.js";
243 | const compiler = getCompiler(testId);
244 | const stats = await compile(compiler);
245 | const codeFromBundle = getCodeFromBundle(stats, compiler);
246 |
247 | expect(codeFromBundle.map).toBeUndefined();
248 | expect(codeFromBundle.code).toMatchSnapshot("code");
249 | expect(getWarnings(stats)).toMatchSnapshot("warnings");
250 | expect(getErrors(stats)).toMatchSnapshot("errors");
251 | });
252 |
253 | it("should warn on invalid SourceMap", async () => {
254 | const testId = "invalid-source-map.js";
255 | const compiler = getCompiler(testId);
256 | const stats = await compile(compiler);
257 | const codeFromBundle = getCodeFromBundle(stats, compiler);
258 | const deps = stats.compilation.fileDependencies;
259 |
260 | const dependencies = [
261 | path.resolve(__dirname, "fixtures", "invalid-source-map.map"),
262 | ];
263 |
264 | dependencies.forEach((fixture) => {
265 | expect(deps.has(fixture)).toBe(true);
266 | });
267 |
268 | expect(codeFromBundle.map).toBeUndefined();
269 | expect(codeFromBundle.code).toMatchSnapshot("code");
270 |
271 | const match = process.version.match(
272 | /^v(\d{1,2})\.(\d{1,2})\.(\d{1,2})(?:-([0-9A-Za-z-.]+))?(?:\+([0-9A-Za-z-.]+))?$/,
273 | );
274 |
275 | if (parseInt(match[1], 10) >= 20) {
276 | expect(getWarnings(stats)[0]).toContain(
277 | `SyntaxError: Unexpected non-whitespace character after JSON at position 102`,
278 | );
279 | } else {
280 | expect(getWarnings(stats)[0]).toContain(
281 | `SyntaxError: Unexpected string in JSON at position 102`,
282 | );
283 | }
284 | expect(getErrors(stats)).toMatchSnapshot("errors");
285 | });
286 |
287 | it("should warn on missing SourceMap", async () => {
288 | const testId = "missing-source-map.js";
289 | const compiler = getCompiler(testId);
290 | const stats = await compile(compiler);
291 | const codeFromBundle = getCodeFromBundle(stats, compiler);
292 |
293 | expect(codeFromBundle.map).toBeUndefined();
294 | expect(codeFromBundle.code).toMatchSnapshot("code");
295 | expect(getWarnings(stats)).toMatchSnapshot("warnings");
296 | expect(getErrors(stats)).toMatchSnapshot("errors");
297 | });
298 |
299 | it("should warn on missing source file", async () => {
300 | const testId = "missing-source-map2.js";
301 | const compiler = getCompiler(testId);
302 | const stats = await compile(compiler);
303 | const codeFromBundle = getCodeFromBundle(stats, compiler);
304 | const deps = stats.compilation.fileDependencies;
305 |
306 | const dependencies = [
307 | path.resolve(__dirname, "fixtures", "missing-source-map2.map"),
308 | ];
309 |
310 | dependencies.forEach((fixture) => {
311 | expect(deps.has(fixture)).toBe(true);
312 | });
313 | expect(codeFromBundle.map).toBeDefined();
314 | expect(normalizeMap(codeFromBundle.map)).toMatchSnapshot("map");
315 | expect(codeFromBundle.code).toMatchSnapshot("code");
316 | expect(getWarnings(stats)).toMatchSnapshot("warnings");
317 | expect(getErrors(stats)).toMatchSnapshot("errors");
318 | });
319 |
320 | it("should process inlined SourceMaps with charset", async () => {
321 | const testId = "charset-inline-source-map.js";
322 | const compiler = getCompiler(testId);
323 | const stats = await compile(compiler);
324 | const codeFromBundle = getCodeFromBundle(stats, compiler);
325 |
326 | expect(codeFromBundle.map).toBeDefined();
327 | expect(normalizeMap(codeFromBundle.map)).toMatchSnapshot("map");
328 | expect(codeFromBundle.code).toMatchSnapshot("code");
329 | expect(getWarnings(stats)).toMatchSnapshot("warnings");
330 | expect(getErrors(stats)).toMatchSnapshot("errors");
331 | });
332 |
333 | it("should support absolute sourceRoot paths in sourcemaps", async () => {
334 | const sourceRoot = path.resolve(__dirname, "fixtures");
335 | const javaScriptFilename = "absolute-sourceRoot-source-map.js";
336 | const sourceFilename = "absolute-sourceRoot-source-map.txt";
337 | const rootRelativeSourcePath = path.join(sourceRoot, sourceFilename);
338 | const sourceMapPath = path.join(
339 | sourceRoot,
340 | "absolute-sourceRoot-source-map.map",
341 | );
342 |
343 | // Create the sourcemap file
344 | const rawSourceMap = {
345 | version: 3,
346 | file: javaScriptFilename,
347 | sourceRoot,
348 | sources: [sourceFilename],
349 | mappings: "AAAA",
350 | };
351 | fs.writeFileSync(sourceMapPath, JSON.stringify(rawSourceMap));
352 |
353 | const compiler = getCompiler(javaScriptFilename);
354 | const stats = await compile(compiler);
355 | const codeFromBundle = getCodeFromBundle(stats, compiler);
356 | const deps = stats.compilation.fileDependencies;
357 |
358 | const dependencies = [sourceMapPath, rootRelativeSourcePath];
359 |
360 | dependencies.forEach((fixture) => {
361 | expect(deps.has(fixture)).toBe(true);
362 | });
363 | expect(codeFromBundle.map).toBeDefined();
364 | expect(normalizeMap(codeFromBundle.map)).toMatchSnapshot("map");
365 | expect(codeFromBundle.code).toMatchSnapshot("code");
366 | expect(getWarnings(stats)).toMatchSnapshot("warnings");
367 | expect(getErrors(stats)).toMatchSnapshot("errors");
368 | });
369 |
370 | it("should support relative sourceRoot paths in sourcemaps", async () => {
371 | const sourceFilename = "relative-sourceRoot-source-map.txt";
372 | const rootRelativeSourcePath = path.join(
373 | __dirname,
374 | "fixtures",
375 | "data",
376 | sourceFilename,
377 | );
378 | const sourceMapPath = path.join(
379 | __dirname,
380 | "fixtures",
381 | "relative-sourceRoot-source-map.map",
382 | );
383 |
384 | const testId = "relative-sourceRoot-source-map.js";
385 | const compiler = getCompiler(testId);
386 | const stats = await compile(compiler);
387 | const codeFromBundle = getCodeFromBundle(stats, compiler);
388 | const deps = stats.compilation.fileDependencies;
389 |
390 | const dependencies = [sourceMapPath, rootRelativeSourcePath];
391 |
392 | dependencies.forEach((fixture) => {
393 | expect(deps.has(fixture)).toBe(true);
394 | });
395 | expect(codeFromBundle.map).toBeDefined();
396 | expect(normalizeMap(codeFromBundle.map)).toMatchSnapshot("map");
397 | expect(codeFromBundle.code).toMatchSnapshot("code");
398 | expect(getWarnings(stats)).toMatchSnapshot("warnings");
399 | expect(getErrors(stats)).toMatchSnapshot("errors");
400 | });
401 |
402 | it("should support indexed sourcemaps", async () => {
403 | const currentDirPath = path.join(
404 | __dirname,
405 | "fixtures",
406 | "indexed-sourcemap",
407 | );
408 |
409 | const testId = path.join(currentDirPath, "file.js");
410 | const compiler = getCompiler(testId);
411 | const stats = await compile(compiler);
412 | const codeFromBundle = getCodeFromBundle(stats, compiler);
413 | const deps = stats.compilation.fileDependencies;
414 |
415 | const dependencies = [
416 | path.join(currentDirPath, "file.js"),
417 | path.join(currentDirPath, "file.js.map"),
418 | ];
419 |
420 | dependencies.forEach((fixture) => {
421 | expect(deps.has(fixture)).toBe(true);
422 | });
423 | expect(codeFromBundle.map).toBeDefined();
424 | expect(normalizeMap(codeFromBundle.map)).toMatchSnapshot("map");
425 | expect(codeFromBundle.code).toMatchSnapshot("code");
426 | expect(getWarnings(stats)).toMatchSnapshot("warnings");
427 | expect(getErrors(stats)).toMatchSnapshot("errors");
428 | });
429 |
430 | it("should support indexed sourcemaps 2", async () => {
431 | const currentDirPath = path.join(
432 | __dirname,
433 | "fixtures",
434 | "indexed-sourcemap",
435 | );
436 |
437 | const testId = path.join(currentDirPath, "file2.js");
438 | const compiler = getCompiler(testId);
439 | const stats = await compile(compiler);
440 | const codeFromBundle = getCodeFromBundle(stats, compiler);
441 | const deps = stats.compilation.fileDependencies;
442 |
443 | const dependencies = [
444 | path.join(currentDirPath, "file2.js"),
445 | path.join(currentDirPath, "file2.js.map"),
446 | ];
447 |
448 | dependencies.forEach((fixture) => {
449 | expect(deps.has(fixture)).toBe(true);
450 | });
451 | expect(codeFromBundle.map).toBeDefined();
452 | expect(normalizeMap(codeFromBundle.map)).toMatchSnapshot("map");
453 | expect(codeFromBundle.code).toMatchSnapshot("code");
454 | expect(getWarnings(stats)).toMatchSnapshot("warnings");
455 | expect(getErrors(stats)).toMatchSnapshot("errors");
456 | });
457 |
458 | it("should transform to webpack", async () => {
459 | const currentDirPath = path.join(
460 | __dirname,
461 | "fixtures",
462 | "indexed-sourcemap",
463 | );
464 |
465 | const testId = path.join(currentDirPath, "file.js");
466 | const compiler = getCompiler(testId, {}, {}, true);
467 | const stats = await compile(compiler);
468 | const bundle = readAsset("main.bundle.js.map", compiler, stats);
469 |
470 | const dependencies = [
471 | path.normalize("indexed-sourcemap/nested1.js"),
472 | path.normalize("/different/root/nested2.js"),
473 | ];
474 |
475 | const map = JSON.parse(bundle);
476 | const normalizedSources = map.sources.map((source) =>
477 | path.normalize(
478 | source
479 | .replace(/webpack:\/\/sourceMapLoaderExport\//, "")
480 | .replace("..", ""),
481 | ),
482 | );
483 |
484 | expect(new Set(normalizedSources)).toEqual(new Set(dependencies));
485 | });
486 |
487 | it("should process protocol-relative-url-path", async () => {
488 | const testId = "protocol-relative-url-path.js";
489 | const compiler = getCompiler(testId);
490 | const stats = await compile(compiler);
491 | const codeFromBundle = getCodeFromBundle(stats, compiler);
492 |
493 | expect(codeFromBundle.map).toBeUndefined();
494 | expect(codeFromBundle.code).toMatchSnapshot("code");
495 | expect(getWarnings(stats)).toMatchSnapshot("warnings");
496 | expect(getErrors(stats)).toMatchSnapshot("errors");
497 | });
498 |
499 | it("should support mixed paths in sources without sourceRoot", async () => {
500 | const sourceRoot = path.resolve(__dirname, "fixtures");
501 | const javaScriptFilename = "absolute-path.js";
502 | const entryFileAbsolutePath = path.join(sourceRoot, javaScriptFilename);
503 | const sourceMapPath = path.join(
504 | sourceRoot,
505 | "map-without-sourceroot.js.map",
506 | );
507 |
508 | // Create the sourcemap file
509 | const rawSourceMap = {
510 | version: 3,
511 | sources: [
512 | "normal-file.js",
513 | path.resolve(__dirname, "fixtures", "normal-file2.js"),
514 | "http://path-to-map.com",
515 | "ftp://path-to-map.com",
516 | ],
517 | mappings: "CAAC,IAAI,IAAM,SAAUA,GAClB,OAAOA",
518 | };
519 | fs.writeFileSync(sourceMapPath, JSON.stringify(rawSourceMap));
520 |
521 | // Create the entryPointFile file
522 | const entryFileContent = `// Some content \r\n // # sourceMappingURL=${sourceMapPath}`;
523 | fs.writeFileSync(entryFileAbsolutePath, entryFileContent);
524 |
525 | const compiler = getCompiler(javaScriptFilename);
526 | const stats = await compile(compiler);
527 | const codeFromBundle = getCodeFromBundle(stats, compiler);
528 |
529 | expect(codeFromBundle.map).toBeDefined();
530 | expect(normalizeMap(codeFromBundle.map)).toMatchSnapshot("map");
531 | expect(codeFromBundle.code).toMatchSnapshot("code");
532 | expect(getWarnings(stats)).toMatchSnapshot("warnings");
533 | expect(getErrors(stats)).toMatchSnapshot("errors");
534 | });
535 |
536 | it("should support mixed paths in sources with sourceRoot", async () => {
537 | const sourceRoot = path.resolve(__dirname, "fixtures");
538 | const javaScriptFilename = "absolute-path.js";
539 | const entryFileAbsolutePath = path.join(sourceRoot, javaScriptFilename);
540 | const sourceMapPath = path.join(sourceRoot, "map-with-sourceroot.js.map");
541 |
542 | // Create the sourcemap file
543 | const rawSourceMap = {
544 | version: 3,
545 | sourceRoot,
546 | sources: [
547 | "normal-file.js",
548 | path.resolve(__dirname, "fixtures", "normal-file2.js"),
549 | "http://path-to-map.com",
550 | "ftp://path-to-map.com",
551 | ],
552 | mappings: "CAAC,IAAI,IAAM,SAAUA,GAClB,OAAOA",
553 | };
554 | fs.writeFileSync(sourceMapPath, JSON.stringify(rawSourceMap));
555 |
556 | // Create the entryPointFile file
557 | const entryFileContent = `// Some content \r\n // # sourceMappingURL=${sourceMapPath}`;
558 | fs.writeFileSync(entryFileAbsolutePath, entryFileContent);
559 |
560 | const compiler = getCompiler(javaScriptFilename);
561 | const stats = await compile(compiler);
562 | const codeFromBundle = getCodeFromBundle(stats, compiler);
563 |
564 | expect(codeFromBundle.map).toBeDefined();
565 | expect(normalizeMap(codeFromBundle.map)).toMatchSnapshot("map");
566 | expect(codeFromBundle.code).toMatchSnapshot("code");
567 | expect(getWarnings(stats)).toMatchSnapshot("warnings");
568 | expect(getErrors(stats)).toMatchSnapshot("errors");
569 | });
570 |
571 | it("should support absolute paths to sourcemaps", async () => {
572 | const sourceRoot = path.resolve(__dirname, "fixtures");
573 | const javaScriptFilename = "absolute-path.js";
574 | const entryFileAbsolutePath = path.join(sourceRoot, javaScriptFilename);
575 | const sourceMapPath = path.join(sourceRoot, "normal-map.js.map");
576 |
577 | // Create the sourcemap file
578 | const rawSourceMap = {
579 | version: 3,
580 | sourceRoot,
581 | sources: [
582 | "normal-file.js",
583 | path.resolve(__dirname, "fixtures", "normal-file2.js"),
584 | ],
585 | mappings: "CAAC,IAAI,IAAM,SAAUA,GAClB,OAAOA",
586 | };
587 | fs.writeFileSync(sourceMapPath, JSON.stringify(rawSourceMap));
588 |
589 | // Create the entryPointFile file
590 | const entryFileContent = `// Some content \r\n // # sourceMappingURL=${sourceMapPath}`;
591 | fs.writeFileSync(entryFileAbsolutePath, entryFileContent);
592 |
593 | const compiler = getCompiler(javaScriptFilename);
594 | const stats = await compile(compiler);
595 | const codeFromBundle = getCodeFromBundle(stats, compiler);
596 |
597 | expect(codeFromBundle.map).toBeDefined();
598 | expect(normalizeMap(codeFromBundle.map)).toMatchSnapshot("map");
599 | expect(codeFromBundle.code).toMatchSnapshot("code");
600 | expect(getWarnings(stats)).toMatchSnapshot("warnings");
601 | expect(getErrors(stats)).toMatchSnapshot("errors");
602 | });
603 |
604 | it("should reject not support url", async () => {
605 | const testId = "unSupport-file-source-map.js";
606 | const compiler = getCompiler(testId);
607 | const stats = await compile(compiler);
608 | const codeFromBundle = getCodeFromBundle(stats, compiler);
609 |
610 | expect(codeFromBundle.code).toMatchSnapshot("code");
611 | expect(getWarnings(stats)).toMatchSnapshot("warnings");
612 | expect(getErrors(stats)).toMatchSnapshot("errors");
613 | });
614 |
615 | it("should process inlined sources", async () => {
616 | const testId = "inline-sources.js";
617 | const compiler = getCompiler(testId);
618 | const stats = await compile(compiler);
619 | const codeFromBundle = getCodeFromBundle(stats, compiler);
620 |
621 | expect(codeFromBundle.map).toBeDefined();
622 | expect(normalizeMap(codeFromBundle.map)).toMatchSnapshot("map");
623 | expect(codeFromBundle.code).toMatchSnapshot("code");
624 | expect(getWarnings(stats)).toMatchSnapshot("warnings");
625 | expect(getErrors(stats)).toMatchSnapshot("errors");
626 | });
627 |
628 | it("should process css sourceMap", async () => {
629 | const testId = "app.css";
630 | const compiler = getCompiler(testId);
631 | const stats = await compile(compiler);
632 | const codeFromBundle = getCodeFromBundle(stats, compiler);
633 |
634 | expect(codeFromBundle.map).toBeDefined();
635 | expect(normalizeMap(codeFromBundle.map)).toMatchSnapshot("map");
636 | expect(codeFromBundle.code).toMatchSnapshot("code");
637 | expect(getWarnings(stats)).toMatchSnapshot("warnings");
638 | expect(getErrors(stats)).toMatchSnapshot("errors");
639 | });
640 |
641 | it("should process css sourceMap", async () => {
642 | const testId = "skip-sourcesContent.js";
643 | const compiler = getCompiler(testId);
644 | const stats = await compile(compiler);
645 | const codeFromBundle = getCodeFromBundle(stats, compiler);
646 |
647 | expect(codeFromBundle.map).toBeDefined();
648 | expect(normalizeMap(codeFromBundle.map)).toMatchSnapshot("map");
649 | expect(codeFromBundle.code).toMatchSnapshot("code");
650 | expect(getWarnings(stats)).toMatchSnapshot("warnings");
651 | expect(getErrors(stats)).toMatchSnapshot("errors");
652 | });
653 |
654 | it("should allow to filter warnings", async () => {
655 | const testId = "invalid-inline-source-map2.js";
656 | const compiler = getCompiler(testId);
657 | const stats = await compile(compiler);
658 | const codeFromBundle = getCodeFromBundle(stats, compiler);
659 |
660 | expect(
661 | stats.toString({ warningsFilter: /Failed to parse source map/ }),
662 | ).not.toContain("Failed to parse source map");
663 | expect(codeFromBundle.map).toBeUndefined();
664 | expect(codeFromBundle.code).toMatchSnapshot("code");
665 | expect(getWarnings(stats)).toMatchSnapshot("warnings");
666 | expect(getErrors(stats)).toMatchSnapshot("errors");
667 | });
668 |
669 | it("should process server-relative-url-path", async () => {
670 | const sourceRoot = path.resolve(__dirname, "fixtures");
671 | const javaScriptFilename = "server-relative-url-path.js";
672 | const sourceFilename = "server-relative-url-path.js";
673 | const sourceMapPath = path.join(
674 | sourceRoot,
675 | "server-relative-url-path.js.map",
676 | );
677 |
678 | // Create the sourcemap file
679 | const rawSourceMap = {
680 | version: 3,
681 | file: javaScriptFilename,
682 | sourceRoot,
683 | sources: [sourceFilename],
684 | mappings: "AAAA",
685 | };
686 |
687 | fs.writeFileSync(sourceMapPath, JSON.stringify(rawSourceMap));
688 |
689 | const testId = "server-relative-url-path.js";
690 | const compiler = getCompiler(testId);
691 | const stats = await compile(compiler);
692 | const codeFromBundle = getCodeFromBundle(stats, compiler);
693 |
694 | expect(codeFromBundle.code).toMatchSnapshot("code");
695 | expect(normalizeMap(codeFromBundle.map)).toMatchSnapshot("map");
696 | expect(getWarnings(stats)).toMatchSnapshot("warnings");
697 | expect(getErrors(stats)).toMatchSnapshot("errors");
698 | });
699 |
700 | it("should emit warning when unresolved server-relative-url-path", async () => {
701 | const testId = "unresolved-server-relative-url-path.js";
702 | const compiler = getCompiler(testId);
703 | const stats = await compile(compiler);
704 | const codeFromBundle = getCodeFromBundle(stats, compiler);
705 |
706 | expect(codeFromBundle.code).toMatchSnapshot("code");
707 | expect(getWarnings(stats, true)).toMatchSnapshot("warnings");
708 | expect(getErrors(stats)).toMatchSnapshot("errors");
709 | });
710 |
711 | it("should add only valid `sources` to dependencies", async () => {
712 | const testId = "dependencies.js";
713 | const compiler = getCompiler(testId);
714 | const stats = await compile(compiler);
715 | const codeFromBundle = getCodeFromBundle(stats, compiler);
716 | const deps = stats.compilation.fileDependencies;
717 |
718 | const dependencies = [
719 | path.resolve(__dirname, "fixtures", "dependencies.js.map"),
720 | path.resolve(
721 | __dirname,
722 | "fixtures",
723 | "data/relative-sourceRoot-source-map.txt",
724 | ),
725 | ];
726 | const notInDependencies = ["", "data:invalid;A;a", "./data/not-found.txt"];
727 |
728 | dependencies.forEach((fixture) => {
729 | expect(deps.has(fixture)).toBe(true);
730 | });
731 | notInDependencies.forEach((fixture) => {
732 | expect(deps.has(fixture)).toBe(false);
733 | });
734 | expect(codeFromBundle.code).toMatchSnapshot("code");
735 | expect(normalizeMap(codeFromBundle.map)).toMatchSnapshot("map");
736 | expect(getWarnings(stats)).toMatchSnapshot("warnings");
737 | expect(getErrors(stats)).toMatchSnapshot("errors");
738 | });
739 |
740 | it("should add only valid `sources` with `sourceContent` to dependencies", async () => {
741 | const testId = "dependencies2.js";
742 | const compiler = getCompiler(testId);
743 | const stats = await compile(compiler);
744 | const codeFromBundle = getCodeFromBundle(stats, compiler);
745 | const deps = stats.compilation.fileDependencies;
746 |
747 | const dependencies = [
748 | path.resolve(__dirname, "fixtures", "dependencies2.js.map"),
749 | ];
750 | const notInDependencies = [
751 | "./data/relative-sourceRoot-source-map.txt",
752 | path.resolve(__dirname, "./data/relative-sourceRoot-source-map.txt"),
753 | "./data/not-found.txt",
754 | "data:application/json;base64,c29tZSBraW5kIGNvbnRlbnQ=",
755 | "data:invalid;A;a",
756 | ];
757 |
758 | dependencies.forEach((fixture) => {
759 | expect(deps.has(fixture)).toBe(true);
760 | });
761 | notInDependencies.forEach((fixture) => {
762 | expect(deps.has(fixture)).toBe(false);
763 | });
764 | expect(codeFromBundle.code).toMatchSnapshot("code");
765 | expect(normalizeMap(codeFromBundle.map)).toMatchSnapshot("map");
766 | expect(getWarnings(stats)).toMatchSnapshot("warnings");
767 | expect(getErrors(stats)).toMatchSnapshot("errors");
768 | });
769 |
770 | it("should process absolute URL in sourceRoot", async () => {
771 | const testId = "absolute-source-root.js";
772 | const compiler = getCompiler(testId);
773 | const stats = await compile(compiler);
774 | const codeFromBundle = getCodeFromBundle(stats, compiler);
775 |
776 | expect(codeFromBundle.map).toBeDefined();
777 | expect(normalizeMap(codeFromBundle.map)).toMatchSnapshot("map");
778 | expect(codeFromBundle.code).toMatchSnapshot("code");
779 | expect(getWarnings(stats)).toMatchSnapshot("warnings");
780 | expect(getErrors(stats)).toMatchSnapshot("errors");
781 | });
782 | });
783 |
--------------------------------------------------------------------------------
/test/parseDataUrl.test.js:
--------------------------------------------------------------------------------
1 | import parseDataUrl from "../src/parse-data-url";
2 |
3 | const dataUrls = [
4 | "data://test/,X",
5 | "http://domain.com",
6 | "data://test:test/,X",
7 | "data:,X",
8 | "data:text/html",
9 | "data:text/html ;charset=x ",
10 | "data:,",
11 | "data:,X#X",
12 | "data:,%FF",
13 | "data:text/plain,X",
14 | "data:text/plain ,X",
15 | "data:text/plain%20,X",
16 | "data:text/plain\f,X",
17 | "data:text/plain%0C,X",
18 | "data:text/plain;,X",
19 | "data:;x=x;charset=x,X",
20 | "data:;x=x,X",
21 | "data:text/plain;charset=windows-1252,%C2%B1",
22 | "data:text/plain;Charset=UTF-8,%C2%B1",
23 | "data:image/gif,%C2%B1",
24 | "data:IMAGE/gif,%C2%B1",
25 | "data:IMAGE/gif;hi=x,%C2%B1",
26 | "data:IMAGE/gif;CHARSET=x,%C2%B1",
27 | "data: ,%FF",
28 | "data:%20,%FF",
29 | "data:\f,%FF",
30 | "data:%1F,%FF",
31 | "data:\u0000,%FF",
32 | "data:%00,%FF",
33 | "data:text/html ,X",
34 | "data:text / html,X",
35 | "data:†,X",
36 | "data:†/†,X",
37 | "data:X,X",
38 | "data:image/png,X X",
39 | "data:application/javascript,X X",
40 | "data:application/xml,X X",
41 | "data:text/javascript,X X",
42 | "data:text/plain,X X",
43 | "data:unknown/unknown,X X",
44 | 'data:text/plain;a=",",X',
45 | "data:text/plain;a=%2C,X",
46 | "data:;base64;base64,WA",
47 | "data:x/x;base64;base64,WA",
48 | "data:x/x;base64;charset=x,WA",
49 | "data:x/x;base64;charset=x;base64,WA",
50 | "data:x/x;base64;base64x,WA",
51 | "data:;base64,W%20A",
52 | "data:;base64,W%0CA",
53 | "data:x;base64x,WA",
54 | "data:x;base64;x,WA",
55 | "data:x;base64=x,WA",
56 | "data:; base64,WA",
57 | "data:; base64,WA",
58 | "data: ;charset=x ; base64,WA",
59 | "data:;base64;,WA",
60 | "data:;base64 ,WA",
61 | "data:;base64 ,WA",
62 | "data:;base 64,WA",
63 | "data:;BASe64,WA",
64 | "data:;%62ase64,WA",
65 | "data:%3Bbase64,WA",
66 | "data:;charset=x,X",
67 | "data:; charset=x,X",
68 | "data:;charset =x,X",
69 | "data:;charset= x,X",
70 | "data:;charset=,X",
71 | "data:;charset,X",
72 | 'data:;charset="x",X',
73 | 'data:;CHARSET="X",X',
74 | 'no-data:;CHARSET="X",X',
75 | "data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==",
76 | "DATA:IMAGE/GIF;BASE64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==",
77 | "data:,Hello%2C%20World!",
78 | "data:,%%%",
79 | "data:,%%a",
80 | "data:,%%1",
81 | "data:,%1%",
82 | "data:,a",
83 | "data:, a",
84 | "data:,a ",
85 | "data:, a ",
86 | "data:,a\tb",
87 | "data:,a\nb",
88 | "data:,a\fb",
89 | "data:,a\rb",
90 | "data:,a b",
91 | "data:,ab\\u00a0cd",
92 | "data:,ab\\t\\n\\f\\r cd",
93 | "data:, \\t\\n\\f\\r ab\\t\\n\\f\\r cd\\t\\n\\f\\r ",
94 | "data:, ab\\t\\n\\f\\r =\\t\\n\\f\\r =\\t\\n\\f\\r ",
95 | "data:,/",
96 | "data:,/A",
97 | "data:text/plain;base64,abcd",
98 | "data:text/plain;base64, abcd",
99 | "data:text/plain;base64,abcd ",
100 | "data:text/plain;base64, abcd===",
101 | "data:text/plain;base64,abcd=== ",
102 | "data:text/plain;base64,abcd ===",
103 | "data:text/plain;base64,a",
104 | "data:text/plain;base64,ab",
105 | "data:text/plain;base64,abc",
106 | "data:text/plain;base64,abcde",
107 | "data:text/plain;base64,\uD800\uDC00",
108 | "data:text/plain;base64,=",
109 | "data:text/plain;base64,==",
110 | "data:text/plain;base64,===",
111 | "data:text/plain;base64,====",
112 | "data:text/plain;base64,=====",
113 | "data:text/plain;base64,a=",
114 | "data:text/plain;base64,a==",
115 | "data:text/plain;base64,a===",
116 | "data:text/plain;base64,a====",
117 | "data:text/plain;base64,a=====",
118 | "data:text/plain;base64,ab=",
119 | "data:text/plain;base64,ab==",
120 | "data:text/plain;base64,ab===",
121 | "data:text/plain;base64,ab====",
122 | "data:text/plain;base64,ab=====",
123 | "data:text/plain;base64,abc=",
124 | "data:text/plain;base64,abc==",
125 | "data:text/plain;base64,abc===",
126 | "data:text/plain;base64,abc====",
127 | "data:text/plain;base64,abc=====",
128 | "data:text/plain;base64,abcd=",
129 | "data:text/plain;base64,abcd==",
130 | "data:text/plain;base64,abcd===",
131 | "data:text/plain;base64,abcd====",
132 | "data:text/plain;base64,abcd=====",
133 | "data:text/plain;base64,abcde=",
134 | "data:text/plain;base64,abcde==",
135 | "data:text/plain;base64,abcde===",
136 | "data:text/plain;base64,abcde====",
137 | "data:text/plain;base64,abcde=====",
138 | "data:text/plain;base64,=a",
139 | "data:text/plain;base64,=a=",
140 | "data:text/plain;base64,a=b",
141 | "data:text/plain;base64,a=b=",
142 | "data:text/plain;base64,ab=c",
143 | "data:text/plain;base64,ab=c=",
144 | "data:text/plain;base64,abc=d",
145 | "data:text/plain;base64,abc=d=",
146 | "data:text/plain;base64,ab\tcd",
147 | "data:text/plain;base64,ab\ncd",
148 | "data:text/plain;base64,ab\fcd",
149 | "data:text/plain;base64,ab\rcd",
150 | "data:text/plain;base64,ab cd",
151 | "data:text/plain;base64,ab\u00a0cd",
152 | "data:text/plain;base64,ab\t\n\f\r cd",
153 | "data:text/plain;base64, \t\n\f\r ab\t\n\f\r cd\t\n\f\r ",
154 | "data:text/plain;base64,ab\t\n\f\r =\t\n\f\r =\t\n\f\r ",
155 | "data:text/plain;base64,A",
156 | "data:text/plain;base64,/A",
157 | "data:text/plain;base64,//A",
158 | "data:text/plain;base64,///A",
159 | "data:text/plain;base64,////A",
160 | "data:text/plain;base64,/",
161 | "data:text/plain;base64,A/",
162 | "data:text/plain;base64,AA/",
163 | "data:text/plain;base64,AAAA/",
164 | "data:text/plain;base64,AAA/",
165 | "data:text/plain;base64,\\0nonsense",
166 | "data:text/plain;base64,abcd\\0nonsense",
167 | "data:,Hello%2C%20World!",
168 | "data:,Привет%2C%20Мир!",
169 | "data:text/plain;base64,SGVsbG8sIFdvcmxkIQ==",
170 | "data:text/html,%3Ch1%3EHello%2C%20World!%3C%2Fh1%3E",
171 | "data:text/html,\n",
172 | "data:,а",
173 | "data:,a",
174 | "data:text/plain;,hello",
175 | "data:text;,hello",
176 | "data:text/0000;,hello",
177 | "data:text/ ;,hello",
178 | "data:text/html;charset=foo,%D0%9F%D1%80%D0%B8%D0%B2%D0%B5%D1%82%2C%20World!<%2Fh1>",
179 | "data:text/html;charset=utf-8;charset=foo,%D0%9F%D1%80%D0%B8%D0%B2%D0%B5%D1%82%2C%20World!<%2Fh1>",
180 | "data:text/html;charset=utf-8;foo=bar,%D0%9F%D1%80%D0%B8%D0%B2%D0%B5%D1%82%2C%20World!<%2Fh1>",
181 | "data:text/html;charset=utf-8;foo=bar;foo=baz,%D0%9F%D1%80%D0%B8%D0%B2%D0%B5%D1%82%2C%20World!<%2Fh1>",
182 | "data:application/json;charset=utf-8;base64,eyJmb28iOiJiYXIifQ==",
183 | "data:application/json;base64,eyJmb28iOiJiYXIifQ==",
184 | "data:application/zzz;base64,eyJmb28iOiJiYXIifQ==",
185 | "data:,test",
186 | ];
187 | describe("parse-data-url", () => {
188 | dataUrls.forEach((dataUrl, index) => {
189 | it(`should work with url by "${index}" index`, async () => {
190 | const parsed = parseDataUrl(dataUrl);
191 |
192 | expect({ original: dataUrl, parsed }).toMatchSnapshot();
193 | });
194 | });
195 | });
196 |
--------------------------------------------------------------------------------
/test/sourceMapperRegexp.test.js:
--------------------------------------------------------------------------------
1 | import { getSourceMappingURL } from "../src/utils";
2 |
3 | describe("source-map-loader", () => {
4 | const cases = [
5 | "/*#sourceMappingURL=absolute-sourceRoot-source-map.map*/",
6 | "/* #sourceMappingURL=absolute-sourceRoot-source-map.map */",
7 | "//#sourceMappingURL=absolute-sourceRoot-source-map.map",
8 | "//@sourceMappingURL=absolute-sourceRoot-source-map.map",
9 | " // #sourceMappingURL=absolute-sourceRoot-source-map.map",
10 | " // # sourceMappingURL = absolute-sourceRoot-source-map.map ",
11 | "// #sourceMappingURL = http://sampledomain.com/external-source-map2.map",
12 | "// #sourceMappingURL = //sampledomain.com/external-source-map2.map",
13 | "// @sourceMappingURL=data:application/source-map;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5saW5lLXNvdXJjZS1tYXAuanMiLCJzb3VyY2VzIjpbImlubGluZS1zb3VyY2UtbWFwLnR4dCJdLCJzb3VyY2VzQ29udGVudCI6WyJ3aXRoIFNvdXJjZU1hcCJdLCJtYXBwaW5ncyI6IkFBQUEifQ==",
14 | `
15 | with SourceMap
16 |
17 | // #sourceMappingURL = /sample-source-map.map
18 | // comment
19 | `,
20 | `
21 | with SourceMap
22 | // #sourceMappingURL = /sample-source-map-1.map
23 | // #sourceMappingURL = /sample-source-map-2.map
24 | // #sourceMappingURL = /sample-source-map-last.map
25 | // comment
26 | `,
27 | `"
28 | /*# sourceMappingURL=data:application/json;base64,"+btoa(unescape(encodeURIComponent(JSON.stringify(sourceMap))))+" */";`,
29 | `anInvalidDirective = "\\n/*# sourceMappingURL=data:application/json;base64,"+btoa(unescape(encodeURIComponent(JSON.stringify(sourceMap))))+" */";`,
30 | `// # sourceMappingURL=data:application/json;base64,"+btoa(unescape(encodeURIComponent(JSON.stringify(sourceMap))))+"`,
31 | ];
32 |
33 | cases.forEach((item) => {
34 | it(`should work with "${item}" url`, async () => {
35 | const { sourceMappingURL } = getSourceMappingURL(item);
36 |
37 | expect(sourceMappingURL).toMatchSnapshot("result");
38 | });
39 | });
40 | });
41 |
--------------------------------------------------------------------------------
/test/validate-options.test.js:
--------------------------------------------------------------------------------
1 | import { getCompiler, compile } from "./helpers";
2 |
3 | describe("validate options", () => {
4 | const tests = {
5 | filterSourceMappingUrl: {
6 | success: [() => false, () => "false", () => "remove", () => "skip"],
7 | failure: [1, true, false, "test", /test/, [], {}, { foo: "bar" }],
8 | },
9 | unknown: {
10 | success: [],
11 | failure: [1, true, false, "test", /test/, [], {}, { foo: "bar" }],
12 | },
13 | };
14 |
15 | function stringifyValue(value) {
16 | if (
17 | Array.isArray(value) ||
18 | (value && typeof value === "object" && value.constructor === Object)
19 | ) {
20 | return JSON.stringify(value);
21 | }
22 |
23 | return value;
24 | }
25 |
26 | async function createTestCase(key, value, type) {
27 | it(`should ${
28 | type === "success" ? "successfully validate" : "throw an error on"
29 | } the "${key}" option with "${stringifyValue(value)}" value`, async () => {
30 | const compiler = getCompiler("normal-file.js", { [key]: value });
31 |
32 | let stats;
33 |
34 | try {
35 | stats = await compile(compiler);
36 | } finally {
37 | if (type === "success") {
38 | expect(stats.hasErrors()).toBe(false);
39 | } else if (type === "failure") {
40 | const {
41 | compilation: { errors },
42 | } = stats;
43 |
44 | expect(errors).toHaveLength(1);
45 | expect(() => {
46 | throw new Error(errors[0].error.message);
47 | }).toThrowErrorMatchingSnapshot();
48 | }
49 | }
50 | });
51 | }
52 |
53 | for (const [key, values] of Object.entries(tests)) {
54 | for (const type of Object.keys(values)) {
55 | for (const value of values[type]) {
56 | createTestCase(key, value, type);
57 | }
58 | }
59 | }
60 | });
61 |
--------------------------------------------------------------------------------