Compare commits

..

No commits in common. "e7661983f712671f3bedbb9c233394f3fd7ee6f7" and "1cb14a02d33d62527da79d625870ec550aaecc8b" have entirely different histories.

49 changed files with 78 additions and 629 deletions

View File

@ -7,7 +7,6 @@ import noUnsanitized from "eslint-plugin-no-unsanitized";
import perfectionist from "eslint-plugin-perfectionist";
import preferMathClamp from "./external/eslint_plugins/prefer-math-clamp.mjs";
import prettierRecommended from "eslint-plugin-prettier/recommended";
import regexpPlugin from "eslint-plugin-regexp";
import unicorn from "eslint-plugin-unicorn";
const jsFiles = folder => {
@ -56,14 +55,6 @@ export default [
\* ======================================================================== */
prettierRecommended,
{
files: jsFiles("."),
plugins: regexpPlugin.configs["flat/recommended"].plugins,
rules: {
...regexpPlugin.configs["flat/recommended"].rules,
"regexp/no-legacy-features": "off",
},
},
{
files: ["**/*.json", "**/.*.json"],
language: "json/json",

View File

@ -45,7 +45,7 @@ function watchObjectOrEmbed(elem) {
// <embed src> <object data>
var srcAttribute = "src" in elem ? "src" : "data";
var path = elem[srcAttribute];
if (!mimeType && !/\.pdf(?:$|[?#])/i.test(path)) {
if (!mimeType && !/\.pdf($|[?#])/i.test(path)) {
return;
}

View File

@ -132,7 +132,7 @@ function preprocess(inFilename, outFilename, defines) {
}
}
function expand(line) {
line = line.replaceAll(/__\w+__/g, function (variable) {
line = line.replaceAll(/__[\w]+__/g, function (variable) {
variable = variable.substring(2, variable.length - 2);
if (variable in defines) {
return defines[variable];
@ -158,7 +158,6 @@ function preprocess(inFilename, outFilename, defines) {
let state = STATE_NONE;
const stack = [];
const control =
// eslint-disable-next-line regexp/no-super-linear-backtracking
/^(?:\/\/|\s*\/\*|\s*<!--)\s*#(if|elif|else|endif|expand|include|error)\b(?:\s+(.*?)(?:\*\/|-->)?$)?/;
while ((line = readLine()) !== null) {

View File

@ -43,7 +43,7 @@ function extractFtlIds(ftlPath) {
const lines = readFileSync(ftlPath, "utf8").split("\n");
const ids = [];
for (const line of lines) {
const match = line.match(/^([a-z][a-z0-9-]*)\s*=/i);
const match = line.match(/^([a-zA-Z][a-zA-Z0-9-]*)\s*=/);
if (match) {
ids.push(match[1]);
}

View File

@ -14,7 +14,7 @@
*/
function parseAdobeCMap(content) {
let m = /(\bbegincmap\b[\s\S]+?)\bendcmap\b/.exec(content);
let m = /(\bbegincmap\b[\s\S]*?)\bendcmap\b/.exec(content);
if (!m) {
throw new Error("cmap was not found");
}
@ -37,7 +37,7 @@ function parseAdobeCMap(content) {
result.usecmap = m[1];
}
const re =
/(\d+)\s+(begincodespacerange|beginnotdefrange|begincidchar|begincidrange|beginbfchar|beginbfrange)\n([\s\S]*?)\n(?:endcodespacerange|endnotdefrange|endcidchar|endcidrange|endbfchar|endbfrange)/g;
/(\d+)\s+(begincodespacerange|beginnotdefrange|begincidchar|begincidrange|beginbfchar|beginbfrange)\n([\s\S]*?)\n(endcodespacerange|endnotdefrange|endcidchar|endcidrange|endbfchar|endbfrange)/g;
while ((m = re.exec(body))) {
const lines = m[3].toLowerCase().split("\n");

View File

@ -1135,7 +1135,7 @@ gulp.task("locale", function () {
if (!checkDir(dirPath)) {
continue;
}
if (!/^[a-z]{2,3}(?:-[A-Z]{2})?$/.test(locale)) {
if (!/^[a-z][a-z]([a-z])?(-[A-Z][A-Z])?$/.test(locale)) {
console.log("Skipping invalid locale: " + locale);
continue;
}

75
package-lock.json generated
View File

@ -31,7 +31,6 @@
"eslint-plugin-no-unsanitized": "^4.1.5",
"eslint-plugin-perfectionist": "^5.9.0",
"eslint-plugin-prettier": "^5.5.5",
"eslint-plugin-regexp": "^3.1.0",
"eslint-plugin-unicorn": "^64.0.0",
"globals": "^17.6.0",
"gulp": "^5.0.1",
@ -5463,28 +5462,6 @@
}
}
},
"node_modules/eslint-plugin-regexp": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/eslint-plugin-regexp/-/eslint-plugin-regexp-3.1.0.tgz",
"integrity": "sha512-qGXIC3DIKZHcK1H9A9+Byz9gmndY6TTSRkSMTZpNXdyCw2ObSehRgccJv35n9AdUakEjQp5VFNLas6BMXizCZg==",
"dev": true,
"license": "MIT",
"dependencies": {
"@eslint-community/eslint-utils": "^4.2.0",
"@eslint-community/regexpp": "^4.11.0",
"comment-parser": "^1.4.0",
"jsdoc-type-pratt-parser": "^7.0.0",
"refa": "^0.12.1",
"regexp-ast-analysis": "^0.7.1",
"scslre": "^0.3.0"
},
"engines": {
"node": "^20.19.0 || ^22.13.0 || >=24"
},
"peerDependencies": {
"eslint": ">=9.38.0"
}
},
"node_modules/eslint-plugin-unicorn": {
"version": "64.0.0",
"resolved": "https://registry.npmjs.org/eslint-plugin-unicorn/-/eslint-plugin-unicorn-64.0.0.tgz",
@ -7401,16 +7378,6 @@
"node": ">=12.0.0"
}
},
"node_modules/jsdoc-type-pratt-parser": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/jsdoc-type-pratt-parser/-/jsdoc-type-pratt-parser-7.2.0.tgz",
"integrity": "sha512-dh140MMgjyg3JhJZY/+iEzW+NO5xR2gpbDFKHqotCmexElVntw7GjWjt511+C/Ef02RU5TKYrJo/Xlzk+OLaTw==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=20.0.0"
}
},
"node_modules/jsdoc/node_modules/escape-string-regexp": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz",
@ -9125,19 +9092,6 @@
"node": ">= 10.13.0"
}
},
"node_modules/refa": {
"version": "0.12.1",
"resolved": "https://registry.npmjs.org/refa/-/refa-0.12.1.tgz",
"integrity": "sha512-J8rn6v4DBb2nnFqkqwy6/NnTYMcgLA+sLr0iIO41qpv0n+ngb7ksag2tMRl0inb1bbO/esUwzW1vbJi7K0sI0g==",
"dev": true,
"license": "MIT",
"dependencies": {
"@eslint-community/regexpp": "^4.8.0"
},
"engines": {
"node": "^12.0.0 || ^14.0.0 || >=16.0.0"
}
},
"node_modules/regenerate": {
"version": "1.4.2",
"resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz",
@ -9158,20 +9112,6 @@
"node": ">=4"
}
},
"node_modules/regexp-ast-analysis": {
"version": "0.7.1",
"resolved": "https://registry.npmjs.org/regexp-ast-analysis/-/regexp-ast-analysis-0.7.1.tgz",
"integrity": "sha512-sZuz1dYW/ZsfG17WSAG7eS85r5a0dDsvg+7BiiYR5o6lKCAtUrEwdmRmaGF6rwVj3LcmAeYkOWKEPlbPzN3Y3A==",
"dev": true,
"license": "MIT",
"dependencies": {
"@eslint-community/regexpp": "^4.8.0",
"refa": "^0.12.1"
},
"engines": {
"node": "^12.0.0 || ^14.0.0 || >=16.0.0"
}
},
"node_modules/regexp-tree": {
"version": "0.1.27",
"resolved": "https://registry.npmjs.org/regexp-tree/-/regexp-tree-0.1.27.tgz",
@ -9506,21 +9446,6 @@
"dev": true,
"license": "MIT"
},
"node_modules/scslre": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/scslre/-/scslre-0.3.0.tgz",
"integrity": "sha512-3A6sD0WYP7+QrjbfNA2FN3FsOaGGFoekCVgTyypy53gPxhbkCIjtO6YWgdrfM+n/8sI8JeXZOIxsHjMTNxQ4nQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@eslint-community/regexpp": "^4.8.0",
"refa": "^0.12.0",
"regexp-ast-analysis": "^0.7.0"
},
"engines": {
"node": "^14.0.0 || >=16.0.0"
}
},
"node_modules/section-matter": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/section-matter/-/section-matter-1.0.0.tgz",

View File

@ -26,7 +26,6 @@
"eslint-plugin-no-unsanitized": "^4.1.5",
"eslint-plugin-perfectionist": "^5.9.0",
"eslint-plugin-prettier": "^5.5.5",
"eslint-plugin-regexp": "^3.1.0",
"eslint-plugin-unicorn": "^64.0.0",
"globals": "^17.6.0",
"gulp": "^5.0.1",

View File

@ -564,7 +564,7 @@ function validateFontName(fontFamily, mustWarn = false) {
} else {
// See https://developer.mozilla.org/en-US/docs/Web/CSS/custom-ident.
for (const ident of fontFamily.split(/[ \t]+/)) {
if (/^(?:\d|-[\d-])/.test(ident) || !/^[\w\\-]+$/.test(ident)) {
if (/^(\d|(-(\d|-)))/.test(ident) || !/^[\w-\\]+$/.test(ident)) {
if (mustWarn) {
warn(`FontFamily contains invalid <custom-ident>: ${fontFamily}.`);
}

View File

@ -1392,7 +1392,7 @@ class PDFDocument {
}
let fontFamily = descriptor.get("FontFamily");
// For example, "Wingdings 3" is not a valid font name in the css specs.
fontFamily = fontFamily.replaceAll(/ +(\d)/g, "$1");
fontFamily = fontFamily.replaceAll(/[ ]+(\d)/g, "$1");
const fontWeight = descriptor.get("FontWeight");
// Angle is expressed in degrees counterclockwise in PDF

View File

@ -4203,7 +4203,9 @@ class PartialEvaluator {
isSerifFont(baseFontName) {
// Simulating descriptor flags attribute
const fontNameWoStyle = baseFontName.split("-", 1)[0];
return fontNameWoStyle in getSerifFonts() || /serif/i.test(fontNameWoStyle);
return (
fontNameWoStyle in getSerifFonts() || /serif/gi.test(fontNameWoStyle)
);
}
getBaseFontMetrics(name) {
@ -4434,13 +4436,6 @@ class PartialEvaluator {
// FontDescriptor is only required for Type3 fonts when the document
// is a tagged pdf.
descriptor = Dict.empty;
} else if (composite) {
// Some PDFs omit the FontDescriptor on the descendant CIDFont when
// referencing one of the standard Acrobat CJK fonts via a predefined
// CMap (e.g. /Encoding /90ms-RKSJ-H with /BaseFont /HeiseiMin-W3).
// Fall through so the CMap is loaded by the composite-font path
// below; otherwise multi-byte codes would be decoded byte-by-byte.
descriptor = Dict.empty;
} else {
// Before PDF 1.5 if the font was one of the base 14 fonts, having a
// FontDescriptor was not required.

View File

@ -37,10 +37,13 @@ function getFloat214(view, offset) {
function getSubroutineBias(subrs) {
const numSubrs = subrs.length;
if (numSubrs >= 33900) {
return 32768;
let bias = 32768;
if (numSubrs < 1240) {
bias = 107;
} else if (numSubrs < 33900) {
bias = 1131;
}
return numSubrs < 1240 ? 107 : 1131;
return bias;
}
function parseCmap(data, start, end) {

View File

@ -21,10 +21,6 @@ const NORMAL = {
style: "normal",
weight: "normal",
};
const MEDIUM = {
style: "normal",
weight: "500",
};
const BOLD = {
style: "normal",
weight: "bold",
@ -368,194 +364,6 @@ const substitutionMap = new Map([
alias: "\xCB\xCE\xCC\xE5",
},
],
// Standard Acrobat CJK fonts. These BaseFont names appear in PDFs that
// don't embed a CJK font and rely on the reader having Acrobat's bundled
// CJK fonts installed.
// Adobe-Japan1 - Mincho (serif).
[
"HeiseiMin-W3",
{
local: [
"Hiragino Mincho ProN",
"Hiragino Mincho Pro",
"Yu Mincho",
"YuMincho",
"Source Han Serif JP",
"Noto Serif JP",
"Noto Serif CJK JP",
"IPAexMincho",
"IPAMincho",
"Takao Mincho",
"MS Mincho",
"MS PMincho",
],
style: NORMAL,
ultimate: "serif",
},
],
// Adobe-Japan1 - Gothic (sans-serif).
[
"HeiseiKakuGo-W5",
{
local: [
"Hiragino Kaku Gothic ProN",
"Hiragino Kaku Gothic Pro",
"Hiragino Sans",
"Yu Gothic",
"YuGothic",
"Source Han Sans JP",
"Noto Sans JP",
"Noto Sans CJK JP",
"IPAexGothic",
"IPAGothic",
"Takao Gothic",
"Meiryo",
"MS Gothic",
"MS PGothic",
],
style: MEDIUM,
ultimate: "sans-serif",
},
],
// Common Adobe-Japan1 variants and Kozuka names.
["HeiseiMin-W3-Acro", { alias: "HeiseiMin-W3" }],
["HeiseiKakuGo-W5-Acro", { alias: "HeiseiKakuGo-W5" }],
["KozMinPro-Regular", { alias: "HeiseiMin-W3" }],
["KozMinProVI-Regular", { alias: "HeiseiMin-W3" }],
["KozMinPr6N-Regular", { alias: "HeiseiMin-W3" }],
["KozGoPro-Regular", { alias: "HeiseiKakuGo-W5" }],
["KozGoProVI-Regular", { alias: "HeiseiKakuGo-W5" }],
["KozGoPr6N-Regular", { alias: "HeiseiKakuGo-W5" }],
// Adobe-GB1 - Song (Simplified Chinese serif).
[
"STSong-Light",
{
local: [
"STSong",
"Songti SC",
"Source Han Serif SC",
"Source Han Serif CN",
"Noto Serif SC",
"Noto Serif CJK SC",
"AR PL UMing CN",
"SimSun",
"NSimSun",
],
style: NORMAL,
ultimate: "serif",
},
],
// Adobe-GB1 - Hei (Simplified Chinese sans-serif).
[
"STHeiti-Regular",
{
local: [
"STHeiti",
"Heiti SC",
"PingFang SC",
"Source Han Sans SC",
"Source Han Sans CN",
"Noto Sans SC",
"Noto Sans CJK SC",
"Microsoft YaHei",
"SimHei",
"WenQuanYi Zen Hei",
],
style: NORMAL,
ultimate: "sans-serif",
},
],
["STSongStd-Light", { alias: "STSong-Light" }],
["AdobeSongStd-Light", { alias: "STSong-Light" }],
["AdobeHeitiStd-Regular", { alias: "STHeiti-Regular" }],
// KaiTi (regular script) and FangSong (imitation Song) are different
// typographic styles; route to the existing GB2312-keyed entries above.
["AdobeKaitiStd-Regular", { alias: "\xBF\xAC\xCC\xE5" }],
["AdobeFangsongStd-Regular", { alias: "\xB7\xC2\xCB\xCE" }],
// Adobe-CNS1 - Sung (Traditional Chinese serif).
[
"MSung-Light",
{
local: [
"Songti TC",
"LiSong Pro",
"Source Han Serif TC",
"Source Han Serif TW",
"Noto Serif TC",
"Noto Serif CJK TC",
"AR PL UMing TW",
"PMingLiU",
"MingLiU",
"MingLiU_HKSCS",
],
style: NORMAL,
ultimate: "serif",
},
],
// Adobe-CNS1 - Hei (Traditional Chinese sans-serif).
[
"MHei-Medium",
{
local: [
"Heiti TC",
"STHeiti",
"Source Han Sans TC",
"Source Han Sans TW",
"Noto Sans TC",
"Noto Sans CJK TC",
"PingFang TC",
"Microsoft JhengHei",
],
style: MEDIUM,
ultimate: "sans-serif",
},
],
["MSungStd-Light", { alias: "MSung-Light" }],
["AdobeMingStd-Light", { alias: "MSung-Light" }],
// Adobe-Korea1 - Myeongjo (Korean serif).
[
"HYSMyeongJo-Medium",
{
local: [
"AppleMyungjo",
"Source Han Serif KR",
"Noto Serif KR",
"Noto Serif CJK KR",
"Nanum Myeongjo",
"Batang",
],
style: MEDIUM,
ultimate: "serif",
},
],
// Adobe-Korea1 - Gothic (Korean sans-serif).
[
"HYGoThic-Medium",
{
local: [
"Apple SD Gothic Neo",
"AppleGothic",
"Source Han Sans KR",
"Noto Sans KR",
"Noto Sans CJK KR",
"Nanum Gothic",
"Malgun Gothic",
"Dotum",
"Gulim",
],
style: MEDIUM,
ultimate: "sans-serif",
},
],
["HYSMyeongJoStd-Medium", { alias: "HYSMyeongJo-Medium" }],
["AdobeMyungjoStd-Medium", { alias: "HYSMyeongJo-Medium" }],
// Bold variants reuse the same fallback list with a bold style override
// so the @font-face declaration requests a bold local() match.
["HYGoThic-Bold", { alias: "HYGoThic-Medium", style: BOLD }],
["AdobeGothicStd-Bold", { alias: "HYGoThic-Medium", style: BOLD }],
]);
const fontAliases = new Map([["Arial-Black", "ArialBlack"]]);
@ -771,8 +579,8 @@ function getFontSubstitution(
return null;
}
// Maybe we'll be lucky and the OS will have the font.
const bold = /bold/i.test(baseFontName);
const italic = /oblique|italic/i.test(baseFontName);
const bold = /bold/gi.test(baseFontName);
const italic = /oblique|italic/gi.test(baseFontName);
const style =
(bold && italic && BOLDITALIC) ||
(bold && BOLD) ||

View File

@ -1235,16 +1235,16 @@ class Font {
}
}
this.bold = /bold/i.test(fontName);
this.italic = /oblique|italic/i.test(fontName);
this.bold = /bold/gi.test(fontName);
this.italic = /oblique|italic/gi.test(fontName);
// Use 'name' instead of 'fontName' here because the original
// name ArialBlack for example will be replaced by Helvetica.
this.black = /Black/.test(name);
this.black = /Black/g.test(name);
// Use 'name' instead of 'fontName' here because the original
// name ArialNarrow for example will be replaced by Helvetica.
const isNarrow = /Narrow/.test(name);
const isNarrow = /Narrow/g.test(name);
// if at least one width is present, remeasure all chars when exists
this.remeasure =

View File

@ -132,7 +132,7 @@ class Lexer {
this.pos = 0;
this.len = data.length;
// Sticky regexes: set lastIndex before exec() to match at an exact offset.
this._numberPattern = /[+-]?(?:\d+\.?\d*|\.\d+)(?:e[+-]?\d+)?/iy;
this._numberPattern = /[+-]?(?:\d+\.?\d*|\.\d+)(?:[eE][+-]?\d+)?/y;
this._identifierPattern = /[a-z]+/y;
}

View File

@ -16,11 +16,7 @@
import { stringToBytes, Util, warn } from "../shared/util.js";
function isAscii(str) {
return (
typeof str === "string" &&
// eslint-disable-next-line no-control-regex
(!str || /^[\x00-\x7F]*$/.test(str))
);
return typeof str === "string" && (!str || /^[\x00-\x7F]*$/.test(str));
}
// If the string is null or undefined then it is returned as is.
@ -95,7 +91,6 @@ function stringToPDFString(str, keepEscapeSequence = false) {
if (keepEscapeSequence || !decoded.includes("\x1b")) {
return decoded;
}
// eslint-disable-next-line no-control-regex
return decoded.replaceAll(/\x1b[^\x1b]*(?:\x1b|$)/g, "");
} catch (ex) {
warn(`stringToPDFString: "${ex}".`);

View File

@ -242,7 +242,7 @@ function getUnicodeRangeFor(value, lastPosition = -1) {
return -1;
}
const SpecialCharRegExp = /^(\s)|(\p{Mn})|(\p{Cf})$/u;
const SpecialCharRegExp = new RegExp("^(\\s)|(\\p{Mn})|(\\p{Cf})$", "u");
const CategoryCache = new Map();
function getCharUnicodeCategory(char) {

View File

@ -1003,7 +1003,7 @@ class Rename extends ContentObject {
// is no colon.
if (
this[$content].toLowerCase().startsWith("xml") ||
/[\p{L}_][\p{L}\d._\p{M}-]*/u.test(this[$content])
new RegExp("[\\p{L}_][\\p{L}\\d._\\p{M}-]*", "u").test(this[$content])
) {
warn("XFA - Rename: invalid XFA name");
}

View File

@ -90,7 +90,7 @@ class FontFinder {
return font;
}
const pattern = /[,\-_ ]|bolditalic|bold|italic|regular|it/gi;
const pattern = /,|-|_| |bolditalic|bold|italic|regular|it/gi;
let name = fontName.replaceAll(pattern, "");
font = this.fonts.get(name);
if (font) {

View File

@ -116,11 +116,11 @@ const TOKEN = {
upto: 54,
};
const hexPattern = /^u([0-9a-f]{4,8})/i;
const numberPattern = /^\d*(?:\.\d*)?(?:E[+-]?\d+)?/i;
const dotNumberPattern = /^\d*(?:E[+-]?\d+)?/i;
const hexPattern = /^[uU]([0-9a-fA-F]{4,8})/;
const numberPattern = /^\d*(?:\.\d*)?(?:[Ee][+-]?\d+)?/;
const dotNumberPattern = /^\d*(?:[Ee][+-]?\d+)?/;
const eolPattern = /[\r\n]+/;
const identifierPattern = /^[\p{L}_$!][\p{L}\p{N}_$]*/u;
const identifierPattern = new RegExp("^[\\p{L}_$!][\\p{L}\\p{N}_$]*", "u");
class Token {
constructor(id, value = null) {

View File

@ -134,7 +134,8 @@ function mapStyle(styleStr, node, richText) {
? `${style[key]} ${newValue}`
: newValue;
} else {
style[key.replaceAll(/-([a-z])/gi, (_, x) => x.toUpperCase())] = newValue;
style[key.replaceAll(/-([a-zA-Z])/g, (_, x) => x.toUpperCase())] =
newValue;
}
}

View File

@ -1793,14 +1793,16 @@ class TextWidgetAnnotationElement extends WidgetAnnotationElement {
case "deleteWordBackward": {
const match = value
.substring(0, selectionStart)
.match(/\w*\W*$/);
.match(/\w*[^\w]*$/);
if (match) {
selStart -= match[0].length;
}
break;
}
case "deleteWordForward": {
const match = value.substring(selectionStart).match(/^\W*\w*/);
const match = value
.substring(selectionStart)
.match(/^[^\w]*\w*/);
if (match) {
selEnd += match[0].length;
}

View File

@ -81,7 +81,6 @@ function getFilenameFromContentDispositionHeader(contentDisposition) {
}
function textdecode(encoding, value) {
if (encoding) {
// eslint-disable-next-line no-control-regex
if (!/^[\x00-\xFF]+$/.test(value)) {
return value;
}
@ -185,7 +184,6 @@ function getFilenameFromContentDispositionHeader(contentDisposition) {
// Firefox also decodes words even where RFC 2047 section 5 states:
// "An 'encoded-word' MUST NOT appear within a 'quoted-string'."
// eslint-disable-next-line no-control-regex
if (!value.startsWith("=?") || /[\x00-\x19\x80-\xff]/.test(value)) {
return value;
}
@ -197,12 +195,12 @@ function getFilenameFromContentDispositionHeader(contentDisposition) {
// encoded-text = any printable ASCII character other than ? or space.
// ... but Firefox permits ? and space.
return value.replaceAll(
/=\?([\w-]*)\?([QB])\?((?:[^?]|\?(?!=))*)\?=/gi,
/=\?([\w-]*)\?([QqBb])\?((?:[^?]|\?(?!=))*)\?=/g,
function (matches, charset, encoding, text) {
if (encoding === "q" || encoding === "Q") {
// RFC 2047 section 4.2.
text = text.replaceAll("_", " ");
text = text.replaceAll(/=([0-9a-f]{2})/gi, function (match, hex) {
text = text.replaceAll(/=([0-9a-fA-F]{2})/g, function (match, hex) {
return String.fromCharCode(parseInt(hex, 16));
});
return textdecode(charset, text);

View File

@ -296,7 +296,7 @@ class PDFDateString {
"(\\d{2})?" + // Hour (optional)
"(\\d{2})?" + // Minute (optional)
"(\\d{2})?" + // Second (optional)
"([Z|+\\-])?" + // Universal time relation (optional)
"([Z|+|-])?" + // Universal time relation (optional)
"(\\d{2})?" + // Offset hour (optional)
"'?" + // Splitting apostrophe (optional)
"(\\d{2})?" + // Offset minute (optional)
@ -756,7 +756,7 @@ function renderRichText({ html, dir, className }, container) {
if (typeof html === "string") {
const p = document.createElement("p");
p.dir = dir || "auto";
const lines = html.split(/\r\n?|\n/);
const lines = html.split(/(?:\r\n?|\n)/);
for (let i = 0, ii = lines.length; i < ii; ++i) {
const line = lines[i];
p.append(document.createTextNode(line));

View File

@ -132,9 +132,6 @@ class DOMFilterFactory extends BaseFilterFactory {
if (!this.#_defs) {
const div = this.#document.createElement("div");
const { style } = div;
// The pdf colors are mostly in light mode (white background with a black
// foreground), so the filters are created in light mode.
style.colorScheme = "only light";
style.visibility = "hidden";
style.contain = "strict";
style.width = style.height = 0;

View File

@ -140,7 +140,7 @@ class PDFNetworkStream extends BasePDFStream {
const chunk = getArrayBuffer(xhr.response);
if (xhrStatus === PARTIAL_CONTENT_RESPONSE) {
const rangeHeader = xhr.getResponseHeader("Content-Range");
if (/bytes \d+-\d+\/\d+/.test(rangeHeader)) {
if (/bytes (\d+)-(\d+)\/(\d+)/.test(rangeHeader)) {
pendingRequest.onDone(chunk);
} else {
warn(`Missing or invalid "Content-Range" header.`);

View File

@ -473,8 +473,7 @@ class TextLayer {
// OffscreenCanvas.
const canvas = document.createElement("canvas");
canvas.style.cssText =
"position:absolute;top:0;left:0;width:0;height:0;display:none;" +
"letter-spacing:normal;word-spacing:normal";
"position:absolute;top:0;left:0;width:0;height:0;display:none";
canvas.lang = lang;
document.body.append(canvas);
ctx = canvas.getContext("2d", {

View File

@ -26,9 +26,8 @@ class AForm {
// The e-mail address regex below originates from:
// https://html.spec.whatwg.org/multipage/input.html#valid-e-mail-address
// eslint-disable-next-line regexp/use-ignore-case
this._emailRegex = new RegExp(
"^[\\w.!#$%&'*+/=?^`{|}~-]+" +
"^[a-zA-Z0-9.!#$%&'*+\\/=?^_`{|}~-]+" +
"@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?" +
"(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$"
);
@ -185,12 +184,12 @@ class AForm {
// comma sep
pattern = event.willCommit
? /^[+-]?(\d+(,\d*)?|,\d+)$/
: /^[+-]?\d*(?:,\d*)?$/;
: /^[+-]?\d*,?\d*$/;
} else {
// dot sep
pattern = event.willCommit
? /^[+-]?(\d+(\.\d*)?|\.\d+)$/
: /^[+-]?\d*(?:\.\d*)?$/;
: /^[+-]?\d*\.?\d*$/;
}
if (!pattern.test(value)) {
@ -572,7 +571,7 @@ class AForm {
event.rc = true;
}
const re = /[-()\s]+/g;
const re = /([-()]|\s)+/g;
value = value.replaceAll(re, "");
for (const format of formats) {
this.#AFSpecial_KeystrokeEx_helper(

View File

@ -62,7 +62,6 @@ class Util extends PDFObject {
throw new TypeError("First argument of printf must be a string");
}
// eslint-disable-next-line regexp/no-misleading-capturing-group
const pattern = /%(,[0-4])?([+ 0#]+)?(\d+)?(\.\d+)?(.)/g;
const PLUS = 1;
const SPACE = 2;

View File

@ -1039,7 +1039,7 @@ function normalizeUnicode(str) {
// required.
// It appears that most the chars here contain some ligatures.
NormalizeRegex =
/([\u00a0\u00b5\u037e\u0eb3\u2000-\u200a\u202f\u2126\ufb00-\ufb04\ufb06\ufb20-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufba1\ufba4-\ufba9\ufbae-\ufbb1\ufbd3-\ufbdc\ufbde-\ufbe7\ufbea-\ufbf8\ufbfc\ufbfd\ufc00-\ufc5d\ufc64-\ufcf1\ufcf5-\ufd3d\ufd88\ufdf4\ufdfa\ufdfb\ufe71\ufe77\ufe79\ufe7b\ufe7d]+)|(\ufb05+)/gu;
/([\u00a0\u00b5\u037e\u0eb3\u2000-\u200a\u202f\u2126\ufb00-\ufb04\ufb06\ufb20-\ufb36\ufb38-\ufb3c\ufb3e\ufb40-\ufb41\ufb43-\ufb44\ufb46-\ufba1\ufba4-\ufba9\ufbae-\ufbb1\ufbd3-\ufbdc\ufbde-\ufbe7\ufbea-\ufbf8\ufbfc-\ufbfd\ufc00-\ufc5d\ufc64-\ufcf1\ufcf5-\ufd3d\ufd88\ufdf4\ufdfa-\ufdfb\ufe71\ufe77\ufe79\ufe7b\ufe7d]+)|(\ufb05+)/gu;
NormalizationMap = new Map([["ſt", "ſt"]]);
}
return str.replaceAll(NormalizeRegex, (_, p1, p2) =>

View File

@ -21,7 +21,7 @@ function rewriteWebArchiveUrl(url) {
// Without this, an HTML page containing an iframe with the PDF file
// will be served instead (issue 8920).
const webArchiveRegex =
/(^https?:\/\/web\.archive\.org\/web\/)(\d+)(\/https?:\/\/.+)/;
/(^https?:\/\/web\.archive\.org\/web\/)(\d+)(\/https?:\/\/.+)/g;
const urlParts = webArchiveRegex.exec(url);
if (urlParts) {
return `${urlParts[1]}${urlParts[2]}if_${urlParts[3]}`;

View File

@ -36,7 +36,7 @@ describe("font_fpgm", function () {
verifyTtxOutput(output);
expect(
/(?:ENDF\[ \]|SVTCA\[0\])\s*\/\*.*\*\/\s*<\/assembly>\s*<\/fpgm>/.test(
/(ENDF\[ \]|SVTCA\[0\])\s*\/\*.*\*\/\s*<\/assembly>\s*<\/fpgm>/.test(
output
)
).toEqual(true);

View File

@ -109,7 +109,7 @@ describe("font_glyf", function () {
);
expect(notdef).not.toBeNull();
expect(notdef[1] || "").not.toMatch(
/<component\b[^>]+glyphName="\.notdef"/
/<component\b[^>]*glyphName="\.notdef"/
);
});
});
@ -132,7 +132,7 @@ describe("font_glyf", function () {
const output = await ttx(font.data);
verifyTtxOutput(output);
expect(
/<OS_2>\s*(?:<!--[\s\S]*?-->\s*)?<version value="3"\/>/.test(output)
/<OS_2>\s*(<!--[\s\S]*?-->\s*)?<version value="3"\/>/.test(output)
).toEqual(true);
expect(/<sCapHeight\b/.test(output)).toEqual(true);
expect(/<usMaxContext\b/.test(output)).toEqual(true);

View File

@ -49,61 +49,6 @@ import { startBrowser } from "../test.mjs";
*/
describe("Text layer", () => {
describe("Text layout", () => {
let pages;
beforeEach(async () => {
pages = await loadAndWait(
"tracemonkey.pdf",
".textLayer .endOfContent",
100,
{
postPageSetup: async page => {
await page.evaluate(() => {
const style = document.createElement("style");
style.textContent = `
body,
#mainContainer {
letter-spacing: 5px;
word-spacing: 5px;
}
`;
document.documentElement.append(style);
});
},
}
);
});
afterEach(async () => {
await closePages(pages);
});
it("must ignore inherited text spacing styles", async () => {
await Promise.all(
pages.map(async ([_, page]) => {
const spacing = await page.evaluate(() => {
const textLayer = document.querySelector(".textLayer");
const span = textLayer.querySelector("span");
const textLayerStyle = getComputedStyle(textLayer);
const spanStyle = getComputedStyle(span);
return {
textLayerLetterSpacing: textLayerStyle.letterSpacing,
textLayerWordSpacing: textLayerStyle.wordSpacing,
spanLetterSpacing: spanStyle.letterSpacing,
spanWordSpacing: spanStyle.wordSpacing,
};
});
expect(spacing.textLayerLetterSpacing).toEqual("normal");
expect(spacing.spanLetterSpacing).toEqual("normal");
expect(["0px", "normal"]).toContain(spacing.textLayerWordSpacing);
expect(["0px", "normal"]).toContain(spacing.spanWordSpacing);
})
);
});
});
describe("Text selection", () => {
// page.mouse.move(x, y, { steps: ... }) doesn't work in Firefox, because
// puppeteer will send fractional intermediate positions and Firefox doesn't
@ -585,7 +530,7 @@ describe("Text layer", () => {
// Selection starts mid-word in Heading 1, so assert the stable
// trailing content rather than exact full-line boundaries.
.toHaveRoughlySelected(
/ing 1\s+This paragraph 1\.\s+Heading 2\s+This paragraph 2/
/ing 1\s+This paragraph 1\.\s+Heading 2\s+This paragraph 2/s
);
})
);

View File

@ -924,4 +924,3 @@
!Embedded_font.pdf
!issue18548_reduced.pdf
!issue_cff_unsigned_bbox.pdf
!90ms_rksj_h_sample.pdf

View File

@ -1,67 +0,0 @@
%PDF-1.4
%âãÏÓ
1 0 obj
<< /Type /Catalog /Pages 2 0 R >>
endobj
2 0 obj
<< /Type /Pages /Kids [3 0 R] /Count 1 >>
endobj
3 0 obj
<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792]
/Contents 4 0 R
/Resources << /Font << /F0 5 0 R /F1 7 0 R >> >> >>
endobj
4 0 obj
<< /Length 92 >>
stream
BT
/F0 14 Tf
72 720 Td
(Hello ASCII) Tj
0 -28 Td
/F1 14 Tf
<93FA967B8CEA836583588367> Tj
ET
endstream
endobj
5 0 obj
<< /Type /Font /Subtype /Type1
/BaseFont /Helvetica
/Encoding /WinAnsiEncoding >>
endobj
6 0 obj
<< /Type /Font /Subtype /CIDFontType2
/BaseFont /HeiseiMin-W3
/CIDSystemInfo << /Registry (Adobe) /Ordering (Japan1) /Supplement 2 >>
/DW 1000 >>
endobj
7 0 obj
<< /Type /Font /Subtype /Type0
/BaseFont /HeiseiMin-W3
/Encoding /90ms-RKSJ-H
/DescendantFonts [6 0 R] >>
endobj
xref
0 8
0000000000 65535 f
0000000016 00000 n
0000000066 00000 n
0000000124 00000 n
0000000267 00000 n
0000000410 00000 n
0000000514 00000 n
0000000685 00000 n
trailer
<< /Size 8 /Root 1 0 R >>
startxref
816
%%EOF

View File

@ -205,7 +205,7 @@ window.onload = function () {
}
line = match[1];
match = line.match(
/^(TEST-PASS|TEST-UNEXPECTED-PASS|TEST-KNOWN-FAIL|TEST-UNEXPECTED-FAIL)(\(EXPECTED RANDOM\))? \| ([^|]+) \|(.*)/
/^(TEST-PASS|TEST-UNEXPECTED-PASS|TEST-KNOWN-FAIL|TEST-UNEXPECTED-FAIL)(\(EXPECTED RANDOM\)|) \| ([^|]+) \|(.*)/
);
if (match) {
const state = match[1];
@ -225,7 +225,7 @@ window.onload = function () {
continue;
}
match = line.match(
/^ {2}IMAGE[^:]*\((\d+(?:\.\d*)?)x(\d+(?:\.\d*)?)x(\d+(?:\.\d*)?)\): (.*)$/
/^ {2}IMAGE[^:]*\((\d+\.?\d*)x(\d+\.?\d*)x(\d+\.?\d*)\): (.*)$/
);
if (match) {
const item = gTestItems.at(-1);

View File

@ -78,7 +78,7 @@ function parseOptions() {
// Expand `-X=value` short-option forms into `["-X", "value"]` since
// parseArgs only strips the `=` separator for long options (--foo=bar).
const args = process.argv.slice(2).flatMap(arg => {
const m = arg.match(/^(-[a-z])=(.*)/is);
const m = arg.match(/^(-[a-zA-Z])=(.*)/s);
return m ? [m[1], m[2]] : [arg];
});
const { values } = parseArgs({
@ -423,38 +423,15 @@ async function startRefTest(masterMode, showRefImages) {
checkRefsTmp();
}
async function handleSessionTimeout(session) {
if (session.closed || session.recovering) {
function handleSessionTimeout(session) {
if (session.closed) {
return;
}
const inflightIds = Object.keys(session.tasks);
const suffix = inflightIds.length > 0 ? ` (${inflightIds.join(", ")})` : "";
console.log(
`${TEST_UNEXPECTED_FAIL} | test failed ${session.name} has not responded in ${browserTimeout}s${suffix}`
`${TEST_UNEXPECTED_FAIL} | test failed ${session.name} has not responded in ${browserTimeout}s`
);
session.numErrors += session.remaining;
session.remaining = 0;
session.taskResults = {};
session.tasks = {};
monitorBrowserTimeout(session, null);
if (session.page) {
session.recovering = true;
try {
await session.page.reload({
timeout: browserTimeout * 1000,
waitUntil: "domcontentloaded",
});
session.recovering = false;
monitorBrowserTimeout(session, handleSessionTimeout);
return;
} catch (err) {
console.log(
`Failed to reload ${session.name} after timeout: ${err.message}`
);
session.recovering = false;
}
}
closeSession(session.name);
}
@ -791,15 +768,9 @@ async function handleWsBinaryResult(data) {
const { browser, id, round, page, failure, lastPageNum, numberOfTasks } =
meta;
const session = getSession(browser);
if (!session || session.closed) {
return;
}
monitorBrowserTimeout(session, handleSessionTimeout);
const taskResults = session.taskResults[id];
if (!taskResults) {
return;
}
if (!taskResults[round]) {
taskResults[round] = [];
}

View File

@ -4009,25 +4009,6 @@ Caron Broadcasting, Inc., an Ohio corporation (“Lessee”).`)
await loadingTask.destroy();
});
it("gets text content from a Type0 composite font with no FontDescriptor, using a predefined CMap", async function () {
const loadingTask = getDocument(
buildGetDocumentParams("90ms_rksj_h_sample.pdf", {
cMapUrl: CMAP_URL,
useWorkerFetch: false,
})
);
const pdfDoc = await loadingTask.promise;
const pdfPage = await pdfDoc.getPage(1);
const { items } = await pdfPage.getTextContent({
disableNormalization: true,
});
const text = mergeText(items);
expect(text).toEqual("Hello ASCII\n日本語テスト");
await loadingTask.destroy();
});
it("gets text content with a rised text", async function () {
const loadingTask = getDocument(buildGetDocumentParams("issue16221.pdf"));
const pdfDoc = await loadingTask.promise;

View File

@ -91,7 +91,7 @@ describe("custom ownerDocument", function () {
const checkFont = font => /g_d\d+_f1/.test(font.family);
const checkFontFaceRule = rule =>
/^@font-face \{font-family:"g_d\d+_f1";src:/.test(rule);
/^@font-face {font-family:"g_d\d+_f1";src:/.test(rule);
beforeEach(() => {
globalThis.FontFace = function MockFontFace(name) {

View File

@ -546,96 +546,4 @@ describe("getFontSubstitution", function () {
/^"ArialBlack",g_d(\d+)_sf(\d+),sans-serif$/
);
});
it("should substitute HeiseiMin-W3", () => {
const fontName = "HeiseiMin-W3";
const fontSubstitution = getFontSubstitution(
new Map(),
idFactory,
localFontPath,
fontName,
undefined,
"CIDFontType2"
);
expect(fontSubstitution).toEqual(
jasmine.objectContaining({
guessFallback: false,
baseFontName: "HeiseiMin-W3",
src:
"local(Hiragino Mincho ProN),local(Hiragino Mincho Pro)," +
"local(Yu Mincho),local(YuMincho),local(Source Han Serif JP)," +
"local(Noto Serif JP),local(Noto Serif CJK JP)," +
"local(IPAexMincho),local(IPAMincho),local(Takao Mincho)," +
"local(MS Mincho),local(MS PMincho)",
style: {
style: "normal",
weight: "normal",
},
})
);
expect(fontSubstitution.css).toMatch(
/^"HeiseiMin W3",g_d(\d+)_sf(\d+),serif$/
);
});
it("should substitute a Kozuka Mincho alias", () => {
const fontName = "KozMinPr6N-Regular";
const fontSubstitution = getFontSubstitution(
new Map(),
idFactory,
localFontPath,
fontName,
undefined,
"CIDFontType0"
);
expect(fontSubstitution).toEqual(
jasmine.objectContaining({
guessFallback: false,
baseFontName: "KozMinPr6N-Regular",
src:
"local(Hiragino Mincho ProN),local(Hiragino Mincho Pro)," +
"local(Yu Mincho),local(YuMincho),local(Source Han Serif JP)," +
"local(Noto Serif JP),local(Noto Serif CJK JP)," +
"local(IPAexMincho),local(IPAMincho),local(Takao Mincho)," +
"local(MS Mincho),local(MS PMincho)",
style: {
style: "normal",
weight: "normal",
},
})
);
expect(fontSubstitution.css).toMatch(
/^"KozMinPr6N",g_d(\d+)_sf(\d+),serif$/
);
});
it("should substitute HYGoThic-Medium", () => {
const fontName = "HYGoThic-Medium";
const fontSubstitution = getFontSubstitution(
new Map(),
idFactory,
localFontPath,
fontName,
undefined,
"CIDFontType2"
);
expect(fontSubstitution).toEqual(
jasmine.objectContaining({
guessFallback: false,
baseFontName: "HYGoThic-Medium",
src:
"local(Apple SD Gothic Neo),local(AppleGothic)," +
"local(Source Han Sans KR),local(Noto Sans KR)," +
"local(Noto Sans CJK KR),local(Nanum Gothic)," +
"local(Malgun Gothic),local(Dotum),local(Gulim)",
style: {
style: "normal",
weight: "500",
},
})
);
expect(fontSubstitution.css).toMatch(
/^"HYGoThic",g_d(\d+)_sf(\d+),sans-serif$/
);
});
});

View File

@ -1115,7 +1115,7 @@ const PDFViewerApplication = {
// - The title may contain incorrectly encoded characters, which thus
// looks broken, hence we ignore the Metadata entry when it contains
// characters from the Specials Unicode block (fixes bug 1605526).
if (title !== "Untitled" && !/[\uFFF0-\uFFFF]/.test(title)) {
if (title !== "Untitled" && !/[\uFFF0-\uFFFF]/g.test(title)) {
return title;
}
}

View File

@ -19,7 +19,7 @@ if (typeof PDFJSDev === "undefined" || PDFJSDev.test("GENERIC")) {
const isAndroid = /Android/.test(userAgent);
const isIOS =
/\b(?:iPad|iPhone|iPod)(?=;)/.test(userAgent) ||
/\b(iPad|iPhone|iPod)(?=;)/.test(userAgent) ||
(platform === "MacIntel" && maxTouchPoints > 1);
// Limit canvas size to 5 mega-pixels on mobile.

View File

@ -138,8 +138,7 @@ class Autolinker {
static findLinks(text) {
// Regex can be tested and verified at https://regex101.com/r/rXoLiT/2.
this.#regex ??=
// eslint-disable-next-line regexp/no-super-linear-backtracking
/\b(?:https?:\/\/|mailto:|www\.)(?:[\S--[\p{P}<>]]|\/|[\S--[\[\]]]+[\S--[\p{P}<>]])+|(?=\p{L})[\S--[@\p{Ps}\p{Pe}<>]]+@([\S--[[\p{P}--\-]<>]]+(?:\.[\S--[[\p{P}--\-]<>]]+)+)/gv;
/\b(?:https?:\/\/|mailto:|www\.)(?:[\S--[\p{P}<>]]|\/|[\S--[\[\]]]+[\S--[\p{P}<>]])+|(?=\p{L})[\S--[@\p{Ps}\p{Pe}<>]]+@([\S--[[\p{P}--\-]<>]]+(?:\.[\S--[[\p{P}--\-]<>]]+)+)/gmv;
const [normalizedText, diffs] = normalize(text, { ignoreDashEOL: true });
const matches = normalizedText.matchAll(this.#regex);

View File

@ -36,8 +36,8 @@ if (typeof PDFJSDev === "undefined" || !PDFJSDev.test("CHROME")) {
// Run this code outside DOMContentLoaded to make sure that the URL
// is rewritten as soon as possible.
const queryString = document.location.search.slice(1);
const m = /(?:^|&)file=([^&]*)/.exec(queryString);
let defaultUrl = m ? decodeURIComponent(m[1]) : "";
const m = /(^|&)file=([^&]*)/.exec(queryString);
let defaultUrl = m ? decodeURIComponent(m[2]) : "";
if (!defaultUrl && queryString.startsWith("DNR:")) {
// Redirected via DNR, see registerPdfRedirectRule in pdfHandler.js.
defaultUrl = queryString.slice(4);

View File

@ -115,7 +115,10 @@ class FontView {
return;
}
const ext = MIMETYPE_TO_EXTENSION.get(font.mimetype) ?? "font";
const name = (font.name || font.loadedName).replaceAll(/[^\w-]/g, "_");
const name = (font.name || font.loadedName).replaceAll(
/[^a-z0-9_-]/gi,
"_"
);
const blob = new Blob([font.data], { type: font.mimetype });
const url = URL.createObjectURL(blob);
const a = document.createElement("a");

View File

@ -75,8 +75,8 @@ let DIACRITICS_EXCEPTION_STR; // Lazily initialized, see below.
const DIACRITICS_REG_EXP = /\p{M}+/gu;
const SPECIAL_CHARS_REG_EXP = /([+^$|])|(\p{P}+)|(\s+)|(\p{M})|(\p{L})/gu;
const NOT_DIACRITIC_FROM_END_REG_EXP = /(\P{M})\p{M}*$/u;
const NOT_DIACRITIC_FROM_START_REG_EXP = /^\p{M}*(\P{M})/u;
const NOT_DIACRITIC_FROM_END_REG_EXP = /([^\p{M}])\p{M}*$/u;
const NOT_DIACRITIC_FROM_START_REG_EXP = /^\p{M}*([^\p{M}])/u;
// The range [AC00-D7AF] corresponds to the Hangul syllables.
// The few other chars are some CJK Compatibility Ideographs.
@ -149,7 +149,7 @@ function normalize(text, options = {}) {
];
normalizationRegex = new RegExp(
regexps.map(r => `(${r})`).join("|"),
"gmu"
"gum"
);
if (hasSyllables) {

View File

@ -22,8 +22,6 @@
overflow: clip;
opacity: 1;
line-height: 1;
letter-spacing: normal;
word-spacing: normal;
text-size-adjust: none;
forced-color-adjust: none;
transform-origin: 0 0;

View File

@ -175,7 +175,6 @@ function parseQueryString(query) {
return params;
}
// eslint-disable-next-line no-control-regex
const InvisibleCharsRegExp = /[\x00-\x1F]/g;
/**
@ -267,11 +266,14 @@ function approximateFraction(x) {
b = q;
}
}
let result;
// Select closest of the neighbours to x.
if (x_ - a / b < c / d - x_) {
return x_ === x ? [a, b] : [b, a];
result = x_ === x ? [a, b] : [b, a];
} else {
result = x_ === x ? [c, d] : [d, c];
}
return x_ === x ? [c, d] : [d, c];
return result;
}
/**