Skip to content
Merged
Changes from 1 commit
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
80 changes: 75 additions & 5 deletions src/manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,7 @@
if (symbols.has(id)) {
lock(`Sign error: another plugin signed as "${id}".`);
}
const token = Symbol(id);
const token = Private.OriginalSymbol(id);
const plugin = factory(token);
if (id !== plugin.id) {
lock(`Sign error: plugin ID mismatch "${plugin.id}"≠"${id}".`);
Expand All @@ -276,20 +276,87 @@
}

namespace Private {
namespace SafeMapNs {
// Capture the original Map constructor and prototype methods.
const MapConstructor = Object.getPrototypeOf(new Map()).constructor;
const _get = MapConstructor.prototype.get;
const _has = MapConstructor.prototype.has;
const _set = MapConstructor.prototype.set;
const _delete = MapConstructor.prototype.delete;
const _clear = MapConstructor.prototype.clear;
const _entries = MapConstructor.prototype.entries;
const _keys = MapConstructor.prototype.keys;
const _values = MapConstructor.prototype.values;
const _forEach = MapConstructor.prototype.forEach;

export class SafeMap<K, V> {
private _map: InstanceType<typeof MapConstructor>;

constructor(entries?: readonly (readonly [K, V])[] | null) {
this._map = Reflect.construct(MapConstructor, entries ? [entries] : []);
}
s;

Check failure on line 298 in src/manager.ts

View workflow job for this annotation

GitHub Actions / check_release

Member 's' implicitly has an 'any' type.
Copy link
Collaborator

@brichet brichet Oct 6, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this expected (the s variable) ?

Copy link
Member Author

@trungleduc trungleduc Oct 6, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah nope, thanks for catching this

get(key: K): V | undefined {
return _get.call(this._map, key);
}
has(key: K): boolean {
return _has.call(this._map, key);
}
entries() {
return _entries.call(this._map);
}
keys() {
return _keys.call(this._map);
}
values() {
return _values.call(this._map);
}
forEach(cb: (v: V, k: K, m: Map<K, V>) => void) {
return _forEach.call(this._map, cb);
}

set(key: K, value: V): this {
_set.call(this._map, key, value);
return this;
}
delete(key: K): boolean {
return _delete.call(this._map, key);
}
clear(): void {
_clear.call(this._map);
}

get size(): number {
return this._map.size;
}

// Iterator
[Symbol.iterator]() {
return _entries.call(this._map);
}
}
}

/**
* Internal 'locked' status.
*/
let locked: boolean = false;

/**
* The original Symbol constructor, used to create unique symbols for plugin
* identification and namespace protection.
*/
export const OriginalSymbol = Symbol;

/**
* The namespace associated to a symbol.
*/
export const namespaces = new Map<symbol, string>();
export const namespaces = new SafeMapNs.SafeMap<symbol, string>();

/**
* The symbol associated to a namespace.
*/
export const symbols = new Map<string, symbol>();
export const symbols = new SafeMapNs.SafeMap<string, symbol>();

/**
* Lock the manager.
Expand Down Expand Up @@ -415,12 +482,15 @@
/**
* The inputs elements attached to the manager.
*/
export const inputs = new Map<string, HTMLInputElement>();
export const inputs = new SafeMapNs.SafeMap<string, HTMLInputElement>();

/**
* The secret path associated to an input.
*/
export const secretPath = new Map<HTMLInputElement, SecretPath>();
export const secretPath = new SafeMapNs.SafeMap<
HTMLInputElement,
SecretPath
>();

/**
* Build the secret id from the namespace and id.
Expand Down
Loading