Jean-Yves Didier

added full support for a remote console

...@@ -14,6 +14,7 @@ __webpack_require__.r(__webpack_exports__); ...@@ -14,6 +14,7 @@ __webpack_require__.r(__webpack_exports__);
14 /* harmony import */ var _connection_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(9); 14 /* harmony import */ var _connection_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(9);
15 /* harmony import */ var _sheet_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(10); 15 /* harmony import */ var _sheet_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(10);
16 /* harmony import */ var _application_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(11); 16 /* harmony import */ var _application_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(11);
17 +/* harmony import */ var _remoteconsole_js__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(12);
17 // no longer needed with the use of imports 18 // no longer needed with the use of imports
18 19
19 20
...@@ -25,6 +26,7 @@ __webpack_require__.r(__webpack_exports__); ...@@ -25,6 +26,7 @@ __webpack_require__.r(__webpack_exports__);
25 26
26 27
27 28
29 +
28 let ARCS = { 30 let ARCS = {
29 Component: _component_js__WEBPACK_IMPORTED_MODULE_0__["default"], 31 Component: _component_js__WEBPACK_IMPORTED_MODULE_0__["default"],
30 isInNode : _isinnode_js__WEBPACK_IMPORTED_MODULE_2__["default"], 32 isInNode : _isinnode_js__WEBPACK_IMPORTED_MODULE_2__["default"],
...@@ -33,6 +35,7 @@ let ARCS = { ...@@ -33,6 +35,7 @@ let ARCS = {
33 Invocation: _invocation_js__WEBPACK_IMPORTED_MODULE_4__["default"], 35 Invocation: _invocation_js__WEBPACK_IMPORTED_MODULE_4__["default"],
34 Connection: _connection_js__WEBPACK_IMPORTED_MODULE_5__["default"], 36 Connection: _connection_js__WEBPACK_IMPORTED_MODULE_5__["default"],
35 Sheet: _sheet_js__WEBPACK_IMPORTED_MODULE_6__["default"], 37 Sheet: _sheet_js__WEBPACK_IMPORTED_MODULE_6__["default"],
38 + RemoteConsole: _remoteconsole_js__WEBPACK_IMPORTED_MODULE_8__["default"],
36 Application: _application_js__WEBPACK_IMPORTED_MODULE_7__["default"], 39 Application: _application_js__WEBPACK_IMPORTED_MODULE_7__["default"],
37 __lib__: ()=>{} 40 __lib__: ()=>{}
38 }; 41 };
...@@ -2565,6 +2568,113 @@ Application.slot("finish"); ...@@ -2565,6 +2568,113 @@ Application.slot("finish");
2565 /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (Application); 2568 /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (Application);
2566 2569
2567 2570
2571 +/***/ }),
2572 +/* 12 */
2573 +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
2574 +
2575 +__webpack_require__.r(__webpack_exports__);
2576 +/* harmony export */ __webpack_require__.d(__webpack_exports__, {
2577 +/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__)
2578 +/* harmony export */ });
2579 +
2580 +class RemoteConsole {
2581 + #stack= [];
2582 + #server;
2583 + #idxSource;
2584 + _log = globalThis.console.log;
2585 + _info = globalThis.console.info;
2586 + _warn = globalThis.console.warn;
2587 + _error = globalThis.console.error;
2588 +
2589 + constructor(address) {
2590 + let self = this;
2591 +
2592 + console.error = this.error;
2593 + console.warn = this.warn;
2594 + console.info = this.info;
2595 + console.log = this.log;
2596 + console.tainted = true;
2597 +
2598 + if (globalThis.window) {
2599 + globalThis.window.onerror = this.runtimeException;
2600 + }
2601 +
2602 + if (globalThis.WebSocket && globalThis.navigator) {
2603 + this.#server = new globalThis.WebSocket(address);
2604 + this.#idxSource = (globalThis.navigator.userAgent.match(/firefox|fxios/i))?2:3;
2605 + this.#server.onopen = function() {
2606 + self.#flush();
2607 + }
2608 + }
2609 + }
2610 +
2611 + #currentPlace() {
2612 + let err = new Error();
2613 + let lst = err.stack.split("\n");
2614 + return lst[this.#idxSource];
2615 + }
2616 +
2617 + #send(data) {
2618 + if (!this.#server) return ;
2619 +
2620 + if (this.#server.readyState === WebSocket.OPEN ) {
2621 + this.#server.send(data);
2622 + } else {
2623 + this.#stack.push(data);
2624 + }
2625 + }
2626 +
2627 + #flush () {
2628 + if (!this.#server) return ;
2629 +
2630 + if (this.#server.readyState !== WebSocket.OPEN)
2631 + return ;
2632 + this.#stack.forEach(elt => this.#server.send(elt));
2633 + this.#stack = [];
2634 + }
2635 +
2636 + #notify(type) {
2637 + let self = this;
2638 + return function() {
2639 + let obj = { type, args: Array.from(arguments), context: self.#currentPlace() };
2640 + self[`_${type}`].apply(globalThis.console, obj.args);
2641 +
2642 + let serializedObject = "";
2643 +
2644 + try {
2645 + serializedObject = JSON.stringify(obj);
2646 + } catch(e) {
2647 + obj.args= [ 'Argument(s) not serializable' ];
2648 + serializedObject = JSON.stringify(obj);
2649 + }
2650 + self.#send(serializedObject);
2651 + };
2652 + }
2653 +
2654 + #runtimeException (msg, url, line, column,err) {
2655 + if (!this.#server) return false;
2656 +
2657 + this.#server.send(
2658 + JSON.stringify(
2659 + {type: "exception", args: [{ message: msg, url: url, line: line, column: column }] }
2660 + )
2661 + );
2662 + return false;
2663 + }
2664 +
2665 + log = this.#notify('log');
2666 + info = this.#notify('info');
2667 + warn = this.#notify('warn');
2668 + error = this.#notify('error');
2669 +
2670 +};
2671 +
2672 +
2673 +/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (RemoteConsole);
2674 +
2675 +
2676 +
2677 +
2568 /***/ }) 2678 /***/ })
2569 /******/ ]); 2679 /******/ ]);
2570 /************************************************************************/ 2680 /************************************************************************/
......
This diff is collapsed. Click to expand it.
...@@ -19,6 +19,11 @@ requireMarkup = document.querySelector('[data-arcsapp]'); ...@@ -19,6 +19,11 @@ requireMarkup = document.querySelector('[data-arcsapp]');
19 if (requireMarkup !== undefined) { 19 if (requireMarkup !== undefined) {
20 baseUrl = requireMarkup.dataset.baseUrl ; 20 baseUrl = requireMarkup.dataset.baseUrl ;
21 appDescription = requireMarkup.dataset.arcsapp || "arcsapp.json"; 21 appDescription = requireMarkup.dataset.arcsapp || "arcsapp.json";
22 +
23 + if( "remoteConsole" in requireMarkup.dataset ) {
24 + let address = requireMarkup.dataset.remoteConsole || "ws://localhost:8088";
25 + let remoteConsole = new ARCS.RemoteConsole(address);
26 + }
22 } 27 }
23 28
24 29
......
...@@ -37,8 +37,9 @@ ...@@ -37,8 +37,9 @@
37 "license": "GPL-3.0-or-later", 37 "license": "GPL-3.0-or-later",
38 "devDependencies": { 38 "devDependencies": {
39 "chai": "4.3.4", 39 "chai": "4.3.4",
40 + "chalk": "^5.2.0",
41 + "ws": "^8.13.0",
40 "copy-webpack-plugin": "^9.0.1", 42 "copy-webpack-plugin": "^9.0.1",
41 - "eslint": "^8.7.0",
42 "eslint-webpack-plugin": "^3.0.1", 43 "eslint-webpack-plugin": "^3.0.1",
43 "jsdoc-webpack-plugin": "^0.3.0", 44 "jsdoc-webpack-plugin": "^0.3.0",
44 "mocha": "^9.1.4", 45 "mocha": "^9.1.4",
......
...@@ -8,6 +8,7 @@ import Invocation from './invocation.js'; ...@@ -8,6 +8,7 @@ import Invocation from './invocation.js';
8 import Connection from './connection.js'; 8 import Connection from './connection.js';
9 import Sheet from './sheet.js'; 9 import Sheet from './sheet.js';
10 import Application from './application.js'; 10 import Application from './application.js';
11 +import RemoteConsole from './remoteconsole.js';
11 12
12 let ARCS = { 13 let ARCS = {
13 Component: Component, 14 Component: Component,
...@@ -17,6 +18,7 @@ let ARCS = { ...@@ -17,6 +18,7 @@ let ARCS = {
17 Invocation: Invocation, 18 Invocation: Invocation,
18 Connection: Connection, 19 Connection: Connection,
19 Sheet: Sheet, 20 Sheet: Sheet,
21 + RemoteConsole: RemoteConsole,
20 Application: Application, 22 Application: Application,
21 __lib__: ()=>{} 23 __lib__: ()=>{}
22 }; 24 };
......
...@@ -19,6 +19,11 @@ requireMarkup = document.querySelector('[data-arcsapp]'); ...@@ -19,6 +19,11 @@ requireMarkup = document.querySelector('[data-arcsapp]');
19 if (requireMarkup !== undefined) { 19 if (requireMarkup !== undefined) {
20 baseUrl = requireMarkup.dataset.baseUrl ; 20 baseUrl = requireMarkup.dataset.baseUrl ;
21 appDescription = requireMarkup.dataset.arcsapp || "arcsapp.json"; 21 appDescription = requireMarkup.dataset.arcsapp || "arcsapp.json";
22 +
23 + if( "remoteConsole" in requireMarkup.dataset ) {
24 + let address = requireMarkup.dataset.remoteConsole || "ws://localhost:8088";
25 + let remoteConsole = new ARCS.RemoteConsole(address);
26 + }
22 } 27 }
23 28
24 29
......
1 -
2 -class ARCSRemoteConsole {
3 - #stack= [];
4 - #server;
5 - #idxSource;
6 -
7 - constructor(address) {
8 - this.#server = new globalThis.WebSocket(address);
9 - this.#idxSource = (globalThis.navigator.userAgent.match(/firefox|fxios/i))?2:3;
10 - let self = this;
11 -
12 - this.#server.onopen = function() {
13 - self.flush();
14 - }
15 - }
16 -
17 - #currentPlace() {
18 - let err = new Error();
19 - let lst = err.stack.split("\n");
20 - return lst[this.#idxSource];
21 - }
22 -
23 - #send(data) {
24 - if (server.readyState === WebSocket.OPEN ) {
25 - server.send(data);
26 - } else {
27 - this.#stack.push(data);
28 - }
29 - }
30 -
31 - #flush () {
32 - if (server.readyState !== WebSocket.OPEN)
33 - return ;
34 - this.#stack.forEach(elt => server.send(elt));
35 - this.#stack = [];
36 - }
37 -
38 - #notify(type) {
39 - let self = this;
40 - return function() {
41 - let obj = { type, args: Array.from(arguments), context: self.#currentPlace() };
42 -
43 - let serializedObject = "";
44 -
45 - try {
46 - serializedObject = JSON.stringify(obj);
47 - } catch(e) {
48 - obj.args= [ 'Argument(s) not serializable' ];
49 - serializedObject = JSON.stringify(obj);
50 - }
51 - self.#send(serializedObject);
52 - };
53 - }
54 -
55 - #runtimeException (msg, url, line, column,err) {
56 - server.send(
57 - JSON.stringify(
58 - {type: "exception", args: [{ message: msg, url: url, line: line, column: column }] }
59 - )
60 - );
61 - return false;
62 - }
63 -
64 - log = this.notify('log');
65 - info = this.notify('info');
66 - warn = this.notify('warn');
67 - error = this.notify('error');
68 -
69 - static init(address) {
70 - let _address = address || 'ws://localhost:8088';
71 - const remoteConsole = new ARCSRemoteConsole(address);
72 -
73 - const console = globalThis.console;
74 - console.error = remoteConsole.error;
75 - console.warn = remoteConsole.warn;
76 - console.info = remoteConsole.info;
77 - console.log = remoteConsole.log;
78 - console.tainted = true;
79 - const window = globalThis.window;
80 - window.onerror = remoteConsole.runtimeException;
81 - }
82 -
83 -}
84 -
...@@ -25,7 +25,7 @@ class RemoteConsole { ...@@ -25,7 +25,7 @@ class RemoteConsole {
25 this.#server = new globalThis.WebSocket(address); 25 this.#server = new globalThis.WebSocket(address);
26 this.#idxSource = (globalThis.navigator.userAgent.match(/firefox|fxios/i))?2:3; 26 this.#idxSource = (globalThis.navigator.userAgent.match(/firefox|fxios/i))?2:3;
27 this.#server.onopen = function() { 27 this.#server.onopen = function() {
28 - self.flush(); 28 + self.#flush();
29 } 29 }
30 } 30 }
31 } 31 }
......
1 +import WebSocket, {WebSocketServer} from 'ws';
2 +import Chalk from 'chalk';
3 +
4 +let serverConfig = {
5 + port: 8088,
6 +};
7 +
8 +
9 +if (process.argv.length > 2) {
10 + serverConfig.port = parseInt(process.argv[2]);
11 +}
12 +
13 +let wss = new WebSocketServer(serverConfig);
14 +wss.on('connection', function (ws) {
15 + ws.on('message', function (message) {
16 + let obj = JSON.parse(message);
17 + switch(obj.type) {
18 + case 'log':
19 + console.log(Chalk.green("[log]"), Chalk.white.dim(obj.context),"\n", ...obj.args);
20 + break;
21 + case 'info':
22 + console.log(Chalk.cyan("[info]"), Chalk.white.dim(obj.context),"\n", ...obj.args);
23 + break;
24 + case 'warn':
25 + console.log(Chalk.yellow("[warn]"),Chalk.white.dim(obj.context),"\n", ...obj.args);
26 + break;
27 + case 'error':
28 + console.log(Chalk.red("[error]"), Chalk.white.dim(obj.context),"\n", ...obj.args);
29 + break;
30 + }
31 + //console.log('received: %s', message);
32 + });
33 +});