Deep freeze name/tokens/lines/frontMatterLines properties of params object before passing to (custom) rules for shared access.

This commit is contained in:
David Anson 2021-12-23 04:34:25 +00:00 committed by GitHub
parent 5253669495
commit 5f0040679d
4 changed files with 98 additions and 16 deletions

View file

@ -276,6 +276,7 @@ function isMathBlock(token) {
token.type.startsWith("math_block") &&
!token.type.endsWith("_end"));
}
module.exports.isMathBlock = isMathBlock;
// Get line metadata array
module.exports.getLineMetadata = function getLineMetadata(params) {
var lineMetadata = params.lines.map(function (line, index) { return [line, index, false, 0, false, false, false, false]; });
@ -336,10 +337,6 @@ module.exports.flattenLists = function flattenLists(tokens) {
var nestingStack = [];
var lastWithMap = { "map": [0, 1] };
tokens.forEach(function (token) {
if (isMathBlock(token) && token.map[1]) {
// markdown-it-texmath plugin does not account for math_block_end
token.map[1]++;
}
if ((token.type === "bullet_list_open") ||
(token.type === "ordered_list_open")) {
// Save current context and start a new one
@ -840,6 +837,28 @@ function getNextChildToken(parentToken, childToken, nextType, nextNextType) {
return null;
}
module.exports.getNextChildToken = getNextChildToken;
/**
* Calls Object.freeze() on an object and its children.
*
* @param {Object} obj Object to deep freeze.
* @returns {Object} Object passed to the function.
*/
function deepFreeze(obj) {
var pending = [obj];
var current = null;
while ((current = pending.shift())) {
Object.freeze(current);
for (var _i = 0, _a = Object.getOwnPropertyNames(current); _i < _a.length; _i++) {
var name = _a[_i];
var value = current[name];
if (value && (typeof value === "object")) {
pending.push(value);
}
}
}
return obj;
}
module.exports.deepFreeze = deepFreeze;
/***/ }),
@ -1120,6 +1139,11 @@ function annotateTokens(tokens, lines) {
if (!token.map && trMap) {
token.map = __spreadArray([], trMap, true);
}
// Adjust maps for math blocks
if (helpers.isMathBlock(token) && token.map[1]) {
// markdown-it-texmath plugin does not account for math_block_end
token.map[1]++;
}
// Update token metadata
if (token.map) {
token.line = lines[token.map[0]];
@ -1359,10 +1383,10 @@ function lintContent(ruleList, name, content, md, config, frontMatter, handleRul
var _a = getEnabledRulesPerLineNumber(ruleList, lines, frontMatterLines, noInlineConfig, config, aliasToRuleNames), effectiveConfig = _a.effectiveConfig, enabledRulesPerLineNumber = _a.enabledRulesPerLineNumber;
// Create parameters for rules
var params = {
name: name,
tokens: tokens,
lines: lines,
frontMatterLines: frontMatterLines
"name": helpers.deepFreeze(name),
"tokens": helpers.deepFreeze(tokens),
"lines": helpers.deepFreeze(lines),
"frontMatterLines": helpers.deepFreeze(frontMatterLines)
};
cache.lineMetadata(helpers.getLineMetadata(params));
cache.flattenedLists(helpers.flattenLists(params.tokens));

View file

@ -276,6 +276,7 @@ function isMathBlock(token) {
!token.type.endsWith("_end")
);
}
module.exports.isMathBlock = isMathBlock;
// Get line metadata array
module.exports.getLineMetadata = function getLineMetadata(params) {
@ -341,10 +342,6 @@ module.exports.flattenLists = function flattenLists(tokens) {
const nestingStack = [];
let lastWithMap = { "map": [ 0, 1 ] };
tokens.forEach((token) => {
if (isMathBlock(token) && token.map[1]) {
// markdown-it-texmath plugin does not account for math_block_end
token.map[1]++;
}
if ((token.type === "bullet_list_open") ||
(token.type === "ordered_list_open")) {
// Save current context and start a new one
@ -876,3 +873,25 @@ function getNextChildToken(parentToken, childToken, nextType, nextNextType) {
return null;
}
module.exports.getNextChildToken = getNextChildToken;
/**
* Calls Object.freeze() on an object and its children.
*
* @param {Object} obj Object to deep freeze.
* @returns {Object} Object passed to the function.
*/
function deepFreeze(obj) {
const pending = [ obj ];
let current = null;
while ((current = pending.shift())) {
Object.freeze(current);
for (const name of Object.getOwnPropertyNames(current)) {
const value = current[name];
if (value && (typeof value === "object")) {
pending.push(value);
}
}
}
return obj;
}
module.exports.deepFreeze = deepFreeze;

View file

@ -206,6 +206,11 @@ function annotateTokens(tokens, lines) {
if (!token.map && trMap) {
token.map = [ ...trMap ];
}
// Adjust maps for math blocks
if (helpers.isMathBlock(token) && token.map[1]) {
// markdown-it-texmath plugin does not account for math_block_end
token.map[1]++;
}
// Update token metadata
if (token.map) {
token.line = lines[token.map[0]];
@ -481,10 +486,10 @@ function lintContent(
);
// Create parameters for rules
const params = {
name,
tokens,
lines,
frontMatterLines
"name": helpers.deepFreeze(name),
"tokens": helpers.deepFreeze(tokens),
"lines": helpers.deepFreeze(lines),
"frontMatterLines": helpers.deepFreeze(frontMatterLines)
};
cache.lineMetadata(helpers.getLineMetadata(params));
cache.flattenedLists(helpers.flattenLists(params.tokens));

View file

@ -938,3 +938,37 @@ test("applyFixes", (t) => {
t.is(actual, expected, "Incorrect fix applied.");
});
});
test("deepFreeze", (t) => {
t.plan(6);
const obj = {
"prop": true,
"func": () => true,
"sub": {
"prop": [ 1 ],
"sub": {
"prop": "one"
}
}
};
t.is(helpers.deepFreeze(obj), obj, "Did not return object.");
[
() => {
obj.prop = false;
},
() => {
obj.func = () => false;
},
() => {
obj.sub.prop = [];
},
() => {
obj.sub.prop[0] = 0;
},
() => {
obj.sub.sub.prop = "zero";
}
].forEach((scenario) => {
t.throws(scenario, null, "Assigned to frozen object.");
});
});