opal 1.6.1 → 1.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (212) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/build.yml +17 -0
  3. data/CHANGELOG.md +35 -1
  4. data/Gemfile +1 -0
  5. data/HACKING.md +47 -26
  6. data/benchmark/benchmarks +415 -103
  7. data/benchmark/bm_call_overhead.yml +28 -0
  8. data/benchmark/run.rb +61 -40
  9. data/docs/cdp_common.json +3364 -0
  10. data/docs/cdp_common.md +18 -0
  11. data/docs/{headless_chrome.md → headless_browsers.md} +31 -12
  12. data/lib/opal/ast/builder.rb +1 -1
  13. data/lib/opal/builder.rb +6 -1
  14. data/lib/opal/builder_processors.rb +5 -3
  15. data/lib/opal/cache.rb +1 -7
  16. data/lib/opal/cli_options.rb +72 -58
  17. data/lib/opal/cli_runners/chrome.rb +47 -9
  18. data/lib/opal/cli_runners/chrome_cdp_interface.rb +238 -112
  19. data/lib/opal/cli_runners/compiler.rb +146 -13
  20. data/lib/opal/cli_runners/deno.rb +32 -0
  21. data/lib/opal/cli_runners/firefox.rb +350 -0
  22. data/lib/opal/cli_runners/firefox_cdp_interface.rb +212 -0
  23. data/lib/opal/cli_runners/node_modules/.bin/chrome-remote-interface.cmd +17 -0
  24. data/lib/opal/cli_runners/node_modules/.bin/chrome-remote-interface.ps1 +28 -0
  25. data/lib/opal/cli_runners/node_modules/.package-lock.json +41 -0
  26. data/lib/opal/cli_runners/node_modules/chrome-remote-interface/LICENSE +1 -1
  27. data/lib/opal/cli_runners/node_modules/chrome-remote-interface/README.md +322 -182
  28. data/lib/opal/cli_runners/node_modules/chrome-remote-interface/bin/client.js +99 -114
  29. data/lib/opal/cli_runners/node_modules/chrome-remote-interface/chrome-remote-interface.js +1 -11
  30. data/lib/opal/cli_runners/node_modules/chrome-remote-interface/index.js +16 -11
  31. data/lib/opal/cli_runners/node_modules/chrome-remote-interface/lib/api.js +41 -33
  32. data/lib/opal/cli_runners/node_modules/chrome-remote-interface/lib/chrome.js +224 -214
  33. data/lib/opal/cli_runners/node_modules/chrome-remote-interface/lib/devtools.js +71 -191
  34. data/lib/opal/cli_runners/node_modules/chrome-remote-interface/lib/external-request.js +26 -6
  35. data/lib/opal/cli_runners/node_modules/chrome-remote-interface/lib/protocol.json +20788 -9049
  36. data/lib/opal/cli_runners/node_modules/chrome-remote-interface/lib/websocket-wrapper.js +10 -3
  37. data/lib/opal/cli_runners/node_modules/chrome-remote-interface/package.json +59 -123
  38. data/lib/opal/cli_runners/node_modules/chrome-remote-interface/webpack.config.js +25 -32
  39. data/lib/opal/cli_runners/node_modules/commander/History.md +298 -0
  40. data/lib/opal/cli_runners/node_modules/commander/LICENSE +22 -0
  41. data/lib/opal/cli_runners/node_modules/commander/Readme.md +217 -61
  42. data/lib/opal/cli_runners/node_modules/commander/index.js +431 -145
  43. data/lib/opal/cli_runners/node_modules/commander/package.json +16 -79
  44. data/lib/opal/cli_runners/node_modules/ws/README.md +334 -98
  45. data/lib/opal/cli_runners/node_modules/ws/browser.js +8 -0
  46. data/lib/opal/cli_runners/node_modules/ws/index.js +5 -10
  47. data/lib/opal/cli_runners/node_modules/ws/lib/buffer-util.js +129 -0
  48. data/lib/opal/cli_runners/node_modules/ws/lib/constants.js +10 -0
  49. data/lib/opal/cli_runners/node_modules/ws/lib/event-target.js +184 -0
  50. data/lib/opal/cli_runners/node_modules/ws/lib/extension.js +223 -0
  51. data/lib/opal/cli_runners/node_modules/ws/lib/limiter.js +55 -0
  52. data/lib/opal/cli_runners/node_modules/ws/lib/permessage-deflate.js +518 -0
  53. data/lib/opal/cli_runners/node_modules/ws/lib/receiver.js +607 -0
  54. data/lib/opal/cli_runners/node_modules/ws/lib/sender.js +409 -0
  55. data/lib/opal/cli_runners/node_modules/ws/lib/stream.js +180 -0
  56. data/lib/opal/cli_runners/node_modules/ws/lib/validation.js +104 -0
  57. data/lib/opal/cli_runners/node_modules/ws/lib/websocket-server.js +447 -0
  58. data/lib/opal/cli_runners/node_modules/ws/lib/websocket.js +1195 -0
  59. data/lib/opal/cli_runners/node_modules/ws/package.json +40 -106
  60. data/lib/opal/cli_runners/package-lock.json +62 -0
  61. data/lib/opal/cli_runners/package.json +1 -1
  62. data/lib/opal/cli_runners.rb +26 -4
  63. data/lib/opal/nodes/args/prepare_post_args.rb +2 -2
  64. data/lib/opal/nodes/def.rb +8 -8
  65. data/lib/opal/nodes/iter.rb +12 -12
  66. data/lib/opal/nodes/logic.rb +1 -1
  67. data/lib/opal/nodes/masgn.rb +2 -2
  68. data/lib/opal/parser/with_ruby_lexer.rb +1 -1
  69. data/lib/opal/paths.rb +14 -0
  70. data/lib/opal/rewriter.rb +2 -0
  71. data/lib/opal/rewriters/forward_args.rb +52 -4
  72. data/lib/opal/rewriters/targeted_patches.rb +94 -0
  73. data/lib/opal/version.rb +1 -1
  74. data/opal/corelib/basic_object.rb +1 -1
  75. data/opal/corelib/boolean.rb +2 -2
  76. data/opal/corelib/class.rb +11 -0
  77. data/opal/corelib/constants.rb +3 -3
  78. data/opal/corelib/enumerable.rb +4 -0
  79. data/opal/corelib/enumerator.rb +1 -1
  80. data/opal/corelib/hash.rb +2 -2
  81. data/opal/corelib/helpers.rb +1 -1
  82. data/opal/corelib/kernel.rb +3 -3
  83. data/opal/corelib/method.rb +1 -1
  84. data/opal/corelib/module.rb +29 -8
  85. data/opal/corelib/proc.rb +7 -5
  86. data/opal/corelib/runtime.js +141 -78
  87. data/opal/corelib/set.rb +252 -0
  88. data/opal/corelib/string.rb +2 -1
  89. data/opal/corelib/time.rb +2 -2
  90. data/opal/opal.rb +1 -0
  91. data/opal.gemspec +1 -0
  92. data/spec/filters/bugs/array.rb +22 -13
  93. data/spec/filters/bugs/base64.rb +5 -5
  94. data/spec/filters/bugs/basicobject.rb +16 -8
  95. data/spec/filters/bugs/bigdecimal.rb +161 -160
  96. data/spec/filters/bugs/binding.rb +10 -10
  97. data/spec/filters/bugs/class.rb +8 -8
  98. data/spec/filters/bugs/complex.rb +2 -1
  99. data/spec/filters/bugs/date.rb +79 -81
  100. data/spec/filters/bugs/datetime.rb +29 -29
  101. data/spec/filters/bugs/delegate.rb +1 -3
  102. data/spec/filters/bugs/encoding.rb +69 -69
  103. data/spec/filters/bugs/enumerable.rb +22 -20
  104. data/spec/filters/bugs/enumerator.rb +88 -85
  105. data/spec/filters/bugs/exception.rb +46 -40
  106. data/spec/filters/bugs/file.rb +32 -32
  107. data/spec/filters/bugs/float.rb +26 -21
  108. data/spec/filters/bugs/freeze.rb +88 -0
  109. data/spec/filters/bugs/hash.rb +39 -38
  110. data/spec/filters/bugs/integer.rb +57 -44
  111. data/spec/filters/bugs/io.rb +1 -1
  112. data/spec/filters/bugs/kernel.rb +349 -269
  113. data/spec/filters/bugs/language.rb +220 -188
  114. data/spec/filters/bugs/main.rb +5 -3
  115. data/spec/filters/bugs/marshal.rb +38 -38
  116. data/spec/filters/bugs/math.rb +2 -1
  117. data/spec/filters/bugs/method.rb +73 -62
  118. data/spec/filters/bugs/module.rb +163 -143
  119. data/spec/filters/bugs/numeric.rb +6 -6
  120. data/spec/filters/bugs/objectspace.rb +16 -16
  121. data/spec/filters/bugs/openstruct.rb +1 -1
  122. data/spec/filters/bugs/pack_unpack.rb +51 -51
  123. data/spec/filters/bugs/pathname.rb +7 -7
  124. data/spec/filters/bugs/proc.rb +63 -63
  125. data/spec/filters/bugs/random.rb +7 -6
  126. data/spec/filters/bugs/range.rb +12 -9
  127. data/spec/filters/bugs/rational.rb +8 -7
  128. data/spec/filters/bugs/regexp.rb +49 -48
  129. data/spec/filters/bugs/ruby-32.rb +56 -0
  130. data/spec/filters/bugs/set.rb +30 -30
  131. data/spec/filters/bugs/singleton.rb +4 -4
  132. data/spec/filters/bugs/string.rb +187 -99
  133. data/spec/filters/bugs/stringio.rb +7 -0
  134. data/spec/filters/bugs/stringscanner.rb +68 -68
  135. data/spec/filters/bugs/struct.rb +11 -9
  136. data/spec/filters/bugs/symbol.rb +1 -1
  137. data/spec/filters/bugs/time.rb +78 -63
  138. data/spec/filters/bugs/trace_point.rb +4 -4
  139. data/spec/filters/bugs/unboundmethod.rb +32 -17
  140. data/spec/filters/bugs/warnings.rb +8 -12
  141. data/spec/filters/unsupported/array.rb +24 -107
  142. data/spec/filters/unsupported/basicobject.rb +12 -12
  143. data/spec/filters/unsupported/bignum.rb +27 -52
  144. data/spec/filters/unsupported/class.rb +1 -2
  145. data/spec/filters/unsupported/delegator.rb +3 -3
  146. data/spec/filters/unsupported/enumerable.rb +2 -9
  147. data/spec/filters/unsupported/enumerator.rb +2 -11
  148. data/spec/filters/unsupported/file.rb +1 -1
  149. data/spec/filters/unsupported/float.rb +28 -47
  150. data/spec/filters/unsupported/hash.rb +8 -14
  151. data/spec/filters/unsupported/integer.rb +75 -91
  152. data/spec/filters/unsupported/kernel.rb +17 -35
  153. data/spec/filters/unsupported/language.rb +11 -19
  154. data/spec/filters/unsupported/marshal.rb +22 -41
  155. data/spec/filters/unsupported/matchdata.rb +28 -52
  156. data/spec/filters/unsupported/math.rb +1 -1
  157. data/spec/filters/unsupported/privacy.rb +229 -285
  158. data/spec/filters/unsupported/range.rb +1 -5
  159. data/spec/filters/unsupported/regexp.rb +40 -66
  160. data/spec/filters/unsupported/set.rb +2 -2
  161. data/spec/filters/unsupported/singleton.rb +4 -4
  162. data/spec/filters/unsupported/string.rb +305 -508
  163. data/spec/filters/unsupported/struct.rb +3 -4
  164. data/spec/filters/unsupported/symbol.rb +15 -18
  165. data/spec/filters/unsupported/thread.rb +1 -7
  166. data/spec/filters/unsupported/time.rb +159 -202
  167. data/spec/filters/unsupported/usage_of_files.rb +170 -259
  168. data/spec/lib/builder_spec.rb +4 -4
  169. data/spec/lib/rewriters/forward_args_spec.rb +32 -12
  170. data/spec/mspec-opal/runner.rb +2 -0
  171. data/spec/ruby_specs +4 -0
  172. data/stdlib/deno/base.rb +28 -0
  173. data/stdlib/deno/file.rb +340 -0
  174. data/stdlib/{headless_chrome.rb → headless_browser/base.rb} +1 -1
  175. data/stdlib/headless_browser/file.rb +15 -0
  176. data/stdlib/headless_browser.rb +4 -0
  177. data/stdlib/native.rb +1 -1
  178. data/stdlib/nodejs/file.rb +5 -0
  179. data/stdlib/opal/platform.rb +8 -6
  180. data/stdlib/opal-platform.rb +14 -8
  181. data/stdlib/set.rb +1 -258
  182. data/tasks/benchmarking.rake +62 -19
  183. data/tasks/performance.rake +1 -1
  184. data/tasks/testing.rake +5 -3
  185. data/test/nodejs/test_file.rb +29 -10
  186. data/test/opal/http_server.rb +28 -11
  187. data/test/opal/unsupported_and_bugs.rb +2 -1
  188. metadata +89 -50
  189. data/lib/opal/cli_runners/node_modules/ultron/LICENSE +0 -22
  190. data/lib/opal/cli_runners/node_modules/ultron/index.js +0 -138
  191. data/lib/opal/cli_runners/node_modules/ultron/package.json +0 -112
  192. data/lib/opal/cli_runners/node_modules/ws/SECURITY.md +0 -33
  193. data/lib/opal/cli_runners/node_modules/ws/lib/BufferUtil.fallback.js +0 -56
  194. data/lib/opal/cli_runners/node_modules/ws/lib/BufferUtil.js +0 -15
  195. data/lib/opal/cli_runners/node_modules/ws/lib/ErrorCodes.js +0 -28
  196. data/lib/opal/cli_runners/node_modules/ws/lib/EventTarget.js +0 -158
  197. data/lib/opal/cli_runners/node_modules/ws/lib/Extensions.js +0 -69
  198. data/lib/opal/cli_runners/node_modules/ws/lib/PerMessageDeflate.js +0 -339
  199. data/lib/opal/cli_runners/node_modules/ws/lib/Receiver.js +0 -520
  200. data/lib/opal/cli_runners/node_modules/ws/lib/Sender.js +0 -438
  201. data/lib/opal/cli_runners/node_modules/ws/lib/Validation.fallback.js +0 -9
  202. data/lib/opal/cli_runners/node_modules/ws/lib/Validation.js +0 -17
  203. data/lib/opal/cli_runners/node_modules/ws/lib/WebSocket.js +0 -705
  204. data/lib/opal/cli_runners/node_modules/ws/lib/WebSocketServer.js +0 -336
  205. data/spec/filters/bugs/boolean.rb +0 -3
  206. data/spec/filters/bugs/matrix.rb +0 -3
  207. data/spec/filters/unsupported/fixnum.rb +0 -15
  208. data/spec/filters/unsupported/freeze.rb +0 -102
  209. data/spec/filters/unsupported/pathname.rb +0 -4
  210. data/spec/filters/unsupported/proc.rb +0 -4
  211. data/spec/filters/unsupported/random.rb +0 -5
  212. data/spec/filters/unsupported/taint.rb +0 -162
