Git Product home page Git Product logo

remapping's Introduction

@ampproject/remapping

Remap sequential sourcemaps through transformations to point at the original source code

Remapping allows you to take the sourcemaps generated through transforming your code and "remap" them to the original source locations. Think "my minified code, transformed with babel and bundled with webpack", all pointing to the correct location in your original source code.

With remapping, none of your source code transformations need to be aware of the input's sourcemap, they only need to generate an output sourcemap. This greatly simplifies building custom transformations (think a find-and-replace).

Installation

npm install @ampproject/remapping

Usage

function remapping(
  map: SourceMap | SourceMap[],
  loader: (file: string, ctx: LoaderContext) => (SourceMap | null | undefined),
  options?: { excludeContent: boolean, decodedMappings: boolean }
): SourceMap;

// LoaderContext gives the loader the importing sourcemap, tree depth, the ability to override the
// "source" location (where child sources are resolved relative to, or the location of original
// source), and the ability to override the "content" of an original source for inclusion in the
// output sourcemap.
type LoaderContext = {
 readonly importer: string;
 readonly depth: number;
 source: string;
 content: string | null | undefined;
}

remapping takes the final output sourcemap, and a loader function. For every source file pointer in the sourcemap, the loader will be called with the resolved path. If the path itself represents a transformed file (it has a sourcmap associated with it), then the loader should return that sourcemap. If not, the path will be treated as an original, untransformed source code.

// Babel transformed "helloworld.js" into "transformed.js"
const transformedMap = JSON.stringify({
  file: 'transformed.js',
  // 1st column of 2nd line of output file translates into the 1st source
  // file, line 3, column 2
  mappings: ';CAEE',
  sources: ['helloworld.js'],
  version: 3,
});

// Uglify minified "transformed.js" into "transformed.min.js"
const minifiedTransformedMap = JSON.stringify({
  file: 'transformed.min.js',
  // 0th column of 1st line of output file translates into the 1st source
  // file, line 2, column 1.
  mappings: 'AACC',
  names: [],
  sources: ['transformed.js'],
  version: 3,
});

const remapped = remapping(
  minifiedTransformedMap,
  (file, ctx) => {

    // The "transformed.js" file is an transformed file.
    if (file === 'transformed.js') {
      // The root importer is empty.
      console.assert(ctx.importer === '');
      // The depth in the sourcemap tree we're currently loading.
      // The root `minifiedTransformedMap` is depth 0, and its source children are depth 1, etc.
      console.assert(ctx.depth === 1);

      return transformedMap;
    }

    // Loader will be called to load transformedMap's source file pointers as well.
    console.assert(file === 'helloworld.js');
    // `transformed.js`'s sourcemap points into `helloworld.js`.
    console.assert(ctx.importer === 'transformed.js');
    // This is a source child of `transformed`, which is a source child of `minifiedTransformedMap`.
    console.assert(ctx.depth === 2);
    return null;
  }
);

console.log(remapped);
// {
//   file: 'transpiled.min.js',
//   mappings: 'AAEE',
//   sources: ['helloworld.js'],
//   version: 3,
// };

In this example, loader will be called twice:

  1. "transformed.js", the first source file pointer in the minifiedTransformedMap. We return the associated sourcemap for it (its a transformed file, after all) so that sourcemap locations can be traced through it into the source files it represents.
  2. "helloworld.js", our original, unmodified source code. This file does not have a sourcemap, so we return null.

The remapped sourcemap now points from transformed.min.js into locations in helloworld.js. If you were to read the mappings, it says "0th column of the first line output line points to the 1st column of the 2nd line of the file helloworld.js".

Multiple transformations of a file

As a convenience, if you have multiple single-source transformations of a file, you may pass an array of sourcemap files in the order of most-recent transformation sourcemap first. Note that this changes the importer and depth of each call to our loader. So our above example could have been written as:

const remapped = remapping(
  [minifiedTransformedMap, transformedMap],
  () => null
);

console.log(remapped);
// {
//   file: 'transpiled.min.js',
//   mappings: 'AAEE',
//   sources: ['helloworld.js'],
//   version: 3,
// };

Advanced control of the loading graph

source

The source property can overridden to any value to change the location of the current load. Eg, for an original source file, it allows us to change the location to the original source regardless of what the sourcemap source entry says. And for transformed files, it allows us to change the relative resolving location for child sources of the loaded sourcemap.

