Skip to content

Commit

Permalink
Revert "rework central dispatch"
Browse files Browse the repository at this point in the history
This reverts commit b9e7513.
  • Loading branch information
joshgoebel committed Oct 29, 2020
1 parent f6d6e4d commit 8297e73
Showing 1 changed file with 56 additions and 67 deletions.
123 changes: 56 additions & 67 deletions src/highlight.js
Expand Up @@ -374,7 +374,7 @@ const HLJS = function(hljs) {
list.forEach(item => emitter.openNode(item));
}

/** @type {{type?: MatchType, index?: number, rule?: Mode, top?: Mode}}} */
/** @type {{type?: MatchType, index?: number, rule?: Mode}}} */
var lastMatch = {};

/**
Expand All @@ -386,93 +386,78 @@ const HLJS = function(hljs) {
function processLexeme(textBeforeMatch, match) {
var lexeme = match && match[0];

// add non-matched text to the current mode buffer
modeBuffer += textBeforeMatch;

if (lexeme == null) {
processBuffer();
return 0;
}

// infinite loops are BAD, this is a last ditch catch all. if we have a
// decent number of iterations yet our index (cursor position in our
// parsing) still 10x behind our index then something is very wrong
// so we bail
if (match.type === "begin" && iterations >= 10000 && iterations > match.index * 10) {
if (!SAFE_MODE) {
const err = new Error(`we appear stuck, more iterations ${iterations} than progress ${match.index}`);
throw err;
}
// try to move past it
modeBuffer += codeToHighlight.slice(match.index, match.index + 1);
// give us some breathing room
iterations -= 25;
return 1;
}

// we've found a 0 width match and we're stuck, so we need to advance
// this happens when we have badly behaved rules that have optional matchers to the degree that
// sometimes they can end up matching nothing at all
// Ref: https://github.com/highlightjs/highlight.js/issues/2140
if (lastMatch.type === "begin" && match.type === "end" && lastMatch.index === match.index && lexeme === "") {
let rule = lastMatch.rule;
if (!rule.starts || rule.contains === []) {
if (!SAFE_MODE) {
/** @type {AnnotatedError} */
const err = new Error('0 width match regex');
err.languageName = languageName;
err.badRule = lastMatch.rule;
throw err;
}
// spit the "skipped" character that our regex choked on back into the output sequence
modeBuffer += codeToHighlight.slice(match.index, match.index + 1);
return 1;
// spit the "skipped" character that our regex choked on back into the output sequence
modeBuffer += codeToHighlight.slice(match.index, match.index + 1);
if (!SAFE_MODE) {
/** @type {AnnotatedError} */
const err = new Error('0 width match regex');
err.languageName = languageName;
err.badRule = lastMatch.rule;
throw err;
}
return 1;
}
lastMatch = match;

/** @type {Symbol | number} */
let processed = 0;
switch (match.type) {
case "begin":
processed = doBeginMatch(match);
return processed;
case "end":
processed = doEndMatch(match);

/*
Why might be find ourselves here? Only one occasion now. An end match that was
triggered but could not be completed. When might this happen? When an `endSameasBegin`
rule sets the end rule to a specific match. Since the overall mode termination rule that's
being used to scan the text isn't recompiled that means that any match that LOOKS like
the end (but is not, because it is not an exact match to the beginning) will
end up here. A definite end match, but when `doEndMatch` tries to "reapply"
the end rule and fails to match, we wind up here, and just silently ignore the end.
This causes no real harm other than stopping a few times too many.
*/
if (processed === NO_MATCH) {
modeBuffer += lexeme;
return lexeme.length;
}

return processed;
case "illegal":
if (ignoreIllegals) {
// edge case for when illegal matches $ (end of line) which is technically
// a 0 width match but not a begin/end match so it's not caught by the
// first handler (when ignoreIllegals is true)
if (lexeme === "") return 1;

modeBuffer += lexeme;
return lexeme.length;
}

if (match.type === "begin") {
return doBeginMatch(match);
} else if (match.type === "illegal" && !ignoreIllegals) {
// illegal match, we do not continue processing
/** @type {AnnotatedError} */
var err = new Error('Illegal lexeme "' + lexeme + '" for mode "' + (top.className || '<unnamed>') + '"');
const err = new Error('Illegal lexeme "' + lexeme + '" for mode "' + (top.className || '<unnamed>') + '"');
err.mode = top;
throw err;
} else if (match.type === "end") {
var processed = doEndMatch(match);
if (processed !== NO_MATCH) {
return processed;
}
}

// edge case for when illegal matches $ (end of line) which is technically
// a 0 width match but not a begin/end match so it's not caught by the
// first handler (when ignoreIllegals is true)
if (match.type === "illegal" && lexeme === "") {
// advance so we aren't stuck in an infinite loop
return 1;
}

// infinite loops are BAD, this is a last ditch catch all. if we have a
// decent number of iterations yet our index (cursor position in our
// parsing) still 3x behind our index then something is very wrong
// so we bail
if (iterations > 100000 && iterations > match.index * 3) {
const err = new Error('potential infinite loop, way more iterations than matches');
throw err;
}

/*
Why might be find ourselves here? Only one occasion now. An end match that was
triggered but could not be completed. When might this happen? When an `endSameasBegin`
rule sets the end rule to a specific match. Since the overall mode termination rule that's
being used to scan the text isn't recompiled that means that any match that LOOKS like
the end (but is not, because it is not an exact match to the beginning) will
end up here. A definite end match, but when `doEndMatch` tries to "reapply"
the end rule and fails to match, we wind up here, and just silently ignore the end.
This causes no real harm other than stopping a few times too many.
*/

modeBuffer += lexeme;
return lexeme.length;
}

var language = getLanguage(languageName);
Expand Down Expand Up @@ -721,6 +706,10 @@ const HLJS = function(hljs) {
* @param {{}} userOptions
*/
function configure(userOptions) {
if (userOptions.useBR) {
console.warn("'useBR' option is deprecated and will be removed entirely in v11.0");
console.warn("Please see https://github.com/highlightjs/highlight.js/issues/2559");
}
options = inherit(options, userOptions);
}

Expand Down

0 comments on commit 8297e73

Please sign in to comment.