fallback to json dance if structureClone fails
authorJustin Wind <justin.wind+git@gmail.com>
Sun, 24 Mar 2024 21:53:14 +0000 (14:53 -0700)
committerJustin Wind <justin.wind+git@gmail.com>
Sun, 24 Mar 2024 21:53:14 +0000 (14:53 -0700)
lib/logger.js
test/lib/logger.js

index 3f336ab4c7121d17fbeaca6eacfee45bc678c043..6cc4a2b4f30065b6d51e41de253d2267a780ee95 100644 (file)
@@ -3,7 +3,7 @@
 const jsonReplacers = require('./json-replacers');
 const dataSanitizers = require('./data-sanitizers');
 
-const nop = () => { /**/ };
+const nop = () => undefined;
 
 class Logger {
   /**
@@ -94,7 +94,11 @@ class Logger {
 
     if (this.sanitizationNeeded(data)) {
       // Create copy of data so we are not changing anything important.
-      data = structuredClone(data);
+      try {
+        data = structuredClone(data);
+      } catch (e) {
+        data = JSON.parse(JSON.stringify(data, replacer));
+      }
       this.sanitize(data);
     }
 
@@ -150,7 +154,7 @@ class Logger {
         while (ancestors.length > 0 && ancestors.at(-1) !== this) {
           ancestors.pop();
         }
-        if (ancestors.includes(value)) { // eslint-disable-line security/detect-object-injection
+        if (ancestors.includes(value)) {
           return '[Circular]';
         } else {
           ancestors.push(value);
@@ -158,7 +162,7 @@ class Logger {
       }
 
       return value;
-    }
+    };
   }
 
 }
index a2efb537fd5e2eb0b00e4d72274f0567ce5488cc..939c61f4f25960fbe19790e492db0dd7db91fd6f 100644 (file)
@@ -11,6 +11,18 @@ const asyncLocalStorage = new AsyncLocalStorage();
 describe('Logger', function () {
   let config, logger, commonObject, scope, message;
 
+  function sanitizeCredential(data, sanitize = true) {
+    let unclean = false;
+    const credentialLength = data?.ctx?.parsedBody?.credential?.length;
+    if (credentialLength) {
+      unclean = true;
+    }
+    if (unclean && sanitize) {
+      data.ctx.parsedBody.credential = '*'.repeat(credentialLength);
+    }
+    return unclean;
+  }
+
   beforeEach(function () {
     config = {};
     commonObject = {
@@ -76,17 +88,7 @@ describe('Logger', function () {
   });
 
   it('sanitizes', function () {
-    logger.dataSanitizers.push((data, sanitize = true) => {
-      let unclean = false;
-      const credentialLength = data?.ctx?.parsedBody?.credential?.length;
-      if (credentialLength) {
-        unclean = true;
-      }
-      if (unclean && sanitize) {
-        data.ctx.parsedBody.credential = '*'.repeat(credentialLength);
-      }
-      return unclean;
-    });
+    logger.dataSanitizers.push(sanitizeCredential);
     logger.info(scope, message, {
       ctx: {
         parsedBody: {
@@ -157,4 +159,19 @@ describe('Logger', function () {
     assert(logger.backend.info.called);
     assert(logger.backend.info.args[0][0].includes('[Circular]'));
   });
+
+  it('covers non-serializable objects', function () {
+    logger.dataSanitizers.push(sanitizeCredential);
+    const data = {
+      ctx: {
+        parsedBody: {
+          credential: 'foo',
+        },
+      },
+      foo: new WeakMap(),
+    };
+    logger.info(scope, message, data);
+    assert(logger.backend.info.called);
+  });
+
 }); // Logger
\ No newline at end of file