//BEGIN enum LogLevel
/**
* Instances of `LogLevel`
* @type LogLevel[]
*/
const generatedLogLevelInstances = [, , , , , , ];
/**
* A log level.
*
* If this were in a module, you'd export the class, but not the array above.
*
* @enum {string|number}
*/
class LogLevel {
/**
* The current log level as a number
* @type number
*/
#lv;
/**
* The current log level as a string
* @type string
*/
#name;
constructor(lv) {
switch (typeof lv) {
case 'number':
if (lv < 0 || lv > this.constructor.values.length - 1)
throw new TypeError(`LogLevel(lv) must be within [0,${this.constructor.values.length - 1}]!`);
if (generatedLogLevelInstances[lv])
return generatedLogLevelInstances[lv];
[this.#lv, this.#name] = [lv, this.constructor.values[lv]];
generatedLogLevelInstances[lv] = this;
break;
case 'string':
const name = lv.toUpperCase();
const level = this.constructor.values.indexOf(name);
if (generatedLogLevelInstances[level])
return generatedLogLevelInstances[level];
if (level === -1)
throw new TypeError(`LogLevel(lv) must be within [0,${this.constructor.values.length - 1}]!`);
[this.#lv, this.#name] = [level, name];
generatedLogLevelInstances[level] = this;
break;
case 'object':
if (lv instanceof this.constructor)
return lv;
default:
throw new TypeError('LogLevel must be number, string or LogLevel!');
}
Object.freeze(this);
}
/**
* The possible values of LogLevel
*/
static get values() {
return Object.freeze([
'CRITICAL',
'ERROR',
'WARNING',
'INFO',
'LOG',
'DEBUG',
'TRACE'
]);
}
[Symbol.toPrimitive](hint) {
switch (hint) {
case 'default':
case 'number':
return this.#lv;
default:
return this.#name;
}
}
[Symbol.name]() {
return this[Symbol.toStringTag]();
}
[Symbol.toStringTag]() {
return 'LogLevel';
}
/**
* Log level 0
* @returns {LogLevel}
*/
static get CRITICAL() {
return new LogLevel(0);
}
/**
* Log level 1
* @returns {LogLevel}
*/
static get ERROR() {
return new LogLevel(1);
}
/**
* Log level 2
* @returns {LogLevel}
*/
static get WARNING() {
return new LogLevel(2);
}
/**
* Log level 3
* @returns {LogLevel}
*/
static get INFO() {
return new LogLevel(3);
}
/**
* Log level 4
* @returns {LogLevel}
*/
static get LOG() {
return new LogLevel(4);
}
/**
* Log level 5
* @returns {LogLevel}
*/
static get DEBUG() {
return new LogLevel(5);
}
/**
* Log level 6
* @returns {LogLevel}
*/
static get TRACE() {
return new LogLevel(6);
}
}
Object.freeze(LogLevel);
//END enum LogLevel
//------------------------------==============================------------------------------
//BEGIN tests
const tests = [
['LogLevel.INFO===new LogLevel("INFO")', true],
['LogLevel.INFO===new LogLevel(3)', true],
['LogLevel.INFO===LogLevel.INFO', true],
['LogLevel.INFO==3', true],
['String(LogLevel.INFO)==="INFO"', true],
['LogLevel.ERROR<LogLevel.INFO', true],
['LogLevel.INFO===LogLevel.DEBUG', false],
['LogLevel.TRACE<LogLevel.DEBUG', false],
['LogLevel.INFO*3', 9],
['String(new LogLevel(LogLevel.INFO+2))', 'DEBUG'],
['`A message of level ${LogLevel.ERROR} got logged!`', 'A message of level ERROR got logged!'],
['new LogLevel("OOPS")', new TypeError('LogLevel(lv) must be within [0,6]!')],
['new LogLevel(7)', new TypeError('LogLevel(lv) must be within [0,6]!')],
['LogLevel.someNonexistentProp = 7', new TypeError('can\'t define property "someNonexistentProp": Function is not extensible')],
['LogLevel.INFO.someNonexistentProp = "Oops!"', new TypeError('can\'t define property "someNonexistentProp": Object is not extensible')],
['LogLevel.someNonexistentProp', undefined],
['LogLevel.INFO.someNonexistentProp', ]
];
console.info('All tests run in strict mode.');
console.info('Please note that expected error messages are written with Firefox in mind. If you are on a different browser the exact error message may look different but should be equivalent.');
for (const test of tests) {
let result;
try {
result = eval(`'use strict';\n${test[0]}`, {
generatedLogLevelInstances,
LogLevel
});
} catch (err) {
result = err;
}
console.log(`Test: ${test[0]}\nExpect: ${(test[1] instanceof Error)?test[1]:JSON.stringify(test[1])}\nResult: ${(result instanceof Error)?result:JSON.stringify(result)}`);
}
//END tests
div.as-console-wrapper {
/* Make the StackSnippet console fill the entire iframe.
Not needed for JS to work, just as convenience. */
top: 0 !important;
bottom: 0 !important;
max-height: 100vh !important;
}
JSON.stringify(). Can't serialize / deserializeSymbol.