From bf48eccf8c4bf64986c097f79f9eafba2889ca87 Mon Sep 17 00:00:00 2001 From: Florian Hotze Date: Mon, 5 Dec 2022 20:46:17 +0100 Subject: [PATCH] [jsscripting] Refactor log formatting & Respect toString polyfills (#13844) * [jsscripting] Refactor log formatting & Respect toString polyfills * [jsscripting] Catch errors in log formatting & Improve handling of Java obj * [jsscripting] Update log format failure message Signed-off-by: Florian Hotze --- .../node_modules/@jsscripting-globals.js | 93 +++++++++---------- 1 file changed, 45 insertions(+), 48 deletions(-) diff --git a/bundles/org.openhab.automation.jsscripting/src/main/resources/node_modules/@jsscripting-globals.js b/bundles/org.openhab.automation.jsscripting/src/main/resources/node_modules/@jsscripting-globals.js index b68f05ebc9..444955f0d0 100644 --- a/bundles/org.openhab.automation.jsscripting/src/main/resources/node_modules/@jsscripting-globals.js +++ b/bundles/org.openhab.automation.jsscripting/src/main/resources/node_modules/@jsscripting-globals.js @@ -19,66 +19,63 @@ function stringify (value) { try { - if (Java.isJavaObject(value) || value instanceof Error) { - return value.toString(); - } else { - // special cases - if (value === undefined) { - return 'undefined'; - } - if (typeof value === 'function') { - return '[Function]'; - } - if (value instanceof RegExp) { - return value.toString(); - } - // fallback to JSON + if (typeof value === 'string') return value; + // special cases + if (value === undefined) { + return 'undefined'; + } + if (value === null) { + return 'null'; + } + // JSON.stringify all objects that do not polyfill toString() + const str = value.toString(); + if (typeof value === 'object' && (str === '[object Object]') || str === '[object Java]') { return JSON.stringify(value, null, 2); } + return str; } catch (e) { - return '[Circular: ' + e + ']'; + return 'Error: failed to format log message: ' + e; } } function format (f) { - if (typeof f !== 'string') { - const objects = []; - for (let index = 0; index < arguments.length; index++) { - objects.push(stringify(arguments[index])); - } - return objects.join(' '); - } - - if (arguments.length === 1) return f; - - let i = 1; - const args = arguments; - const len = args.length; - let str = String(f).replace(formatRegExp, function (x) { - if (x === '%%') return '%'; - if (i >= len) return x; - switch (x) { - case '%s': return String(args[i++]); - case '%d': return Number(args[i++]); - case '%j': - try { - return stringify(args[i++]); - } catch (_) { - return '[Circular]'; + try { + const args = arguments; + + // If there is only one argument, stringify and return it + if (args.length === 1) return stringify(f); + + // Else if the first arg is string, do regex string formatting + // the number of args after the formatted string must match the number of % placeholder + let str; + let i = 1; + if (typeof f === 'string') { + str = String(f).replace(formatRegExp, function (x) { + if (x === '%%') return '%'; + if (i >= args.length) return x; + switch (x) { + case '%s': return String(args[i++]); + case '%d': return Number(args[i++]); + case '%j': + try { + return stringify(args[i++]); + } catch (e) { + return '[Circular]'; + } + // falls through + default: + return x; } - // falls through - default: - return x; + }); } - }); - for (let x = args[i]; i < len; x = args[++i]) { - if (x === null || (typeof x !== 'object' && typeof x !== 'symbol')) { - str += ' ' + x; - } else { + // Else stringify and join all args + for (let x = args[i]; i < args.length; x = args[++i]) { str += ' ' + stringify(x); } + return str; + } catch (e) { + return 'Error: failed to format log message: ' + e; } - return str; } const counters = {}; -- 2.47.3