Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: catch decoding errors #1167

Merged
merged 1 commit into from
Nov 9, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading