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 |