const remapped = remapping(
  minifiedTransformedMap,
  (file, ctx) => {

    if (file === 'transformed.js') {
      // We pretend the transformed.js file actually exists in the 'src/' directory. When the nested
      // source files are loaded, they will now be relative to `src/`.
      ctx.source = 'src/transformed.js';
      return transformedMap;
    }

    console.assert(file === 'src/helloworld.js');
    // We could futher change the source of this original file, eg, to be inside a nested directory
    // itself. This will be reflected in the remapped sourcemap.
    ctx.source = 'src/nested/transformed.js';
    return null;
  }
);

console.log(remapped);
// {
//   …,
//   sources: ['src/nested/helloworld.js'],
// };

content

The content property can be overridden when we encounter an original source file. Eg, this allows you to manually provide the source content of the original file regardless of whether the sourcesContent field is present in the parent sourcemap. It can also be set to null to remove the source content.

const remapped = remapping(
  minifiedTransformedMap,
  (file, ctx) => {

    if (file === 'transformed.js') {
      // transformedMap does not include a `sourcesContent` field, so usually the remapped sourcemap
      // would not include any `sourcesContent` values.
      return transformedMap;
    }

    console.assert(file === 'helloworld.js');
    // We can read the file to provide the source content.
    ctx.content = fs.readFileSync(file, 'utf8');
    return null;
  }
);

console.log(remapped);
// {
//   …,
//   sourcesContent: [
//     'console.log("Hello world!")',
//   ],
// };

Options

excludeContent

By default, excludeContent is false. Passing { excludeContent: true } will exclude the sourcesContent field from the returned sourcemap. This is mainly useful when you want to reduce the size out the sourcemap.

decodedMappings

By default, decodedMappings is false. Passing { decodedMappings: true } will leave the mappings field in a decoded state instead of encoding into a VLQ string.

remapping's People

Contributors

dependabot[bot] avatar h-a-n-a avatar halfnelson avatar jridgewell avatar milahu avatar renovate-bot avatar renovate[bot] avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

remapping's Issues

Experiencing `Cannot read property 'originalPositionFor' of undefined` in `jest`

I was wondering if this is an issue that is relevant at the root, even though I'm experiencing it with Jest.

When I try to collect coverage with Jest, it will fail hard with some of my files and remapping is what is complaining about my files:

ERROR: /home/oliver/fairmanager/core-web3/packages/core-graphql/source/edges/IndexedUserProfileFields.ts: Cannot read property 'originalPositionFor' of undefined
STACK: TypeError: /home/oliver/fairmanager/core-web3/packages/core-graphql/source/edges/IndexedUserProfileFields.ts: Cannot read property 'originalPositionFor' of undefined
    at SourceMapTree.originalPositionFor (/home/oliver/fairmanager/core-web3/node_modules/@ampproject/remapping/dist/remapping.umd.js:159:27)
    at trace (/home/oliver/fairmanager/core-web3/node_modules/@ampproject/remapping/dist/remapping.umd.js:102:37)
    at EncodedSourceMapImpl.map (/home/oliver/fairmanager/core-web3/node_modules/@jridgewell/trace-mapping/dist/trace-mapping.umd.js:347:36)
    at TraceMap.map (/home/oliver/fairmanager/core-web3/node_modules/@jridgewell/trace-mapping/dist/trace-mapping.umd.js:430:31)
    at SourceMapTree.traceMappings (/home/oliver/fairmanager/core-web3/node_modules/@ampproject/remapping/dist/remapping.umd.js:85:34)
    at remapping (/home/oliver/fairmanager/core-web3/node_modules/@ampproject/remapping/dist/remapping.umd.js:258:36)
    at mergeSingleSource (/home/oliver/fairmanager/core-web3/node_modules/@babel/core/lib/transformation/file/merge-map.js:42:22)
    at mergeSourceMap (/home/oliver/fairmanager/core-web3/node_modules/@babel/core/lib/transformation/file/merge-map.js:31:14)
    at generateCode (/home/oliver/fairmanager/core-web3/node_modules/@babel/core/lib/transformation/file/generate.js:75:39)
    at run (/home/oliver/fairmanager/core-web3/node_modules/@babel/core/lib/transformation/index.js:55:33)

The file (IndexedUserProfileFields.ts) it complains about only exports types, which I assume is the issue:

export type IndexedUserProfileFields = {
  costUnit: string;
  country: string;
  email: string;
  nameFirst: string;
  nameLast: string;
};

I investigated this a bit at the source level and was wondering what segment is if source is undefiend. In this error situation, it's [,NaN,NaN,NaN,NaN]. It didn't seem right to me and maybe this is a case that already needs to be handled here.

TypeError: genMapping.encodedMap is not a function

Same issue this other person described here in an Angular project:

https://stackoverflow.com/questions/73074976/angular-build-error-genmapping-encodedmap-is-not-a-function

My project build is roughly:

  System:
    OS: macOS 12.5
  Binaries:
    Node: 18.8.0 - ~/.n-node-versions/bin/node
    npm: 8.19.1 - ~/.npm-packages/bin/npm
  npmPackages:
    @babel/cli: ^7.11.6 => 7.18.10 
    @babel/core: ^7.11.6 => 7.19.1 
    @babel/plugin-proposal-class-properties: ^7.10.4 => 7.18.6 
    @babel/plugin-proposal-class-static-block: ^7.18.6 => 7.18.6 
    @babel/plugin-proposal-decorators: ^7.10.5 => 7.19.1 
    @babel/plugin-proposal-nullish-coalescing-operator: ^7.10.4 => 7.18.6 
    @babel/plugin-proposal-optional-chaining: ^7.11.0 => 7.18.9 
    @babel/preset-typescript: ^7.12.7 => 7.18.6 
    @babel/runtime: ^7.11.2 => 7.19.0 
    babel-loader: ^8.2.2 => 8.2.5 
    babel-preset-solid: ^1.0.0 => 1.5.4 
    webpack: ^5.72.0 => 5.74.0 

where @babel/core depends on @ampproject/remapping at version 2.2.0.

The full error is:

Module build failed (from ./node_modules/babel-loader/lib/index.js):
TypeError: /Users/trusktr/src/lume+lume/packages/classy-solid/dist/index.test.js: genMapping.encodedMap is not a function
    at new SourceMap (/Users/trusktr/src/lume+lume/packages/classy-solid/node_modules/@ampproject/remapping/dist/remapping.umd.js:169:91)
    at remapping (/Users/trusktr/src/lume+lume/packages/classy-solid/node_modules/@ampproject/remapping/dist/remapping.umd.js:203:16)
    at mergeSourceMap (/Users/trusktr/src/lume+lume/packages/classy-solid/node_modules/@babel/core/lib/transformation/file/merge-map.js:22:30)
    at generateCode (/Users/trusktr/src/lume+lume/packages/classy-solid/node_modules/@babel/core/lib/transformation/file/generate.js:76:41)
    at run (/Users/trusktr/src/lume+lume/packages/classy-solid/node_modules/@babel/core/lib/transformation/index.js:55:33)
    at run.next (<anonymous>)
    at transform (/Users/trusktr/src/lume+lume/packages/classy-solid/node_modules/@babel/core/lib/transform.js:29:41)
    at transform.next (<anonymous>)
    at step (/Users/trusktr/src/lume+lume/packages/classy-solid/node_modules/gensync/index.js:261:32)
    at /Users/trusktr/src/lume+lume/packages/classy-solid/node_modules/gensync/index.js:273:13
    at async.call.result.err.err (/Users/trusktr/src/lume+lume/packages/classy-solid/node_modules/gensync/index.js:223:11)
    at /Users/trusktr/src/lume+lume/packages/classy-solid/node_modules/gensync/index.js:189:28
    at /Users/trusktr/src/lume+lume/packages/classy-solid/node_modules/@babel/core/lib/gensync-utils/async.js:84:7
    at /Users/trusktr/src/lume+lume/packages/classy-solid/node_modules/gensync/index.js:113:33
    at step (/Users/trusktr/src/lume+lume/packages/classy-solid/node_modules/gensync/index.js:287:14)
    at /Users/trusktr/src/lume+lume/packages/classy-solid/node_modules/gensync/index.js:273:13
    at async.call.result.err.err (/Users/trusktr/src/lume+lume/packages/classy-solid/node_modules/gensync/index.js:223:11)

