1
0
Fork 0
mirror of https://github.com/rails/rails.git synced 2022-11-09 12:12:34 -05:00
rails--rails/actioncable/app/assets/javascripts/action_cable.js

489 lines
18 KiB
JavaScript
Raw Normal View History

Convert ActionCable javascript to ES2015 modules with modern build environment We've replaced the sprockets `//= require` directives with ES2015 imports. As a result, the ActionCable javascript can now be compiled with rollup (like ActiveStorage already is). - Rename action_cable/index.js.erb -> action_cable/index.js - Add rake task to generate a javascript module of the ActionCable::INTERNAL ruby hash This will allow us to get rid of ERB from the actioncable javascript, since it is only used to interpolate ActionCable::INTERNAL.to_json. - Import INTERNAL directly in ActionCable Connection module This is necessary to remove a load-order dependency conflict in the rollup-compiled build. Using ActionCable.INTERNAL would result in a runtime error: ``` TypeError: Cannot read property 'INTERNAL' of undefined ``` because ActionCable.INTERNAL is not set before the Connection module is executed. All other ActionCable.* references are executed inside of the body of a function, so there is no load-order dependency there. - Add eslint and eslint-plugin-import devDependencies to actioncable These will be used to add a linting setup to actioncable like the one in activestorage. - Add .eslintrc to actioncable This lint configuration was copied from activestorage - Add lint script to actioncable This is the same as the lint script in activestorage - Add babel-core, babel-plugin-external-helpers, and babel-preset-env devDependencies to actioncable These will be used to add ES2015 transpilation support to actioncable like we have in activestorage. - Add .babelrc to actioncable This configuration was copied from activestorage - Enable loose mode in ActionCable's babel config This generates a smaller bundle when compiled - Add rollup devDependencies to actioncable These will be used to add a modern build pipeline to actioncable like the one in activestorage. - Add rollup config to actioncable This is essentially the same as the rollup config from activestorage - Add prebuild and build scripts to actioncable package These scripts were copied from activestorage - Invoke code generation task as part of actioncable's prebuild script This will guarantee that the action_cable/internal.js module is available at build time (which is important, because two other modules now depend on it). - Update actioncable package to reference the rollup-compiled files Now that we have a fully functional rollup pipeline in actioncable, we can use the compiled output in our npm package. - Remove build section from ActionCable blade config Now that rollup is responsible for building ActionCable, we can remove that responsibility from Blade. - Remove assets:compile and assets:verify tasks from ActionCable Now that we've added a compiled ActionCable bundle to version control, we don't need to compile and verify it at publish-time. (We're following the pattern set in ActiveStorage.) - Include compiled ActionCable javascript bundle in published gem This is necessary to maintain support for depending on the ActionCable javascript through the Sprockets asset pipeline. - Add compiled ActionCable bundle to version control This mirrors what we do in ActiveStorage, and allows ActionCable to continue to be consumed via the sprockets-based asset pipeline when using a git source instead of a published version of the gem.
2018-01-21 02:33:32 -05:00
(function(global, factory) {
Remove circular dependency warnings in ActionCable javascript and publish source modules with fine-grained exports (#34370) * Replace several ActionCable.* references with finer-grained imports This reduces the number of circular dependencies among the module imports from 4: ``` (!) Circular dependency: app/javascript/action_cable/index.js -> app/javascript/action_cable/connection.js -> app/javascript/action_cable/index.js (!) Circular dependency: app/javascript/action_cable/index.js -> app/javascript/action_cable/connection_monitor.js -> app/javascript/action_cable/index.js (!) Circular dependency: app/javascript/action_cable/index.js -> app/javascript/action_cable/consumer.js -> app/javascript/action_cable/index.js (!) Circular dependency: app/javascript/action_cable/index.js -> app/javascript/action_cable/subscriptions.js -> app/javascript/action_cable/index.js ``` to 2: ``` (!) Circular dependency: app/javascript/action_cable/index.js -> app/javascript/action_cable/connection.js -> app/javascript/action_cable/index.js (!) Circular dependency: app/javascript/action_cable/index.js -> app/javascript/action_cable/connection.js -> app/javascript/action_cable/connection_monitor.js -> app/javascript/action_cable/index.js ``` * Remove tests that only test javascript object property assignment These tests really only assert that you can assign a property to the ActionCable global object. That's true for pretty much any object in javascript (it would only be false if the object has been frozen, or has explicitly set some properties to be nonconfigurable). * Refactor ActionCable to provide individual named exports By providing individual named exports rather than a default export which is an object with all of those properties, we enable applications to only import the functions they need: any unused functions will be removed via tree shaking. Additionally, this restructuring removes the remaining circular dependencies by extracting the separate adapters and logger modules, so there are now no warnings when compiling the ActionCable bundle. Note: This produces two small breaking API changes: - The `ActionCable.WebSocket` getter and setter would be moved to `ActionCable.adapters.WebSocket`. If a user is currently configuring this, when upgrading they'd need to either add a delegated getter/setter themselves, or change it like this: ```diff - ActionCable.WebSocket = MyWebSocket + ActionCable.adapters.WebSocket = MyWebSocket ``` Applications which don't change the WebSocket adapter would not need any changes for this when upgrading. - Similarly, the `ActionCable.logger` getter and setter would be moved to `ActionCable.adapters.logger`. If a user is currently configuring this, when upgrading they'd need to either add a delegated getter/setter themselves, or change it like this: ```diff - ActionCable.logger = myLogger + ActionCable.adapters.logger = myLogger ``` Applications which don't change the logger would not need any changes for this when upgrading. These two aspects of the public API have to change because there's no way to export a property setter for `WebSocket` (or `logger`) such that this: ```js import ActionCable from "actioncable" ActionCable.WebSocket = MyWebSocket ``` would actually update `adapters.WebSocket`. (We can only offer that if we have two separate source files like if `index.js` uses `import * as ActionCable from "./action_cable" and then exports a wrapper which has delegated getters and setters for those properties.) This API change is very minor - it should be easy for applications to add the `adapters.` prefix in their assignments or to patch in delegated setters. And especially because most applications in the wild are not ever changing the default value of `ActionCable.WebSocket` or `ActionCable.logger` (because the default values are perfect), this API breakage is worth the tree-shaking benefits we gain. * Include source code in published actioncable npm package This allows actioncable users to ship smaller javascript bundles to visitors using modern browsers, as demonstrated in this repository: https://github.com/rmacklin/actioncable-es2015-build-example In that example, the bundle shrinks by 2.8K (25.2%) when you simply change the actioncable import to point to the untranspiled src. If you go a step further, like this: ``` diff --git a/app/scripts/main.js b/app/scripts/main.js index 17bc031..1a2b2e0 100644 --- a/app/scripts/main.js +++ b/app/scripts/main.js @@ -1,6 +1,6 @@ -import ActionCable from 'actioncable'; +import * as ActionCable from 'actioncable'; let cable = ActionCable.createConsumer('wss://cable.example.com'); cable.subscriptions.create('AppearanceChannel', { ``` then the bundle shrinks by 3.6K (31.7%)! In addition to allowing smaller bundles for those who ship untranspiled code to modern browsers, including the source code in the published package can be useful in other ways: 1. Users can import individual modules rather than the whole library 2. As a result of (1), users can also monkey patch parts of actioncable by importing the relevant module, modifying the exported object, and then importing the rest of actioncable (which would then use the patched object). Note: This is the same enhancement that we made to activestorage in c0368ad090b79c19300a4aa133bb188b2d9ab611 * Remove unused commonjs & resolve plugins from ActionCable rollup config These were added when we copied the rollup config from ActiveStorage, but ActionCable does not have any commonjs dependencies (it doesn't have any external dependencies at all), so these plugins are unnecessary here * Change ActionCable.startDebugging() -> ActionCable.logger.enabled=true and ActionCable.stopDebugging() -> ActionCable.logger.enabled=false This API is simpler and more clearly describes what it does * Change Travis configuration to run yarn install at the root for ActionCable builds This is necessary now that the repository is using Yarn Workspaces
2018-12-01 16:25:02 -05:00
typeof exports === "object" && typeof module !== "undefined" ? factory(exports) : typeof define === "function" && define.amd ? define([ "exports" ], factory) : factory(global.ActionCable = {});
})(this, function(exports) {
Convert ActionCable javascript to ES2015 modules with modern build environment We've replaced the sprockets `//= require` directives with ES2015 imports. As a result, the ActionCable javascript can now be compiled with rollup (like ActiveStorage already is). - Rename action_cable/index.js.erb -> action_cable/index.js - Add rake task to generate a javascript module of the ActionCable::INTERNAL ruby hash This will allow us to get rid of ERB from the actioncable javascript, since it is only used to interpolate ActionCable::INTERNAL.to_json. - Import INTERNAL directly in ActionCable Connection module This is necessary to remove a load-order dependency conflict in the rollup-compiled build. Using ActionCable.INTERNAL would result in a runtime error: ``` TypeError: Cannot read property 'INTERNAL' of undefined ``` because ActionCable.INTERNAL is not set before the Connection module is executed. All other ActionCable.* references are executed inside of the body of a function, so there is no load-order dependency there. - Add eslint and eslint-plugin-import devDependencies to actioncable These will be used to add a linting setup to actioncable like the one in activestorage. - Add .eslintrc to actioncable This lint configuration was copied from activestorage - Add lint script to actioncable This is the same as the lint script in activestorage - Add babel-core, babel-plugin-external-helpers, and babel-preset-env devDependencies to actioncable These will be used to add ES2015 transpilation support to actioncable like we have in activestorage. - Add .babelrc to actioncable This configuration was copied from activestorage - Enable loose mode in ActionCable's babel config This generates a smaller bundle when compiled - Add rollup devDependencies to actioncable These will be used to add a modern build pipeline to actioncable like the one in activestorage. - Add rollup config to actioncable This is essentially the same as the rollup config from activestorage - Add prebuild and build scripts to actioncable package These scripts were copied from activestorage - Invoke code generation task as part of actioncable's prebuild script This will guarantee that the action_cable/internal.js module is available at build time (which is important, because two other modules now depend on it). - Update actioncable package to reference the rollup-compiled files Now that we have a fully functional rollup pipeline in actioncable, we can use the compiled output in our npm package. - Remove build section from ActionCable blade config Now that rollup is responsible for building ActionCable, we can remove that responsibility from Blade. - Remove assets:compile and assets:verify tasks from ActionCable Now that we've added a compiled ActionCable bundle to version control, we don't need to compile and verify it at publish-time. (We're following the pattern set in ActiveStorage.) - Include compiled ActionCable javascript bundle in published gem This is necessary to maintain support for depending on the ActionCable javascript through the Sprockets asset pipeline. - Add compiled ActionCable bundle to version control This mirrors what we do in ActiveStorage, and allows ActionCable to continue to be consumed via the sprockets-based asset pipeline when using a git source instead of a published version of the gem.
2018-01-21 02:33:32 -05:00
"use strict";
Remove circular dependency warnings in ActionCable javascript and publish source modules with fine-grained exports (#34370) * Replace several ActionCable.* references with finer-grained imports This reduces the number of circular dependencies among the module imports from 4: ``` (!) Circular dependency: app/javascript/action_cable/index.js -> app/javascript/action_cable/connection.js -> app/javascript/action_cable/index.js (!) Circular dependency: app/javascript/action_cable/index.js -> app/javascript/action_cable/connection_monitor.js -> app/javascript/action_cable/index.js (!) Circular dependency: app/javascript/action_cable/index.js -> app/javascript/action_cable/consumer.js -> app/javascript/action_cable/index.js (!) Circular dependency: app/javascript/action_cable/index.js -> app/javascript/action_cable/subscriptions.js -> app/javascript/action_cable/index.js ``` to 2: ``` (!) Circular dependency: app/javascript/action_cable/index.js -> app/javascript/action_cable/connection.js -> app/javascript/action_cable/index.js (!) Circular dependency: app/javascript/action_cable/index.js -> app/javascript/action_cable/connection.js -> app/javascript/action_cable/connection_monitor.js -> app/javascript/action_cable/index.js ``` * Remove tests that only test javascript object property assignment These tests really only assert that you can assign a property to the ActionCable global object. That's true for pretty much any object in javascript (it would only be false if the object has been frozen, or has explicitly set some properties to be nonconfigurable). * Refactor ActionCable to provide individual named exports By providing individual named exports rather than a default export which is an object with all of those properties, we enable applications to only import the functions they need: any unused functions will be removed via tree shaking. Additionally, this restructuring removes the remaining circular dependencies by extracting the separate adapters and logger modules, so there are now no warnings when compiling the ActionCable bundle. Note: This produces two small breaking API changes: - The `ActionCable.WebSocket` getter and setter would be moved to `ActionCable.adapters.WebSocket`. If a user is currently configuring this, when upgrading they'd need to either add a delegated getter/setter themselves, or change it like this: ```diff - ActionCable.WebSocket = MyWebSocket + ActionCable.adapters.WebSocket = MyWebSocket ``` Applications which don't change the WebSocket adapter would not need any changes for this when upgrading. - Similarly, the `ActionCable.logger` getter and setter would be moved to `ActionCable.adapters.logger`. If a user is currently configuring this, when upgrading they'd need to either add a delegated getter/setter themselves, or change it like this: ```diff - ActionCable.logger = myLogger + ActionCable.adapters.logger = myLogger ``` Applications which don't change the logger would not need any changes for this when upgrading. These two aspects of the public API have to change because there's no way to export a property setter for `WebSocket` (or `logger`) such that this: ```js import ActionCable from "actioncable" ActionCable.WebSocket = MyWebSocket ``` would actually update `adapters.WebSocket`. (We can only offer that if we have two separate source files like if `index.js` uses `import * as ActionCable from "./action_cable" and then exports a wrapper which has delegated getters and setters for those properties.) This API change is very minor - it should be easy for applications to add the `adapters.` prefix in their assignments or to patch in delegated setters. And especially because most applications in the wild are not ever changing the default value of `ActionCable.WebSocket` or `ActionCable.logger` (because the default values are perfect), this API breakage is worth the tree-shaking benefits we gain. * Include source code in published actioncable npm package This allows actioncable users to ship smaller javascript bundles to visitors using modern browsers, as demonstrated in this repository: https://github.com/rmacklin/actioncable-es2015-build-example In that example, the bundle shrinks by 2.8K (25.2%) when you simply change the actioncable import to point to the untranspiled src. If you go a step further, like this: ``` diff --git a/app/scripts/main.js b/app/scripts/main.js index 17bc031..1a2b2e0 100644 --- a/app/scripts/main.js +++ b/app/scripts/main.js @@ -1,6 +1,6 @@ -import ActionCable from 'actioncable'; +import * as ActionCable from 'actioncable'; let cable = ActionCable.createConsumer('wss://cable.example.com'); cable.subscriptions.create('AppearanceChannel', { ``` then the bundle shrinks by 3.6K (31.7%)! In addition to allowing smaller bundles for those who ship untranspiled code to modern browsers, including the source code in the published package can be useful in other ways: 1. Users can import individual modules rather than the whole library 2. As a result of (1), users can also monkey patch parts of actioncable by importing the relevant module, modifying the exported object, and then importing the rest of actioncable (which would then use the patched object). Note: This is the same enhancement that we made to activestorage in c0368ad090b79c19300a4aa133bb188b2d9ab611 * Remove unused commonjs & resolve plugins from ActionCable rollup config These were added when we copied the rollup config from ActiveStorage, but ActionCable does not have any commonjs dependencies (it doesn't have any external dependencies at all), so these plugins are unnecessary here * Change ActionCable.startDebugging() -> ActionCable.logger.enabled=true and ActionCable.stopDebugging() -> ActionCable.logger.enabled=false This API is simpler and more clearly describes what it does * Change Travis configuration to run yarn install at the root for ActionCable builds This is necessary now that the repository is using Yarn Workspaces
2018-12-01 16:25:02 -05:00
var adapters = {
logger: window.console,
WebSocket: window.WebSocket
};
var logger = {
log: function log() {
if (this.enabled) {
var _adapters$logger;
for (var _len = arguments.length, messages = Array(_len), _key = 0; _key < _len; _key++) {
messages[_key] = arguments[_key];
}
messages.push(Date.now());
(_adapters$logger = adapters.logger).log.apply(_adapters$logger, [ "[ActionCable]" ].concat(messages));
}
}
Convert ActionCable javascript to ES2015 modules with modern build environment We've replaced the sprockets `//= require` directives with ES2015 imports. As a result, the ActionCable javascript can now be compiled with rollup (like ActiveStorage already is). - Rename action_cable/index.js.erb -> action_cable/index.js - Add rake task to generate a javascript module of the ActionCable::INTERNAL ruby hash This will allow us to get rid of ERB from the actioncable javascript, since it is only used to interpolate ActionCable::INTERNAL.to_json. - Import INTERNAL directly in ActionCable Connection module This is necessary to remove a load-order dependency conflict in the rollup-compiled build. Using ActionCable.INTERNAL would result in a runtime error: ``` TypeError: Cannot read property 'INTERNAL' of undefined ``` because ActionCable.INTERNAL is not set before the Connection module is executed. All other ActionCable.* references are executed inside of the body of a function, so there is no load-order dependency there. - Add eslint and eslint-plugin-import devDependencies to actioncable These will be used to add a linting setup to actioncable like the one in activestorage. - Add .eslintrc to actioncable This lint configuration was copied from activestorage - Add lint script to actioncable This is the same as the lint script in activestorage - Add babel-core, babel-plugin-external-helpers, and babel-preset-env devDependencies to actioncable These will be used to add ES2015 transpilation support to actioncable like we have in activestorage. - Add .babelrc to actioncable This configuration was copied from activestorage - Enable loose mode in ActionCable's babel config This generates a smaller bundle when compiled - Add rollup devDependencies to actioncable These will be used to add a modern build pipeline to actioncable like the one in activestorage. - Add rollup config to actioncable This is essentially the same as the rollup config from activestorage - Add prebuild and build scripts to actioncable package These scripts were copied from activestorage - Invoke code generation task as part of actioncable's prebuild script This will guarantee that the action_cable/internal.js module is available at build time (which is important, because two other modules now depend on it). - Update actioncable package to reference the rollup-compiled files Now that we have a fully functional rollup pipeline in actioncable, we can use the compiled output in our npm package. - Remove build section from ActionCable blade config Now that rollup is responsible for building ActionCable, we can remove that responsibility from Blade. - Remove assets:compile and assets:verify tasks from ActionCable Now that we've added a compiled ActionCable bundle to version control, we don't need to compile and verify it at publish-time. (We're following the pattern set in ActiveStorage.) - Include compiled ActionCable javascript bundle in published gem This is necessary to maintain support for depending on the ActionCable javascript through the Sprockets asset pipeline. - Add compiled ActionCable bundle to version control This mirrors what we do in ActiveStorage, and allows ActionCable to continue to be consumed via the sprockets-based asset pipeline when using a git source instead of a published version of the gem.
2018-01-21 02:33:32 -05:00
};
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function(obj) {
return typeof obj;
} : function(obj) {
return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
};
var classCallCheck = function(instance, Constructor) {
if (!(instance instanceof Constructor)) {
throw new TypeError("Cannot call a class as a function");
}
};
Remove circular dependency warnings in ActionCable javascript and publish source modules with fine-grained exports (#34370) * Replace several ActionCable.* references with finer-grained imports This reduces the number of circular dependencies among the module imports from 4: ``` (!) Circular dependency: app/javascript/action_cable/index.js -> app/javascript/action_cable/connection.js -> app/javascript/action_cable/index.js (!) Circular dependency: app/javascript/action_cable/index.js -> app/javascript/action_cable/connection_monitor.js -> app/javascript/action_cable/index.js (!) Circular dependency: app/javascript/action_cable/index.js -> app/javascript/action_cable/consumer.js -> app/javascript/action_cable/index.js (!) Circular dependency: app/javascript/action_cable/index.js -> app/javascript/action_cable/subscriptions.js -> app/javascript/action_cable/index.js ``` to 2: ``` (!) Circular dependency: app/javascript/action_cable/index.js -> app/javascript/action_cable/connection.js -> app/javascript/action_cable/index.js (!) Circular dependency: app/javascript/action_cable/index.js -> app/javascript/action_cable/connection.js -> app/javascript/action_cable/connection_monitor.js -> app/javascript/action_cable/index.js ``` * Remove tests that only test javascript object property assignment These tests really only assert that you can assign a property to the ActionCable global object. That's true for pretty much any object in javascript (it would only be false if the object has been frozen, or has explicitly set some properties to be nonconfigurable). * Refactor ActionCable to provide individual named exports By providing individual named exports rather than a default export which is an object with all of those properties, we enable applications to only import the functions they need: any unused functions will be removed via tree shaking. Additionally, this restructuring removes the remaining circular dependencies by extracting the separate adapters and logger modules, so there are now no warnings when compiling the ActionCable bundle. Note: This produces two small breaking API changes: - The `ActionCable.WebSocket` getter and setter would be moved to `ActionCable.adapters.WebSocket`. If a user is currently configuring this, when upgrading they'd need to either add a delegated getter/setter themselves, or change it like this: ```diff - ActionCable.WebSocket = MyWebSocket + ActionCable.adapters.WebSocket = MyWebSocket ``` Applications which don't change the WebSocket adapter would not need any changes for this when upgrading. - Similarly, the `ActionCable.logger` getter and setter would be moved to `ActionCable.adapters.logger`. If a user is currently configuring this, when upgrading they'd need to either add a delegated getter/setter themselves, or change it like this: ```diff - ActionCable.logger = myLogger + ActionCable.adapters.logger = myLogger ``` Applications which don't change the logger would not need any changes for this when upgrading. These two aspects of the public API have to change because there's no way to export a property setter for `WebSocket` (or `logger`) such that this: ```js import ActionCable from "actioncable" ActionCable.WebSocket = MyWebSocket ``` would actually update `adapters.WebSocket`. (We can only offer that if we have two separate source files like if `index.js` uses `import * as ActionCable from "./action_cable" and then exports a wrapper which has delegated getters and setters for those properties.) This API change is very minor - it should be easy for applications to add the `adapters.` prefix in their assignments or to patch in delegated setters. And especially because most applications in the wild are not ever changing the default value of `ActionCable.WebSocket` or `ActionCable.logger` (because the default values are perfect), this API breakage is worth the tree-shaking benefits we gain. * Include source code in published actioncable npm package This allows actioncable users to ship smaller javascript bundles to visitors using modern browsers, as demonstrated in this repository: https://github.com/rmacklin/actioncable-es2015-build-example In that example, the bundle shrinks by 2.8K (25.2%) when you simply change the actioncable import to point to the untranspiled src. If you go a step further, like this: ``` diff --git a/app/scripts/main.js b/app/scripts/main.js index 17bc031..1a2b2e0 100644 --- a/app/scripts/main.js +++ b/app/scripts/main.js @@ -1,6 +1,6 @@ -import ActionCable from 'actioncable'; +import * as ActionCable from 'actioncable'; let cable = ActionCable.createConsumer('wss://cable.example.com'); cable.subscriptions.create('AppearanceChannel', { ``` then the bundle shrinks by 3.6K (31.7%)! In addition to allowing smaller bundles for those who ship untranspiled code to modern browsers, including the source code in the published package can be useful in other ways: 1. Users can import individual modules rather than the whole library 2. As a result of (1), users can also monkey patch parts of actioncable by importing the relevant module, modifying the exported object, and then importing the rest of actioncable (which would then use the patched object). Note: This is the same enhancement that we made to activestorage in c0368ad090b79c19300a4aa133bb188b2d9ab611 * Remove unused commonjs & resolve plugins from ActionCable rollup config These were added when we copied the rollup config from ActiveStorage, but ActionCable does not have any commonjs dependencies (it doesn't have any external dependencies at all), so these plugins are unnecessary here * Change ActionCable.startDebugging() -> ActionCable.logger.enabled=true and ActionCable.stopDebugging() -> ActionCable.logger.enabled=false This API is simpler and more clearly describes what it does * Change Travis configuration to run yarn install at the root for ActionCable builds This is necessary now that the repository is using Yarn Workspaces
2018-12-01 16:25:02 -05:00
var now = function now() {
return new Date().getTime();
};
var secondsSince = function secondsSince(time) {
return (now() - time) / 1e3;
};
var clamp = function clamp(number, min, max) {
return Math.max(min, Math.min(max, number));
};
var ConnectionMonitor = function() {
function ConnectionMonitor(connection) {
classCallCheck(this, ConnectionMonitor);
this.visibilityDidChange = this.visibilityDidChange.bind(this);
this.connection = connection;
this.reconnectAttempts = 0;
}
ConnectionMonitor.prototype.start = function start() {
if (!this.isRunning()) {
this.startedAt = now();
delete this.stoppedAt;
this.startPolling();
document.addEventListener("visibilitychange", this.visibilityDidChange);
logger.log("ConnectionMonitor started. pollInterval = " + this.getPollInterval() + " ms");
}
};
ConnectionMonitor.prototype.stop = function stop() {
if (this.isRunning()) {
this.stoppedAt = now();
this.stopPolling();
document.removeEventListener("visibilitychange", this.visibilityDidChange);
logger.log("ConnectionMonitor stopped");
}
};
ConnectionMonitor.prototype.isRunning = function isRunning() {
return this.startedAt && !this.stoppedAt;
};
ConnectionMonitor.prototype.recordPing = function recordPing() {
this.pingedAt = now();
};
ConnectionMonitor.prototype.recordConnect = function recordConnect() {
this.reconnectAttempts = 0;
this.recordPing();
delete this.disconnectedAt;
logger.log("ConnectionMonitor recorded connect");
};
ConnectionMonitor.prototype.recordDisconnect = function recordDisconnect() {
this.disconnectedAt = now();
logger.log("ConnectionMonitor recorded disconnect");
};
ConnectionMonitor.prototype.startPolling = function startPolling() {
this.stopPolling();
this.poll();
};
ConnectionMonitor.prototype.stopPolling = function stopPolling() {
clearTimeout(this.pollTimeout);
};
ConnectionMonitor.prototype.poll = function poll() {
var _this = this;
this.pollTimeout = setTimeout(function() {
_this.reconnectIfStale();
_this.poll();
}, this.getPollInterval());
};
ConnectionMonitor.prototype.getPollInterval = function getPollInterval() {
var _constructor$pollInte = this.constructor.pollInterval, min = _constructor$pollInte.min, max = _constructor$pollInte.max, multiplier = _constructor$pollInte.multiplier;
var interval = multiplier * Math.log(this.reconnectAttempts + 1);
return Math.round(clamp(interval, min, max) * 1e3);
};
ConnectionMonitor.prototype.reconnectIfStale = function reconnectIfStale() {
if (this.connectionIsStale()) {
logger.log("ConnectionMonitor detected stale connection. reconnectAttempts = " + this.reconnectAttempts + ", pollInterval = " + this.getPollInterval() + " ms, time disconnected = " + secondsSince(this.disconnectedAt) + " s, stale threshold = " + this.constructor.staleThreshold + " s");
this.reconnectAttempts++;
if (this.disconnectedRecently()) {
logger.log("ConnectionMonitor skipping reopening recent disconnect");
} else {
logger.log("ConnectionMonitor reopening");
this.connection.reopen();
}
}
};
ConnectionMonitor.prototype.connectionIsStale = function connectionIsStale() {
return secondsSince(this.pingedAt ? this.pingedAt : this.startedAt) > this.constructor.staleThreshold;
};
ConnectionMonitor.prototype.disconnectedRecently = function disconnectedRecently() {
return this.disconnectedAt && secondsSince(this.disconnectedAt) < this.constructor.staleThreshold;
};
ConnectionMonitor.prototype.visibilityDidChange = function visibilityDidChange() {
var _this2 = this;
if (document.visibilityState === "visible") {
setTimeout(function() {
if (_this2.connectionIsStale() || !_this2.connection.isOpen()) {
logger.log("ConnectionMonitor reopening stale connection on visibilitychange. visbilityState = " + document.visibilityState);
_this2.connection.reopen();
}
}, 200);
}
};
return ConnectionMonitor;
}();
ConnectionMonitor.pollInterval = {
min: 3,
max: 30,
multiplier: 5
};
ConnectionMonitor.staleThreshold = 6;
var INTERNAL = {
message_types: {
welcome: "welcome",
disconnect: "disconnect",
Remove circular dependency warnings in ActionCable javascript and publish source modules with fine-grained exports (#34370) * Replace several ActionCable.* references with finer-grained imports This reduces the number of circular dependencies among the module imports from 4: ``` (!) Circular dependency: app/javascript/action_cable/index.js -> app/javascript/action_cable/connection.js -> app/javascript/action_cable/index.js (!) Circular dependency: app/javascript/action_cable/index.js -> app/javascript/action_cable/connection_monitor.js -> app/javascript/action_cable/index.js (!) Circular dependency: app/javascript/action_cable/index.js -> app/javascript/action_cable/consumer.js -> app/javascript/action_cable/index.js (!) Circular dependency: app/javascript/action_cable/index.js -> app/javascript/action_cable/subscriptions.js -> app/javascript/action_cable/index.js ``` to 2: ``` (!) Circular dependency: app/javascript/action_cable/index.js -> app/javascript/action_cable/connection.js -> app/javascript/action_cable/index.js (!) Circular dependency: app/javascript/action_cable/index.js -> app/javascript/action_cable/connection.js -> app/javascript/action_cable/connection_monitor.js -> app/javascript/action_cable/index.js ``` * Remove tests that only test javascript object property assignment These tests really only assert that you can assign a property to the ActionCable global object. That's true for pretty much any object in javascript (it would only be false if the object has been frozen, or has explicitly set some properties to be nonconfigurable). * Refactor ActionCable to provide individual named exports By providing individual named exports rather than a default export which is an object with all of those properties, we enable applications to only import the functions they need: any unused functions will be removed via tree shaking. Additionally, this restructuring removes the remaining circular dependencies by extracting the separate adapters and logger modules, so there are now no warnings when compiling the ActionCable bundle. Note: This produces two small breaking API changes: - The `ActionCable.WebSocket` getter and setter would be moved to `ActionCable.adapters.WebSocket`. If a user is currently configuring this, when upgrading they'd need to either add a delegated getter/setter themselves, or change it like this: ```diff - ActionCable.WebSocket = MyWebSocket + ActionCable.adapters.WebSocket = MyWebSocket ``` Applications which don't change the WebSocket adapter would not need any changes for this when upgrading. - Similarly, the `ActionCable.logger` getter and setter would be moved to `ActionCable.adapters.logger`. If a user is currently configuring this, when upgrading they'd need to either add a delegated getter/setter themselves, or change it like this: ```diff - ActionCable.logger = myLogger + ActionCable.adapters.logger = myLogger ``` Applications which don't change the logger would not need any changes for this when upgrading. These two aspects of the public API have to change because there's no way to export a property setter for `WebSocket` (or `logger`) such that this: ```js import ActionCable from "actioncable" ActionCable.WebSocket = MyWebSocket ``` would actually update `adapters.WebSocket`. (We can only offer that if we have two separate source files like if `index.js` uses `import * as ActionCable from "./action_cable" and then exports a wrapper which has delegated getters and setters for those properties.) This API change is very minor - it should be easy for applications to add the `adapters.` prefix in their assignments or to patch in delegated setters. And especially because most applications in the wild are not ever changing the default value of `ActionCable.WebSocket` or `ActionCable.logger` (because the default values are perfect), this API breakage is worth the tree-shaking benefits we gain. * Include source code in published actioncable npm package This allows actioncable users to ship smaller javascript bundles to visitors using modern browsers, as demonstrated in this repository: https://github.com/rmacklin/actioncable-es2015-build-example In that example, the bundle shrinks by 2.8K (25.2%) when you simply change the actioncable import to point to the untranspiled src. If you go a step further, like this: ``` diff --git a/app/scripts/main.js b/app/scripts/main.js index 17bc031..1a2b2e0 100644 --- a/app/scripts/main.js +++ b/app/scripts/main.js @@ -1,6 +1,6 @@ -import ActionCable from 'actioncable'; +import * as ActionCable from 'actioncable'; let cable = ActionCable.createConsumer('wss://cable.example.com'); cable.subscriptions.create('AppearanceChannel', { ``` then the bundle shrinks by 3.6K (31.7%)! In addition to allowing smaller bundles for those who ship untranspiled code to modern browsers, including the source code in the published package can be useful in other ways: 1. Users can import individual modules rather than the whole library 2. As a result of (1), users can also monkey patch parts of actioncable by importing the relevant module, modifying the exported object, and then importing the rest of actioncable (which would then use the patched object). Note: This is the same enhancement that we made to activestorage in c0368ad090b79c19300a4aa133bb188b2d9ab611 * Remove unused commonjs & resolve plugins from ActionCable rollup config These were added when we copied the rollup config from ActiveStorage, but ActionCable does not have any commonjs dependencies (it doesn't have any external dependencies at all), so these plugins are unnecessary here * Change ActionCable.startDebugging() -> ActionCable.logger.enabled=true and ActionCable.stopDebugging() -> ActionCable.logger.enabled=false This API is simpler and more clearly describes what it does * Change Travis configuration to run yarn install at the root for ActionCable builds This is necessary now that the repository is using Yarn Workspaces
2018-12-01 16:25:02 -05:00
ping: "ping",
confirmation: "confirm_subscription",
rejection: "reject_subscription"
},
disconnect_reasons: {
unauthorized: "unauthorized",
invalid_request: "invalid_request",
server_restart: "server_restart"
},
Remove circular dependency warnings in ActionCable javascript and publish source modules with fine-grained exports (#34370) * Replace several ActionCable.* references with finer-grained imports This reduces the number of circular dependencies among the module imports from 4: ``` (!) Circular dependency: app/javascript/action_cable/index.js -> app/javascript/action_cable/connection.js -> app/javascript/action_cable/index.js (!) Circular dependency: app/javascript/action_cable/index.js -> app/javascript/action_cable/connection_monitor.js -> app/javascript/action_cable/index.js (!) Circular dependency: app/javascript/action_cable/index.js -> app/javascript/action_cable/consumer.js -> app/javascript/action_cable/index.js (!) Circular dependency: app/javascript/action_cable/index.js -> app/javascript/action_cable/subscriptions.js -> app/javascript/action_cable/index.js ``` to 2: ``` (!) Circular dependency: app/javascript/action_cable/index.js -> app/javascript/action_cable/connection.js -> app/javascript/action_cable/index.js (!) Circular dependency: app/javascript/action_cable/index.js -> app/javascript/action_cable/connection.js -> app/javascript/action_cable/connection_monitor.js -> app/javascript/action_cable/index.js ``` * Remove tests that only test javascript object property assignment These tests really only assert that you can assign a property to the ActionCable global object. That's true for pretty much any object in javascript (it would only be false if the object has been frozen, or has explicitly set some properties to be nonconfigurable). * Refactor ActionCable to provide individual named exports By providing individual named exports rather than a default export which is an object with all of those properties, we enable applications to only import the functions they need: any unused functions will be removed via tree shaking. Additionally, this restructuring removes the remaining circular dependencies by extracting the separate adapters and logger modules, so there are now no warnings when compiling the ActionCable bundle. Note: This produces two small breaking API changes: - The `ActionCable.WebSocket` getter and setter would be moved to `ActionCable.adapters.WebSocket`. If a user is currently configuring this, when upgrading they'd need to either add a delegated getter/setter themselves, or change it like this: ```diff - ActionCable.WebSocket = MyWebSocket + ActionCable.adapters.WebSocket = MyWebSocket ``` Applications which don't change the WebSocket adapter would not need any changes for this when upgrading. - Similarly, the `ActionCable.logger` getter and setter would be moved to `ActionCable.adapters.logger`. If a user is currently configuring this, when upgrading they'd need to either add a delegated getter/setter themselves, or change it like this: ```diff - ActionCable.logger = myLogger + ActionCable.adapters.logger = myLogger ``` Applications which don't change the logger would not need any changes for this when upgrading. These two aspects of the public API have to change because there's no way to export a property setter for `WebSocket` (or `logger`) such that this: ```js import ActionCable from "actioncable" ActionCable.WebSocket = MyWebSocket ``` would actually update `adapters.WebSocket`. (We can only offer that if we have two separate source files like if `index.js` uses `import * as ActionCable from "./action_cable" and then exports a wrapper which has delegated getters and setters for those properties.) This API change is very minor - it should be easy for applications to add the `adapters.` prefix in their assignments or to patch in delegated setters. And especially because most applications in the wild are not ever changing the default value of `ActionCable.WebSocket` or `ActionCable.logger` (because the default values are perfect), this API breakage is worth the tree-shaking benefits we gain. * Include source code in published actioncable npm package This allows actioncable users to ship smaller javascript bundles to visitors using modern browsers, as demonstrated in this repository: https://github.com/rmacklin/actioncable-es2015-build-example In that example, the bundle shrinks by 2.8K (25.2%) when you simply change the actioncable import to point to the untranspiled src. If you go a step further, like this: ``` diff --git a/app/scripts/main.js b/app/scripts/main.js index 17bc031..1a2b2e0 100644 --- a/app/scripts/main.js +++ b/app/scripts/main.js @@ -1,6 +1,6 @@ -import ActionCable from 'actioncable'; +import * as ActionCable from 'actioncable'; let cable = ActionCable.createConsumer('wss://cable.example.com'); cable.subscriptions.create('AppearanceChannel', { ``` then the bundle shrinks by 3.6K (31.7%)! In addition to allowing smaller bundles for those who ship untranspiled code to modern browsers, including the source code in the published package can be useful in other ways: 1. Users can import individual modules rather than the whole library 2. As a result of (1), users can also monkey patch parts of actioncable by importing the relevant module, modifying the exported object, and then importing the rest of actioncable (which would then use the patched object). Note: This is the same enhancement that we made to activestorage in c0368ad090b79c19300a4aa133bb188b2d9ab611 * Remove unused commonjs & resolve plugins from ActionCable rollup config These were added when we copied the rollup config from ActiveStorage, but ActionCable does not have any commonjs dependencies (it doesn't have any external dependencies at all), so these plugins are unnecessary here * Change ActionCable.startDebugging() -> ActionCable.logger.enabled=true and ActionCable.stopDebugging() -> ActionCable.logger.enabled=false This API is simpler and more clearly describes what it does * Change Travis configuration to run yarn install at the root for ActionCable builds This is necessary now that the repository is using Yarn Workspaces
2018-12-01 16:25:02 -05:00
default_mount_path: "/cable",
protocols: [ "actioncable-v1-json", "actioncable-unsupported" ]
};
Convert ActionCable javascript to ES2015 modules with modern build environment We've replaced the sprockets `//= require` directives with ES2015 imports. As a result, the ActionCable javascript can now be compiled with rollup (like ActiveStorage already is). - Rename action_cable/index.js.erb -> action_cable/index.js - Add rake task to generate a javascript module of the ActionCable::INTERNAL ruby hash This will allow us to get rid of ERB from the actioncable javascript, since it is only used to interpolate ActionCable::INTERNAL.to_json. - Import INTERNAL directly in ActionCable Connection module This is necessary to remove a load-order dependency conflict in the rollup-compiled build. Using ActionCable.INTERNAL would result in a runtime error: ``` TypeError: Cannot read property 'INTERNAL' of undefined ``` because ActionCable.INTERNAL is not set before the Connection module is executed. All other ActionCable.* references are executed inside of the body of a function, so there is no load-order dependency there. - Add eslint and eslint-plugin-import devDependencies to actioncable These will be used to add a linting setup to actioncable like the one in activestorage. - Add .eslintrc to actioncable This lint configuration was copied from activestorage - Add lint script to actioncable This is the same as the lint script in activestorage - Add babel-core, babel-plugin-external-helpers, and babel-preset-env devDependencies to actioncable These will be used to add ES2015 transpilation support to actioncable like we have in activestorage. - Add .babelrc to actioncable This configuration was copied from activestorage - Enable loose mode in ActionCable's babel config This generates a smaller bundle when compiled - Add rollup devDependencies to actioncable These will be used to add a modern build pipeline to actioncable like the one in activestorage. - Add rollup config to actioncable This is essentially the same as the rollup config from activestorage - Add prebuild and build scripts to actioncable package These scripts were copied from activestorage - Invoke code generation task as part of actioncable's prebuild script This will guarantee that the action_cable/internal.js module is available at build time (which is important, because two other modules now depend on it). - Update actioncable package to reference the rollup-compiled files Now that we have a fully functional rollup pipeline in actioncable, we can use the compiled output in our npm package. - Remove build section from ActionCable blade config Now that rollup is responsible for building ActionCable, we can remove that responsibility from Blade. - Remove assets:compile and assets:verify tasks from ActionCable Now that we've added a compiled ActionCable bundle to version control, we don't need to compile and verify it at publish-time. (We're following the pattern set in ActiveStorage.) - Include compiled ActionCable javascript bundle in published gem This is necessary to maintain support for depending on the ActionCable javascript through the Sprockets asset pipeline. - Add compiled ActionCable bundle to version control This mirrors what we do in ActiveStorage, and allows ActionCable to continue to be consumed via the sprockets-based asset pipeline when using a git source instead of a published version of the gem.
2018-01-21 02:33:32 -05:00
var message_types = INTERNAL.message_types, protocols = INTERNAL.protocols;
var supportedProtocols = protocols.slice(0, protocols.length - 1);
var indexOf = [].indexOf;
var Connection = function() {
function Connection(consumer) {
classCallCheck(this, Connection);
this.open = this.open.bind(this);
this.consumer = consumer;
this.subscriptions = this.consumer.subscriptions;
Remove circular dependency warnings in ActionCable javascript and publish source modules with fine-grained exports (#34370) * Replace several ActionCable.* references with finer-grained imports This reduces the number of circular dependencies among the module imports from 4: ``` (!) Circular dependency: app/javascript/action_cable/index.js -> app/javascript/action_cable/connection.js -> app/javascript/action_cable/index.js (!) Circular dependency: app/javascript/action_cable/index.js -> app/javascript/action_cable/connection_monitor.js -> app/javascript/action_cable/index.js (!) Circular dependency: app/javascript/action_cable/index.js -> app/javascript/action_cable/consumer.js -> app/javascript/action_cable/index.js (!) Circular dependency: app/javascript/action_cable/index.js -> app/javascript/action_cable/subscriptions.js -> app/javascript/action_cable/index.js ``` to 2: ``` (!) Circular dependency: app/javascript/action_cable/index.js -> app/javascript/action_cable/connection.js -> app/javascript/action_cable/index.js (!) Circular dependency: app/javascript/action_cable/index.js -> app/javascript/action_cable/connection.js -> app/javascript/action_cable/connection_monitor.js -> app/javascript/action_cable/index.js ``` * Remove tests that only test javascript object property assignment These tests really only assert that you can assign a property to the ActionCable global object. That's true for pretty much any object in javascript (it would only be false if the object has been frozen, or has explicitly set some properties to be nonconfigurable). * Refactor ActionCable to provide individual named exports By providing individual named exports rather than a default export which is an object with all of those properties, we enable applications to only import the functions they need: any unused functions will be removed via tree shaking. Additionally, this restructuring removes the remaining circular dependencies by extracting the separate adapters and logger modules, so there are now no warnings when compiling the ActionCable bundle. Note: This produces two small breaking API changes: - The `ActionCable.WebSocket` getter and setter would be moved to `ActionCable.adapters.WebSocket`. If a user is currently configuring this, when upgrading they'd need to either add a delegated getter/setter themselves, or change it like this: ```diff - ActionCable.WebSocket = MyWebSocket + ActionCable.adapters.WebSocket = MyWebSocket ``` Applications which don't change the WebSocket adapter would not need any changes for this when upgrading. - Similarly, the `ActionCable.logger` getter and setter would be moved to `ActionCable.adapters.logger`. If a user is currently configuring this, when upgrading they'd need to either add a delegated getter/setter themselves, or change it like this: ```diff - ActionCable.logger = myLogger + ActionCable.adapters.logger = myLogger ``` Applications which don't change the logger would not need any changes for this when upgrading. These two aspects of the public API have to change because there's no way to export a property setter for `WebSocket` (or `logger`) such that this: ```js import ActionCable from "actioncable" ActionCable.WebSocket = MyWebSocket ``` would actually update `adapters.WebSocket`. (We can only offer that if we have two separate source files like if `index.js` uses `import * as ActionCable from "./action_cable" and then exports a wrapper which has delegated getters and setters for those properties.) This API change is very minor - it should be easy for applications to add the `adapters.` prefix in their assignments or to patch in delegated setters. And especially because most applications in the wild are not ever changing the default value of `ActionCable.WebSocket` or `ActionCable.logger` (because the default values are perfect), this API breakage is worth the tree-shaking benefits we gain. * Include source code in published actioncable npm package This allows actioncable users to ship smaller javascript bundles to visitors using modern browsers, as demonstrated in this repository: https://github.com/rmacklin/actioncable-es2015-build-example In that example, the bundle shrinks by 2.8K (25.2%) when you simply change the actioncable import to point to the untranspiled src. If you go a step further, like this: ``` diff --git a/app/scripts/main.js b/app/scripts/main.js index 17bc031..1a2b2e0 100644 --- a/app/scripts/main.js +++ b/app/scripts/main.js @@ -1,6 +1,6 @@ -import ActionCable from 'actioncable'; +import * as ActionCable from 'actioncable'; let cable = ActionCable.createConsumer('wss://cable.example.com'); cable.subscriptions.create('AppearanceChannel', { ``` then the bundle shrinks by 3.6K (31.7%)! In addition to allowing smaller bundles for those who ship untranspiled code to modern browsers, including the source code in the published package can be useful in other ways: 1. Users can import individual modules rather than the whole library 2. As a result of (1), users can also monkey patch parts of actioncable by importing the relevant module, modifying the exported object, and then importing the rest of actioncable (which would then use the patched object). Note: This is the same enhancement that we made to activestorage in c0368ad090b79c19300a4aa133bb188b2d9ab611 * Remove unused commonjs & resolve plugins from ActionCable rollup config These were added when we copied the rollup config from ActiveStorage, but ActionCable does not have any commonjs dependencies (it doesn't have any external dependencies at all), so these plugins are unnecessary here * Change ActionCable.startDebugging() -> ActionCable.logger.enabled=true and ActionCable.stopDebugging() -> ActionCable.logger.enabled=false This API is simpler and more clearly describes what it does * Change Travis configuration to run yarn install at the root for ActionCable builds This is necessary now that the repository is using Yarn Workspaces
2018-12-01 16:25:02 -05:00
this.monitor = new ConnectionMonitor(this);
Convert ActionCable javascript to ES2015 modules with modern build environment We've replaced the sprockets `//= require` directives with ES2015 imports. As a result, the ActionCable javascript can now be compiled with rollup (like ActiveStorage already is). - Rename action_cable/index.js.erb -> action_cable/index.js - Add rake task to generate a javascript module of the ActionCable::INTERNAL ruby hash This will allow us to get rid of ERB from the actioncable javascript, since it is only used to interpolate ActionCable::INTERNAL.to_json. - Import INTERNAL directly in ActionCable Connection module This is necessary to remove a load-order dependency conflict in the rollup-compiled build. Using ActionCable.INTERNAL would result in a runtime error: ``` TypeError: Cannot read property 'INTERNAL' of undefined ``` because ActionCable.INTERNAL is not set before the Connection module is executed. All other ActionCable.* references are executed inside of the body of a function, so there is no load-order dependency there. - Add eslint and eslint-plugin-import devDependencies to actioncable These will be used to add a linting setup to actioncable like the one in activestorage. - Add .eslintrc to actioncable This lint configuration was copied from activestorage - Add lint script to actioncable This is the same as the lint script in activestorage - Add babel-core, babel-plugin-external-helpers, and babel-preset-env devDependencies to actioncable These will be used to add ES2015 transpilation support to actioncable like we have in activestorage. - Add .babelrc to actioncable This configuration was copied from activestorage - Enable loose mode in ActionCable's babel config This generates a smaller bundle when compiled - Add rollup devDependencies to actioncable These will be used to add a modern build pipeline to actioncable like the one in activestorage. - Add rollup config to actioncable This is essentially the same as the rollup config from activestorage - Add prebuild and build scripts to actioncable package These scripts were copied from activestorage - Invoke code generation task as part of actioncable's prebuild script This will guarantee that the action_cable/internal.js module is available at build time (which is important, because two other modules now depend on it). - Update actioncable package to reference the rollup-compiled files Now that we have a fully functional rollup pipeline in actioncable, we can use the compiled output in our npm package. - Remove build section from ActionCable blade config Now that rollup is responsible for building ActionCable, we can remove that responsibility from Blade. - Remove assets:compile and assets:verify tasks from ActionCable Now that we've added a compiled ActionCable bundle to version control, we don't need to compile and verify it at publish-time. (We're following the pattern set in ActiveStorage.) - Include compiled ActionCable javascript bundle in published gem This is necessary to maintain support for depending on the ActionCable javascript through the Sprockets asset pipeline. - Add compiled ActionCable bundle to version control This mirrors what we do in ActiveStorage, and allows ActionCable to continue to be consumed via the sprockets-based asset pipeline when using a git source instead of a published version of the gem.
2018-01-21 02:33:32 -05:00
this.disconnected = true;
}
Connection.prototype.send = function send(data) {
if (this.isOpen()) {
this.webSocket.send(JSON.stringify(data));
return true;
} else {
return false;
}
};
Connection.prototype.open = function open() {
if (this.isActive()) {
Remove circular dependency warnings in ActionCable javascript and publish source modules with fine-grained exports (#34370) * Replace several ActionCable.* references with finer-grained imports This reduces the number of circular dependencies among the module imports from 4: ``` (!) Circular dependency: app/javascript/action_cable/index.js -> app/javascript/action_cable/connection.js -> app/javascript/action_cable/index.js (!) Circular dependency: app/javascript/action_cable/index.js -> app/javascript/action_cable/connection_monitor.js -> app/javascript/action_cable/index.js (!) Circular dependency: app/javascript/action_cable/index.js -> app/javascript/action_cable/consumer.js -> app/javascript/action_cable/index.js (!) Circular dependency: app/javascript/action_cable/index.js -> app/javascript/action_cable/subscriptions.js -> app/javascript/action_cable/index.js ``` to 2: ``` (!) Circular dependency: app/javascript/action_cable/index.js -> app/javascript/action_cable/connection.js -> app/javascript/action_cable/index.js (!) Circular dependency: app/javascript/action_cable/index.js -> app/javascript/action_cable/connection.js -> app/javascript/action_cable/connection_monitor.js -> app/javascript/action_cable/index.js ``` * Remove tests that only test javascript object property assignment These tests really only assert that you can assign a property to the ActionCable global object. That's true for pretty much any object in javascript (it would only be false if the object has been frozen, or has explicitly set some properties to be nonconfigurable). * Refactor ActionCable to provide individual named exports By providing individual named exports rather than a default export which is an object with all of those properties, we enable applications to only import the functions they need: any unused functions will be removed via tree shaking. Additionally, this restructuring removes the remaining circular dependencies by extracting the separate adapters and logger modules, so there are now no warnings when compiling the ActionCable bundle. Note: This produces two small breaking API changes: - The `ActionCable.WebSocket` getter and setter would be moved to `ActionCable.adapters.WebSocket`. If a user is currently configuring this, when upgrading they'd need to either add a delegated getter/setter themselves, or change it like this: ```diff - ActionCable.WebSocket = MyWebSocket + ActionCable.adapters.WebSocket = MyWebSocket ``` Applications which don't change the WebSocket adapter would not need any changes for this when upgrading. - Similarly, the `ActionCable.logger` getter and setter would be moved to `ActionCable.adapters.logger`. If a user is currently configuring this, when upgrading they'd need to either add a delegated getter/setter themselves, or change it like this: ```diff - ActionCable.logger = myLogger + ActionCable.adapters.logger = myLogger ``` Applications which don't change the logger would not need any changes for this when upgrading. These two aspects of the public API have to change because there's no way to export a property setter for `WebSocket` (or `logger`) such that this: ```js import ActionCable from "actioncable" ActionCable.WebSocket = MyWebSocket ``` would actually update `adapters.WebSocket`. (We can only offer that if we have two separate source files like if `index.js` uses `import * as ActionCable from "./action_cable" and then exports a wrapper which has delegated getters and setters for those properties.) This API change is very minor - it should be easy for applications to add the `adapters.` prefix in their assignments or to patch in delegated setters. And especially because most applications in the wild are not ever changing the default value of `ActionCable.WebSocket` or `ActionCable.logger` (because the default values are perfect), this API breakage is worth the tree-shaking benefits we gain. * Include source code in published actioncable npm package This allows actioncable users to ship smaller javascript bundles to visitors using modern browsers, as demonstrated in this repository: https://github.com/rmacklin/actioncable-es2015-build-example In that example, the bundle shrinks by 2.8K (25.2%) when you simply change the actioncable import to point to the untranspiled src. If you go a step further, like this: ``` diff --git a/app/scripts/main.js b/app/scripts/main.js index 17bc031..1a2b2e0 100644 --- a/app/scripts/main.js +++ b/app/scripts/main.js @@ -1,6 +1,6 @@ -import ActionCable from 'actioncable'; +import * as ActionCable from 'actioncable'; let cable = ActionCable.createConsumer('wss://cable.example.com'); cable.subscriptions.create('AppearanceChannel', { ``` then the bundle shrinks by 3.6K (31.7%)! In addition to allowing smaller bundles for those who ship untranspiled code to modern browsers, including the source code in the published package can be useful in other ways: 1. Users can import individual modules rather than the whole library 2. As a result of (1), users can also monkey patch parts of actioncable by importing the relevant module, modifying the exported object, and then importing the rest of actioncable (which would then use the patched object). Note: This is the same enhancement that we made to activestorage in c0368ad090b79c19300a4aa133bb188b2d9ab611 * Remove unused commonjs & resolve plugins from ActionCable rollup config These were added when we copied the rollup config from ActiveStorage, but ActionCable does not have any commonjs dependencies (it doesn't have any external dependencies at all), so these plugins are unnecessary here * Change ActionCable.startDebugging() -> ActionCable.logger.enabled=true and ActionCable.stopDebugging() -> ActionCable.logger.enabled=false This API is simpler and more clearly describes what it does * Change Travis configuration to run yarn install at the root for ActionCable builds This is necessary now that the repository is using Yarn Workspaces
2018-12-01 16:25:02 -05:00
logger.log("Attempted to open WebSocket, but existing socket is " + this.getState());
Convert ActionCable javascript to ES2015 modules with modern build environment We've replaced the sprockets `//= require` directives with ES2015 imports. As a result, the ActionCable javascript can now be compiled with rollup (like ActiveStorage already is). - Rename action_cable/index.js.erb -> action_cable/index.js - Add rake task to generate a javascript module of the ActionCable::INTERNAL ruby hash This will allow us to get rid of ERB from the actioncable javascript, since it is only used to interpolate ActionCable::INTERNAL.to_json. - Import INTERNAL directly in ActionCable Connection module This is necessary to remove a load-order dependency conflict in the rollup-compiled build. Using ActionCable.INTERNAL would result in a runtime error: ``` TypeError: Cannot read property 'INTERNAL' of undefined ``` because ActionCable.INTERNAL is not set before the Connection module is executed. All other ActionCable.* references are executed inside of the body of a function, so there is no load-order dependency there. - Add eslint and eslint-plugin-import devDependencies to actioncable These will be used to add a linting setup to actioncable like the one in activestorage. - Add .eslintrc to actioncable This lint configuration was copied from activestorage - Add lint script to actioncable This is the same as the lint script in activestorage - Add babel-core, babel-plugin-external-helpers, and babel-preset-env devDependencies to actioncable These will be used to add ES2015 transpilation support to actioncable like we have in activestorage. - Add .babelrc to actioncable This configuration was copied from activestorage - Enable loose mode in ActionCable's babel config This generates a smaller bundle when compiled - Add rollup devDependencies to actioncable These will be used to add a modern build pipeline to actioncable like the one in activestorage. - Add rollup config to actioncable This is essentially the same as the rollup config from activestorage - Add prebuild and build scripts to actioncable package These scripts were copied from activestorage - Invoke code generation task as part of actioncable's prebuild script This will guarantee that the action_cable/internal.js module is available at build time (which is important, because two other modules now depend on it). - Update actioncable package to reference the rollup-compiled files Now that we have a fully functional rollup pipeline in actioncable, we can use the compiled output in our npm package. - Remove build section from ActionCable blade config Now that rollup is responsible for building ActionCable, we can remove that responsibility from Blade. - Remove assets:compile and assets:verify tasks from ActionCable Now that we've added a compiled ActionCable bundle to version control, we don't need to compile and verify it at publish-time. (We're following the pattern set in ActiveStorage.) - Include compiled ActionCable javascript bundle in published gem This is necessary to maintain support for depending on the ActionCable javascript through the Sprockets asset pipeline. - Add compiled ActionCable bundle to version control This mirrors what we do in ActiveStorage, and allows ActionCable to continue to be consumed via the sprockets-based asset pipeline when using a git source instead of a published version of the gem.
2018-01-21 02:33:32 -05:00
return false;
} else {
Remove circular dependency warnings in ActionCable javascript and publish source modules with fine-grained exports (#34370) * Replace several ActionCable.* references with finer-grained imports This reduces the number of circular dependencies among the module imports from 4: ``` (!) Circular dependency: app/javascript/action_cable/index.js -> app/javascript/action_cable/connection.js -> app/javascript/action_cable/index.js (!) Circular dependency: app/javascript/action_cable/index.js -> app/javascript/action_cable/connection_monitor.js -> app/javascript/action_cable/index.js (!) Circular dependency: app/javascript/action_cable/index.js -> app/javascript/action_cable/consumer.js -> app/javascript/action_cable/index.js (!) Circular dependency: app/javascript/action_cable/index.js -> app/javascript/action_cable/subscriptions.js -> app/javascript/action_cable/index.js ``` to 2: ``` (!) Circular dependency: app/javascript/action_cable/index.js -> app/javascript/action_cable/connection.js -> app/javascript/action_cable/index.js (!) Circular dependency: app/javascript/action_cable/index.js -> app/javascript/action_cable/connection.js -> app/javascript/action_cable/connection_monitor.js -> app/javascript/action_cable/index.js ``` * Remove tests that only test javascript object property assignment These tests really only assert that you can assign a property to the ActionCable global object. That's true for pretty much any object in javascript (it would only be false if the object has been frozen, or has explicitly set some properties to be nonconfigurable). * Refactor ActionCable to provide individual named exports By providing individual named exports rather than a default export which is an object with all of those properties, we enable applications to only import the functions they need: any unused functions will be removed via tree shaking. Additionally, this restructuring removes the remaining circular dependencies by extracting the separate adapters and logger modules, so there are now no warnings when compiling the ActionCable bundle. Note: This produces two small breaking API changes: - The `ActionCable.WebSocket` getter and setter would be moved to `ActionCable.adapters.WebSocket`. If a user is currently configuring this, when upgrading they'd need to either add a delegated getter/setter themselves, or change it like this: ```diff - ActionCable.WebSocket = MyWebSocket + ActionCable.adapters.WebSocket = MyWebSocket ``` Applications which don't change the WebSocket adapter would not need any changes for this when upgrading. - Similarly, the `ActionCable.logger` getter and setter would be moved to `ActionCable.adapters.logger`. If a user is currently configuring this, when upgrading they'd need to either add a delegated getter/setter themselves, or change it like this: ```diff - ActionCable.logger = myLogger + ActionCable.adapters.logger = myLogger ``` Applications which don't change the logger would not need any changes for this when upgrading. These two aspects of the public API have to change because there's no way to export a property setter for `WebSocket` (or `logger`) such that this: ```js import ActionCable from "actioncable" ActionCable.WebSocket = MyWebSocket ``` would actually update `adapters.WebSocket`. (We can only offer that if we have two separate source files like if `index.js` uses `import * as ActionCable from "./action_cable" and then exports a wrapper which has delegated getters and setters for those properties.) This API change is very minor - it should be easy for applications to add the `adapters.` prefix in their assignments or to patch in delegated setters. And especially because most applications in the wild are not ever changing the default value of `ActionCable.WebSocket` or `ActionCable.logger` (because the default values are perfect), this API breakage is worth the tree-shaking benefits we gain. * Include source code in published actioncable npm package This allows actioncable users to ship smaller javascript bundles to visitors using modern browsers, as demonstrated in this repository: https://github.com/rmacklin/actioncable-es2015-build-example In that example, the bundle shrinks by 2.8K (25.2%) when you simply change the actioncable import to point to the untranspiled src. If you go a step further, like this: ``` diff --git a/app/scripts/main.js b/app/scripts/main.js index 17bc031..1a2b2e0 100644 --- a/app/scripts/main.js +++ b/app/scripts/main.js @@ -1,6 +1,6 @@ -import ActionCable from 'actioncable'; +import * as ActionCable from 'actioncable'; let cable = ActionCable.createConsumer('wss://cable.example.com'); cable.subscriptions.create('AppearanceChannel', { ``` then the bundle shrinks by 3.6K (31.7%)! In addition to allowing smaller bundles for those who ship untranspiled code to modern browsers, including the source code in the published package can be useful in other ways: 1. Users can import individual modules rather than the whole library 2. As a result of (1), users can also monkey patch parts of actioncable by importing the relevant module, modifying the exported object, and then importing the rest of actioncable (which would then use the patched object). Note: This is the same enhancement that we made to activestorage in c0368ad090b79c19300a4aa133bb188b2d9ab611 * Remove unused commonjs & resolve plugins from ActionCable rollup config These were added when we copied the rollup config from ActiveStorage, but ActionCable does not have any commonjs dependencies (it doesn't have any external dependencies at all), so these plugins are unnecessary here * Change ActionCable.startDebugging() -> ActionCable.logger.enabled=true and ActionCable.stopDebugging() -> ActionCable.logger.enabled=false This API is simpler and more clearly describes what it does * Change Travis configuration to run yarn install at the root for ActionCable builds This is necessary now that the repository is using Yarn Workspaces
2018-12-01 16:25:02 -05:00
logger.log("Opening WebSocket, current state is " + this.getState() + ", subprotocols: " + protocols);
Convert ActionCable javascript to ES2015 modules with modern build environment We've replaced the sprockets `//= require` directives with ES2015 imports. As a result, the ActionCable javascript can now be compiled with rollup (like ActiveStorage already is). - Rename action_cable/index.js.erb -> action_cable/index.js - Add rake task to generate a javascript module of the ActionCable::INTERNAL ruby hash This will allow us to get rid of ERB from the actioncable javascript, since it is only used to interpolate ActionCable::INTERNAL.to_json. - Import INTERNAL directly in ActionCable Connection module This is necessary to remove a load-order dependency conflict in the rollup-compiled build. Using ActionCable.INTERNAL would result in a runtime error: ``` TypeError: Cannot read property 'INTERNAL' of undefined ``` because ActionCable.INTERNAL is not set before the Connection module is executed. All other ActionCable.* references are executed inside of the body of a function, so there is no load-order dependency there. - Add eslint and eslint-plugin-import devDependencies to actioncable These will be used to add a linting setup to actioncable like the one in activestorage. - Add .eslintrc to actioncable This lint configuration was copied from activestorage - Add lint script to actioncable This is the same as the lint script in activestorage - Add babel-core, babel-plugin-external-helpers, and babel-preset-env devDependencies to actioncable These will be used to add ES2015 transpilation support to actioncable like we have in activestorage. - Add .babelrc to actioncable This configuration was copied from activestorage - Enable loose mode in ActionCable's babel config This generates a smaller bundle when compiled - Add rollup devDependencies to actioncable These will be used to add a modern build pipeline to actioncable like the one in activestorage. - Add rollup config to actioncable This is essentially the same as the rollup config from activestorage - Add prebuild and build scripts to actioncable package These scripts were copied from activestorage - Invoke code generation task as part of actioncable's prebuild script This will guarantee that the action_cable/internal.js module is available at build time (which is important, because two other modules now depend on it). - Update actioncable package to reference the rollup-compiled files Now that we have a fully functional rollup pipeline in actioncable, we can use the compiled output in our npm package. - Remove build section from ActionCable blade config Now that rollup is responsible for building ActionCable, we can remove that responsibility from Blade. - Remove assets:compile and assets:verify tasks from ActionCable Now that we've added a compiled ActionCable bundle to version control, we don't need to compile and verify it at publish-time. (We're following the pattern set in ActiveStorage.) - Include compiled ActionCable javascript bundle in published gem This is necessary to maintain support for depending on the ActionCable javascript through the Sprockets asset pipeline. - Add compiled ActionCable bundle to version control This mirrors what we do in ActiveStorage, and allows ActionCable to continue to be consumed via the sprockets-based asset pipeline when using a git source instead of a published version of the gem.
2018-01-21 02:33:32 -05:00
if (this.webSocket) {
this.uninstallEventHandlers();
}
Remove circular dependency warnings in ActionCable javascript and publish source modules with fine-grained exports (#34370) * Replace several ActionCable.* references with finer-grained imports This reduces the number of circular dependencies among the module imports from 4: ``` (!) Circular dependency: app/javascript/action_cable/index.js -> app/javascript/action_cable/connection.js -> app/javascript/action_cable/index.js (!) Circular dependency: app/javascript/action_cable/index.js -> app/javascript/action_cable/connection_monitor.js -> app/javascript/action_cable/index.js (!) Circular dependency: app/javascript/action_cable/index.js -> app/javascript/action_cable/consumer.js -> app/javascript/action_cable/index.js (!) Circular dependency: app/javascript/action_cable/index.js -> app/javascript/action_cable/subscriptions.js -> app/javascript/action_cable/index.js ``` to 2: ``` (!) Circular dependency: app/javascript/action_cable/index.js -> app/javascript/action_cable/connection.js -> app/javascript/action_cable/index.js (!) Circular dependency: app/javascript/action_cable/index.js -> app/javascript/action_cable/connection.js -> app/javascript/action_cable/connection_monitor.js -> app/javascript/action_cable/index.js ``` * Remove tests that only test javascript object property assignment These tests really only assert that you can assign a property to the ActionCable global object. That's true for pretty much any object in javascript (it would only be false if the object has been frozen, or has explicitly set some properties to be nonconfigurable). * Refactor ActionCable to provide individual named exports By providing individual named exports rather than a default export which is an object with all of those properties, we enable applications to only import the functions they need: any unused functions will be removed via tree shaking. Additionally, this restructuring removes the remaining circular dependencies by extracting the separate adapters and logger modules, so there are now no warnings when compiling the ActionCable bundle. Note: This produces two small breaking API changes: - The `ActionCable.WebSocket` getter and setter would be moved to `ActionCable.adapters.WebSocket`. If a user is currently configuring this, when upgrading they'd need to either add a delegated getter/setter themselves, or change it like this: ```diff - ActionCable.WebSocket = MyWebSocket + ActionCable.adapters.WebSocket = MyWebSocket ``` Applications which don't change the WebSocket adapter would not need any changes for this when upgrading. - Similarly, the `ActionCable.logger` getter and setter would be moved to `ActionCable.adapters.logger`. If a user is currently configuring this, when upgrading they'd need to either add a delegated getter/setter themselves, or change it like this: ```diff - ActionCable.logger = myLogger + ActionCable.adapters.logger = myLogger ``` Applications which don't change the logger would not need any changes for this when upgrading. These two aspects of the public API have to change because there's no way to export a property setter for `WebSocket` (or `logger`) such that this: ```js import ActionCable from "actioncable" ActionCable.WebSocket = MyWebSocket ``` would actually update `adapters.WebSocket`. (We can only offer that if we have two separate source files like if `index.js` uses `import * as ActionCable from "./action_cable" and then exports a wrapper which has delegated getters and setters for those properties.) This API change is very minor - it should be easy for applications to add the `adapters.` prefix in their assignments or to patch in delegated setters. And especially because most applications in the wild are not ever changing the default value of `ActionCable.WebSocket` or `ActionCable.logger` (because the default values are perfect), this API breakage is worth the tree-shaking benefits we gain. * Include source code in published actioncable npm package This allows actioncable users to ship smaller javascript bundles to visitors using modern browsers, as demonstrated in this repository: https://github.com/rmacklin/actioncable-es2015-build-example In that example, the bundle shrinks by 2.8K (25.2%) when you simply change the actioncable import to point to the untranspiled src. If you go a step further, like this: ``` diff --git a/app/scripts/main.js b/app/scripts/main.js index 17bc031..1a2b2e0 100644 --- a/app/scripts/main.js +++ b/app/scripts/main.js @@ -1,6 +1,6 @@ -import ActionCable from 'actioncable'; +import * as ActionCable from 'actioncable'; let cable = ActionCable.createConsumer('wss://cable.example.com'); cable.subscriptions.create('AppearanceChannel', { ``` then the bundle shrinks by 3.6K (31.7%)! In addition to allowing smaller bundles for those who ship untranspiled code to modern browsers, including the source code in the published package can be useful in other ways: 1. Users can import individual modules rather than the whole library 2. As a result of (1), users can also monkey patch parts of actioncable by importing the relevant module, modifying the exported object, and then importing the rest of actioncable (which would then use the patched object). Note: This is the same enhancement that we made to activestorage in c0368ad090b79c19300a4aa133bb188b2d9ab611 * Remove unused commonjs & resolve plugins from ActionCable rollup config These were added when we copied the rollup config from ActiveStorage, but ActionCable does not have any commonjs dependencies (it doesn't have any external dependencies at all), so these plugins are unnecessary here * Change ActionCable.startDebugging() -> ActionCable.logger.enabled=true and ActionCable.stopDebugging() -> ActionCable.logger.enabled=false This API is simpler and more clearly describes what it does * Change Travis configuration to run yarn install at the root for ActionCable builds This is necessary now that the repository is using Yarn Workspaces
2018-12-01 16:25:02 -05:00
this.webSocket = new adapters.WebSocket(this.consumer.url, protocols);
Convert ActionCable javascript to ES2015 modules with modern build environment We've replaced the sprockets `//= require` directives with ES2015 imports. As a result, the ActionCable javascript can now be compiled with rollup (like ActiveStorage already is). - Rename action_cable/index.js.erb -> action_cable/index.js - Add rake task to generate a javascript module of the ActionCable::INTERNAL ruby hash This will allow us to get rid of ERB from the actioncable javascript, since it is only used to interpolate ActionCable::INTERNAL.to_json. - Import INTERNAL directly in ActionCable Connection module This is necessary to remove a load-order dependency conflict in the rollup-compiled build. Using ActionCable.INTERNAL would result in a runtime error: ``` TypeError: Cannot read property 'INTERNAL' of undefined ``` because ActionCable.INTERNAL is not set before the Connection module is executed. All other ActionCable.* references are executed inside of the body of a function, so there is no load-order dependency there. - Add eslint and eslint-plugin-import devDependencies to actioncable These will be used to add a linting setup to actioncable like the one in activestorage. - Add .eslintrc to actioncable This lint configuration was copied from activestorage - Add lint script to actioncable This is the same as the lint script in activestorage - Add babel-core, babel-plugin-external-helpers, and babel-preset-env devDependencies to actioncable These will be used to add ES2015 transpilation support to actioncable like we have in activestorage. - Add .babelrc to actioncable This configuration was copied from activestorage - Enable loose mode in ActionCable's babel config This generates a smaller bundle when compiled - Add rollup devDependencies to actioncable These will be used to add a modern build pipeline to actioncable like the one in activestorage. - Add rollup config to actioncable This is essentially the same as the rollup config from activestorage - Add prebuild and build scripts to actioncable package These scripts were copied from activestorage - Invoke code generation task as part of actioncable's prebuild script This will guarantee that the action_cable/internal.js module is available at build time (which is important, because two other modules now depend on it). - Update actioncable package to reference the rollup-compiled files Now that we have a fully functional rollup pipeline in actioncable, we can use the compiled output in our npm package. - Remove build section from ActionCable blade config Now that rollup is responsible for building ActionCable, we can remove that responsibility from Blade. - Remove assets:compile and assets:verify tasks from ActionCable Now that we've added a compiled ActionCable bundle to version control, we don't need to compile and verify it at publish-time. (We're following the pattern set in ActiveStorage.) - Include compiled ActionCable javascript bundle in published gem This is necessary to maintain support for depending on the ActionCable javascript through the Sprockets asset pipeline. - Add compiled ActionCable bundle to version control This mirrors what we do in ActiveStorage, and allows ActionCable to continue to be consumed via the sprockets-based asset pipeline when using a git source instead of a published version of the gem.
2018-01-21 02:33:32 -05:00
this.installEventHandlers();
this.monitor.start();
return true;
}
};
Connection.prototype.close = function close() {
var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {
allowReconnect: true
}, allowReconnect = _ref.allowReconnect;
if (!allowReconnect) {
this.monitor.stop();
}
if (this.isActive()) {
return this.webSocket ? this.webSocket.close() : undefined;
}
};
Connection.prototype.reopen = function reopen() {
Remove circular dependency warnings in ActionCable javascript and publish source modules with fine-grained exports (#34370) * Replace several ActionCable.* references with finer-grained imports This reduces the number of circular dependencies among the module imports from 4: ``` (!) Circular dependency: app/javascript/action_cable/index.js -> app/javascript/action_cable/connection.js -> app/javascript/action_cable/index.js (!) Circular dependency: app/javascript/action_cable/index.js -> app/javascript/action_cable/connection_monitor.js -> app/javascript/action_cable/index.js (!) Circular dependency: app/javascript/action_cable/index.js -> app/javascript/action_cable/consumer.js -> app/javascript/action_cable/index.js (!) Circular dependency: app/javascript/action_cable/index.js -> app/javascript/action_cable/subscriptions.js -> app/javascript/action_cable/index.js ``` to 2: ``` (!) Circular dependency: app/javascript/action_cable/index.js -> app/javascript/action_cable/connection.js -> app/javascript/action_cable/index.js (!) Circular dependency: app/javascript/action_cable/index.js -> app/javascript/action_cable/connection.js -> app/javascript/action_cable/connection_monitor.js -> app/javascript/action_cable/index.js ``` * Remove tests that only test javascript object property assignment These tests really only assert that you can assign a property to the ActionCable global object. That's true for pretty much any object in javascript (it would only be false if the object has been frozen, or has explicitly set some properties to be nonconfigurable). * Refactor ActionCable to provide individual named exports By providing individual named exports rather than a default export which is an object with all of those properties, we enable applications to only import the functions they need: any unused functions will be removed via tree shaking. Additionally, this restructuring removes the remaining circular dependencies by extracting the separate adapters and logger modules, so there are now no warnings when compiling the ActionCable bundle. Note: This produces two small breaking API changes: - The `ActionCable.WebSocket` getter and setter would be moved to `ActionCable.adapters.WebSocket`. If a user is currently configuring this, when upgrading they'd need to either add a delegated getter/setter themselves, or change it like this: ```diff - ActionCable.WebSocket = MyWebSocket + ActionCable.adapters.WebSocket = MyWebSocket ``` Applications which don't change the WebSocket adapter would not need any changes for this when upgrading. - Similarly, the `ActionCable.logger` getter and setter would be moved to `ActionCable.adapters.logger`. If a user is currently configuring this, when upgrading they'd need to either add a delegated getter/setter themselves, or change it like this: ```diff - ActionCable.logger = myLogger + ActionCable.adapters.logger = myLogger ``` Applications which don't change the logger would not need any changes for this when upgrading. These two aspects of the public API have to change because there's no way to export a property setter for `WebSocket` (or `logger`) such that this: ```js import ActionCable from "actioncable" ActionCable.WebSocket = MyWebSocket ``` would actually update `adapters.WebSocket`. (We can only offer that if we have two separate source files like if `index.js` uses `import * as ActionCable from "./action_cable" and then exports a wrapper which has delegated getters and setters for those properties.) This API change is very minor - it should be easy for applications to add the `adapters.` prefix in their assignments or to patch in delegated setters. And especially because most applications in the wild are not ever changing the default value of `ActionCable.WebSocket` or `ActionCable.logger` (because the default values are perfect), this API breakage is worth the tree-shaking benefits we gain. * Include source code in published actioncable npm package This allows actioncable users to ship smaller javascript bundles to visitors using modern browsers, as demonstrated in this repository: https://github.com/rmacklin/actioncable-es2015-build-example In that example, the bundle shrinks by 2.8K (25.2%) when you simply change the actioncable import to point to the untranspiled src. If you go a step further, like this: ``` diff --git a/app/scripts/main.js b/app/scripts/main.js index 17bc031..1a2b2e0 100644 --- a/app/scripts/main.js +++ b/app/scripts/main.js @@ -1,6 +1,6 @@ -import ActionCable from 'actioncable'; +import * as ActionCable from 'actioncable'; let cable = ActionCable.createConsumer('wss://cable.example.com'); cable.subscriptions.create('AppearanceChannel', { ``` then the bundle shrinks by 3.6K (31.7%)! In addition to allowing smaller bundles for those who ship untranspiled code to modern browsers, including the source code in the published package can be useful in other ways: 1. Users can import individual modules rather than the whole library 2. As a result of (1), users can also monkey patch parts of actioncable by importing the relevant module, modifying the exported object, and then importing the rest of actioncable (which would then use the patched object). Note: This is the same enhancement that we made to activestorage in c0368ad090b79c19300a4aa133bb188b2d9ab611 * Remove unused commonjs & resolve plugins from ActionCable rollup config These were added when we copied the rollup config from ActiveStorage, but ActionCable does not have any commonjs dependencies (it doesn't have any external dependencies at all), so these plugins are unnecessary here * Change ActionCable.startDebugging() -> ActionCable.logger.enabled=true and ActionCable.stopDebugging() -> ActionCable.logger.enabled=false This API is simpler and more clearly describes what it does * Change Travis configuration to run yarn install at the root for ActionCable builds This is necessary now that the repository is using Yarn Workspaces
2018-12-01 16:25:02 -05:00
logger.log("Reopening WebSocket, current state is " + this.getState());
Convert ActionCable javascript to ES2015 modules with modern build environment We've replaced the sprockets `//= require` directives with ES2015 imports. As a result, the ActionCable javascript can now be compiled with rollup (like ActiveStorage already is). - Rename action_cable/index.js.erb -> action_cable/index.js - Add rake task to generate a javascript module of the ActionCable::INTERNAL ruby hash This will allow us to get rid of ERB from the actioncable javascript, since it is only used to interpolate ActionCable::INTERNAL.to_json. - Import INTERNAL directly in ActionCable Connection module This is necessary to remove a load-order dependency conflict in the rollup-compiled build. Using ActionCable.INTERNAL would result in a runtime error: ``` TypeError: Cannot read property 'INTERNAL' of undefined ``` because ActionCable.INTERNAL is not set before the Connection module is executed. All other ActionCable.* references are executed inside of the body of a function, so there is no load-order dependency there. - Add eslint and eslint-plugin-import devDependencies to actioncable These will be used to add a linting setup to actioncable like the one in activestorage. - Add .eslintrc to actioncable This lint configuration was copied from activestorage - Add lint script to actioncable This is the same as the lint script in activestorage - Add babel-core, babel-plugin-external-helpers, and babel-preset-env devDependencies to actioncable These will be used to add ES2015 transpilation support to actioncable like we have in activestorage. - Add .babelrc to actioncable This configuration was copied from activestorage - Enable loose mode in ActionCable's babel config This generates a smaller bundle when compiled - Add rollup devDependencies to actioncable These will be used to add a modern build pipeline to actioncable like the one in activestorage. - Add rollup config to actioncable This is essentially the same as the rollup config from activestorage - Add prebuild and build scripts to actioncable package These scripts were copied from activestorage - Invoke code generation task as part of actioncable's prebuild script This will guarantee that the action_cable/internal.js module is available at build time (which is important, because two other modules now depend on it). - Update actioncable package to reference the rollup-compiled files Now that we have a fully functional rollup pipeline in actioncable, we can use the compiled output in our npm package. - Remove build section from ActionCable blade config Now that rollup is responsible for building ActionCable, we can remove that responsibility from Blade. - Remove assets:compile and assets:verify tasks from ActionCable Now that we've added a compiled ActionCable bundle to version control, we don't need to compile and verify it at publish-time. (We're following the pattern set in ActiveStorage.) - Include compiled ActionCable javascript bundle in published gem This is necessary to maintain support for depending on the ActionCable javascript through the Sprockets asset pipeline. - Add compiled ActionCable bundle to version control This mirrors what we do in ActiveStorage, and allows ActionCable to continue to be consumed via the sprockets-based asset pipeline when using a git source instead of a published version of the gem.
2018-01-21 02:33:32 -05:00
if (this.isActive()) {
try {
return this.close();
} catch (error) {
Remove circular dependency warnings in ActionCable javascript and publish source modules with fine-grained exports (#34370) * Replace several ActionCable.* references with finer-grained imports This reduces the number of circular dependencies among the module imports from 4: ``` (!) Circular dependency: app/javascript/action_cable/index.js -> app/javascript/action_cable/connection.js -> app/javascript/action_cable/index.js (!) Circular dependency: app/javascript/action_cable/index.js -> app/javascript/action_cable/connection_monitor.js -> app/javascript/action_cable/index.js (!) Circular dependency: app/javascript/action_cable/index.js -> app/javascript/action_cable/consumer.js -> app/javascript/action_cable/index.js (!) Circular dependency: app/javascript/action_cable/index.js -> app/javascript/action_cable/subscriptions.js -> app/javascript/action_cable/index.js ``` to 2: ``` (!) Circular dependency: app/javascript/action_cable/index.js -> app/javascript/action_cable/connection.js -> app/javascript/action_cable/index.js (!) Circular dependency: app/javascript/action_cable/index.js -> app/javascript/action_cable/connection.js -> app/javascript/action_cable/connection_monitor.js -> app/javascript/action_cable/index.js ``` * Remove tests that only test javascript object property assignment These tests really only assert that you can assign a property to the ActionCable global object. That's true for pretty much any object in javascript (it would only be false if the object has been frozen, or has explicitly set some properties to be nonconfigurable). * Refactor ActionCable to provide individual named exports By providing individual named exports rather than a default export which is an object with all of those properties, we enable applications to only import the functions they need: any unused functions will be removed via tree shaking. Additionally, this restructuring removes the remaining circular dependencies by extracting the separate adapters and logger modules, so there are now no warnings when compiling the ActionCable bundle. Note: This produces two small breaking API changes: - The `ActionCable.WebSocket` getter and setter would be moved to `ActionCable.adapters.WebSocket`. If a user is currently configuring this, when upgrading they'd need to either add a delegated getter/setter themselves, or change it like this: ```diff - ActionCable.WebSocket = MyWebSocket + ActionCable.adapters.WebSocket = MyWebSocket ``` Applications which don't change the WebSocket adapter would not need any changes for this when upgrading. - Similarly, the `ActionCable.logger` getter and setter would be moved to `ActionCable.adapters.logger`. If a user is currently configuring this, when upgrading they'd need to either add a delegated getter/setter themselves, or change it like this: ```diff - ActionCable.logger = myLogger + ActionCable.adapters.logger = myLogger ``` Applications which don't change the logger would not need any changes for this when upgrading. These two aspects of the public API have to change because there's no way to export a property setter for `WebSocket` (or `logger`) such that this: ```js import ActionCable from "actioncable" ActionCable.WebSocket = MyWebSocket ``` would actually update `adapters.WebSocket`. (We can only offer that if we have two separate source files like if `index.js` uses `import * as ActionCable from "./action_cable" and then exports a wrapper which has delegated getters and setters for those properties.) This API change is very minor - it should be easy for applications to add the `adapters.` prefix in their assignments or to patch in delegated setters. And especially because most applications in the wild are not ever changing the default value of `ActionCable.WebSocket` or `ActionCable.logger` (because the default values are perfect), this API breakage is worth the tree-shaking benefits we gain. * Include source code in published actioncable npm package This allows actioncable users to ship smaller javascript bundles to visitors using modern browsers, as demonstrated in this repository: https://github.com/rmacklin/actioncable-es2015-build-example In that example, the bundle shrinks by 2.8K (25.2%) when you simply change the actioncable import to point to the untranspiled src. If you go a step further, like this: ``` diff --git a/app/scripts/main.js b/app/scripts/main.js index 17bc031..1a2b2e0 100644 --- a/app/scripts/main.js +++ b/app/scripts/main.js @@ -1,6 +1,6 @@ -import ActionCable from 'actioncable'; +import * as ActionCable from 'actioncable'; let cable = ActionCable.createConsumer('wss://cable.example.com'); cable.subscriptions.create('AppearanceChannel', { ``` then the bundle shrinks by 3.6K (31.7%)! In addition to allowing smaller bundles for those who ship untranspiled code to modern browsers, including the source code in the published package can be useful in other ways: 1. Users can import individual modules rather than the whole library 2. As a result of (1), users can also monkey patch parts of actioncable by importing the relevant module, modifying the exported object, and then importing the rest of actioncable (which would then use the patched object). Note: This is the same enhancement that we made to activestorage in c0368ad090b79c19300a4aa133bb188b2d9ab611 * Remove unused commonjs & resolve plugins from ActionCable rollup config These were added when we copied the rollup config from ActiveStorage, but ActionCable does not have any commonjs dependencies (it doesn't have any external dependencies at all), so these plugins are unnecessary here * Change ActionCable.startDebugging() -> ActionCable.logger.enabled=true and ActionCable.stopDebugging() -> ActionCable.logger.enabled=false This API is simpler and more clearly describes what it does * Change Travis configuration to run yarn install at the root for ActionCable builds This is necessary now that the repository is using Yarn Workspaces
2018-12-01 16:25:02 -05:00
logger.log("Failed to reopen WebSocket", error);
Convert ActionCable javascript to ES2015 modules with modern build environment We've replaced the sprockets `//= require` directives with ES2015 imports. As a result, the ActionCable javascript can now be compiled with rollup (like ActiveStorage already is). - Rename action_cable/index.js.erb -> action_cable/index.js - Add rake task to generate a javascript module of the ActionCable::INTERNAL ruby hash This will allow us to get rid of ERB from the actioncable javascript, since it is only used to interpolate ActionCable::INTERNAL.to_json. - Import INTERNAL directly in ActionCable Connection module This is necessary to remove a load-order dependency conflict in the rollup-compiled build. Using ActionCable.INTERNAL would result in a runtime error: ``` TypeError: Cannot read property 'INTERNAL' of undefined ``` because ActionCable.INTERNAL is not set before the Connection module is executed. All other ActionCable.* references are executed inside of the body of a function, so there is no load-order dependency there. - Add eslint and eslint-plugin-import devDependencies to actioncable These will be used to add a linting setup to actioncable like the one in activestorage. - Add .eslintrc to actioncable This lint configuration was copied from activestorage - Add lint script to actioncable This is the same as the lint script in activestorage - Add babel-core, babel-plugin-external-helpers, and babel-preset-env devDependencies to actioncable These will be used to add ES2015 transpilation support to actioncable like we have in activestorage. - Add .babelrc to actioncable This configuration was copied from activestorage - Enable loose mode in ActionCable's babel config This generates a smaller bundle when compiled - Add rollup devDependencies to actioncable These will be used to add a modern build pipeline to actioncable like the one in activestorage. - Add rollup config to actioncable This is essentially the same as the rollup config from activestorage - Add prebuild and build scripts to actioncable package These scripts were copied from activestorage - Invoke code generation task as part of actioncable's prebuild script This will guarantee that the action_cable/internal.js module is available at build time (which is important, because two other modules now depend on it). - Update actioncable package to reference the rollup-compiled files Now that we have a fully functional rollup pipeline in actioncable, we can use the compiled output in our npm package. - Remove build section from ActionCable blade config Now that rollup is responsible for building ActionCable, we can remove that responsibility from Blade. - Remove assets:compile and assets:verify tasks from ActionCable Now that we've added a compiled ActionCable bundle to version control, we don't need to compile and verify it at publish-time. (We're following the pattern set in ActiveStorage.) - Include compiled ActionCable javascript bundle in published gem This is necessary to maintain support for depending on the ActionCable javascript through the Sprockets asset pipeline. - Add compiled ActionCable bundle to version control This mirrors what we do in ActiveStorage, and allows ActionCable to continue to be consumed via the sprockets-based asset pipeline when using a git source instead of a published version of the gem.
2018-01-21 02:33:32 -05:00
} finally {
Remove circular dependency warnings in ActionCable javascript and publish source modules with fine-grained exports (#34370) * Replace several ActionCable.* references with finer-grained imports This reduces the number of circular dependencies among the module imports from 4: ``` (!) Circular dependency: app/javascript/action_cable/index.js -> app/javascript/action_cable/connection.js -> app/javascript/action_cable/index.js (!) Circular dependency: app/javascript/action_cable/index.js -> app/javascript/action_cable/connection_monitor.js -> app/javascript/action_cable/index.js (!) Circular dependency: app/javascript/action_cable/index.js -> app/javascript/action_cable/consumer.js -> app/javascript/action_cable/index.js (!) Circular dependency: app/javascript/action_cable/index.js -> app/javascript/action_cable/subscriptions.js -> app/javascript/action_cable/index.js ``` to 2: ``` (!) Circular dependency: app/javascript/action_cable/index.js -> app/javascript/action_cable/connection.js -> app/javascript/action_cable/index.js (!) Circular dependency: app/javascript/action_cable/index.js -> app/javascript/action_cable/connection.js -> app/javascript/action_cable/connection_monitor.js -> app/javascript/action_cable/index.js ``` * Remove tests that only test javascript object property assignment These tests really only assert that you can assign a property to the ActionCable global object. That's true for pretty much any object in javascript (it would only be false if the object has been frozen, or has explicitly set some properties to be nonconfigurable). * Refactor ActionCable to provide individual named exports By providing individual named exports rather than a default export which is an object with all of those properties, we enable applications to only import the functions they need: any unused functions will be removed via tree shaking. Additionally, this restructuring removes the remaining circular dependencies by extracting the separate adapters and logger modules, so there are now no warnings when compiling the ActionCable bundle. Note: This produces two small breaking API changes: - The `ActionCable.WebSocket` getter and setter would be moved to `ActionCable.adapters.WebSocket`. If a user is currently configuring this, when upgrading they'd need to either add a delegated getter/setter themselves, or change it like this: ```diff - ActionCable.WebSocket = MyWebSocket + ActionCable.adapters.WebSocket = MyWebSocket ``` Applications which don't change the WebSocket adapter would not need any changes for this when upgrading. - Similarly, the `ActionCable.logger` getter and setter would be moved to `ActionCable.adapters.logger`. If a user is currently configuring this, when upgrading they'd need to either add a delegated getter/setter themselves, or change it like this: ```diff - ActionCable.logger = myLogger + ActionCable.adapters.logger = myLogger ``` Applications which don't change the logger would not need any changes for this when upgrading. These two aspects of the public API have to change because there's no way to export a property setter for `WebSocket` (or `logger`) such that this: ```js import ActionCable from "actioncable" ActionCable.WebSocket = MyWebSocket ``` would actually update `adapters.WebSocket`. (We can only offer that if we have two separate source files like if `index.js` uses `import * as ActionCable from "./action_cable" and then exports a wrapper which has delegated getters and setters for those properties.) This API change is very minor - it should be easy for applications to add the `adapters.` prefix in their assignments or to patch in delegated setters. And especially because most applications in the wild are not ever changing the default value of `ActionCable.WebSocket` or `ActionCable.logger` (because the default values are perfect), this API breakage is worth the tree-shaking benefits we gain. * Include source code in published actioncable npm package This allows actioncable users to ship smaller javascript bundles to visitors using modern browsers, as demonstrated in this repository: https://github.com/rmacklin/actioncable-es2015-build-example In that example, the bundle shrinks by 2.8K (25.2%) when you simply change the actioncable import to point to the untranspiled src. If you go a step further, like this: ``` diff --git a/app/scripts/main.js b/app/scripts/main.js index 17bc031..1a2b2e0 100644 --- a/app/scripts/main.js +++ b/app/scripts/main.js @@ -1,6 +1,6 @@ -import ActionCable from 'actioncable'; +import * as ActionCable from 'actioncable'; let cable = ActionCable.createConsumer('wss://cable.example.com'); cable.subscriptions.create('AppearanceChannel', { ``` then the bundle shrinks by 3.6K (31.7%)! In addition to allowing smaller bundles for those who ship untranspiled code to modern browsers, including the source code in the published package can be useful in other ways: 1. Users can import individual modules rather than the whole library 2. As a result of (1), users can also monkey patch parts of actioncable by importing the relevant module, modifying the exported object, and then importing the rest of actioncable (which would then use the patched object). Note: This is the same enhancement that we made to activestorage in c0368ad090b79c19300a4aa133bb188b2d9ab611 * Remove unused commonjs & resolve plugins from ActionCable rollup config These were added when we copied the rollup config from ActiveStorage, but ActionCable does not have any commonjs dependencies (it doesn't have any external dependencies at all), so these plugins are unnecessary here * Change ActionCable.startDebugging() -> ActionCable.logger.enabled=true and ActionCable.stopDebugging() -> ActionCable.logger.enabled=false This API is simpler and more clearly describes what it does * Change Travis configuration to run yarn install at the root for ActionCable builds This is necessary now that the repository is using Yarn Workspaces
2018-12-01 16:25:02 -05:00
logger.log("Reopening WebSocket in " + this.constructor.reopenDelay + "ms");
Convert ActionCable javascript to ES2015 modules with modern build environment We've replaced the sprockets `//= require` directives with ES2015 imports. As a result, the ActionCable javascript can now be compiled with rollup (like ActiveStorage already is). - Rename action_cable/index.js.erb -> action_cable/index.js - Add rake task to generate a javascript module of the ActionCable::INTERNAL ruby hash This will allow us to get rid of ERB from the actioncable javascript, since it is only used to interpolate ActionCable::INTERNAL.to_json. - Import INTERNAL directly in ActionCable Connection module This is necessary to remove a load-order dependency conflict in the rollup-compiled build. Using ActionCable.INTERNAL would result in a runtime error: ``` TypeError: Cannot read property 'INTERNAL' of undefined ``` because ActionCable.INTERNAL is not set before the Connection module is executed. All other ActionCable.* references are executed inside of the body of a function, so there is no load-order dependency there. - Add eslint and eslint-plugin-import devDependencies to actioncable These will be used to add a linting setup to actioncable like the one in activestorage. - Add .eslintrc to actioncable This lint configuration was copied from activestorage - Add lint script to actioncable This is the same as the lint script in activestorage - Add babel-core, babel-plugin-external-helpers, and babel-preset-env devDependencies to actioncable These will be used to add ES2015 transpilation support to actioncable like we have in activestorage. - Add .babelrc to actioncable This configuration was copied from activestorage - Enable loose mode in ActionCable's babel config This generates a smaller bundle when compiled - Add rollup devDependencies to actioncable These will be used to add a modern build pipeline to actioncable like the one in activestorage. - Add rollup config to actioncable This is essentially the same as the rollup config from activestorage - Add prebuild and build scripts to actioncable package These scripts were copied from activestorage - Invoke code generation task as part of actioncable's prebuild script This will guarantee that the action_cable/internal.js module is available at build time (which is important, because two other modules now depend on it). - Update actioncable package to reference the rollup-compiled files Now that we have a fully functional rollup pipeline in actioncable, we can use the compiled output in our npm package. - Remove build section from ActionCable blade config Now that rollup is responsible for building ActionCable, we can remove that responsibility from Blade. - Remove assets:compile and assets:verify tasks from ActionCable Now that we've added a compiled ActionCable bundle to version control, we don't need to compile and verify it at publish-time. (We're following the pattern set in ActiveStorage.) - Include compiled ActionCable javascript bundle in published gem This is necessary to maintain support for depending on the ActionCable javascript through the Sprockets asset pipeline. - Add compiled ActionCable bundle to version control This mirrors what we do in ActiveStorage, and allows ActionCable to continue to be consumed via the sprockets-based asset pipeline when using a git source instead of a published version of the gem.
2018-01-21 02:33:32 -05:00
setTimeout(this.open, this.constructor.reopenDelay);
}
} else {
return this.open();
}
};
Connection.prototype.getProtocol = function getProtocol() {
return this.webSocket ? this.webSocket.protocol : undefined;
};
Connection.prototype.isOpen = function isOpen() {
return this.isState("open");
};
Connection.prototype.isActive = function isActive() {
return this.isState("open", "connecting");
};
Connection.prototype.isProtocolSupported = function isProtocolSupported() {
return indexOf.call(supportedProtocols, this.getProtocol()) >= 0;
};
Connection.prototype.isState = function isState() {
for (var _len = arguments.length, states = Array(_len), _key = 0; _key < _len; _key++) {
states[_key] = arguments[_key];
}
return indexOf.call(states, this.getState()) >= 0;
};
Connection.prototype.getState = function getState() {
if (this.webSocket) {
for (var state in adapters.WebSocket) {
if (adapters.WebSocket[state] === this.webSocket.readyState) {
Convert ActionCable javascript to ES2015 modules with modern build environment We've replaced the sprockets `//= require` directives with ES2015 imports. As a result, the ActionCable javascript can now be compiled with rollup (like ActiveStorage already is). - Rename action_cable/index.js.erb -> action_cable/index.js - Add rake task to generate a javascript module of the ActionCable::INTERNAL ruby hash This will allow us to get rid of ERB from the actioncable javascript, since it is only used to interpolate ActionCable::INTERNAL.to_json. - Import INTERNAL directly in ActionCable Connection module This is necessary to remove a load-order dependency conflict in the rollup-compiled build. Using ActionCable.INTERNAL would result in a runtime error: ``` TypeError: Cannot read property 'INTERNAL' of undefined ``` because ActionCable.INTERNAL is not set before the Connection module is executed. All other ActionCable.* references are executed inside of the body of a function, so there is no load-order dependency there. - Add eslint and eslint-plugin-import devDependencies to actioncable These will be used to add a linting setup to actioncable like the one in activestorage. - Add .eslintrc to actioncable This lint configuration was copied from activestorage - Add lint script to actioncable This is the same as the lint script in activestorage - Add babel-core, babel-plugin-external-helpers, and babel-preset-env devDependencies to actioncable These will be used to add ES2015 transpilation support to actioncable like we have in activestorage. - Add .babelrc to actioncable This configuration was copied from activestorage - Enable loose mode in ActionCable's babel config This generates a smaller bundle when compiled - Add rollup devDependencies to actioncable These will be used to add a modern build pipeline to actioncable like the one in activestorage. - Add rollup config to actioncable This is essentially the same as the rollup config from activestorage - Add prebuild and build scripts to actioncable package These scripts were copied from activestorage - Invoke code generation task as part of actioncable's prebuild script This will guarantee that the action_cable/internal.js module is available at build time (which is important, because two other modules now depend on it). - Update actioncable package to reference the rollup-compiled files Now that we have a fully functional rollup pipeline in actioncable, we can use the compiled output in our npm package. - Remove build section from ActionCable blade config Now that rollup is responsible for building ActionCable, we can remove that responsibility from Blade. - Remove assets:compile and assets:verify tasks from ActionCable Now that we've added a compiled ActionCable bundle to version control, we don't need to compile and verify it at publish-time. (We're following the pattern set in ActiveStorage.) - Include compiled ActionCable javascript bundle in published gem This is necessary to maintain support for depending on the ActionCable javascript through the Sprockets asset pipeline. - Add compiled ActionCable bundle to version control This mirrors what we do in ActiveStorage, and allows ActionCable to continue to be consumed via the sprockets-based asset pipeline when using a git source instead of a published version of the gem.
2018-01-21 02:33:32 -05:00
return state.toLowerCase();
}
}
}
return null;
};
Connection.prototype.installEventHandlers = function installEventHandlers() {
for (var eventName in this.events) {
var handler = this.events[eventName].bind(this);
this.webSocket["on" + eventName] = handler;
}
};
Connection.prototype.uninstallEventHandlers = function uninstallEventHandlers() {
for (var eventName in this.events) {
this.webSocket["on" + eventName] = function() {};
}
};
return Connection;
}();
Connection.reopenDelay = 500;
Connection.prototype.events = {
message: function message(event) {
if (!this.isProtocolSupported()) {
return;
}
var _JSON$parse = JSON.parse(event.data), identifier = _JSON$parse.identifier, message = _JSON$parse.message, reason = _JSON$parse.reason, reconnect = _JSON$parse.reconnect, type = _JSON$parse.type;
Convert ActionCable javascript to ES2015 modules with modern build environment We've replaced the sprockets `//= require` directives with ES2015 imports. As a result, the ActionCable javascript can now be compiled with rollup (like ActiveStorage already is). - Rename action_cable/index.js.erb -> action_cable/index.js - Add rake task to generate a javascript module of the ActionCable::INTERNAL ruby hash This will allow us to get rid of ERB from the actioncable javascript, since it is only used to interpolate ActionCable::INTERNAL.to_json. - Import INTERNAL directly in ActionCable Connection module This is necessary to remove a load-order dependency conflict in the rollup-compiled build. Using ActionCable.INTERNAL would result in a runtime error: ``` TypeError: Cannot read property 'INTERNAL' of undefined ``` because ActionCable.INTERNAL is not set before the Connection module is executed. All other ActionCable.* references are executed inside of the body of a function, so there is no load-order dependency there. - Add eslint and eslint-plugin-import devDependencies to actioncable These will be used to add a linting setup to actioncable like the one in activestorage. - Add .eslintrc to actioncable This lint configuration was copied from activestorage - Add lint script to actioncable This is the same as the lint script in activestorage - Add babel-core, babel-plugin-external-helpers, and babel-preset-env devDependencies to actioncable These will be used to add ES2015 transpilation support to actioncable like we have in activestorage. - Add .babelrc to actioncable This configuration was copied from activestorage - Enable loose mode in ActionCable's babel config This generates a smaller bundle when compiled - Add rollup devDependencies to actioncable These will be used to add a modern build pipeline to actioncable like the one in activestorage. - Add rollup config to actioncable This is essentially the same as the rollup config from activestorage - Add prebuild and build scripts to actioncable package These scripts were copied from activestorage - Invoke code generation task as part of actioncable's prebuild script This will guarantee that the action_cable/internal.js module is available at build time (which is important, because two other modules now depend on it). - Update actioncable package to reference the rollup-compiled files Now that we have a fully functional rollup pipeline in actioncable, we can use the compiled output in our npm package. - Remove build section from ActionCable blade config Now that rollup is responsible for building ActionCable, we can remove that responsibility from Blade. - Remove assets:compile and assets:verify tasks from ActionCable Now that we've added a compiled ActionCable bundle to version control, we don't need to compile and verify it at publish-time. (We're following the pattern set in ActiveStorage.) - Include compiled ActionCable javascript bundle in published gem This is necessary to maintain support for depending on the ActionCable javascript through the Sprockets asset pipeline. - Add compiled ActionCable bundle to version control This mirrors what we do in ActiveStorage, and allows ActionCable to continue to be consumed via the sprockets-based asset pipeline when using a git source instead of a published version of the gem.
2018-01-21 02:33:32 -05:00
switch (type) {
case message_types.welcome:
this.monitor.recordConnect();
return this.subscriptions.reload();
case message_types.disconnect:
logger.log("Disconnecting. Reason: " + reason);
return this.close({
allowReconnect: reconnect
});
Convert ActionCable javascript to ES2015 modules with modern build environment We've replaced the sprockets `//= require` directives with ES2015 imports. As a result, the ActionCable javascript can now be compiled with rollup (like ActiveStorage already is). - Rename action_cable/index.js.erb -> action_cable/index.js - Add rake task to generate a javascript module of the ActionCable::INTERNAL ruby hash This will allow us to get rid of ERB from the actioncable javascript, since it is only used to interpolate ActionCable::INTERNAL.to_json. - Import INTERNAL directly in ActionCable Connection module This is necessary to remove a load-order dependency conflict in the rollup-compiled build. Using ActionCable.INTERNAL would result in a runtime error: ``` TypeError: Cannot read property 'INTERNAL' of undefined ``` because ActionCable.INTERNAL is not set before the Connection module is executed. All other ActionCable.* references are executed inside of the body of a function, so there is no load-order dependency there. - Add eslint and eslint-plugin-import devDependencies to actioncable These will be used to add a linting setup to actioncable like the one in activestorage. - Add .eslintrc to actioncable This lint configuration was copied from activestorage - Add lint script to actioncable This is the same as the lint script in activestorage - Add babel-core, babel-plugin-external-helpers, and babel-preset-env devDependencies to actioncable These will be used to add ES2015 transpilation support to actioncable like we have in activestorage. - Add .babelrc to actioncable This configuration was copied from activestorage - Enable loose mode in ActionCable's babel config This generates a smaller bundle when compiled - Add rollup devDependencies to actioncable These will be used to add a modern build pipeline to actioncable like the one in activestorage. - Add rollup config to actioncable This is essentially the same as the rollup config from activestorage - Add prebuild and build scripts to actioncable package These scripts were copied from activestorage - Invoke code generation task as part of actioncable's prebuild script This will guarantee that the action_cable/internal.js module is available at build time (which is important, because two other modules now depend on it). - Update actioncable package to reference the rollup-compiled files Now that we have a fully functional rollup pipeline in actioncable, we can use the compiled output in our npm package. - Remove build section from ActionCable blade config Now that rollup is responsible for building ActionCable, we can remove that responsibility from Blade. - Remove assets:compile and assets:verify tasks from ActionCable Now that we've added a compiled ActionCable bundle to version control, we don't need to compile and verify it at publish-time. (We're following the pattern set in ActiveStorage.) - Include compiled ActionCable javascript bundle in published gem This is necessary to maintain support for depending on the ActionCable javascript through the Sprockets asset pipeline. - Add compiled ActionCable bundle to version control This mirrors what we do in ActiveStorage, and allows ActionCable to continue to be consumed via the sprockets-based asset pipeline when using a git source instead of a published version of the gem.
2018-01-21 02:33:32 -05:00
case message_types.ping:
return this.monitor.recordPing();
case message_types.confirmation:
return this.subscriptions.notify(identifier, "connected");
case message_types.rejection:
return this.subscriptions.reject(identifier);
default:
return this.subscriptions.notify(identifier, "received", message);
}
},
open: function open() {
Remove circular dependency warnings in ActionCable javascript and publish source modules with fine-grained exports (#34370) * Replace several ActionCable.* references with finer-grained imports This reduces the number of circular dependencies among the module imports from 4: ``` (!) Circular dependency: app/javascript/action_cable/index.js -> app/javascript/action_cable/connection.js -> app/javascript/action_cable/index.js (!) Circular dependency: app/javascript/action_cable/index.js -> app/javascript/action_cable/connection_monitor.js -> app/javascript/action_cable/index.js (!) Circular dependency: app/javascript/action_cable/index.js -> app/javascript/action_cable/consumer.js -> app/javascript/action_cable/index.js (!) Circular dependency: app/javascript/action_cable/index.js -> app/javascript/action_cable/subscriptions.js -> app/javascript/action_cable/index.js ``` to 2: ``` (!) Circular dependency: app/javascript/action_cable/index.js -> app/javascript/action_cable/connection.js -> app/javascript/action_cable/index.js (!) Circular dependency: app/javascript/action_cable/index.js -> app/javascript/action_cable/connection.js -> app/javascript/action_cable/connection_monitor.js -> app/javascript/action_cable/index.js ``` * Remove tests that only test javascript object property assignment These tests really only assert that you can assign a property to the ActionCable global object. That's true for pretty much any object in javascript (it would only be false if the object has been frozen, or has explicitly set some properties to be nonconfigurable). * Refactor ActionCable to provide individual named exports By providing individual named exports rather than a default export which is an object with all of those properties, we enable applications to only import the functions they need: any unused functions will be removed via tree shaking. Additionally, this restructuring removes the remaining circular dependencies by extracting the separate adapters and logger modules, so there are now no warnings when compiling the ActionCable bundle. Note: This produces two small breaking API changes: - The `ActionCable.WebSocket` getter and setter would be moved to `ActionCable.adapters.WebSocket`. If a user is currently configuring this, when upgrading they'd need to either add a delegated getter/setter themselves, or change it like this: ```diff - ActionCable.WebSocket = MyWebSocket + ActionCable.adapters.WebSocket = MyWebSocket ``` Applications which don't change the WebSocket adapter would not need any changes for this when upgrading. - Similarly, the `ActionCable.logger` getter and setter would be moved to `ActionCable.adapters.logger`. If a user is currently configuring this, when upgrading they'd need to either add a delegated getter/setter themselves, or change it like this: ```diff - ActionCable.logger = myLogger + ActionCable.adapters.logger = myLogger ``` Applications which don't change the logger would not need any changes for this when upgrading. These two aspects of the public API have to change because there's no way to export a property setter for `WebSocket` (or `logger`) such that this: ```js import ActionCable from "actioncable" ActionCable.WebSocket = MyWebSocket ``` would actually update `adapters.WebSocket`. (We can only offer that if we have two separate source files like if `index.js` uses `import * as ActionCable from "./action_cable" and then exports a wrapper which has delegated getters and setters for those properties.) This API change is very minor - it should be easy for applications to add the `adapters.` prefix in their assignments or to patch in delegated setters. And especially because most applications in the wild are not ever changing the default value of `ActionCable.WebSocket` or `ActionCable.logger` (because the default values are perfect), this API breakage is worth the tree-shaking benefits we gain. * Include source code in published actioncable npm package This allows actioncable users to ship smaller javascript bundles to visitors using modern browsers, as demonstrated in this repository: https://github.com/rmacklin/actioncable-es2015-build-example In that example, the bundle shrinks by 2.8K (25.2%) when you simply change the actioncable import to point to the untranspiled src. If you go a step further, like this: ``` diff --git a/app/scripts/main.js b/app/scripts/main.js index 17bc031..1a2b2e0 100644 --- a/app/scripts/main.js +++ b/app/scripts/main.js @@ -1,6 +1,6 @@ -import ActionCable from 'actioncable'; +import * as ActionCable from 'actioncable'; let cable = ActionCable.createConsumer('wss://cable.example.com'); cable.subscriptions.create('AppearanceChannel', { ``` then the bundle shrinks by 3.6K (31.7%)! In addition to allowing smaller bundles for those who ship untranspiled code to modern browsers, including the source code in the published package can be useful in other ways: 1. Users can import individual modules rather than the whole library 2. As a result of (1), users can also monkey patch parts of actioncable by importing the relevant module, modifying the exported object, and then importing the rest of actioncable (which would then use the patched object). Note: This is the same enhancement that we made to activestorage in c0368ad090b79c19300a4aa133bb188b2d9ab611 * Remove unused commonjs & resolve plugins from ActionCable rollup config These were added when we copied the rollup config from ActiveStorage, but ActionCable does not have any commonjs dependencies (it doesn't have any external dependencies at all), so these plugins are unnecessary here * Change ActionCable.startDebugging() -> ActionCable.logger.enabled=true and ActionCable.stopDebugging() -> ActionCable.logger.enabled=false This API is simpler and more clearly describes what it does * Change Travis configuration to run yarn install at the root for ActionCable builds This is necessary now that the repository is using Yarn Workspaces
2018-12-01 16:25:02 -05:00
logger.log("WebSocket onopen event, using '" + this.getProtocol() + "' subprotocol");
Convert ActionCable javascript to ES2015 modules with modern build environment We've replaced the sprockets `//= require` directives with ES2015 imports. As a result, the ActionCable javascript can now be compiled with rollup (like ActiveStorage already is). - Rename action_cable/index.js.erb -> action_cable/index.js - Add rake task to generate a javascript module of the ActionCable::INTERNAL ruby hash This will allow us to get rid of ERB from the actioncable javascript, since it is only used to interpolate ActionCable::INTERNAL.to_json. - Import INTERNAL directly in ActionCable Connection module This is necessary to remove a load-order dependency conflict in the rollup-compiled build. Using ActionCable.INTERNAL would result in a runtime error: ``` TypeError: Cannot read property 'INTERNAL' of undefined ``` because ActionCable.INTERNAL is not set before the Connection module is executed. All other ActionCable.* references are executed inside of the body of a function, so there is no load-order dependency there. - Add eslint and eslint-plugin-import devDependencies to actioncable These will be used to add a linting setup to actioncable like the one in activestorage. - Add .eslintrc to actioncable This lint configuration was copied from activestorage - Add lint script to actioncable This is the same as the lint script in activestorage - Add babel-core, babel-plugin-external-helpers, and babel-preset-env devDependencies to actioncable These will be used to add ES2015 transpilation support to actioncable like we have in activestorage. - Add .babelrc to actioncable This configuration was copied from activestorage - Enable loose mode in ActionCable's babel config This generates a smaller bundle when compiled - Add rollup devDependencies to actioncable These will be used to add a modern build pipeline to actioncable like the one in activestorage. - Add rollup config to actioncable This is essentially the same as the rollup config from activestorage - Add prebuild and build scripts to actioncable package These scripts were copied from activestorage - Invoke code generation task as part of actioncable's prebuild script This will guarantee that the action_cable/internal.js module is available at build time (which is important, because two other modules now depend on it). - Update actioncable package to reference the rollup-compiled files Now that we have a fully functional rollup pipeline in actioncable, we can use the compiled output in our npm package. - Remove build section from ActionCable blade config Now that rollup is responsible for building ActionCable, we can remove that responsibility from Blade. - Remove assets:compile and assets:verify tasks from ActionCable Now that we've added a compiled ActionCable bundle to version control, we don't need to compile and verify it at publish-time. (We're following the pattern set in ActiveStorage.) - Include compiled ActionCable javascript bundle in published gem This is necessary to maintain support for depending on the ActionCable javascript through the Sprockets asset pipeline. - Add compiled ActionCable bundle to version control This mirrors what we do in ActiveStorage, and allows ActionCable to continue to be consumed via the sprockets-based asset pipeline when using a git source instead of a published version of the gem.
2018-01-21 02:33:32 -05:00
this.disconnected = false;
if (!this.isProtocolSupported()) {
Remove circular dependency warnings in ActionCable javascript and publish source modules with fine-grained exports (#34370) * Replace several ActionCable.* references with finer-grained imports This reduces the number of circular dependencies among the module imports from 4: ``` (!) Circular dependency: app/javascript/action_cable/index.js -> app/javascript/action_cable/connection.js -> app/javascript/action_cable/index.js (!) Circular dependency: app/javascript/action_cable/index.js -> app/javascript/action_cable/connection_monitor.js -> app/javascript/action_cable/index.js (!) Circular dependency: app/javascript/action_cable/index.js -> app/javascript/action_cable/consumer.js -> app/javascript/action_cable/index.js (!) Circular dependency: app/javascript/action_cable/index.js -> app/javascript/action_cable/subscriptions.js -> app/javascript/action_cable/index.js ``` to 2: ``` (!) Circular dependency: app/javascript/action_cable/index.js -> app/javascript/action_cable/connection.js -> app/javascript/action_cable/index.js (!) Circular dependency: app/javascript/action_cable/index.js -> app/javascript/action_cable/connection.js -> app/javascript/action_cable/connection_monitor.js -> app/javascript/action_cable/index.js ``` * Remove tests that only test javascript object property assignment These tests really only assert that you can assign a property to the ActionCable global object. That's true for pretty much any object in javascript (it would only be false if the object has been frozen, or has explicitly set some properties to be nonconfigurable). * Refactor ActionCable to provide individual named exports By providing individual named exports rather than a default export which is an object with all of those properties, we enable applications to only import the functions they need: any unused functions will be removed via tree shaking. Additionally, this restructuring removes the remaining circular dependencies by extracting the separate adapters and logger modules, so there are now no warnings when compiling the ActionCable bundle. Note: This produces two small breaking API changes: - The `ActionCable.WebSocket` getter and setter would be moved to `ActionCable.adapters.WebSocket`. If a user is currently configuring this, when upgrading they'd need to either add a delegated getter/setter themselves, or change it like this: ```diff - ActionCable.WebSocket = MyWebSocket + ActionCable.adapters.WebSocket = MyWebSocket ``` Applications which don't change the WebSocket adapter would not need any changes for this when upgrading. - Similarly, the `ActionCable.logger` getter and setter would be moved to `ActionCable.adapters.logger`. If a user is currently configuring this, when upgrading they'd need to either add a delegated getter/setter themselves, or change it like this: ```diff - ActionCable.logger = myLogger + ActionCable.adapters.logger = myLogger ``` Applications which don't change the logger would not need any changes for this when upgrading. These two aspects of the public API have to change because there's no way to export a property setter for `WebSocket` (or `logger`) such that this: ```js import ActionCable from "actioncable" ActionCable.WebSocket = MyWebSocket ``` would actually update `adapters.WebSocket`. (We can only offer that if we have two separate source files like if `index.js` uses `import * as ActionCable from "./action_cable" and then exports a wrapper which has delegated getters and setters for those properties.) This API change is very minor - it should be easy for applications to add the `adapters.` prefix in their assignments or to patch in delegated setters. And especially because most applications in the wild are not ever changing the default value of `ActionCable.WebSocket` or `ActionCable.logger` (because the default values are perfect), this API breakage is worth the tree-shaking benefits we gain. * Include source code in published actioncable npm package This allows actioncable users to ship smaller javascript bundles to visitors using modern browsers, as demonstrated in this repository: https://github.com/rmacklin/actioncable-es2015-build-example In that example, the bundle shrinks by 2.8K (25.2%) when you simply change the actioncable import to point to the untranspiled src. If you go a step further, like this: ``` diff --git a/app/scripts/main.js b/app/scripts/main.js index 17bc031..1a2b2e0 100644 --- a/app/scripts/main.js +++ b/app/scripts/main.js @@ -1,6 +1,6 @@ -import ActionCable from 'actioncable'; +import * as ActionCable from 'actioncable'; let cable = ActionCable.createConsumer('wss://cable.example.com'); cable.subscriptions.create('AppearanceChannel', { ``` then the bundle shrinks by 3.6K (31.7%)! In addition to allowing smaller bundles for those who ship untranspiled code to modern browsers, including the source code in the published package can be useful in other ways: 1. Users can import individual modules rather than the whole library 2. As a result of (1), users can also monkey patch parts of actioncable by importing the relevant module, modifying the exported object, and then importing the rest of actioncable (which would then use the patched object). Note: This is the same enhancement that we made to activestorage in c0368ad090b79c19300a4aa133bb188b2d9ab611 * Remove unused commonjs & resolve plugins from ActionCable rollup config These were added when we copied the rollup config from ActiveStorage, but ActionCable does not have any commonjs dependencies (it doesn't have any external dependencies at all), so these plugins are unnecessary here * Change ActionCable.startDebugging() -> ActionCable.logger.enabled=true and ActionCable.stopDebugging() -> ActionCable.logger.enabled=false This API is simpler and more clearly describes what it does * Change Travis configuration to run yarn install at the root for ActionCable builds This is necessary now that the repository is using Yarn Workspaces
2018-12-01 16:25:02 -05:00
logger.log("Protocol is unsupported. Stopping monitor and disconnecting.");
Convert ActionCable javascript to ES2015 modules with modern build environment We've replaced the sprockets `//= require` directives with ES2015 imports. As a result, the ActionCable javascript can now be compiled with rollup (like ActiveStorage already is). - Rename action_cable/index.js.erb -> action_cable/index.js - Add rake task to generate a javascript module of the ActionCable::INTERNAL ruby hash This will allow us to get rid of ERB from the actioncable javascript, since it is only used to interpolate ActionCable::INTERNAL.to_json. - Import INTERNAL directly in ActionCable Connection module This is necessary to remove a load-order dependency conflict in the rollup-compiled build. Using ActionCable.INTERNAL would result in a runtime error: ``` TypeError: Cannot read property 'INTERNAL' of undefined ``` because ActionCable.INTERNAL is not set before the Connection module is executed. All other ActionCable.* references are executed inside of the body of a function, so there is no load-order dependency there. - Add eslint and eslint-plugin-import devDependencies to actioncable These will be used to add a linting setup to actioncable like the one in activestorage. - Add .eslintrc to actioncable This lint configuration was copied from activestorage - Add lint script to actioncable This is the same as the lint script in activestorage - Add babel-core, babel-plugin-external-helpers, and babel-preset-env devDependencies to actioncable These will be used to add ES2015 transpilation support to actioncable like we have in activestorage. - Add .babelrc to actioncable This configuration was copied from activestorage - Enable loose mode in ActionCable's babel config This generates a smaller bundle when compiled - Add rollup devDependencies to actioncable These will be used to add a modern build pipeline to actioncable like the one in activestorage. - Add rollup config to actioncable This is essentially the same as the rollup config from activestorage - Add prebuild and build scripts to actioncable package These scripts were copied from activestorage - Invoke code generation task as part of actioncable's prebuild script This will guarantee that the action_cable/internal.js module is available at build time (which is important, because two other modules now depend on it). - Update actioncable package to reference the rollup-compiled files Now that we have a fully functional rollup pipeline in actioncable, we can use the compiled output in our npm package. - Remove build section from ActionCable blade config Now that rollup is responsible for building ActionCable, we can remove that responsibility from Blade. - Remove assets:compile and assets:verify tasks from ActionCable Now that we've added a compiled ActionCable bundle to version control, we don't need to compile and verify it at publish-time. (We're following the pattern set in ActiveStorage.) - Include compiled ActionCable javascript bundle in published gem This is necessary to maintain support for depending on the ActionCable javascript through the Sprockets asset pipeline. - Add compiled ActionCable bundle to version control This mirrors what we do in ActiveStorage, and allows ActionCable to continue to be consumed via the sprockets-based asset pipeline when using a git source instead of a published version of the gem.
2018-01-21 02:33:32 -05:00
return this.close({
allowReconnect: false
});
}
},
close: function close(event) {
Remove circular dependency warnings in ActionCable javascript and publish source modules with fine-grained exports (#34370) * Replace several ActionCable.* references with finer-grained imports This reduces the number of circular dependencies among the module imports from 4: ``` (!) Circular dependency: app/javascript/action_cable/index.js -> app/javascript/action_cable/connection.js -> app/javascript/action_cable/index.js (!) Circular dependency: app/javascript/action_cable/index.js -> app/javascript/action_cable/connection_monitor.js -> app/javascript/action_cable/index.js (!) Circular dependency: app/javascript/action_cable/index.js -> app/javascript/action_cable/consumer.js -> app/javascript/action_cable/index.js (!) Circular dependency: app/javascript/action_cable/index.js -> app/javascript/action_cable/subscriptions.js -> app/javascript/action_cable/index.js ``` to 2: ``` (!) Circular dependency: app/javascript/action_cable/index.js -> app/javascript/action_cable/connection.js -> app/javascript/action_cable/index.js (!) Circular dependency: app/javascript/action_cable/index.js -> app/javascript/action_cable/connection.js -> app/javascript/action_cable/connection_monitor.js -> app/javascript/action_cable/index.js ``` * Remove tests that only test javascript object property assignment These tests really only assert that you can assign a property to the ActionCable global object. That's true for pretty much any object in javascript (it would only be false if the object has been frozen, or has explicitly set some properties to be nonconfigurable). * Refactor ActionCable to provide individual named exports By providing individual named exports rather than a default export which is an object with all of those properties, we enable applications to only import the functions they need: any unused functions will be removed via tree shaking. Additionally, this restructuring removes the remaining circular dependencies by extracting the separate adapters and logger modules, so there are now no warnings when compiling the ActionCable bundle. Note: This produces two small breaking API changes: - The `ActionCable.WebSocket` getter and setter would be moved to `ActionCable.adapters.WebSocket`. If a user is currently configuring this, when upgrading they'd need to either add a delegated getter/setter themselves, or change it like this: ```diff - ActionCable.WebSocket = MyWebSocket + ActionCable.adapters.WebSocket = MyWebSocket ``` Applications which don't change the WebSocket adapter would not need any changes for this when upgrading. - Similarly, the `ActionCable.logger` getter and setter would be moved to `ActionCable.adapters.logger`. If a user is currently configuring this, when upgrading they'd need to either add a delegated getter/setter themselves, or change it like this: ```diff - ActionCable.logger = myLogger + ActionCable.adapters.logger = myLogger ``` Applications which don't change the logger would not need any changes for this when upgrading. These two aspects of the public API have to change because there's no way to export a property setter for `WebSocket` (or `logger`) such that this: ```js import ActionCable from "actioncable" ActionCable.WebSocket = MyWebSocket ``` would actually update `adapters.WebSocket`. (We can only offer that if we have two separate source files like if `index.js` uses `import * as ActionCable from "./action_cable" and then exports a wrapper which has delegated getters and setters for those properties.) This API change is very minor - it should be easy for applications to add the `adapters.` prefix in their assignments or to patch in delegated setters. And especially because most applications in the wild are not ever changing the default value of `ActionCable.WebSocket` or `ActionCable.logger` (because the default values are perfect), this API breakage is worth the tree-shaking benefits we gain. * Include source code in published actioncable npm package This allows actioncable users to ship smaller javascript bundles to visitors using modern browsers, as demonstrated in this repository: https://github.com/rmacklin/actioncable-es2015-build-example In that example, the bundle shrinks by 2.8K (25.2%) when you simply change the actioncable import to point to the untranspiled src. If you go a step further, like this: ``` diff --git a/app/scripts/main.js b/app/scripts/main.js index 17bc031..1a2b2e0 100644 --- a/app/scripts/main.js +++ b/app/scripts/main.js @@ -1,6 +1,6 @@ -import ActionCable from 'actioncable'; +import * as ActionCable from 'actioncable'; let cable = ActionCable.createConsumer('wss://cable.example.com'); cable.subscriptions.create('AppearanceChannel', { ``` then the bundle shrinks by 3.6K (31.7%)! In addition to allowing smaller bundles for those who ship untranspiled code to modern browsers, including the source code in the published package can be useful in other ways: 1. Users can import individual modules rather than the whole library 2. As a result of (1), users can also monkey patch parts of actioncable by importing the relevant module, modifying the exported object, and then importing the rest of actioncable (which would then use the patched object). Note: This is the same enhancement that we made to activestorage in c0368ad090b79c19300a4aa133bb188b2d9ab611 * Remove unused commonjs & resolve plugins from ActionCable rollup config These were added when we copied the rollup config from ActiveStorage, but ActionCable does not have any commonjs dependencies (it doesn't have any external dependencies at all), so these plugins are unnecessary here * Change ActionCable.startDebugging() -> ActionCable.logger.enabled=true and ActionCable.stopDebugging() -> ActionCable.logger.enabled=false This API is simpler and more clearly describes what it does * Change Travis configuration to run yarn install at the root for ActionCable builds This is necessary now that the repository is using Yarn Workspaces
2018-12-01 16:25:02 -05:00
logger.log("WebSocket onclose event");
Convert ActionCable javascript to ES2015 modules with modern build environment We've replaced the sprockets `//= require` directives with ES2015 imports. As a result, the ActionCable javascript can now be compiled with rollup (like ActiveStorage already is). - Rename action_cable/index.js.erb -> action_cable/index.js - Add rake task to generate a javascript module of the ActionCable::INTERNAL ruby hash This will allow us to get rid of ERB from the actioncable javascript, since it is only used to interpolate ActionCable::INTERNAL.to_json. - Import INTERNAL directly in ActionCable Connection module This is necessary to remove a load-order dependency conflict in the rollup-compiled build. Using ActionCable.INTERNAL would result in a runtime error: ``` TypeError: Cannot read property 'INTERNAL' of undefined ``` because ActionCable.INTERNAL is not set before the Connection module is executed. All other ActionCable.* references are executed inside of the body of a function, so there is no load-order dependency there. - Add eslint and eslint-plugin-import devDependencies to actioncable These will be used to add a linting setup to actioncable like the one in activestorage. - Add .eslintrc to actioncable This lint configuration was copied from activestorage - Add lint script to actioncable This is the same as the lint script in activestorage - Add babel-core, babel-plugin-external-helpers, and babel-preset-env devDependencies to actioncable These will be used to add ES2015 transpilation support to actioncable like we have in activestorage. - Add .babelrc to actioncable This configuration was copied from activestorage - Enable loose mode in ActionCable's babel config This generates a smaller bundle when compiled - Add rollup devDependencies to actioncable These will be used to add a modern build pipeline to actioncable like the one in activestorage. - Add rollup config to actioncable This is essentially the same as the rollup config from activestorage - Add prebuild and build scripts to actioncable package These scripts were copied from activestorage - Invoke code generation task as part of actioncable's prebuild script This will guarantee that the action_cable/internal.js module is available at build time (which is important, because two other modules now depend on it). - Update actioncable package to reference the rollup-compiled files Now that we have a fully functional rollup pipeline in actioncable, we can use the compiled output in our npm package. - Remove build section from ActionCable blade config Now that rollup is responsible for building ActionCable, we can remove that responsibility from Blade. - Remove assets:compile and assets:verify tasks from ActionCable Now that we've added a compiled ActionCable bundle to version control, we don't need to compile and verify it at publish-time. (We're following the pattern set in ActiveStorage.) - Include compiled ActionCable javascript bundle in published gem This is necessary to maintain support for depending on the ActionCable javascript through the Sprockets asset pipeline. - Add compiled ActionCable bundle to version control This mirrors what we do in ActiveStorage, and allows ActionCable to continue to be consumed via the sprockets-based asset pipeline when using a git source instead of a published version of the gem.
2018-01-21 02:33:32 -05:00
if (this.disconnected) {
return;
}
this.disconnected = true;
this.monitor.recordDisconnect();
return this.subscriptions.notifyAll("disconnected", {
willAttemptReconnect: this.monitor.isRunning()
});
},
error: function error() {
Remove circular dependency warnings in ActionCable javascript and publish source modules with fine-grained exports (#34370) * Replace several ActionCable.* references with finer-grained imports This reduces the number of circular dependencies among the module imports from 4: ``` (!) Circular dependency: app/javascript/action_cable/index.js -> app/javascript/action_cable/connection.js -> app/javascript/action_cable/index.js (!) Circular dependency: app/javascript/action_cable/index.js -> app/javascript/action_cable/connection_monitor.js -> app/javascript/action_cable/index.js (!) Circular dependency: app/javascript/action_cable/index.js -> app/javascript/action_cable/consumer.js -> app/javascript/action_cable/index.js (!) Circular dependency: app/javascript/action_cable/index.js -> app/javascript/action_cable/subscriptions.js -> app/javascript/action_cable/index.js ``` to 2: ``` (!) Circular dependency: app/javascript/action_cable/index.js -> app/javascript/action_cable/connection.js -> app/javascript/action_cable/index.js (!) Circular dependency: app/javascript/action_cable/index.js -> app/javascript/action_cable/connection.js -> app/javascript/action_cable/connection_monitor.js -> app/javascript/action_cable/index.js ``` * Remove tests that only test javascript object property assignment These tests really only assert that you can assign a property to the ActionCable global object. That's true for pretty much any object in javascript (it would only be false if the object has been frozen, or has explicitly set some properties to be nonconfigurable). * Refactor ActionCable to provide individual named exports By providing individual named exports rather than a default export which is an object with all of those properties, we enable applications to only import the functions they need: any unused functions will be removed via tree shaking. Additionally, this restructuring removes the remaining circular dependencies by extracting the separate adapters and logger modules, so there are now no warnings when compiling the ActionCable bundle. Note: This produces two small breaking API changes: - The `ActionCable.WebSocket` getter and setter would be moved to `ActionCable.adapters.WebSocket`. If a user is currently configuring this, when upgrading they'd need to either add a delegated getter/setter themselves, or change it like this: ```diff - ActionCable.WebSocket = MyWebSocket + ActionCable.adapters.WebSocket = MyWebSocket ``` Applications which don't change the WebSocket adapter would not need any changes for this when upgrading. - Similarly, the `ActionCable.logger` getter and setter would be moved to `ActionCable.adapters.logger`. If a user is currently configuring this, when upgrading they'd need to either add a delegated getter/setter themselves, or change it like this: ```diff - ActionCable.logger = myLogger + ActionCable.adapters.logger = myLogger ``` Applications which don't change the logger would not need any changes for this when upgrading. These two aspects of the public API have to change because there's no way to export a property setter for `WebSocket` (or `logger`) such that this: ```js import ActionCable from "actioncable" ActionCable.WebSocket = MyWebSocket ``` would actually update `adapters.WebSocket`. (We can only offer that if we have two separate source files like if `index.js` uses `import * as ActionCable from "./action_cable" and then exports a wrapper which has delegated getters and setters for those properties.) This API change is very minor - it should be easy for applications to add the `adapters.` prefix in their assignments or to patch in delegated setters. And especially because most applications in the wild are not ever changing the default value of `ActionCable.WebSocket` or `ActionCable.logger` (because the default values are perfect), this API breakage is worth the tree-shaking benefits we gain. * Include source code in published actioncable npm package This allows actioncable users to ship smaller javascript bundles to visitors using modern browsers, as demonstrated in this repository: https://github.com/rmacklin/actioncable-es2015-build-example In that example, the bundle shrinks by 2.8K (25.2%) when you simply change the actioncable import to point to the untranspiled src. If you go a step further, like this: ``` diff --git a/app/scripts/main.js b/app/scripts/main.js index 17bc031..1a2b2e0 100644 --- a/app/scripts/main.js +++ b/app/scripts/main.js @@ -1,6 +1,6 @@ -import ActionCable from 'actioncable'; +import * as ActionCable from 'actioncable'; let cable = ActionCable.createConsumer('wss://cable.example.com'); cable.subscriptions.create('AppearanceChannel', { ``` then the bundle shrinks by 3.6K (31.7%)! In addition to allowing smaller bundles for those who ship untranspiled code to modern browsers, including the source code in the published package can be useful in other ways: 1. Users can import individual modules rather than the whole library 2. As a result of (1), users can also monkey patch parts of actioncable by importing the relevant module, modifying the exported object, and then importing the rest of actioncable (which would then use the patched object). Note: This is the same enhancement that we made to activestorage in c0368ad090b79c19300a4aa133bb188b2d9ab611 * Remove unused commonjs & resolve plugins from ActionCable rollup config These were added when we copied the rollup config from ActiveStorage, but ActionCable does not have any commonjs dependencies (it doesn't have any external dependencies at all), so these plugins are unnecessary here * Change ActionCable.startDebugging() -> ActionCable.logger.enabled=true and ActionCable.stopDebugging() -> ActionCable.logger.enabled=false This API is simpler and more clearly describes what it does * Change Travis configuration to run yarn install at the root for ActionCable builds This is necessary now that the repository is using Yarn Workspaces
2018-12-01 16:25:02 -05:00
logger.log("WebSocket onerror event");
Convert ActionCable javascript to ES2015 modules with modern build environment We've replaced the sprockets `//= require` directives with ES2015 imports. As a result, the ActionCable javascript can now be compiled with rollup (like ActiveStorage already is). - Rename action_cable/index.js.erb -> action_cable/index.js - Add rake task to generate a javascript module of the ActionCable::INTERNAL ruby hash This will allow us to get rid of ERB from the actioncable javascript, since it is only used to interpolate ActionCable::INTERNAL.to_json. - Import INTERNAL directly in ActionCable Connection module This is necessary to remove a load-order dependency conflict in the rollup-compiled build. Using ActionCable.INTERNAL would result in a runtime error: ``` TypeError: Cannot read property 'INTERNAL' of undefined ``` because ActionCable.INTERNAL is not set before the Connection module is executed. All other ActionCable.* references are executed inside of the body of a function, so there is no load-order dependency there. - Add eslint and eslint-plugin-import devDependencies to actioncable These will be used to add a linting setup to actioncable like the one in activestorage. - Add .eslintrc to actioncable This lint configuration was copied from activestorage - Add lint script to actioncable This is the same as the lint script in activestorage - Add babel-core, babel-plugin-external-helpers, and babel-preset-env devDependencies to actioncable These will be used to add ES2015 transpilation support to actioncable like we have in activestorage. - Add .babelrc to actioncable This configuration was copied from activestorage - Enable loose mode in ActionCable's babel config This generates a smaller bundle when compiled - Add rollup devDependencies to actioncable These will be used to add a modern build pipeline to actioncable like the one in activestorage. - Add rollup config to actioncable This is essentially the same as the rollup config from activestorage - Add prebuild and build scripts to actioncable package These scripts were copied from activestorage - Invoke code generation task as part of actioncable's prebuild script This will guarantee that the action_cable/internal.js module is available at build time (which is important, because two other modules now depend on it). - Update actioncable package to reference the rollup-compiled files Now that we have a fully functional rollup pipeline in actioncable, we can use the compiled output in our npm package. - Remove build section from ActionCable blade config Now that rollup is responsible for building ActionCable, we can remove that responsibility from Blade. - Remove assets:compile and assets:verify tasks from ActionCable Now that we've added a compiled ActionCable bundle to version control, we don't need to compile and verify it at publish-time. (We're following the pattern set in ActiveStorage.) - Include compiled ActionCable javascript bundle in published gem This is necessary to maintain support for depending on the ActionCable javascript through the Sprockets asset pipeline. - Add compiled ActionCable bundle to version control This mirrors what we do in ActiveStorage, and allows ActionCable to continue to be consumed via the sprockets-based asset pipeline when using a git source instead of a published version of the gem.
2018-01-21 02:33:32 -05:00
}
};
var extend = function extend(object, properties) {
if (properties != null) {
for (var key in properties) {
var value = properties[key];
object[key] = value;
}
}
return object;
};
var Subscription = function() {
function Subscription(consumer) {
var params = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
var mixin = arguments[2];
classCallCheck(this, Subscription);
this.consumer = consumer;
this.identifier = JSON.stringify(params);
extend(this, mixin);
}
Subscription.prototype.perform = function perform(action) {
var data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
data.action = action;
return this.send(data);
};
Subscription.prototype.send = function send(data) {
return this.consumer.send({
command: "message",
identifier: this.identifier,
data: JSON.stringify(data)
});
};
Subscription.prototype.unsubscribe = function unsubscribe() {
return this.consumer.subscriptions.remove(this);
};
return Subscription;
}();
var Subscriptions = function() {
function Subscriptions(consumer) {
classCallCheck(this, Subscriptions);
this.consumer = consumer;
this.subscriptions = [];
}
Subscriptions.prototype.create = function create(channelName, mixin) {
var channel = channelName;
var params = (typeof channel === "undefined" ? "undefined" : _typeof(channel)) === "object" ? channel : {
channel: channel
};
Remove circular dependency warnings in ActionCable javascript and publish source modules with fine-grained exports (#34370) * Replace several ActionCable.* references with finer-grained imports This reduces the number of circular dependencies among the module imports from 4: ``` (!) Circular dependency: app/javascript/action_cable/index.js -> app/javascript/action_cable/connection.js -> app/javascript/action_cable/index.js (!) Circular dependency: app/javascript/action_cable/index.js -> app/javascript/action_cable/connection_monitor.js -> app/javascript/action_cable/index.js (!) Circular dependency: app/javascript/action_cable/index.js -> app/javascript/action_cable/consumer.js -> app/javascript/action_cable/index.js (!) Circular dependency: app/javascript/action_cable/index.js -> app/javascript/action_cable/subscriptions.js -> app/javascript/action_cable/index.js ``` to 2: ``` (!) Circular dependency: app/javascript/action_cable/index.js -> app/javascript/action_cable/connection.js -> app/javascript/action_cable/index.js (!) Circular dependency: app/javascript/action_cable/index.js -> app/javascript/action_cable/connection.js -> app/javascript/action_cable/connection_monitor.js -> app/javascript/action_cable/index.js ``` * Remove tests that only test javascript object property assignment These tests really only assert that you can assign a property to the ActionCable global object. That's true for pretty much any object in javascript (it would only be false if the object has been frozen, or has explicitly set some properties to be nonconfigurable). * Refactor ActionCable to provide individual named exports By providing individual named exports rather than a default export which is an object with all of those properties, we enable applications to only import the functions they need: any unused functions will be removed via tree shaking. Additionally, this restructuring removes the remaining circular dependencies by extracting the separate adapters and logger modules, so there are now no warnings when compiling the ActionCable bundle. Note: This produces two small breaking API changes: - The `ActionCable.WebSocket` getter and setter would be moved to `ActionCable.adapters.WebSocket`. If a user is currently configuring this, when upgrading they'd need to either add a delegated getter/setter themselves, or change it like this: ```diff - ActionCable.WebSocket = MyWebSocket + ActionCable.adapters.WebSocket = MyWebSocket ``` Applications which don't change the WebSocket adapter would not need any changes for this when upgrading. - Similarly, the `ActionCable.logger` getter and setter would be moved to `ActionCable.adapters.logger`. If a user is currently configuring this, when upgrading they'd need to either add a delegated getter/setter themselves, or change it like this: ```diff - ActionCable.logger = myLogger + ActionCable.adapters.logger = myLogger ``` Applications which don't change the logger would not need any changes for this when upgrading. These two aspects of the public API have to change because there's no way to export a property setter for `WebSocket` (or `logger`) such that this: ```js import ActionCable from "actioncable" ActionCable.WebSocket = MyWebSocket ``` would actually update `adapters.WebSocket`. (We can only offer that if we have two separate source files like if `index.js` uses `import * as ActionCable from "./action_cable" and then exports a wrapper which has delegated getters and setters for those properties.) This API change is very minor - it should be easy for applications to add the `adapters.` prefix in their assignments or to patch in delegated setters. And especially because most applications in the wild are not ever changing the default value of `ActionCable.WebSocket` or `ActionCable.logger` (because the default values are perfect), this API breakage is worth the tree-shaking benefits we gain. * Include source code in published actioncable npm package This allows actioncable users to ship smaller javascript bundles to visitors using modern browsers, as demonstrated in this repository: https://github.com/rmacklin/actioncable-es2015-build-example In that example, the bundle shrinks by 2.8K (25.2%) when you simply change the actioncable import to point to the untranspiled src. If you go a step further, like this: ``` diff --git a/app/scripts/main.js b/app/scripts/main.js index 17bc031..1a2b2e0 100644 --- a/app/scripts/main.js +++ b/app/scripts/main.js @@ -1,6 +1,6 @@ -import ActionCable from 'actioncable'; +import * as ActionCable from 'actioncable'; let cable = ActionCable.createConsumer('wss://cable.example.com'); cable.subscriptions.create('AppearanceChannel', { ``` then the bundle shrinks by 3.6K (31.7%)! In addition to allowing smaller bundles for those who ship untranspiled code to modern browsers, including the source code in the published package can be useful in other ways: 1. Users can import individual modules rather than the whole library 2. As a result of (1), users can also monkey patch parts of actioncable by importing the relevant module, modifying the exported object, and then importing the rest of actioncable (which would then use the patched object). Note: This is the same enhancement that we made to activestorage in c0368ad090b79c19300a4aa133bb188b2d9ab611 * Remove unused commonjs & resolve plugins from ActionCable rollup config These were added when we copied the rollup config from ActiveStorage, but ActionCable does not have any commonjs dependencies (it doesn't have any external dependencies at all), so these plugins are unnecessary here * Change ActionCable.startDebugging() -> ActionCable.logger.enabled=true and ActionCable.stopDebugging() -> ActionCable.logger.enabled=false This API is simpler and more clearly describes what it does * Change Travis configuration to run yarn install at the root for ActionCable builds This is necessary now that the repository is using Yarn Workspaces
2018-12-01 16:25:02 -05:00
var subscription = new Subscription(this.consumer, params, mixin);
Convert ActionCable javascript to ES2015 modules with modern build environment We've replaced the sprockets `//= require` directives with ES2015 imports. As a result, the ActionCable javascript can now be compiled with rollup (like ActiveStorage already is). - Rename action_cable/index.js.erb -> action_cable/index.js - Add rake task to generate a javascript module of the ActionCable::INTERNAL ruby hash This will allow us to get rid of ERB from the actioncable javascript, since it is only used to interpolate ActionCable::INTERNAL.to_json. - Import INTERNAL directly in ActionCable Connection module This is necessary to remove a load-order dependency conflict in the rollup-compiled build. Using ActionCable.INTERNAL would result in a runtime error: ``` TypeError: Cannot read property 'INTERNAL' of undefined ``` because ActionCable.INTERNAL is not set before the Connection module is executed. All other ActionCable.* references are executed inside of the body of a function, so there is no load-order dependency there. - Add eslint and eslint-plugin-import devDependencies to actioncable These will be used to add a linting setup to actioncable like the one in activestorage. - Add .eslintrc to actioncable This lint configuration was copied from activestorage - Add lint script to actioncable This is the same as the lint script in activestorage - Add babel-core, babel-plugin-external-helpers, and babel-preset-env devDependencies to actioncable These will be used to add ES2015 transpilation support to actioncable like we have in activestorage. - Add .babelrc to actioncable This configuration was copied from activestorage - Enable loose mode in ActionCable's babel config This generates a smaller bundle when compiled - Add rollup devDependencies to actioncable These will be used to add a modern build pipeline to actioncable like the one in activestorage. - Add rollup config to actioncable This is essentially the same as the rollup config from activestorage - Add prebuild and build scripts to actioncable package These scripts were copied from activestorage - Invoke code generation task as part of actioncable's prebuild script This will guarantee that the action_cable/internal.js module is available at build time (which is important, because two other modules now depend on it). - Update actioncable package to reference the rollup-compiled files Now that we have a fully functional rollup pipeline in actioncable, we can use the compiled output in our npm package. - Remove build section from ActionCable blade config Now that rollup is responsible for building ActionCable, we can remove that responsibility from Blade. - Remove assets:compile and assets:verify tasks from ActionCable Now that we've added a compiled ActionCable bundle to version control, we don't need to compile and verify it at publish-time. (We're following the pattern set in ActiveStorage.) - Include compiled ActionCable javascript bundle in published gem This is necessary to maintain support for depending on the ActionCable javascript through the Sprockets asset pipeline. - Add compiled ActionCable bundle to version control This mirrors what we do in ActiveStorage, and allows ActionCable to continue to be consumed via the sprockets-based asset pipeline when using a git source instead of a published version of the gem.
2018-01-21 02:33:32 -05:00
return this.add(subscription);
};
Subscriptions.prototype.add = function add(subscription) {
this.subscriptions.push(subscription);
this.consumer.ensureActiveConnection();
this.notify(subscription, "initialized");
this.sendCommand(subscription, "subscribe");
return subscription;
};
Subscriptions.prototype.remove = function remove(subscription) {
this.forget(subscription);
if (!this.findAll(subscription.identifier).length) {
this.sendCommand(subscription, "unsubscribe");
}
return subscription;
};
Subscriptions.prototype.reject = function reject(identifier) {
var _this = this;
return this.findAll(identifier).map(function(subscription) {
_this.forget(subscription);
_this.notify(subscription, "rejected");
return subscription;
});
};
Subscriptions.prototype.forget = function forget(subscription) {
this.subscriptions = this.subscriptions.filter(function(s) {
return s !== subscription;
});
return subscription;
};
Subscriptions.prototype.findAll = function findAll(identifier) {
return this.subscriptions.filter(function(s) {
return s.identifier === identifier;
});
};
Subscriptions.prototype.reload = function reload() {
var _this2 = this;
return this.subscriptions.map(function(subscription) {
return _this2.sendCommand(subscription, "subscribe");
});
};
Subscriptions.prototype.notifyAll = function notifyAll(callbackName) {
var _this3 = this;
for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
args[_key - 1] = arguments[_key];
}
return this.subscriptions.map(function(subscription) {
return _this3.notify.apply(_this3, [ subscription, callbackName ].concat(args));
});
};
Subscriptions.prototype.notify = function notify(subscription, callbackName) {
for (var _len2 = arguments.length, args = Array(_len2 > 2 ? _len2 - 2 : 0), _key2 = 2; _key2 < _len2; _key2++) {
args[_key2 - 2] = arguments[_key2];
}
var subscriptions = void 0;
if (typeof subscription === "string") {
subscriptions = this.findAll(subscription);
} else {
subscriptions = [ subscription ];
}
return subscriptions.map(function(subscription) {
return typeof subscription[callbackName] === "function" ? subscription[callbackName].apply(subscription, args) : undefined;
});
};
Subscriptions.prototype.sendCommand = function sendCommand(subscription, command) {
var identifier = subscription.identifier;
return this.consumer.send({
command: command,
identifier: identifier
});
};
return Subscriptions;
}();
Remove circular dependency warnings in ActionCable javascript and publish source modules with fine-grained exports (#34370) * Replace several ActionCable.* references with finer-grained imports This reduces the number of circular dependencies among the module imports from 4: ``` (!) Circular dependency: app/javascript/action_cable/index.js -> app/javascript/action_cable/connection.js -> app/javascript/action_cable/index.js (!) Circular dependency: app/javascript/action_cable/index.js -> app/javascript/action_cable/connection_monitor.js -> app/javascript/action_cable/index.js (!) Circular dependency: app/javascript/action_cable/index.js -> app/javascript/action_cable/consumer.js -> app/javascript/action_cable/index.js (!) Circular dependency: app/javascript/action_cable/index.js -> app/javascript/action_cable/subscriptions.js -> app/javascript/action_cable/index.js ``` to 2: ``` (!) Circular dependency: app/javascript/action_cable/index.js -> app/javascript/action_cable/connection.js -> app/javascript/action_cable/index.js (!) Circular dependency: app/javascript/action_cable/index.js -> app/javascript/action_cable/connection.js -> app/javascript/action_cable/connection_monitor.js -> app/javascript/action_cable/index.js ``` * Remove tests that only test javascript object property assignment These tests really only assert that you can assign a property to the ActionCable global object. That's true for pretty much any object in javascript (it would only be false if the object has been frozen, or has explicitly set some properties to be nonconfigurable). * Refactor ActionCable to provide individual named exports By providing individual named exports rather than a default export which is an object with all of those properties, we enable applications to only import the functions they need: any unused functions will be removed via tree shaking. Additionally, this restructuring removes the remaining circular dependencies by extracting the separate adapters and logger modules, so there are now no warnings when compiling the ActionCable bundle. Note: This produces two small breaking API changes: - The `ActionCable.WebSocket` getter and setter would be moved to `ActionCable.adapters.WebSocket`. If a user is currently configuring this, when upgrading they'd need to either add a delegated getter/setter themselves, or change it like this: ```diff - ActionCable.WebSocket = MyWebSocket + ActionCable.adapters.WebSocket = MyWebSocket ``` Applications which don't change the WebSocket adapter would not need any changes for this when upgrading. - Similarly, the `ActionCable.logger` getter and setter would be moved to `ActionCable.adapters.logger`. If a user is currently configuring this, when upgrading they'd need to either add a delegated getter/setter themselves, or change it like this: ```diff - ActionCable.logger = myLogger + ActionCable.adapters.logger = myLogger ``` Applications which don't change the logger would not need any changes for this when upgrading. These two aspects of the public API have to change because there's no way to export a property setter for `WebSocket` (or `logger`) such that this: ```js import ActionCable from "actioncable" ActionCable.WebSocket = MyWebSocket ``` would actually update `adapters.WebSocket`. (We can only offer that if we have two separate source files like if `index.js` uses `import * as ActionCable from "./action_cable" and then exports a wrapper which has delegated getters and setters for those properties.) This API change is very minor - it should be easy for applications to add the `adapters.` prefix in their assignments or to patch in delegated setters. And especially because most applications in the wild are not ever changing the default value of `ActionCable.WebSocket` or `ActionCable.logger` (because the default values are perfect), this API breakage is worth the tree-shaking benefits we gain. * Include source code in published actioncable npm package This allows actioncable users to ship smaller javascript bundles to visitors using modern browsers, as demonstrated in this repository: https://github.com/rmacklin/actioncable-es2015-build-example In that example, the bundle shrinks by 2.8K (25.2%) when you simply change the actioncable import to point to the untranspiled src. If you go a step further, like this: ``` diff --git a/app/scripts/main.js b/app/scripts/main.js index 17bc031..1a2b2e0 100644 --- a/app/scripts/main.js +++ b/app/scripts/main.js @@ -1,6 +1,6 @@ -import ActionCable from 'actioncable'; +import * as ActionCable from 'actioncable'; let cable = ActionCable.createConsumer('wss://cable.example.com'); cable.subscriptions.create('AppearanceChannel', { ``` then the bundle shrinks by 3.6K (31.7%)! In addition to allowing smaller bundles for those who ship untranspiled code to modern browsers, including the source code in the published package can be useful in other ways: 1. Users can import individual modules rather than the whole library 2. As a result of (1), users can also monkey patch parts of actioncable by importing the relevant module, modifying the exported object, and then importing the rest of actioncable (which would then use the patched object). Note: This is the same enhancement that we made to activestorage in c0368ad090b79c19300a4aa133bb188b2d9ab611 * Remove unused commonjs & resolve plugins from ActionCable rollup config These were added when we copied the rollup config from ActiveStorage, but ActionCable does not have any commonjs dependencies (it doesn't have any external dependencies at all), so these plugins are unnecessary here * Change ActionCable.startDebugging() -> ActionCable.logger.enabled=true and ActionCable.stopDebugging() -> ActionCable.logger.enabled=false This API is simpler and more clearly describes what it does * Change Travis configuration to run yarn install at the root for ActionCable builds This is necessary now that the repository is using Yarn Workspaces
2018-12-01 16:25:02 -05:00
var Consumer = function() {
function Consumer(url) {
classCallCheck(this, Consumer);
this.url = url;
this.subscriptions = new Subscriptions(this);
this.connection = new Connection(this);
}
Consumer.prototype.send = function send(data) {
return this.connection.send(data);
};
Consumer.prototype.connect = function connect() {
return this.connection.open();
};
Consumer.prototype.disconnect = function disconnect() {
return this.connection.close({
allowReconnect: false
});
};
Consumer.prototype.ensureActiveConnection = function ensureActiveConnection() {
if (!this.connection.isActive()) {
return this.connection.open();
Convert ActionCable javascript to ES2015 modules with modern build environment We've replaced the sprockets `//= require` directives with ES2015 imports. As a result, the ActionCable javascript can now be compiled with rollup (like ActiveStorage already is). - Rename action_cable/index.js.erb -> action_cable/index.js - Add rake task to generate a javascript module of the ActionCable::INTERNAL ruby hash This will allow us to get rid of ERB from the actioncable javascript, since it is only used to interpolate ActionCable::INTERNAL.to_json. - Import INTERNAL directly in ActionCable Connection module This is necessary to remove a load-order dependency conflict in the rollup-compiled build. Using ActionCable.INTERNAL would result in a runtime error: ``` TypeError: Cannot read property 'INTERNAL' of undefined ``` because ActionCable.INTERNAL is not set before the Connection module is executed. All other ActionCable.* references are executed inside of the body of a function, so there is no load-order dependency there. - Add eslint and eslint-plugin-import devDependencies to actioncable These will be used to add a linting setup to actioncable like the one in activestorage. - Add .eslintrc to actioncable This lint configuration was copied from activestorage - Add lint script to actioncable This is the same as the lint script in activestorage - Add babel-core, babel-plugin-external-helpers, and babel-preset-env devDependencies to actioncable These will be used to add ES2015 transpilation support to actioncable like we have in activestorage. - Add .babelrc to actioncable This configuration was copied from activestorage - Enable loose mode in ActionCable's babel config This generates a smaller bundle when compiled - Add rollup devDependencies to actioncable These will be used to add a modern build pipeline to actioncable like the one in activestorage. - Add rollup config to actioncable This is essentially the same as the rollup config from activestorage - Add prebuild and build scripts to actioncable package These scripts were copied from activestorage - Invoke code generation task as part of actioncable's prebuild script This will guarantee that the action_cable/internal.js module is available at build time (which is important, because two other modules now depend on it). - Update actioncable package to reference the rollup-compiled files Now that we have a fully functional rollup pipeline in actioncable, we can use the compiled output in our npm package. - Remove build section from ActionCable blade config Now that rollup is responsible for building ActionCable, we can remove that responsibility from Blade. - Remove assets:compile and assets:verify tasks from ActionCable Now that we've added a compiled ActionCable bundle to version control, we don't need to compile and verify it at publish-time. (We're following the pattern set in ActiveStorage.) - Include compiled ActionCable javascript bundle in published gem This is necessary to maintain support for depending on the ActionCable javascript through the Sprockets asset pipeline. - Add compiled ActionCable bundle to version control This mirrors what we do in ActiveStorage, and allows ActionCable to continue to be consumed via the sprockets-based asset pipeline when using a git source instead of a published version of the gem.
2018-01-21 02:33:32 -05:00
}
Remove circular dependency warnings in ActionCable javascript and publish source modules with fine-grained exports (#34370) * Replace several ActionCable.* references with finer-grained imports This reduces the number of circular dependencies among the module imports from 4: ``` (!) Circular dependency: app/javascript/action_cable/index.js -> app/javascript/action_cable/connection.js -> app/javascript/action_cable/index.js (!) Circular dependency: app/javascript/action_cable/index.js -> app/javascript/action_cable/connection_monitor.js -> app/javascript/action_cable/index.js (!) Circular dependency: app/javascript/action_cable/index.js -> app/javascript/action_cable/consumer.js -> app/javascript/action_cable/index.js (!) Circular dependency: app/javascript/action_cable/index.js -> app/javascript/action_cable/subscriptions.js -> app/javascript/action_cable/index.js ``` to 2: ``` (!) Circular dependency: app/javascript/action_cable/index.js -> app/javascript/action_cable/connection.js -> app/javascript/action_cable/index.js (!) Circular dependency: app/javascript/action_cable/index.js -> app/javascript/action_cable/connection.js -> app/javascript/action_cable/connection_monitor.js -> app/javascript/action_cable/index.js ``` * Remove tests that only test javascript object property assignment These tests really only assert that you can assign a property to the ActionCable global object. That's true for pretty much any object in javascript (it would only be false if the object has been frozen, or has explicitly set some properties to be nonconfigurable). * Refactor ActionCable to provide individual named exports By providing individual named exports rather than a default export which is an object with all of those properties, we enable applications to only import the functions they need: any unused functions will be removed via tree shaking. Additionally, this restructuring removes the remaining circular dependencies by extracting the separate adapters and logger modules, so there are now no warnings when compiling the ActionCable bundle. Note: This produces two small breaking API changes: - The `ActionCable.WebSocket` getter and setter would be moved to `ActionCable.adapters.WebSocket`. If a user is currently configuring this, when upgrading they'd need to either add a delegated getter/setter themselves, or change it like this: ```diff - ActionCable.WebSocket = MyWebSocket + ActionCable.adapters.WebSocket = MyWebSocket ``` Applications which don't change the WebSocket adapter would not need any changes for this when upgrading. - Similarly, the `ActionCable.logger` getter and setter would be moved to `ActionCable.adapters.logger`. If a user is currently configuring this, when upgrading they'd need to either add a delegated getter/setter themselves, or change it like this: ```diff - ActionCable.logger = myLogger + ActionCable.adapters.logger = myLogger ``` Applications which don't change the logger would not need any changes for this when upgrading. These two aspects of the public API have to change because there's no way to export a property setter for `WebSocket` (or `logger`) such that this: ```js import ActionCable from "actioncable" ActionCable.WebSocket = MyWebSocket ``` would actually update `adapters.WebSocket`. (We can only offer that if we have two separate source files like if `index.js` uses `import * as ActionCable from "./action_cable" and then exports a wrapper which has delegated getters and setters for those properties.) This API change is very minor - it should be easy for applications to add the `adapters.` prefix in their assignments or to patch in delegated setters. And especially because most applications in the wild are not ever changing the default value of `ActionCable.WebSocket` or `ActionCable.logger` (because the default values are perfect), this API breakage is worth the tree-shaking benefits we gain. * Include source code in published actioncable npm package This allows actioncable users to ship smaller javascript bundles to visitors using modern browsers, as demonstrated in this repository: https://github.com/rmacklin/actioncable-es2015-build-example In that example, the bundle shrinks by 2.8K (25.2%) when you simply change the actioncable import to point to the untranspiled src. If you go a step further, like this: ``` diff --git a/app/scripts/main.js b/app/scripts/main.js index 17bc031..1a2b2e0 100644 --- a/app/scripts/main.js +++ b/app/scripts/main.js @@ -1,6 +1,6 @@ -import ActionCable from 'actioncable'; +import * as ActionCable from 'actioncable'; let cable = ActionCable.createConsumer('wss://cable.example.com'); cable.subscriptions.create('AppearanceChannel', { ``` then the bundle shrinks by 3.6K (31.7%)! In addition to allowing smaller bundles for those who ship untranspiled code to modern browsers, including the source code in the published package can be useful in other ways: 1. Users can import individual modules rather than the whole library 2. As a result of (1), users can also monkey patch parts of actioncable by importing the relevant module, modifying the exported object, and then importing the rest of actioncable (which would then use the patched object). Note: This is the same enhancement that we made to activestorage in c0368ad090b79c19300a4aa133bb188b2d9ab611 * Remove unused commonjs & resolve plugins from ActionCable rollup config These were added when we copied the rollup config from ActiveStorage, but ActionCable does not have any commonjs dependencies (it doesn't have any external dependencies at all), so these plugins are unnecessary here * Change ActionCable.startDebugging() -> ActionCable.logger.enabled=true and ActionCable.stopDebugging() -> ActionCable.logger.enabled=false This API is simpler and more clearly describes what it does * Change Travis configuration to run yarn install at the root for ActionCable builds This is necessary now that the repository is using Yarn Workspaces
2018-12-01 16:25:02 -05:00
};
return Consumer;
}();
function createConsumer() {
var url = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : getConfig("url") || INTERNAL.default_mount_path;
Remove circular dependency warnings in ActionCable javascript and publish source modules with fine-grained exports (#34370) * Replace several ActionCable.* references with finer-grained imports This reduces the number of circular dependencies among the module imports from 4: ``` (!) Circular dependency: app/javascript/action_cable/index.js -> app/javascript/action_cable/connection.js -> app/javascript/action_cable/index.js (!) Circular dependency: app/javascript/action_cable/index.js -> app/javascript/action_cable/connection_monitor.js -> app/javascript/action_cable/index.js (!) Circular dependency: app/javascript/action_cable/index.js -> app/javascript/action_cable/consumer.js -> app/javascript/action_cable/index.js (!) Circular dependency: app/javascript/action_cable/index.js -> app/javascript/action_cable/subscriptions.js -> app/javascript/action_cable/index.js ``` to 2: ``` (!) Circular dependency: app/javascript/action_cable/index.js -> app/javascript/action_cable/connection.js -> app/javascript/action_cable/index.js (!) Circular dependency: app/javascript/action_cable/index.js -> app/javascript/action_cable/connection.js -> app/javascript/action_cable/connection_monitor.js -> app/javascript/action_cable/index.js ``` * Remove tests that only test javascript object property assignment These tests really only assert that you can assign a property to the ActionCable global object. That's true for pretty much any object in javascript (it would only be false if the object has been frozen, or has explicitly set some properties to be nonconfigurable). * Refactor ActionCable to provide individual named exports By providing individual named exports rather than a default export which is an object with all of those properties, we enable applications to only import the functions they need: any unused functions will be removed via tree shaking. Additionally, this restructuring removes the remaining circular dependencies by extracting the separate adapters and logger modules, so there are now no warnings when compiling the ActionCable bundle. Note: This produces two small breaking API changes: - The `ActionCable.WebSocket` getter and setter would be moved to `ActionCable.adapters.WebSocket`. If a user is currently configuring this, when upgrading they'd need to either add a delegated getter/setter themselves, or change it like this: ```diff - ActionCable.WebSocket = MyWebSocket + ActionCable.adapters.WebSocket = MyWebSocket ``` Applications which don't change the WebSocket adapter would not need any changes for this when upgrading. - Similarly, the `ActionCable.logger` getter and setter would be moved to `ActionCable.adapters.logger`. If a user is currently configuring this, when upgrading they'd need to either add a delegated getter/setter themselves, or change it like this: ```diff - ActionCable.logger = myLogger + ActionCable.adapters.logger = myLogger ``` Applications which don't change the logger would not need any changes for this when upgrading. These two aspects of the public API have to change because there's no way to export a property setter for `WebSocket` (or `logger`) such that this: ```js import ActionCable from "actioncable" ActionCable.WebSocket = MyWebSocket ``` would actually update `adapters.WebSocket`. (We can only offer that if we have two separate source files like if `index.js` uses `import * as ActionCable from "./action_cable" and then exports a wrapper which has delegated getters and setters for those properties.) This API change is very minor - it should be easy for applications to add the `adapters.` prefix in their assignments or to patch in delegated setters. And especially because most applications in the wild are not ever changing the default value of `ActionCable.WebSocket` or `ActionCable.logger` (because the default values are perfect), this API breakage is worth the tree-shaking benefits we gain. * Include source code in published actioncable npm package This allows actioncable users to ship smaller javascript bundles to visitors using modern browsers, as demonstrated in this repository: https://github.com/rmacklin/actioncable-es2015-build-example In that example, the bundle shrinks by 2.8K (25.2%) when you simply change the actioncable import to point to the untranspiled src. If you go a step further, like this: ``` diff --git a/app/scripts/main.js b/app/scripts/main.js index 17bc031..1a2b2e0 100644 --- a/app/scripts/main.js +++ b/app/scripts/main.js @@ -1,6 +1,6 @@ -import ActionCable from 'actioncable'; +import * as ActionCable from 'actioncable'; let cable = ActionCable.createConsumer('wss://cable.example.com'); cable.subscriptions.create('AppearanceChannel', { ``` then the bundle shrinks by 3.6K (31.7%)! In addition to allowing smaller bundles for those who ship untranspiled code to modern browsers, including the source code in the published package can be useful in other ways: 1. Users can import individual modules rather than the whole library 2. As a result of (1), users can also monkey patch parts of actioncable by importing the relevant module, modifying the exported object, and then importing the rest of actioncable (which would then use the patched object). Note: This is the same enhancement that we made to activestorage in c0368ad090b79c19300a4aa133bb188b2d9ab611 * Remove unused commonjs & resolve plugins from ActionCable rollup config These were added when we copied the rollup config from ActiveStorage, but ActionCable does not have any commonjs dependencies (it doesn't have any external dependencies at all), so these plugins are unnecessary here * Change ActionCable.startDebugging() -> ActionCable.logger.enabled=true and ActionCable.stopDebugging() -> ActionCable.logger.enabled=false This API is simpler and more clearly describes what it does * Change Travis configuration to run yarn install at the root for ActionCable builds This is necessary now that the repository is using Yarn Workspaces
2018-12-01 16:25:02 -05:00
return new Consumer(createWebSocketURL(url));
}
function getConfig(name) {
var element = document.head.querySelector("meta[name='action-cable-" + name + "']");
return element ? element.getAttribute("content") : undefined;
}
function createWebSocketURL(url) {
if (url && !/^wss?:/i.test(url)) {
var a = document.createElement("a");
a.href = url;
a.href = a.href;
a.protocol = a.protocol.replace("http", "ws");
return a.href;
} else {
return url;
}
}
exports.Connection = Connection;
exports.ConnectionMonitor = ConnectionMonitor;
exports.Consumer = Consumer;
exports.INTERNAL = INTERNAL;
exports.Subscription = Subscription;
exports.Subscriptions = Subscriptions;
exports.adapters = adapters;
exports.logger = logger;
exports.createConsumer = createConsumer;
exports.getConfig = getConfig;
exports.createWebSocketURL = createWebSocketURL;
Object.defineProperty(exports, "__esModule", {
value: true
});
Convert ActionCable javascript to ES2015 modules with modern build environment We've replaced the sprockets `//= require` directives with ES2015 imports. As a result, the ActionCable javascript can now be compiled with rollup (like ActiveStorage already is). - Rename action_cable/index.js.erb -> action_cable/index.js - Add rake task to generate a javascript module of the ActionCable::INTERNAL ruby hash This will allow us to get rid of ERB from the actioncable javascript, since it is only used to interpolate ActionCable::INTERNAL.to_json. - Import INTERNAL directly in ActionCable Connection module This is necessary to remove a load-order dependency conflict in the rollup-compiled build. Using ActionCable.INTERNAL would result in a runtime error: ``` TypeError: Cannot read property 'INTERNAL' of undefined ``` because ActionCable.INTERNAL is not set before the Connection module is executed. All other ActionCable.* references are executed inside of the body of a function, so there is no load-order dependency there. - Add eslint and eslint-plugin-import devDependencies to actioncable These will be used to add a linting setup to actioncable like the one in activestorage. - Add .eslintrc to actioncable This lint configuration was copied from activestorage - Add lint script to actioncable This is the same as the lint script in activestorage - Add babel-core, babel-plugin-external-helpers, and babel-preset-env devDependencies to actioncable These will be used to add ES2015 transpilation support to actioncable like we have in activestorage. - Add .babelrc to actioncable This configuration was copied from activestorage - Enable loose mode in ActionCable's babel config This generates a smaller bundle when compiled - Add rollup devDependencies to actioncable These will be used to add a modern build pipeline to actioncable like the one in activestorage. - Add rollup config to actioncable This is essentially the same as the rollup config from activestorage - Add prebuild and build scripts to actioncable package These scripts were copied from activestorage - Invoke code generation task as part of actioncable's prebuild script This will guarantee that the action_cable/internal.js module is available at build time (which is important, because two other modules now depend on it). - Update actioncable package to reference the rollup-compiled files Now that we have a fully functional rollup pipeline in actioncable, we can use the compiled output in our npm package. - Remove build section from ActionCable blade config Now that rollup is responsible for building ActionCable, we can remove that responsibility from Blade. - Remove assets:compile and assets:verify tasks from ActionCable Now that we've added a compiled ActionCable bundle to version control, we don't need to compile and verify it at publish-time. (We're following the pattern set in ActiveStorage.) - Include compiled ActionCable javascript bundle in published gem This is necessary to maintain support for depending on the ActionCable javascript through the Sprockets asset pipeline. - Add compiled ActionCable bundle to version control This mirrors what we do in ActiveStorage, and allows ActionCable to continue to be consumed via the sprockets-based asset pipeline when using a git source instead of a published version of the gem.
2018-01-21 02:33:32 -05:00
});