Skip to content

Commit 1efdb24

Browse files
committed
Store original Map and Symbol
1 parent 33fa534 commit 1efdb24

File tree

1 file changed

+75
-5
lines changed

1 file changed

+75
-5
lines changed

src/manager.ts

Lines changed: 75 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -264,7 +264,7 @@ export namespace SecretsManager {
264264
if (symbols.has(id)) {
265265
lock(`Sign error: another plugin signed as "${id}".`);
266266
}
267-
const token = Symbol(id);
267+
const token = Private.OriginalSymbol(id);
268268
const plugin = factory(token);
269269
if (id !== plugin.id) {
270270
lock(`Sign error: plugin ID mismatch "${plugin.id}"≠"${id}".`);
@@ -276,20 +276,87 @@ export namespace SecretsManager {
276276
}
277277

278278
namespace Private {
279+
namespace SafeMapNs {
280+
// Capture the original Map constructor and prototype methods.
281+
const MapConstructor = Object.getPrototypeOf(new Map()).constructor;
282+
const _get = MapConstructor.prototype.get;
283+
const _has = MapConstructor.prototype.has;
284+
const _set = MapConstructor.prototype.set;
285+
const _delete = MapConstructor.prototype.delete;
286+
const _clear = MapConstructor.prototype.clear;
287+
const _entries = MapConstructor.prototype.entries;
288+
const _keys = MapConstructor.prototype.keys;
289+
const _values = MapConstructor.prototype.values;
290+
const _forEach = MapConstructor.prototype.forEach;
291+
292+
export class SafeMap<K, V> {
293+
private _map: InstanceType<typeof MapConstructor>;
294+
295+
constructor(entries?: readonly (readonly [K, V])[] | null) {
296+
this._map = Reflect.construct(MapConstructor, entries ? [entries] : []);
297+
}
298+
s;
299+
get(key: K): V | undefined {
300+
return _get.call(this._map, key);
301+
}
302+
has(key: K): boolean {
303+
return _has.call(this._map, key);
304+
}
305+
entries() {
306+
return _entries.call(this._map);
307+
}
308+
keys() {
309+
return _keys.call(this._map);
310+
}
311+
values() {
312+
return _values.call(this._map);
313+
}
314+
forEach(cb: (v: V, k: K, m: Map<K, V>) => void) {
315+
return _forEach.call(this._map, cb);
316+
}
317+
318+
set(key: K, value: V): this {
319+
_set.call(this._map, key, value);
320+
return this;
321+
}
322+
delete(key: K): boolean {
323+
return _delete.call(this._map, key);
324+
}
325+
clear(): void {
326+
_clear.call(this._map);
327+
}
328+
329+
get size(): number {
330+
return this._map.size;
331+
}
332+
333+
// Iterator
334+
[Symbol.iterator]() {
335+
return _entries.call(this._map);
336+
}
337+
}
338+
}
339+
279340
/**
280341
* Internal 'locked' status.
281342
*/
282343
let locked: boolean = false;
283344

345+
/**
346+
* The original Symbol constructor, used to create unique symbols for plugin
347+
* identification and namespace protection.
348+
*/
349+
export const OriginalSymbol = Symbol;
350+
284351
/**
285352
* The namespace associated to a symbol.
286353
*/
287-
export const namespaces = new Map<symbol, string>();
354+
export const namespaces = new SafeMapNs.SafeMap<symbol, string>();
288355

289356
/**
290357
* The symbol associated to a namespace.
291358
*/
292-
export const symbols = new Map<string, symbol>();
359+
export const symbols = new SafeMapNs.SafeMap<string, symbol>();
293360

294361
/**
295362
* Lock the manager.
@@ -415,12 +482,15 @@ namespace Private {
415482
/**
416483
* The inputs elements attached to the manager.
417484
*/
418-
export const inputs = new Map<string, HTMLInputElement>();
485+
export const inputs = new SafeMapNs.SafeMap<string, HTMLInputElement>();
419486

420487
/**
421488
* The secret path associated to an input.
422489
*/
423-
export const secretPath = new Map<HTMLInputElement, SecretPath>();
490+
export const secretPath = new SafeMapNs.SafeMap<
491+
HTMLInputElement,
492+
SecretPath
493+
>();
424494

425495
/**
426496
* Build the secret id from the namespace and id.

0 commit comments

Comments
 (0)