webpack 5.74.0 compiled with 1 error in 302 ms

Dependency Dashboard

This issue lists Renovate updates and detected dependencies. Read the Dependency Dashboard docs to learn more.

Warning

These dependencies are deprecated:

Datasource Name Replacement PR?
npm npm-run-all Available

Rate-Limited

These updates are currently rate-limited. Click on a checkbox below to force their creation now.

  • Update dependency eslint to v8.57.0
  • Update dependency prettier to v2.8.8
  • Update dependency tslib to v2.6.3
  • Update actions/checkout action to v4
  • Update actions/setup-node action to v4
  • Update dependency @rollup/plugin-typescript to v11
  • Update dependency eslint to v9
  • Update dependency eslint-config-prettier to v9
  • Update dependency prettier to v3
  • Update dependency rollup to v4
  • Update dependency typescript to v5
  • Update typescript-eslint monorepo to v7 (major) (@typescript-eslint/eslint-plugin, @typescript-eslint/parser)
  • 🔐 Create all rate-limited PRs at once 🔐

Edited/Blocked

These updates have been manually edited so Renovate will no longer make changes. To discard all commits and start over, click on a checkbox.

Open

These updates have all been created already. Click a checkbox below to force a retry/rebase of any.

Detected dependencies

github-actions
.github/workflows/nodejs.yml
  • actions/checkout v1
  • actions/setup-node v1
npm
package.json
  • @jridgewell/gen-mapping ^0.3.5
  • @jridgewell/trace-mapping ^0.3.24
  • @rollup/plugin-typescript 8.3.2
  • @types/jest 27.4.1
  • @typescript-eslint/eslint-plugin 5.20.0
  • @typescript-eslint/parser 5.20.0
  • eslint 8.14.0
  • eslint-config-prettier 8.5.0
  • jest 27.5.1
  • jest-config 27.5.1
  • npm-run-all 4.1.5
  • prettier 2.6.2
  • rollup 2.70.2
  • ts-jest 27.1.4
  • tslib 2.4.0
  • typescript 4.6.3
  • node >=6.0.0

  • Check this box to trigger a request for Renovate to run again on this repository

read properties of undefined

jest --coverage output:

FAIL src/pages/pc/tests/app.node.spec.tsx
● Test suite failed to run

TypeError: .../player/dist/cjs/index.js: Cannot read properties of undefined (reading 'originalPositionFor')

  at SourceMapTree.originalPositionFor (../../node_modules/.pnpm/@[email protected]/node_modules/@ampproject/src/source-map-tree.ts:138:19)
  at trace (../../node_modules/.pnpm/@[email protected]/node_modules/@ampproject/src/source-map-tree.ts:70:25)
  at EncodedSourceMapImpl.map (../../node_modules/.pnpm/@[email protected]/node_modules/@jridgewell/src/encoded-map.ts:43:24)
  at TraceMap.map (../../node_modules/.pnpm/@[email protected]/node_modules/@jridgewell/src/trace-mapping.ts:85:23)
  at SourceMapTree.traceMappings (../../node_modules/.pnpm/@[email protected]/node_modules/@ampproject/src/source-map-tree.ts:42:26)
  at remapping (../../node_modules/.pnpm/@[email protected]/node_modules/@ampproject/src/remapping.ts:37:30)
  at mergeSourceMap (../../node_modules/.pnpm/@[email protected]/node_modules/@babel/core/lib/transformation/file/merge-map.js:19:30)
  at generateCode (../../node_modules/.pnpm/@[email protected]/node_modules/@babel/core/lib/transformation/file/generate.js:72:39)
  at run (../../node_modules/.pnpm/@[email protected]/node_modules/@babel/core/lib/transformation/index.js:55:33)
      at run.next (<anonymous>)

should ensure not nil before call the source.originalPositionFor?

const source = this.sources[segment[1]];
return source.originalPositionFor(
segment[2],
segment[3],
segment.length === 5 ? this.map.names[segment[4]] : name
);

`SourceMap` type export

Would like to request that the return type of remapping (SourceMap) be exported. It would be useful when typing functions that expect the returned map.

Currently, it doesn't seem to be exported: https://unpkg.com/@ampproject/[email protected]/dist/types/remapping.d.ts

