123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198 |
- /*
- MIT License http://www.opensource.org/licenses/mit-license.php
- Author Tobias Koppers @sokra
- */
- "use strict";
- const Source = require("./Source");
- const { getMap, getSourceAndMap } = require("./helpers/getFromStreamChunks");
- const getGeneratedSourceInfo = require("./helpers/getGeneratedSourceInfo");
- const splitIntoLines = require("./helpers/splitIntoLines");
- const splitIntoPotentialTokens = require("./helpers/splitIntoPotentialTokens");
- const {
- isDualStringBufferCachingEnabled,
- } = require("./helpers/stringBufferUtils");
- /** @typedef {import("./Source").HashLike} HashLike */
- /** @typedef {import("./Source").MapOptions} MapOptions */
- /** @typedef {import("./Source").RawSourceMap} RawSourceMap */
- /** @typedef {import("./Source").SourceAndMap} SourceAndMap */
- /** @typedef {import("./Source").SourceValue} SourceValue */
- /** @typedef {import("./helpers/getGeneratedSourceInfo").GeneratedSourceInfo} GeneratedSourceInfo */
- /** @typedef {import("./helpers/streamChunks").OnChunk} OnChunk */
- /** @typedef {import("./helpers/streamChunks").OnName} OnName */
- /** @typedef {import("./helpers/streamChunks").OnSource} OnSource */
- /** @typedef {import("./helpers/streamChunks").Options} Options */
- class OriginalSource extends Source {
- /**
- * @param {string | Buffer} value value
- * @param {string} name name
- */
- constructor(value, name) {
- super();
- const isBuffer = Buffer.isBuffer(value);
- /**
- * @private
- * @type {undefined | string}
- */
- this._value = isBuffer ? undefined : value;
- /**
- * @private
- * @type {undefined | Buffer}
- */
- this._valueAsBuffer = isBuffer ? value : undefined;
- this._name = name;
- }
- getName() {
- return this._name;
- }
- /**
- * @returns {SourceValue} source
- */
- source() {
- if (this._value === undefined) {
- const value =
- /** @type {Buffer} */
- (this._valueAsBuffer).toString("utf8");
- if (isDualStringBufferCachingEnabled()) {
- this._value = value;
- }
- return value;
- }
- return this._value;
- }
- buffer() {
- if (this._valueAsBuffer === undefined) {
- const value = Buffer.from(/** @type {string} */ (this._value), "utf8");
- if (isDualStringBufferCachingEnabled()) {
- this._valueAsBuffer = value;
- }
- return value;
- }
- return this._valueAsBuffer;
- }
- /**
- * @param {MapOptions=} options map options
- * @returns {RawSourceMap | null} map
- */
- map(options) {
- return getMap(this, options);
- }
- /**
- * @param {MapOptions=} options map options
- * @returns {SourceAndMap} source and map
- */
- sourceAndMap(options) {
- return getSourceAndMap(this, options);
- }
- /**
- * @param {Options} options options
- * @param {OnChunk} onChunk called for each chunk of code
- * @param {OnSource} onSource called for each source
- * @param {OnName} _onName called for each name
- * @returns {GeneratedSourceInfo} generated source info
- */
- streamChunks(options, onChunk, onSource, _onName) {
- if (this._value === undefined) {
- this._value =
- /** @type {Buffer} */
- (this._valueAsBuffer).toString("utf8");
- }
- onSource(0, this._name, this._value);
- const finalSource = Boolean(options && options.finalSource);
- if (!options || options.columns !== false) {
- // With column info we need to read all lines and split them
- const matches = splitIntoPotentialTokens(this._value);
- let line = 1;
- let column = 0;
- if (matches !== null) {
- for (const match of matches) {
- const isEndOfLine = match.endsWith("\n");
- if (isEndOfLine && match.length === 1) {
- if (!finalSource) onChunk(match, line, column, -1, -1, -1, -1);
- } else {
- const chunk = finalSource ? undefined : match;
- onChunk(chunk, line, column, 0, line, column, -1);
- }
- if (isEndOfLine) {
- line++;
- column = 0;
- } else {
- column += match.length;
- }
- }
- }
- return {
- generatedLine: line,
- generatedColumn: column,
- source: finalSource ? this._value : undefined,
- };
- } else if (finalSource) {
- // Without column info and with final source we only
- // need meta info to generate mapping
- const result = getGeneratedSourceInfo(this._value);
- const { generatedLine, generatedColumn } = result;
- if (generatedColumn === 0) {
- for (
- let line = 1;
- line < /** @type {number} */ (generatedLine);
- line++
- ) {
- onChunk(undefined, line, 0, 0, line, 0, -1);
- }
- } else {
- for (
- let line = 1;
- line <= /** @type {number} */ (generatedLine);
- line++
- ) {
- onChunk(undefined, line, 0, 0, line, 0, -1);
- }
- }
- return result;
- }
- // Without column info, but also without final source
- // we need to split source by lines
- let line = 1;
- const matches = splitIntoLines(this._value);
- /** @type {string | undefined} */
- let match;
- for (match of matches) {
- onChunk(finalSource ? undefined : match, line, 0, 0, line, 0, -1);
- line++;
- }
- return matches.length === 0 || /** @type {string} */ (match).endsWith("\n")
- ? {
- generatedLine: matches.length + 1,
- generatedColumn: 0,
- source: finalSource ? this._value : undefined,
- }
- : {
- generatedLine: matches.length,
- generatedColumn: /** @type {string} */ (match).length,
- source: finalSource ? this._value : undefined,
- };
- }
- /**
- * @param {HashLike} hash hash
- * @returns {void}
- */
- updateHash(hash) {
- hash.update("OriginalSource");
- hash.update(this.buffer());
- hash.update(this._name || "");
- }
- }
- module.exports = OriginalSource;
|