You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

234 lines
7.0 KiB

  1. /*******************************************************************************
  2. uMatrix - a browser extension to block requests.
  3. Copyright (C) 2017 Raymond Hill
  4. This program is free software: you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation, either version 3 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program. If not, see {http://www.gnu.org/licenses/}.
  14. Home: https://github.com/gorhill/uMatrix
  15. This file has been originally imported from:
  16. https://github.com/gorhill/uBlock/tree/master/platform/chromium
  17. */
  18. // For background page or non-background pages
  19. /* exported objectAssign */
  20. 'use strict';
  21. /******************************************************************************/
  22. /******************************************************************************/
  23. // https://github.com/gorhill/uBlock/issues/1067
  24. // https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/String/startsWith
  25. // Firefox 17/Chromium 41 supports `startsWith`.
  26. if ( String.prototype.startsWith instanceof Function === false ) {
  27. String.prototype.startsWith = function(needle, pos) {
  28. if ( typeof pos !== 'number' ) {
  29. pos = 0;
  30. }
  31. return this.lastIndexOf(needle, pos) === pos;
  32. };
  33. }
  34. /******************************************************************************/
  35. // https://github.com/gorhill/uBlock/issues/1067
  36. // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/endsWith
  37. // Firefox 17/Chromium 41 supports `endsWith`.
  38. if ( String.prototype.endsWith instanceof Function === false ) {
  39. String.prototype.endsWith = function(needle, pos) {
  40. if ( typeof pos !== 'number' ) {
  41. pos = this.length;
  42. }
  43. pos -= needle.length;
  44. return this.indexOf(needle, pos) === pos;
  45. };
  46. }
  47. /******************************************************************************/
  48. // As per MDN, Object.assign appeared first in Chromium 45.
  49. // https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Object/assign#Browser_compatibility
  50. var objectAssign = Object.assign || function(target, source) {
  51. var keys = Object.keys(source);
  52. for ( var i = 0, n = keys.length, key; i < n; i++ ) {
  53. key = keys[i];
  54. target[key] = source[key];
  55. }
  56. return target;
  57. };
  58. /******************************************************************************/
  59. // https://github.com/gorhill/uBlock/issues/1070
  60. // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set#Browser_compatibility
  61. // This polyfill is designed to fulfill *only* what uBlock Origin needs -- this
  62. // is not an accurate API of the real Set() type.
  63. if ( self.Set instanceof Function === false ) {
  64. self.Set = function(iter) {
  65. this.clear();
  66. if ( Array.isArray(iter) ) {
  67. for ( var i = 0, n = iter.length; i < n; i++ ) {
  68. this.add(iter[i]);
  69. }
  70. return;
  71. }
  72. };
  73. self.Set.polyfill = true;
  74. self.Set.prototype.clear = function() {
  75. this._set = Object.create(null);
  76. this.size = 0;
  77. // Iterator stuff
  78. this._values = undefined;
  79. this._i = undefined;
  80. this.value = undefined;
  81. this.done = true;
  82. };
  83. self.Set.prototype.add = function(k) {
  84. if ( this._set[k] === undefined ) {
  85. this._set[k] = true;
  86. this.size += 1;
  87. }
  88. return this;
  89. };
  90. self.Set.prototype.delete = function(k) {
  91. if ( this._set[k] !== undefined ) {
  92. delete this._set[k];
  93. this.size -= 1;
  94. return true;
  95. }
  96. return false;
  97. };
  98. self.Set.prototype.has = function(k) {
  99. return this._set[k] !== undefined;
  100. };
  101. self.Set.prototype.next = function() {
  102. if ( this._i < this.size ) {
  103. this.value = this._values[this._i++];
  104. } else {
  105. this._values = undefined;
  106. this.value = undefined;
  107. this.done = true;
  108. }
  109. return this;
  110. };
  111. self.Set.prototype.values = function() {
  112. this._values = Object.keys(this._set);
  113. this._i = 0;
  114. this.value = undefined;
  115. this.done = false;
  116. return this;
  117. };
  118. }
  119. /******************************************************************************/
  120. // https://github.com/gorhill/uBlock/issues/1070
  121. // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set#Browser_compatibility
  122. // This polyfill is designed to fulfill *only* what uBlock Origin needs -- this
  123. // is not an accurate API of the real Map() type.
  124. if ( self.Map instanceof Function === false ) {
  125. self.Map = function(iter) {
  126. this.clear();
  127. if ( Array.isArray(iter) ) {
  128. for ( var i = 0, n = iter.length, entry; i < n; i++ ) {
  129. entry = iter[i];
  130. this.set(entry[0], entry[1]);
  131. }
  132. return;
  133. }
  134. };
  135. self.Map.polyfill = true;
  136. self.Map.prototype.clear = function() {
  137. this._map = Object.create(null);
  138. this.size = 0;
  139. // Iterator stuff
  140. this._keys = undefined;
  141. this._i = undefined;
  142. this.value = undefined;
  143. this.done = true;
  144. };
  145. self.Map.prototype.delete = function(k) {
  146. if ( this._map[k] !== undefined ) {
  147. delete this._map[k];
  148. this.size -= 1;
  149. return true;
  150. }
  151. return false;
  152. };
  153. self.Map.prototype.entries = function() {
  154. this._keys = Object.keys(this._map);
  155. this._i = 0;
  156. this.value = [ undefined, undefined ];
  157. this.done = false;
  158. return this;
  159. };
  160. self.Map.prototype.get = function(k) {
  161. return this._map[k];
  162. };
  163. self.Map.prototype.has = function(k) {
  164. return this._map[k] !== undefined;
  165. };
  166. self.Map.prototype.next = function() {
  167. if ( this._i < this.size ) {
  168. var key = this._keys[this._i++];
  169. this.value[0] = key;
  170. this.value[1] = this._map[key];
  171. } else {
  172. this._keys = undefined;
  173. this.value = undefined;
  174. this.done = true;
  175. }
  176. return this;
  177. };
  178. self.Map.prototype.set = function(k, v) {
  179. if ( v !== undefined ) {
  180. if ( this._map[k] === undefined ) {
  181. this.size += 1;
  182. }
  183. this._map[k] = v;
  184. } else {
  185. if ( this._map[k] !== undefined ) {
  186. this.size -= 1;
  187. }
  188. delete this._map[k];
  189. }
  190. return this;
  191. };
  192. }
  193. /******************************************************************************/