As a side, I wanted to mention a discrepancy between the documentation and code. The documentation says the input SourceMap and the return SourceMap are the same. However, when trying it out, they seem to be different.

From the docs:

function remapping(
  map: SourceMap | SourceMap[],
  loader: (file: string, ctx: LoaderContext) => (SourceMap | null | undefined),
  options?: { excludeContent: boolean, decodedMappings: boolean }
): SourceMap;

From the code:

function remapping(
  input: SourceMapInput | SourceMapInput[],
  loader: SourceMapLoader,
  options?: boolean | Options
): SourceMap;

Error: Transformation map 0 must have exactly one source file

please explain this error

Error: Transformation map 0 must have exactly one source file.
Did you specify these with the most recent transformation maps first?

this is required for all but the last/oldest sourcemap (index -1)

i mean, why must maps 0 to -2 have only one source file?
this looks more like 'not implemented' than 'error'

put differently:
why does remapper not support convergent transform chains?
= multiple input files + single output file, arranged in a tree structure

also, if i recall right, only the first entry of maps[-1].sources
is propagated to result.sources. doesnt that break sourcesIdx values?

reproduce
const remapper = require('@ampproject/remapping');

// segment =
//     [ columnIdx_gen ]
//   | [ columnIdx_gen, sourcesIdx, lineIdx, columnIdx ]
//   | [ columnIdx_gen, sourcesIdx, lineIdx, columnIdx, namesIdx ]

const trigger_error = 1;

const sourcemapList = [
  // map 0
  {
    version: 3,
    sources: trigger_error
      ? [
          'file-3', // src 0
          'file-4', // src 1
        ]
      : [
          'file-3',
        ],
    names: [],
    mappings: [
      trigger_error
      ? [
          [0, 0, 0, 0], // col 0 = src 0
          [1, 1, 0, 0], // col 1 = src 1
        ]
      : [
          [0, 0, 0, 0],
        ]
    ]
  },
  // map 1
  {
    version: 3,
    sources: [
      'file-1', // src 0
      'file-2', // src 1
    ],
    names: [],
    mappings: [
      [
        [0, 0, 0, 0], // col 0 = src 0
        [1, 1, 0, 0], // col 1 = src 1
      ]
    ]
  }
];

const sourcemap = remapper(
  sourcemapList,
  function loader(file) {
    return null;
  }
);
console.dir(sourcemap);

actual result with trigger_error = 0:

    sources: [
      'file-1', // src 0 of map 1
    ],

expected result:

    sources: [
      'file-1',
      'file-2',
      'file-3',
      'file-4',
    ],

Empty source map causes sources to be unset

When combining source maps, and one of the maps is empty, the sources array is empty afterwards.

[
  {
    version: 3,
    names: [],
    sources: [ '..path/to/$layout.svelte' ],
    sourcesContent: [ '<p>asd</p>\r\n' ],
    mappings: ';;;;;;;'
  },
  {
    version: 3,
    mappings: 'AAAA,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;',
    names: [],
    sources: [ '$layout.svelte' ]
  }
]

It produces { version: 3, mappings: ';;;;;;;', names: [], sources: [] } (note the empty sources array. Mappings is also empty, not sure if that is intended).

Digging into the source code, I think that in this function the combination is done, and the line where sources is updated is never reached in case of empty mappings.

tsc failed to build with `import { type xxx} `

