| Index: lib/filterClasses.js | 
| =================================================================== | 
| --- a/lib/filterClasses.js | 
| +++ b/lib/filterClasses.js | 
| @@ -388,19 +388,20 @@ | 
| /** | 
| * Determines whether domainSource is already upper-case, | 
| * can be overridden by subclasses. | 
| * @type {boolean} | 
| */ | 
| domainSourceIsUpperCase: false, | 
|  | 
| /** | 
| -   * Map containing domains that this filter should match on/not match | 
| -   * on or null if the filter should match on all domains | 
| -   * @type {?Map.<string,boolean>} | 
| +   * String specifying the domain that this filter should match on, or map | 
| +   * containing domains that this filter should match on/not match on, or null | 
| +   * if the filter should match on all domains | 
| +   * @type {?Map.<string,boolean>|string} | 
| */ | 
| get domains() | 
| { | 
| // Despite this property being cached, the getter is called | 
| // several times on Safari, due to WebKit bug 132872 | 
| let prop = Object.getOwnPropertyDescriptor(this, "domains"); | 
| if (prop) | 
| return prop.value; | 
| @@ -414,17 +415,17 @@ | 
| { | 
| // RegExpFilter already have uppercase domains | 
| source = source.toUpperCase(); | 
| } | 
| let list = source.split(this.domainSeparator); | 
| if (list.length == 1 && list[0][0] != "~") | 
| { | 
| // Fast track for the common one-domain scenario | 
| -        domains = new Map([["", false], [list[0], true]]); | 
| +        domains = list[0]; | 
| } | 
| else | 
| { | 
| let hasIncludes = false; | 
| for (let i = 0; i < list.length; i++) | 
| { | 
| let domain = list[i]; | 
| if (domain == "") | 
| @@ -483,20 +484,26 @@ | 
|  | 
| // If no domains are set the rule matches everywhere | 
| if (!this.domains) | 
| return true; | 
|  | 
| // If the document has no host name, match only if the filter | 
| // isn't restricted to specific domains | 
| if (!docDomain) | 
| -      return this.domains.get(""); | 
| +      return typeof this.domains != "string" && this.domains.get(""); | 
|  | 
| docDomain = docDomain.replace(/\.+$/, "").toUpperCase(); | 
|  | 
| +    if (typeof this.domains == "string") | 
| +    { | 
| +      return docDomain == this.domains || | 
| +             docDomain.endsWith("." + this.domains); | 
| +    } | 
| + | 
| while (true) | 
| { | 
| let isDomainIncluded = this.domains.get(docDomain); | 
| if (typeof isDomainIncluded != "undefined") | 
| return isDomainIncluded; | 
|  | 
| let nextDot = docDomain.indexOf("."); | 
| if (nextDot < 0) | 
| @@ -508,21 +515,30 @@ | 
|  | 
| /** | 
| * Checks whether this filter is active only on a domain and its subdomains. | 
| * @param {string} docDomain | 
| * @return {boolean} | 
| */ | 
| isActiveOnlyOnDomain(docDomain) | 
| { | 
| -    if (!docDomain || !this.domains || this.domains.get("")) | 
| +    if (!docDomain || !this.domains || | 
| +        typeof this.domains != "string" && this.domains.get("")) | 
| +    { | 
| return false; | 
| +    } | 
|  | 
| docDomain = docDomain.replace(/\.+$/, "").toUpperCase(); | 
|  | 
| +    if (typeof this.domains == "string") | 
| +    { | 
| +      return docDomain == this.domains || | 
| +             this.domains.endsWith("." + docDomain); | 
| +    } | 
| + | 
| for (let [domain, isIncluded] of this.domains) | 
| { | 
| if (isIncluded && domain != docDomain) | 
| { | 
| if (domain.length <= docDomain.length) | 
| return false; | 
|  | 
| if (!domain.endsWith("." + docDomain)) | 
| @@ -535,17 +551,18 @@ | 
|  | 
| /** | 
| * Checks whether this filter is generic or specific | 
| * @return {boolean} | 
| */ | 
| isGeneric() | 
| { | 
| return !(this.sitekeys && this.sitekeys.length) && | 
| -            (!this.domains || this.domains.get("")); | 
| +            (!this.domains || | 
| +             typeof this.domains != "string" && this.domains.get("")); | 
| }, | 
|  | 
| /** | 
| * See Filter.serialize() | 
| * @inheritdoc | 
| */ | 
| serialize(buffer) | 
| { | 
|  |