| Index: lib/filterClasses.js |
| =================================================================== |
| --- a/lib/filterClasses.js |
| +++ b/lib/filterClasses.js |
| @@ -76,16 +76,26 @@ |
| * @type {string} |
| */ |
| get type() |
| { |
| throw new Error("Please define filter type in the subclass"); |
| }, |
| /** |
| + * Whether this object is discarded after use. If <code>false</code>, the |
| + * object is retained in memory once created and every call to |
| + * {@link Filter#fromText} returns the same instance. Defaults to |
| + * <code>false</code>. |
| + * @type {boolean} |
| + * @package |
| + */ |
| + ephemeral: false, |
| + |
| + /** |
| * Subscriptions to which this filter belongs. |
| * @type {?(Subscription|Set.<Subscription>)} |
| * @private |
| */ |
| _subscriptions: null, |
| /** |
| * Whether the filter's subscriptions have already been added to the filter. |
| @@ -179,16 +189,26 @@ |
| else if (subscription == this._subscriptions) |
| { |
| this._subscriptions = null; |
| } |
| } |
| }, |
| /** |
| + * Checks whether the filter should be serialized. |
| + * @return {boolean} |
| + * @protected |
| + */ |
| + shouldSerialize() |
| + { |
| + return false; |
| + }, |
| + |
| + /** |
| * Serializes the filter for writing out on disk. |
| * @yields {string} |
| */ |
| *serialize() |
| { |
| let {text} = this; |
| yield "[Filter]"; |
| @@ -244,17 +264,19 @@ |
| { |
| let match = text.includes("#") ? Filter.contentRegExp.exec(text) : null; |
| if (match) |
| filter = ContentFilter.fromText(text, match[1], match[2], match[3]); |
| else |
| filter = RegExpFilter.fromText(text); |
| } |
| - Filter.knownFilters.set(filter.text, filter); |
| + if (!filter.ephemeral) |
| + Filter.knownFilters.set(filter.text, filter); |
| + |
| return filter; |
| }; |
| /** |
| * Deserializes a filter |
| * |
| * @param {Object} obj map of serialized properties and their values |
| * @return {Filter} filter or null if the filter couldn't be created |
| @@ -265,16 +287,21 @@ |
| if (filter instanceof ActiveFilter) |
| { |
| if ("disabled" in obj) |
| filter._disabled = (obj.disabled == "true"); |
| if ("hitCount" in obj) |
| filter._hitCount = parseInt(obj.hitCount, 10) || 0; |
| if ("lastHit" in obj) |
| filter._lastHit = parseInt(obj.lastHit, 10) || 0; |
| + |
| + // If the filter object is ephemeral, we normally don't keep it, but if it |
| + // has any state then we must. |
| + if (filter.ephemeral && this.shouldSerialize()) |
| + Filter.knownFilters.set(filter.text, filter); |
| } |
| return filter; |
| }; |
| /** |
| * Removes unnecessary whitespaces from filter text, will only return null if |
| * the input parameter is null. |
| * @param {string} text |
| @@ -427,16 +454,20 @@ |
| return this._disabled; |
| }, |
| set disabled(value) |
| { |
| if (value != this._disabled) |
| { |
| let oldValue = this._disabled; |
| this._disabled = value; |
| + |
| + if (value && this.ephemeral) |
|
Manish Jethani
2018/11/18 03:29:12
This could be optimized a little bit, but this pro
Manish Jethani
2018/11/18 06:19:14
Ignore, now removed.
|
| + Filter.knownFilters.set(this.text, this); |
| + |
| filterNotifier.emit("filter.disabled", this, value, oldValue); |
| } |
| return this._disabled; |
| }, |
| /** |
| * Number of hits on the filter since the last reset |
| * @type {number} |
| @@ -446,16 +477,20 @@ |
| return this._hitCount; |
| }, |
| set hitCount(value) |
| { |
| if (value != this._hitCount) |
| { |
| let oldValue = this._hitCount; |
| this._hitCount = value; |
| + |
| + if (value && this.ephemeral) |
| + Filter.knownFilters.set(this.text, this); |
| + |
| filterNotifier.emit("filter.hitCount", this, value, oldValue); |
| } |
| return this._hitCount; |
| }, |
| /** |
| * Last time the filter had a hit (in milliseconds since the beginning of the |
| * epoch) |
| @@ -466,16 +501,20 @@ |
| return this._lastHit; |
| }, |
| set lastHit(value) |
| { |
| if (value != this._lastHit) |
| { |
| let oldValue = this._lastHit; |
| this._lastHit = value; |
| + |
| + if (value && this.ephemeral) |
| + Filter.knownFilters.set(this.text, this); |
| + |
| filterNotifier.emit("filter.lastHit", this, value, oldValue); |
| } |
| return this._lastHit; |
| }, |
| /** |
| * String that the domains property should be generated from |
| * @type {?string} |
| @@ -666,25 +705,33 @@ |
| isGeneric() |
| { |
| let {sitekeys, domains} = this; |
| return !(sitekeys && sitekeys.length) && (!domains || domains.get("")); |
| }, |
| /** |
| + * See Filter.shouldSerialize() |
| + * @inheritdoc |
| + */ |
| + shouldSerialize() |
|
Manish Jethani
2018/11/18 03:29:12
Note that this will always return false in the cur
Manish Jethani
2018/11/18 06:19:14
Ignore, now removed.
An object created with Filte
|
| + { |
| + return this._disabled || this._hitCount || this._lastHit; |
| + }, |
| + |
| + /** |
| * See Filter.serialize() |
| * @inheritdoc |
| */ |
| *serialize() |
| { |
| - let {_disabled, _hitCount, _lastHit} = this; |
| - |
| - if (_disabled || _hitCount || _lastHit) |
| + if (this.shouldSerialize()) |
| { |
| + let {_disabled, _hitCount, _lastHit} = this; |
| yield* Filter.prototype.serialize.call(this); |
| if (_disabled) |
| yield "disabled=true"; |
| if (_hitCount) |
| yield "hitCount=" + _hitCount; |
| if (_lastHit) |
| yield "lastHit=" + _lastHit; |
| } |
| @@ -1311,17 +1358,23 @@ |
| */ |
| function ElemHideFilter(text, domains, selector) |
| { |
| ElemHideBase.call(this, text, domains, selector); |
| } |
| exports.ElemHideFilter = ElemHideFilter; |
| ElemHideFilter.prototype = extend(ElemHideBase, { |
| - type: "elemhide" |
| + type: "elemhide", |
| + |
| + /** |
| + * See Filter.ephemeral |
| + * @inheritdoc |
| + */ |
| + ephemeral: true |
| }); |
| /** |
| * Class for element hiding exceptions |
| * @param {string} text see {@link Filter Filter()} |
| * @param {string} [domains] see {@link ElemHideBase ElemHideBase()} |
| * @param {string} selector see {@link ElemHideBase ElemHideBase()} |
| * @constructor |