import { type syntax seems not working for tsc, even this project can be built successfully, however if we try to import this project from another tsc complains as follows:

../../common/temp/node_modules/.pnpm/@[email protected]/node_modules/@ampproject/remapping/dist/types/source-map.d.ts:1:15 - error TS1005: ',' expected.

1 import { type TraceMap } from '@jridgewell/trace-mapping';

Remapping when there's multiple sources

First, thank you for such a high quality piece of software for source map merging.

With the adoption of this project within Babel 7.17, we're seeing build errors (angular/angular#44972) originating in this project in combination with Angular's linker transform, a Babel plugin that transforms JS source files to become fully AOT compiled for the Angular runtime to execute.

For context, the Angular linker compiles certain template string literals into Angular template functions. Angular templates can have originally been authored in external template files, and the template string literal is mapped into such an external file (typically an .html file). The template string literal in JS might contain escape sequences different to what the original external template contained, which means that source positions in the template literal string may be slightly different to their positions in the external template. To avoid these differences, the Angular linker actually attempts to read the original HTML template from the input source map and then uses that source text as template parsing source, after which it generates Babel AST with a SourceLocation.filename corresponding with that external template source. This will subsequently cause Babel's output map to contain an extra source (or any arbitrary amount of extra sources, really).

Babel used to ignore this case silently, per this logic. This condition is no longer present since babel/babel#14209, so an output source map with multiple sources now causes a hard Transformation map 0 must have exactly one source file error that fails the build. We can workaround this by disabling the Angular's linker plugin sourceMap option so it won't parse external templates using the input source map, but perhaps the condition should be reintroduced in Babel to avoid this breakage (although I realize that the linker's output map never behaved as desired as it wasn't merged).

I am opening this issue here as I'd be interested to see if/how we could 1) support multiple sources in this project, or 2) if you think our current approach is invalid and whether you have suggestions for adapting the Angular linker to deal with this differently. One alternative approach we explored was to record additional parsing offsets due to escape sequences, such that template parsing could take these into account (as the template string can't be assigned multiple source map segments, at least not if it's just a single template literal) but using the original sources from the input source map was far easier and resulted in simpler generated code.

FYI, the Angular compiler has its own source map merging logic which doesn't have the limitation of a single source, I believe.

As for a potential fix in Babel (at least for v7), please let me know if you think that re-adding the single-sources condition sounds reasonable, or if we should implement a workaround in the Angular's linker (which would currently mean to disable the linker's sourceMap option by default)

TypeError [ERR_INVALID_URL]: Invalid URL when sourcemap contains invalid paths

Current

When the sourcemap looks like (which is invalid) @ampproject/remapping will throw an ERR_INVALID_URL exception.

{"version":3,"sources":["webpack://[name]/webpack/universalModuleDefinition", ...rest], ...rest}
./node_modules/@clickup/gantt/codebase/dhtmlxgantt.js - Error: Module build failed (from ./node_modules/@angular-devkit/build-angular/src/babel/webpack-loader.js):
TypeError [ERR_INVALID_URL]: Invalid URL
    at new NodeError (node:internal/errors:371:5)
    at onParseError (node:internal/url:552:9)
    at new URL (node:internal/url:628:5)
    at normalizeSimplePath (/Users/mattlewis/Code/open-source/source-map-bug/node_modules/@ampproject/remapping/dist/remapping.umd.js:301:26)
    at normalizePath (/Users/mattlewis/Code/open-source/source-map-bug/node_modules/@ampproject/remapping/dist/remapping.umd.js:320:20)
    at resolve (/Users/mattlewis/Code/open-source/source-map-bug/node_modules/@ampproject/remapping/dist/remapping.umd.js:386:26)
    at resolve$1 (/Users/mattlewis/Code/open-source/source-map-bug/node_modules/@ampproject/remapping/dist/remapping.umd.js:418:16)
    at /Users/mattlewis/Code/open-source/source-map-bug/node_modules/@ampproject/remapping/dist/remapping.umd.js:737:25
    at Array.map ()
    at buildSourceMapTree (/Users/mattlewis/Code/open-source/source-map-bug/node_modules/@ampproject/remapping/dist/remapping.umd.js:734:34)

Expected

Gracefully handle invalid sourcemaps.

Other

Context angular/angular-cli#22526

Considering publish a new version to NPM?

Thanks for the great work! TS 5.0 has released and the downstream packages are trying to migrating to moduleResolution: bunder(such as Vite). But the latest version of remapping on NPM still relies a old version of @jridgewell/gen-mapping which lacks exports.types that will block TS 5.0 to find the type definition. I saw remapping has bumped the dependency. All we need to do is release a new version. Could the package maintainer do a new release? Thanks! 🤗

Transformation map 0 must have exactly one source file

Hi,

I tried enabling vendor source maps on my Angular 13 project, and I get this error (relevant build log excerpt):

⚡ ng build home --configuration production
✔ Browser application bundle generation complete.

