/** * Copyright (c) 2016-present, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. * * @flow */ 'use strict'; import type {ModuleGroups, ModuleTransportLike, SourceMap} from '../../types.flow'; const newline = /\r\n?|\n|\u2028|\u2029/g; // fastest implementation const countLines = (string: string) => (string.match(newline) || []).length + 1; function lineToLineSourceMap(source: string, filename: string = ''): SourceMap { // The first line mapping in our package is the base64vlq code for zeros (A). const firstLine = 'AAAA;'; // Most other lines in our mappings are all zeros (for module, column etc) // except for the lineno mapping: curLineno - prevLineno = 1; Which is C. const line = 'AACA;'; return { file: filename, mappings: firstLine + Array(countLines(source)).join(line), sources: [filename], names: [], version: 3, }; } const wrapperEnd = wrappedCode => wrappedCode.indexOf('{') + 1; const Section = (line: number, column: number, map: SourceMap) => ({map, offset: {line, column}}); type CombineSourceMapsOptions = { moduleGroups?: ModuleGroups, modules: Array, withCustomOffsets?: boolean, }; function combineSourceMaps({ moduleGroups, modules, withCustomOffsets, }: CombineSourceMapsOptions): SourceMap { let offsets; const sections = []; const sourceMap: Object = { file: '', sections, version: 3, }; if (withCustomOffsets) { offsets = sourceMap.x_facebook_offsets = []; } let line = 0; modules.forEach(moduleTransport => { const {code, id, name} = moduleTransport; let column = 0; let hasOffset = false; let group; let groupLines = 0; let {map} = moduleTransport; if (withCustomOffsets) { if (moduleGroups && moduleGroups.modulesInGroups.has(id)) { // this is a module appended to another module return; } group = moduleGroups && moduleGroups.groups.get(id); if (group && moduleGroups) { const {modulesById} = moduleGroups; const otherModules: Array = Array.from(group || []) .map(moduleId => modulesById.get(moduleId)) .filter(Boolean); // needed to appease flow otherModules.forEach(m => { groupLines += countLines(m.code); }); map = combineSourceMaps({ modules: [moduleTransport].concat(otherModules), }); } hasOffset = id != null; column = wrapperEnd(code); } sections.push(Section(line, column, map || lineToLineSourceMap(code, name))); if (hasOffset) { offsets[id] = line; for (const moduleId of group || []) { offsets[moduleId] = line; } } line += countLines(code) + groupLines; }); return sourceMap; } const joinModules = (modules: Array<*>): string => modules.map(m => m.code).join('\n'); module.exports = { countLines, lineToLineSourceMap, combineSourceMaps, joinModules, };