From 3f1568b51aa215d2797b736ec6778ca38ec1799e Mon Sep 17 00:00:00 2001 From: Jonas Jenwald Date: Thu, 13 Feb 2020 17:20:52 +0100 Subject: [PATCH 1/2] A couple of small improvements of the `Metadata._repair` method - Remove the "capturing group" in the regular expression that removes leading "junk" from the raw metadata, since it's not necessary here (it's simply a case of too much copy-pasting in a prior patch). According to [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions/Cheatsheet#Groups_and_ranges) you want to, for performance reasons, avoid "capturing groups" unless actually needed. - Add inline comments to document a bunch of magic values in the code. --- src/display/metadata.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/display/metadata.js b/src/display/metadata.js index fc09b13e6..39ec932de 100644 --- a/src/display/metadata.js +++ b/src/display/metadata.js @@ -37,7 +37,7 @@ class Metadata { _repair(data) { // Start by removing any "junk" before the first tag (see issue 10395). return data - .replace(/^([^<]+)/, "") + .replace(/^[^<]+/, "") .replace(/>\\376\\377([^<]+)/g, function(all, codes) { const bytes = codes .replace(/\\([0-3])([0-7])([0-7])/g, function(code, d1, d2, d3) { @@ -63,11 +63,11 @@ class Metadata { for (let i = 0, ii = bytes.length; i < ii; i += 2) { const code = bytes.charCodeAt(i) * 256 + bytes.charCodeAt(i + 1); if ( - code >= 32 && - code < 127 && - code !== 60 && - code !== 62 && - code !== 38 + code >= /* Space = */ 32 && + code < /* Delete = */ 127 && + code !== /* '<' = */ 60 && + code !== /* '>' = */ 62 && + code !== /* '&' = */ 38 ) { chars += String.fromCharCode(code); } else { From 5cdfff4a47f0e8a7072777aab5c7d81661131040 Mon Sep 17 00:00:00 2001 From: Jonas Jenwald Date: Thu, 13 Feb 2020 17:45:38 +0100 Subject: [PATCH 2/2] Re-factor how `Metadata` class instances store its data internally Please note that these changes do *not* affect the *public* interface of the `Metadata` class, but only touches internal structures.[1] These changes were prompted by looking at the `getAll` method, which simply returns the "private" metadata object to the consumer. This seems wrong conceptually, since it allows way too easy/accidental changes to the internal parsed metadata. As part of fixing this, the internal metadata was changed to use a `Map` rather than a plain Object. --- [1] Basically, we shouldn't need to worry about someone depending on internal implementation details. --- src/display/metadata.js | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/display/metadata.js b/src/display/metadata.js index 39ec932de..edd1f5935 100644 --- a/src/display/metadata.js +++ b/src/display/metadata.js @@ -27,7 +27,7 @@ class Metadata { const parser = new SimpleXMLParser(); const xmlDocument = parser.parseFromString(data); - this._metadata = Object.create(null); + this._metadataMap = new Map(); if (xmlDocument) { this._parse(xmlDocument); @@ -107,23 +107,26 @@ class Metadata { const entry = desc.childNodes[j]; const name = entry.nodeName.toLowerCase(); - this._metadata[name] = entry.textContent.trim(); + this._metadataMap.set(name, entry.textContent.trim()); } } } } get(name) { - const data = this._metadata[name]; - return typeof data !== "undefined" ? data : null; + return this._metadataMap.has(name) ? this._metadataMap.get(name) : null; } getAll() { - return this._metadata; + const obj = Object.create(null); + for (const [key, value] of this._metadataMap) { + obj[key] = value; + } + return obj; } has(name) { - return typeof this._metadata[name] !== "undefined"; + return this._metadataMap.has(name); } }