./node_modules/@apollo/client/cache/inmemory/fixPolyfills.js - Error: Module build failed (from ./node_modules/@angular-devkit/build-angular/src/babel/webpack-loader.js):
Error: Transformation map 0 must have exactly one source file.
Did you specify these with the most recent transformation maps first?
    at buildSourceMapTree (/cut/node_modules/@ampproject/remapping/dist/remapping.umd.js:729:23)
    at remapping (/cut/node_modules/@ampproject/remapping/dist/remapping.umd.js:831:23)
    at Object.result (/cut/node_modules/@angular-devkit/build-angular/src/babel/webpack-loader.js:202:54)
    at Object.<anonymous> (/cut/node_modules/babel-loader/lib/index.js:221:43)
    at Generator.next (<anonymous>)
    at asyncGeneratorStep (/cut/node_modules/babel-loader/lib/index.js:3:103)
    at _next (/cut/node_modules/babel-loader/lib/index.js:5:194)

That file, ./node_modules/@apollo/client/cache/inmemory/fixPolyfills.js, is empty, it only contains a map file reference:

⚡ cat node_modules/@apollo/client/cache/inmemory/fixPolyfills.js
//# sourceMappingURL=fixPolyfills.js.map% 

And that mapping file exists:

⚡ cat node_modules/@apollo/client/cache/inmemory/fixPolyfills.js.map
{"version":3,"file":"fixPolyfills.js","sourceRoot":"","sources":["../../../src/cache/inmemory/fixPolyfills.ts"],"names":[],"mappings":"","sourcesContent":["// Most JavaScript environments do not need the workarounds implemented in\n// fixPolyfills.native.ts, so importing fixPolyfills.ts merely imports\n// this empty module, adding nothing to bundle sizes or execution times.\n// When bundling for React Native, we substitute fixPolyfills.native.js\n// for fixPolyfills.js (see the \"react-native\" section of package.json),\n// to work around problems with Map and Set polyfills in older versions of\n// React Native (which should have been fixed in [email protected]):\n// https://github.com/apollographql/apollo-client/pull/5962\n"]}% 

I don't know if it occurs on other files, this is crashing the build, but I suspect there's something wrong with that file specifically.

Is that an issue that can be fixed in remapping, or should I post an issue somewhere else (eg. Apollo) ?

This is the version in use:

 yarn why @ampproject/remapping
=> Found "@ampproject/[email protected]"
info Reasons this module exists
   - "@angular-devkit#build-angular" depends on it
   - Hoisted from "@angular-devkit#build-angular#@ampproject#remapping"

Thanks in advance,

remapping works only with high resolution sourcemaps

today i learned, after an hour of debugging ....
remapping via backtracing works only with high resolution sourcemaps

this should at least be documented in the readme
since some sourcemap-generators produce lowres maps by default

package source-map says

SourceMapGenerator.prototype.applySourceMap

Note: The resolution for the resulting mappings is the minimum of this map and the supplied map.

better show a warning when older mappings are not reachable
the warning can be disabled with a allowLossyRemap flag, or so

not possible in a reliable way, without tokenizing source files = out of scope

supporting sourcemap-generators who can only produce lowres maps, is ....

probably out-of-scope

modify the backtracing algorithm, to support lowres sourcemaps
lowres sourcemap means:
if one line was not changed, the mapping line is empty
(probably same for segments)

this is simple with the array interface
where every map has exactly one source file
so we can copy missing mappings from parent to child

in a more complex scene (convergent transform chain)
with multiple source files, we need a way to find the 'main source file'
index zero should work in most cases, but not in all cases

snippet to sometimes detect lost source files
// convergent transform chain:
//           3           2           1
// bundle.js < bundle.js < bundle.js <
//             src-4       src-3       src-1
//                                     src-2
// sample:
// when transform 2 gives a lowres sourcemap
// and 2 does not modify the changes of 1
// then src-1 and src-2 are 'lost source files'
//
// problem:
// this method is not reliable.
// if at least one segment can trace back
// then the sourcefile is not detected as lost

const sourcemap_list = [ /* .... */ ];
const filename = 'bundle.js'; // main source file in every sourcemap
let map_idx = 1;

const map = remapping( // use loader interface
  sourcemap_list[0], // last map
  function loader(sourcefile) {
    if (sourcefile == filename && sourcemap_list[map_idx]) {
      return sourcemap_list[map_idx++]; // idx 1, 2, ...
      // bundle file = branch node
    }
    else return null; // source file = leaf node
  }
);

// show warning if source files were lost
const sources_lost = sourcemap_list
  .map(m => m.sources.filter(s => !map.sources.includes(s)));
