Skip to content

Commit

Permalink
fix: catch decoding errors (#1167)
Browse files Browse the repository at this point in the history
  • Loading branch information
shetzel authored Nov 9, 2023
1 parent aa220b2 commit 15f1137
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 14 deletions.
45 changes: 31 additions & 14 deletions src/collections/decodeableMap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
* Licensed under the BSD 3-Clause license.
* For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
*/
import { Logger } from '@salesforce/core';
import { isString } from '@salesforce/ts-types';

/**
* This is an extension of the Map class that can match keys whether they are encoded or decoded.
Expand All @@ -29,13 +31,22 @@ export class DecodeableMap<K extends string, V> extends Map<string, V> {
// before `this.set()` is called or `TypeErrors` will be thrown.
private internalkeysMap!: Map<string, string>;

private internalLogger!: Logger;

private get keysMap(): Map<string, string> {
if (!this.internalkeysMap) {
this.internalkeysMap = new Map();
}
return this.internalkeysMap;
}

private get logger(): Logger {
if (!this.internalLogger) {
this.internalLogger = Logger.childFromRoot(this.constructor.name);
}
return this.internalLogger;
}

/**
* boolean indicating whether an element with the specified key (matching decoded) exists or not.
*/
Expand Down Expand Up @@ -77,21 +88,27 @@ export class DecodeableMap<K extends string, V> extends Map<string, V> {
if (super.has(key)) {
return key;
} else {
const decodedKey = decodeURIComponent(key);
if (key !== decodedKey) {
// The key is encoded; If this is part of a set operation,
// set the { decodedKey : encodedKey } in the internal map.
if (setInKeysMap) {
this.keysMap.set(decodedKey, key);
}
if (super.has(decodedKey)) {
return decodedKey;
}
} else {
const encodedKey = this.keysMap.get(decodedKey);
if (encodedKey && super.has(encodedKey)) {
return encodedKey;
try {
const decodedKey = decodeURIComponent(key);
if (key !== decodedKey) {
// The key is encoded; If this is part of a set operation,
// set the { decodedKey : encodedKey } in the internal map.
if (setInKeysMap) {
this.keysMap.set(decodedKey, key);
}
if (super.has(decodedKey)) {
return decodedKey;
}
} else {
const encodedKey = this.keysMap.get(decodedKey);
if (encodedKey && super.has(encodedKey)) {
return encodedKey;
}
}
} catch (e: unknown) {
// Log the error and the key
const errMsg = e instanceof Error ? e.message : isString(e) ? e : 'unknown';
this.logger.debug(`Could not decode metadata key: ${key} due to: ${errMsg}`);
}
}
}
Expand Down
6 changes: 6 additions & 0 deletions test/collections/decodeableMap.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,12 @@ describe('DecodeableMap', () => {
expect(hasMapSpy.calledWith(nonExistent_key_encoded)).to.be.true;
expect(hasMapSpy.calledWith(nonExistent_key_decoded)).to.be.true;
});

it('should not match non-decodeable key', () => {
// trying to decode '%E0%A4%A' throws a URIError so DecodeableMap
// should not throw when a non-decodeable key is encountered.
expect(dMap.has('%E0%A4%A')).to.be.false;
});
});

describe('get()', () => {
Expand Down

0 comments on commit 15f1137

Please sign in to comment.