opal 1.6.1 → 1.7.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (212) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/build.yml +17 -0
  3. data/Gemfile +1 -0
  4. data/HACKING.md +47 -26
  5. data/UNRELEASED.md +28 -0
  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 +91 -52
  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;