Convert the BasePreferences class to use private fields

Given that none of these fields were ever intended to be accessed directly from the *outside*, since that will lead to inconsistent/broken state, we can use modern ECMAScript features to ensure that they are indeed private.
This commit is contained in:
Jonas Jenwald 2022-03-12 13:46:59 +01:00
parent 9e4aaf18f7
commit 25d7420035

View File

@ -21,29 +21,36 @@ import { AppOptions, OptionKind } from "./app_options.js";
* or every time the viewer is loaded.
*/
class BasePreferences {
#defaults = Object.freeze(
typeof PDFJSDev === "undefined" || !PDFJSDev.test("PRODUCTION")
? AppOptions.getAll(OptionKind.PREFERENCE)
: PDFJSDev.eval("DEFAULT_PREFERENCES")
);
#prefs = Object.create(null);
#initializedPromise = null;
constructor() {
if (this.constructor === BasePreferences) {
throw new Error("Cannot initialize BasePreferences.");
}
Object.defineProperty(this, "defaults", {
value: Object.freeze(
typeof PDFJSDev === "undefined" || !PDFJSDev.test("PRODUCTION")
? AppOptions.getAll(OptionKind.PREFERENCE)
: PDFJSDev.eval("DEFAULT_PREFERENCES")
),
writable: false,
enumerable: true,
configurable: false,
});
this.prefs = Object.create(null);
this._initializedPromise = this._readFromStorage(this.defaults).then(
if (typeof PDFJSDev !== "undefined" && PDFJSDev.test("CHROME")) {
Object.defineProperty(this, "defaults", {
get() {
return this.#defaults;
},
});
}
this.#initializedPromise = this._readFromStorage(this.#defaults).then(
prefs => {
for (const name in this.defaults) {
for (const name in this.#defaults) {
const prefValue = prefs?.[name];
// Ignore preferences whose types don't match the default values.
if (typeof prefValue === typeof this.defaults[name]) {
this.prefs[name] = prefValue;
if (typeof prefValue === typeof this.#defaults[name]) {
this.#prefs[name] = prefValue;
}
}
}
@ -76,9 +83,9 @@ class BasePreferences {
* have been reset.
*/
async reset() {
await this._initializedPromise;
this.prefs = Object.create(null);
return this._writeToStorage(this.defaults);
await this.#initializedPromise;
this.#prefs = Object.create(null);
return this._writeToStorage(this.#defaults);
}
/**
@ -89,8 +96,8 @@ class BasePreferences {
* provided that the preference exists and the types match.
*/
async set(name, value) {
await this._initializedPromise;
const defaultValue = this.defaults[name];
await this.#initializedPromise;
const defaultValue = this.#defaults[name];
if (defaultValue === undefined) {
throw new Error(`Set preference: "${name}" is undefined.`);
@ -113,8 +120,8 @@ class BasePreferences {
throw new Error(`Set preference: "${value}" must be an integer.`);
}
}
this.prefs[name] = value;
return this._writeToStorage(this.prefs);
this.#prefs[name] = value;
return this._writeToStorage(this.#prefs);
}
/**
@ -124,14 +131,13 @@ class BasePreferences {
* containing the value of the preference.
*/
async get(name) {
await this._initializedPromise;
const defaultValue = this.defaults[name],
prefValue = this.prefs[name];
await this.#initializedPromise;
const defaultValue = this.#defaults[name];
if (defaultValue === undefined) {
throw new Error(`Get preference: "${name}" is undefined.`);
}
return prefValue !== undefined ? prefValue : defaultValue;
return this.#prefs[name] ?? defaultValue;
}
/**
@ -140,12 +146,11 @@ class BasePreferences {
* the values of all preferences.
*/
async getAll() {
await this._initializedPromise;
await this.#initializedPromise;
const obj = Object.create(null);
for (const name in this.defaults) {
const prefValue = this.prefs[name];
obj[name] = prefValue !== undefined ? prefValue : this.defaults[name];
for (const name in this.#defaults) {
obj[name] = this.#prefs[name] ?? this.#defaults[name];
}
return obj;
}