@@ -1,56 +0,0 @@
1
- /*!
2
- * ws: a node.js websocket client
3
- * Copyright(c) 2011 Einar Otto Stangvik <einaros@gmail.com>
4
- * MIT Licensed
5
- */
6
-
7
- 'use strict';
8
-
9
- /**
10
- * Merges an array of buffers into a target buffer.
11
- *
12
- * @param {Buffer} target The target buffer
13
- * @param {Buffer[]} buffers The array of buffers to merge
14
- * @public
15
- */
16
- const merge = (target, buffers) => {
17
- var offset = 0;
18
- for (var i = 0; i < buffers.length; i++) {
19
- const buf = buffers[i];
20
- buf.copy(target, offset);
21
- offset += buf.length;
22
- }
23
- };
24
-
25
- /**
26
- * Masks a buffer using the given mask.
27
- *
28
- * @param {Buffer} source The buffer to mask
29
- * @param {Buffer} mask The mask to use
30
- * @param {Buffer} output The buffer where to store the result
31
- * @param {Number} offset The offset at which to start writing
32
- * @param {Number} length The number of bytes to mask.
33
- * @public
34
- */
35
- const mask = (source, mask, output, offset, length) => {
36
- for (var i = 0; i < length; i++) {
37
- output[offset + i] = source[i] ^ mask[i & 3];
38
- }
39
- };
40
-
41
- /**
42
- * Unmasks a buffer using the given mask.
43
- *
44
- * @param {Buffer} buffer The buffer to unmask
45
- * @param {Buffer} mask The mask to use
46
- * @public
47
- */
48
- const unmask = (buffer, mask) => {
49
- // Required until https://github.com/nodejs/node/issues/9006 is resolved.
50
- const length = buffer.length;
51
- for (var i = 0; i < length; i++) {
52
- buffer[i] ^= mask[i & 3];
53
- }
54
- };
55
-
56
- module.exports = { merge, mask, unmask };
@@ -1,15 +0,0 @@
1
- 'use strict';
2
-
3
- /*!
4
- * ws: a node.js websocket client
5
- * Copyright(c) 2011 Einar Otto Stangvik <einaros@gmail.com>
6
- * MIT Licensed
7
- */
8
-
9
- try {
10
- const bufferUtil = require('bufferutil');
11
-
12
- module.exports = bufferUtil.BufferUtil || bufferUtil;
13
- } catch (e) {
14
- module.exports = require('./BufferUtil.fallback');
15
- }
@@ -1,28 +0,0 @@
1
- /*!
2
- * ws: a node.js websocket client
3
- * Copyright(c) 2011 Einar Otto Stangvik <einaros@gmail.com>
4
- * MIT Licensed
5
- */
6
-
7
- 'use strict';
8
-
9
- module.exports = {
10
- isValidErrorCode: function (code) {
11
- return (code >= 1000 && code <= 1013 && code !== 1004 && code !== 1005 && code !== 1006) ||
12
- (code >= 3000 && code <= 4999);
13
- },
14
- 1000: 'normal',
15
- 1001: 'going away',
16
- 1002: 'protocol error',
17
- 1003: 'unsupported data',
18
- 1004: 'reserved',
19
- 1005: 'reserved for extensions',
20
- 1006: 'reserved for extensions',
21
- 1007: 'inconsistent or invalid data',
22
- 1008: 'policy violation',
23
- 1009: 'message too big',
24
- 1010: 'extension handshake missing',
25
- 1011: 'an unexpected condition prevented the request from being fulfilled',
26
- 1012: 'service restart',
27
- 1013: 'try again later'
28
- };
@@ -1,158 +0,0 @@
1
- 'use strict';
2
-
3
- /**
4
- * Class representing an event.
5
- *
6
- * @private
7
- */
8
- class Event {
9
- /**
10
- * Create a new `Event`.
11
- *
12
- * @param {String} type The name of the event
13
- * @param {Object} target A reference to the target to which the event was dispatched
14
- */
15
- constructor (type, target) {
16
- this.target = target;
17
- this.type = type;
18
- }
19
- }
20
-
21
- /**
22
- * Class representing a message event.
23
- *
24
- * @extends Event
25
- * @private
26
- */
27
- class MessageEvent extends Event {
28
- /**
29
- * Create a new `MessageEvent`.
30
- *
31
- * @param {(String|Buffer|ArrayBuffer)} data The received data
32
- * @param {Boolean} isBinary Specifies if `data` is binary
33
- * @param {WebSocket} target A reference to the target to which the event was dispatched
34
- */
35
- constructor (data, isBinary, target) {
36
- super('message', target);
37
-
38
- this.binary = isBinary; // non-standard.
39
- this.data = data;
40
- }
41
- }
42
-
43
- /**
44
- * Class representing a close event.
45
- *
46
- * @extends Event
47
- * @private
48
- */
49
- class CloseEvent extends Event {
50
- /**
51
- * Create a new `CloseEvent`.
52
- *
53
- * @param {Number} code The status code explaining why the connection is being closed
54
- * @param {String} reason A human-readable string explaining why the connection is closing
55
- * @param {WebSocket} target A reference to the target to which the event was dispatched
56
- */
57
- constructor (code, reason, target) {
58
- super('close', target);
59
-
60
- this.wasClean = code === undefined || code === 1000;
61
- this.reason = reason;
62
- this.target = target;
63
- this.type = 'close';
64
- this.code = code;
65
- }
66
- }
67
-
68
- /**
69
- * Class representing an open event.
70
- *
71
- * @extends Event
72
- * @private
73
- */
74
- class OpenEvent extends Event {
75
- /**
76
- * Create a new `OpenEvent`.
77
- *
78
- * @param {WebSocket} target A reference to the target to which the event was dispatched
79
- */
80
- constructor (target) {
81
- super('open', target);
82
- }
83
- }
84
-
85
- /**
86
- * This provides methods for emulating the `EventTarget` interface. It's not
87
- * meant to be used directly.
88
- *
89
- * @mixin
90
- */
91
- const EventTarget = {
92
- /**
93
- * Register an event listener.
94
- *
95
- * @param {String} method A string representing the event type to listen for
96
- * @param {Function} listener The listener to add
97
- * @public
98
- */
99
- addEventListener (method, listener) {
100
- if (typeof listener !== 'function') return;
101
-
102
- function onMessage (data, flags) {
103
- if (flags.binary && this.binaryType === 'arraybuffer') {
104
- data = new Uint8Array(data).buffer;
105
- }
106
- listener.call(this, new MessageEvent(data, !!flags.binary, this));
107
- }
108
-
109
- function onClose (code, message) {
110
- listener.call(this, new CloseEvent(code, message, this));
111
- }
112
-
113
- function onError (event) {
114
- event.type = 'error';
115
- event.target = this;
116
- listener.call(this, event);
117
- }
118
-
119
- function onOpen () {
120
- listener.call(this, new OpenEvent(this));
121
- }
122
-
123
- if (method === 'message') {
124
- onMessage._listener = listener;
125
- this.on(method, onMessage);
126
- } else if (method === 'close') {
127
- onClose._listener = listener;
128
- this.on(method, onClose);
129
- } else if (method === 'error') {
130
- onError._listener = listener;
131
- this.on(method, onError);
132
- } else if (method === 'open') {
133
- onOpen._listener = listener;
134
- this.on(method, onOpen);
135
- } else {
136
- this.on(method, listener);
137
- }
138
- },
139
-
140
- /**
141
- * Remove an event listener.
142
- *
143
- * @param {String} method A string representing the event type to remove
144
- * @param {Function} listener The listener to remove
145
- * @public
146
- */
147
- removeEventListener (method, listener) {
148
- const listeners = this.listeners(method);
149
-
150
- for (var i = 0; i < listeners.length; i++) {
151
- if (listeners[i] === listener || listeners[i]._listener === listener) {
152
- this.removeListener(method, listeners[i]);
153
- }
154
- }
155
- }
156
- };
157
-
158
- module.exports = EventTarget;
@@ -1,69 +0,0 @@
1
- 'use strict';
2
-
3
- /**
4
- * Module exports.
5
- */
6
-
7
- exports.parse = parse;
8
- exports.format = format;
9
-
10
- /**
11
- * Parse extensions header value
12
- */
13
-
14
- function parse (value) {
15
- value = value || '';
16
-
17
- var extensions = {};
18
-
19
- value.split(',').forEach(function (v) {
20
- var params = v.split(';');
21
- var token = params.shift().trim();
22
- var paramsList = extensions[token] = extensions[token] || [];
23
- var parsedParams = {};
24
-
25
- params.forEach(function (param) {
26
- var parts = param.trim().split('=');
27
- var key = parts[0];
28
- var value = parts[1];
29
- if (value === undefined) {
30
- value = true;
31
- } else {
32
- // unquote value
33
- if (value[0] === '"') {
34
- value = value.slice(1);
35
- }
36
- if (value[value.length - 1] === '"') {
37
- value = value.slice(0, value.length - 1);
38
- }
39
- }
40
- (parsedParams[key] = parsedParams[key] || []).push(value);
41
- });
42
-
43
- paramsList.push(parsedParams);
44
- });
45
-
46
- return extensions;
47
- }
48
-
49
- /**
50
- * Format extensions header value
51
- */
52
-
53
- function format (value) {
54
- return Object.keys(value).map(function (token) {
55
- var paramsList = value[token];
56
- if (!Array.isArray(paramsList)) {
57
- paramsList = [paramsList];
58
- }
59
- return paramsList.map(function (params) {
60
- return [token].concat(Object.keys(params).map(function (k) {
61
- var p = params[k];
62
- if (!Array.isArray(p)) p = [p];
63
- return p.map(function (v) {
64
- return v === true ? k : k + '=' + v;
65
- }).join('; ');
66
- })).join('; ');
67
- }).join(', ');
68
- }).join(', ');
69
- }
@@ -1,339 +0,0 @@
1
- 'use strict';
2
-
3
- const zlib = require('zlib');
4
-
5
- const AVAILABLE_WINDOW_BITS = [8, 9, 10, 11, 12, 13, 14, 15];
6
- const DEFAULT_WINDOW_BITS = 15;
7
- const DEFAULT_MEM_LEVEL = 8;
8
- const TRAILER = Buffer.from([0x00, 0x00, 0xff, 0xff]);
9
- const EMPTY_BLOCK = Buffer.from([0x00]);
10
-
11
- /**
12
- * Per-message Compression Extensions implementation
13
- */
14
- class PerMessageDeflate {
15
- constructor (options, isServer, maxPayload) {
16
- this._options = options || {};
17
- this._isServer = !!isServer;
18
- this._inflate = null;
19
- this._deflate = null;
20
- this.params = null;
21
- this._maxPayload = maxPayload || 0;
22
- this.threshold = this._options.threshold === undefined ? 1024 : this._options.threshold;
23
- }
24
-
25
- /**
26
- * Create extension parameters offer
27
- *
28
- * @api public
29
- */
30
-
31
- offer () {
32
- var params = {};
33
- if (this._options.serverNoContextTakeover) {
34
- params.server_no_context_takeover = true;
35
- }
36
- if (this._options.clientNoContextTakeover) {
37
- params.client_no_context_takeover = true;
38
- }
39
- if (this._options.serverMaxWindowBits) {
40
- params.server_max_window_bits = this._options.serverMaxWindowBits;
41
- }
42
- if (this._options.clientMaxWindowBits) {
43
- params.client_max_window_bits = this._options.clientMaxWindowBits;
44
- } else if (this._options.clientMaxWindowBits == null) {
45
- params.client_max_window_bits = true;
46
- }
47
- return params;
48
- }
49
-
50
- /**
51
- * Accept extension offer
52
- *
53
- * @api public
54
- */
55
- accept (paramsList) {
56
- paramsList = this.normalizeParams(paramsList);
57
-
58
- var params;
59
- if (this._isServer) {
60
- params = this.acceptAsServer(paramsList);
61
- } else {
62
- params = this.acceptAsClient(paramsList);
63
- }
64
-
65
- this.params = params;
66
- return params;
67
- }
68
-
69
- /**
70
- * Releases all resources used by the extension
71
- *
72
- * @api public
73
- */
74
- cleanup () {
75
- if (this._inflate) {
76
- if (this._inflate.writeInProgress) {
77
- this._inflate.pendingClose = true;
78
- } else {
79
- this._inflate.close();
80
- this._inflate = null;
81
- }
82
- }
83
- if (this._deflate) {
84
- if (this._deflate.writeInProgress) {
85
- this._deflate.pendingClose = true;
86
- } else {
87
- this._deflate.close();
88
- this._deflate = null;
89
- }
90
- }
91
- }
92
-
93
- /**
94
- * Accept extension offer from client
95
- *
96
- * @api private
97
- */
98
-
99
- acceptAsServer (paramsList) {
100
- var accepted = {};
101
- var result = paramsList.some((params) => {
102
- accepted = {};
103
- if (this._options.serverNoContextTakeover === false && params.server_no_context_takeover) {
104
- return;
105
- }
106
- if (this._options.serverMaxWindowBits === false && params.server_max_window_bits) {
107
- return;
108
- }
109
- if (typeof this._options.serverMaxWindowBits === 'number' &&
110
- typeof params.server_max_window_bits === 'number' &&
111
- this._options.serverMaxWindowBits > params.server_max_window_bits) {
112
- return;
113
- }
114
- if (typeof this._options.clientMaxWindowBits === 'number' && !params.client_max_window_bits) {
115
- return;
116
- }
117
-
118
- if (this._options.serverNoContextTakeover || params.server_no_context_takeover) {
119
- accepted.server_no_context_takeover = true;
120
- }
121
- if (this._options.clientNoContextTakeover) {
122
- accepted.client_no_context_takeover = true;
123
- }
124
- if (this._options.clientNoContextTakeover !== false && params.client_no_context_takeover) {
125
- accepted.client_no_context_takeover = true;
126
- }
127
- if (typeof this._options.serverMaxWindowBits === 'number') {
128
- accepted.server_max_window_bits = this._options.serverMaxWindowBits;
129
- } else if (typeof params.server_max_window_bits === 'number') {
130
- accepted.server_max_window_bits = params.server_max_window_bits;
131
- }
132
- if (typeof this._options.clientMaxWindowBits === 'number') {
133
- accepted.client_max_window_bits = this._options.clientMaxWindowBits;
134
- } else if (this._options.clientMaxWindowBits !== false && typeof params.client_max_window_bits === 'number') {
135
- accepted.client_max_window_bits = params.client_max_window_bits;
136
- }
137
- return true;
138
- });
139
-
140
- if (!result) {
141
- throw new Error(`Doesn't support the offered configuration`);
142
- }
143
-
144
- return accepted;
145
- }
146
-
147
- /**
148
- * Accept extension response from server
149
- *
150
- * @api privaye
151
- */
152
-
153
- acceptAsClient (paramsList) {
154
- var params = paramsList[0];
155
- if (this._options.clientNoContextTakeover != null) {
156
- if (this._options.clientNoContextTakeover === false && params.client_no_context_takeover) {
157
- throw new Error('Invalid value for "client_no_context_takeover"');
158
- }
159
- }
160
- if (this._options.clientMaxWindowBits != null) {
161
- if (this._options.clientMaxWindowBits === false && params.client_max_window_bits) {
162
- throw new Error('Invalid value for "client_max_window_bits"');
163
- }
164
- if (typeof this._options.clientMaxWindowBits === 'number' &&
165
- (!params.client_max_window_bits || params.client_max_window_bits > this._options.clientMaxWindowBits)) {
166
- throw new Error('Invalid value for "client_max_window_bits"');
167
- }
168
- }
169
- return params;
170
- }
171
-
172
- /**
173
- * Normalize extensions parameters
174
- *
175
- * @api private
176
- */
177
-
178
- normalizeParams (paramsList) {
179
- return paramsList.map((params) => {
180
- Object.keys(params).forEach((key) => {
181
- var value = params[key];
182
- if (value.length > 1) {
183
- throw new Error('Multiple extension parameters for ' + key);
184
- }
185
-
186
- value = value[0];
187
-
188
- switch (key) {
189
- case 'server_no_context_takeover':
190
- case 'client_no_context_takeover':
191
- if (value !== true) {
192
- throw new Error(`invalid extension parameter value for ${key} (${value})`);
193
- }
194
- params[key] = true;
195
- break;
196
- case 'server_max_window_bits':
197
- case 'client_max_window_bits':
198
- if (typeof value === 'string') {
199
- value = parseInt(value, 10);
200
- if (!~AVAILABLE_WINDOW_BITS.indexOf(value)) {
201
- throw new Error(`invalid extension parameter value for ${key} (${value})`);
202
- }
203
- }
204
- if (!this._isServer && value === true) {
205
- throw new Error(`Missing extension parameter value for ${key}`);
206
- }
207
- params[key] = value;
208
- break;
209
- default:
210
- throw new Error(`Not defined extension parameter (${key})`);
211
- }
212
- });
213
- return params;
214
- });
215
- }
216
-
217
- /**
218
- * Decompress data.
219
- *
220
- * @param {Buffer} data Compressed data
221
- * @param {Boolean} fin Specifies whether or not this is the last fragment
222
- * @param {Function} callback Callback
223
- * @public
224
- */
225
- decompress (data, fin, callback) {
226
- const endpoint = this._isServer ? 'client' : 'server';
227
-
228
- if (!this._inflate) {
229
- const maxWindowBits = this.params[`${endpoint}_max_window_bits`];
230
- this._inflate = zlib.createInflateRaw({
231
- windowBits: typeof maxWindowBits === 'number' ? maxWindowBits : DEFAULT_WINDOW_BITS
232
- });
233
- }
234
- this._inflate.writeInProgress = true;
235
-
236
- var totalLength = 0;
237
- const buffers = [];
238
- var err;
239
-
240
- const onData = (data) => {
241
- totalLength += data.length;
242
- if (this._maxPayload < 1 || totalLength <= this._maxPayload) {
243
- return buffers.push(data);
244
- }
245
-
246
- err = new Error('max payload size exceeded');
247
- err.closeCode = 1009;
248
- this._inflate.reset();
249
- };
250
-
251
- const onError = (err) => {
252
- cleanup();
253
- callback(err);
254
- };
255
-
256
- const cleanup = () => {
257
- if (!this._inflate) return;
258
-
259
- this._inflate.removeListener('error', onError);
260
- this._inflate.removeListener('data', onData);
261
- this._inflate.writeInProgress = false;
262
-
263
- if (
264
- fin && this.params[`${endpoint}_no_context_takeover`] ||
265
- this._inflate.pendingClose
266
- ) {
267
- this._inflate.close();
268
- this._inflate = null;
269
- }
270
- };
271
-
272
- this._inflate.on('error', onError).on('data', onData);
273
- this._inflate.write(data);
274
- if (fin) this._inflate.write(TRAILER);
275
-
276
- this._inflate.flush(() => {
277
- cleanup();
278
- if (err) callback(err);
279
- else callback(null, Buffer.concat(buffers, totalLength));
280
- });
281
- }
282
-
283
- /**
284
- * Compress message
285
- *
286
- * @api public
287
- */
288
-
289
- compress (data, fin, callback) {
290
- if (!data || data.length === 0) {
291
- return callback(null, EMPTY_BLOCK);
292
- }
293
-
294
- var endpoint = this._isServer ? 'server' : 'client';
295
-
296
- if (!this._deflate) {
297
- var maxWindowBits = this.params[endpoint + '_max_window_bits'];
298
- this._deflate = zlib.createDeflateRaw({
299
- flush: zlib.Z_SYNC_FLUSH,
300
- windowBits: typeof maxWindowBits === 'number' ? maxWindowBits : DEFAULT_WINDOW_BITS,
301
- memLevel: this._options.memLevel || DEFAULT_MEM_LEVEL
302
- });
303
- }
304
- this._deflate.writeInProgress = true;
305
-
306
- const buffers = [];
307
-
308
- const onData = (data) => buffers.push(data);
309
- const onError = (err) => {
310
- cleanup();
311
- callback(err);
312
- };
313
- const cleanup = () => {
314
- if (!this._deflate) return;
315
- this._deflate.removeListener('error', onError);
316
- this._deflate.removeListener('data', onData);
317
- this._deflate.writeInProgress = false;
318
- if ((fin && this.params[endpoint + '_no_context_takeover']) || this._deflate.pendingClose) {
319
- this._deflate.close();
320
- this._deflate = null;
321
- }
322
- };
323
-
324
- this._deflate.on('error', onError).on('data', onData);
325
- this._deflate.write(data);
326
- this._deflate.flush(zlib.Z_SYNC_FLUSH, () => {
327
- cleanup();
328
- var data = Buffer.concat(buffers);
329
- if (fin) {
330
- data = data.slice(0, data.length - 4);
331
- }
332
- callback(null, data);
333
- });
334
- }
335
- }
336
-
337
- PerMessageDeflate.extensionName = 'permessage-deflate';
338
-
339
- module.exports = PerMessageDeflate;