Source code

Revision control

Copy as Markdown

Other Tools

/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
/**
* Get the source text offset equivalent to a given line/column pair.
*
* @param {Debugger.Source} source
* @param {number} line The 1-based line number.
* @param {number} column The 0-based column number.
* @returns {number} The codepoint offset into the source's text.
*/
function findSourceOffset(source, line, column) {
const offsets = getSourceLineOffsets(source);
const offset = offsets[line - 1];
if (offset) {
// Make sure that columns that technically don't exist in the line text
// don't cause the offset to wrap to the next line.
return Math.min(offset.start + column, offset.textEnd);
}
return line < 0 ? 0 : offsets[offsets.length - 1].end;
}
exports.findSourceOffset = findSourceOffset;
const NEWLINE = /(\r?\n|\r|\u2028|\u2029)/g;
const SOURCE_OFFSETS = new WeakMap();
/**
* Generate and cache line information for a given source to track what
* text offsets mark the start and end of lines. Each entry in the array
* represents a line in the source text.
*
* @param {Debugger.Source} source
* @returns {Array<{ start, textEnd, end }>}
* - start - The codepoint offset of the start of the line.
* - textEnd - The codepoint offset just after the last non-newline character.
* - end - The codepoint offset of the end of the line. This will be
* be the same as the 'start' value of the next offset object,
* and this includes the newlines for the line itself, where
* 'textEnd' excludes newline characters.
*/
function getSourceLineOffsets(source) {
const cached = SOURCE_OFFSETS.get(source);
if (cached) {
return cached;
}
const { text } = source;
const lines = text.split(NEWLINE);
const offsets = [];
let offset = 0;
for (let i = 0; i < lines.length; i += 2) {
const line = lines[i];
const start = offset;
// Calculate the end codepoint offset.
let end = offset;
// eslint-disable-next-line no-unused-vars
for (const c of line) {
end++;
}
const textEnd = end;
if (i + 1 < lines.length) {
end += lines[i + 1].length;
}
offsets.push(Object.freeze({ start, textEnd, end }));
offset = end;
}
Object.freeze(offsets);
SOURCE_OFFSETS.set(source, offsets);
return offsets;
}
/**
* Given a target actor and a source platform internal ID,
* return the related SourceActor ID.
* @param TargetActor targetActor
* The Target Actor from which this source originates.
* @param String id
* Platform Source ID
* @return String
* The SourceActor ID
*/
function getActorIdForInternalSourceId(targetActor, id) {
const actor = targetActor.sourcesManager.getSourceActorByInternalSourceId(id);
return actor ? actor.actorID : null;
}
exports.getActorIdForInternalSourceId = getActorIdForInternalSourceId;