mirror of
https://github.com/github/codeql-action.git
synced 2025-12-27 17:50:07 +08:00
72 lines
1.7 KiB
JavaScript
72 lines
1.7 KiB
JavaScript
'use strict';
|
|
|
|
/**
|
|
* Record objects that pass by in a stream. If the same object is used more
|
|
* than once, it can be value-shared using shared values.
|
|
*
|
|
* @see {@link http://cbor.schmorp.de/value-sharing}
|
|
*/
|
|
class ObjectRecorder {
|
|
constructor() {
|
|
this.clear();
|
|
}
|
|
|
|
/**
|
|
* Clear all of the objects that have been seen. Revert to recording mode.
|
|
*/
|
|
clear() {
|
|
this.map = new WeakMap();
|
|
this.count = 0;
|
|
this.recording = true;
|
|
}
|
|
|
|
/**
|
|
* Stop recording.
|
|
*/
|
|
stop() {
|
|
this.recording = false;
|
|
}
|
|
|
|
/**
|
|
* Determine if wrapping a tag 28 or 29 around an object that has been
|
|
* reused is appropriate. This method stores state for which objects have
|
|
* been seen.
|
|
*
|
|
* @param {object} obj Any object about to be serialized.
|
|
* @returns {number} If recording: -1 for first use, index for second use.
|
|
* If not recording, -1 for never-duplicated, -2 for first use, index for
|
|
* subsequent uses.
|
|
* @throws {Error} Recording does not match playback.
|
|
*/
|
|
check(obj) {
|
|
const val = this.map.get(obj);
|
|
if (val) {
|
|
if (val.length > 1) {
|
|
if (val[0] || this.recording) {
|
|
return val[1];
|
|
}
|
|
|
|
val[0] = true;
|
|
return ObjectRecorder.FIRST;
|
|
}
|
|
if (!this.recording) {
|
|
return ObjectRecorder.NEVER;
|
|
}
|
|
val.push(this.count++);
|
|
// Second use while recording
|
|
return val[1];
|
|
}
|
|
if (!this.recording) {
|
|
throw new Error('New object detected when not recording');
|
|
}
|
|
this.map.set(obj, [false]);
|
|
// First use while recording
|
|
return ObjectRecorder.NEVER;
|
|
}
|
|
}
|
|
|
|
ObjectRecorder.NEVER = -1;
|
|
ObjectRecorder.FIRST = -2;
|
|
|
|
module.exports = ObjectRecorder;
|