if (sources_lost.find(a => a.length > 0))
  console.log('warning. combine_sourcemaps lost source files:\n'
    + JSON.stringify(sources_lost, null, 2)
    + '\nprobably you want to generate high-resolution sourcemaps.'
  );

Maximum call stack size exceeded

Webpack-based projects (including Vue CLI scaffolded projects, and Quasar projects) are failing with Maximum call stack size exceeded, starting from buildSourceMapTree() and infinitely recursing in build(). This seems to occur when building the source map.

Steps to reproduce:

  1. Scaffold a new Vue CLI project with:

     npx @vue/cli create --default my-vue-app
  2. Change into the source directory with:

    cd my-vue-app
  3. Start the webpack devserver:

    npm run serve
  4. Observe the error in the console.

Call stack
 (/Users/tony/src/tmp/test-vue-app123/node_modules/@ampproject/remapping/dist/remapping.umd.js:230)
build (/Users/tony/src/tmp/test-vue-app123/node_modules/@ampproject/remapping/dist/remapping.umd.js:206)
 (/Users/tony/src/tmp/test-vue-app123/node_modules/@ampproject/remapping/dist/remapping.umd.js:230)
build (/Users/tony/src/tmp/test-vue-app123/node_modules/@ampproject/remapping/dist/remapping.umd.js:206)
 (/Users/tony/src/tmp/test-vue-app123/node_modules/@ampproject/remapping/dist/remapping.umd.js:230)
build (/Users/tony/src/tmp/test-vue-app123/node_modules/@ampproject/remapping/dist/remapping.umd.js:206)
 (/Users/tony/src/tmp/test-vue-app123/node_modules/@ampproject/remapping/dist/remapping.umd.js:230)
build (/Users/tony/src/tmp/test-vue-app123/node_modules/@ampproject/remapping/dist/remapping.umd.js:206)
 (/Users/tony/src/tmp/test-vue-app123/node_modules/@ampproject/remapping/dist/remapping.umd.js:230)
build (/Users/tony/src/tmp/test-vue-app123/node_modules/@ampproject/remapping/dist/remapping.umd.js:206)
 (/Users/tony/src/tmp/test-vue-app123/node_modules/@ampproject/remapping/dist/remapping.umd.js:230)
build (/Users/tony/src/tmp/test-vue-app123/node_modules/@ampproject/remapping/dist/remapping.umd.js:206)
buildSourceMapTree (/Users/tony/src/tmp/test-vue-app123/node_modules/@ampproject/remapping/dist/remapping.umd.js:198)
remapping (/Users/tony/src/tmp/test-vue-app123/node_modules/@ampproject/remapping/dist/remapping.umd.js:273)
mergeSourceMap (/Users/tony/src/tmp/test-vue-app123/node_modules/@babel/core/lib/transformation/file/merge-map.js:19)
generateCode (/Users/tony/src/tmp/test-vue-app123/node_modules/@babel/core/lib/transformation/file/generate.js:75)
run (/Users/tony/src/tmp/test-vue-app123/node_modules/@babel/core/lib/transformation/index.js:55)
transform (/Users/tony/src/tmp/test-vue-app123/node_modules/@babel/core/lib/transform.js:25)
step (/Users/tony/src/tmp/test-vue-app123/node_modules/gensync/index.js:261)
 (/Users/tony/src/tmp/test-vue-app123/node_modules/gensync/index.js:273)
async.call.result.err.err (/Users/tony/src/tmp/test-vue-app123/node_modules/gensync/index.js:223)
 (/Users/tony/src/tmp/test-vue-app123/node_modules/gensync/index.js:189)
 (/Users/tony/src/tmp/test-vue-app123/node_modules/@babel/core/lib/gensync-utils/async.js:74)
 (/Users/tony/src/tmp/test-vue-app123/node_modules/gensync/index.js:113)
step (/Users/tony/src/tmp/test-vue-app123/node_modules/gensync/index.js:287)
 (/Users/tony/src/tmp/test-vue-app123/node_modules/gensync/index.js:273)
async.call.result.err.err (/Users/tony/src/tmp/test-vue-app123/node_modules/gensync/index.js:223)

Environment

  • @ampproject/remapping - 2.1.1
  • macOS Big Sur
  • Node 17

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.