CodeOceanEditorWebsocket = { websocket: null, createSocketUrl: function(url, span) { const sockURL = new URL(url, window.location); // not needed any longer, we put it directly into the url: sockURL.pathname = url; // replace `http` with `ws` for the WebSocket connection. This also works with `https` and `wss`. sockURL.protocol = sockURL.protocol.replace("http", "ws"); // strip anchor if it is in the url sockURL.hash = ''; if (span) { sockURL.searchParams.set('HTTP_SENTRY_TRACE', span.toTraceparent()); const dynamicContext = this.sentryTransaction.getDynamicSamplingContext(); const baggage = SentryUtils.dynamicSamplingContextToSentryBaggageHeader(dynamicContext); sockURL.searchParams.set('HTTP_BAGGAGE', baggage); } return sockURL.toString(); }, initializeSocket: function(url, closeCallback) { const cleanedPath = url.replace(/\/\d+\//, '/*/').replace(/\/[^\/]+$/, '/*'); const websocketHost = window.location.origin.replace(/^http/, 'ws'); const sentryDescription = `WebSocket ${websocketHost}${cleanedPath}`; const span = this.sentryTransaction?.startChild({op: 'websocket.client', description: sentryDescription}) this.websocket = new CommandSocket(this.createSocketUrl(url, span), function (evt) { this.resetOutputTab(); }.bind(this) ); CodeOceanEditorWebsocket.websocket = this.websocket; this.websocket.onError(this.showWebsocketError.bind(this)); this.websocket.onClose( function(span, callback){ span?.finish() if(callback != null){ callback(); } }.bind(this, span, closeCallback)); }, initializeSocketForTesting: function(url) { this.initializeSocket(url); this.websocket.on('default',this.handleTestResponse.bind(this)); this.websocket.on('exit', this.handleExitCommand.bind(this)); }, initializeSocketForScoring: function(url) { this.initializeSocket(url, function() { $('#assess').one('click', this.scoreCode.bind(this)) }.bind(this)); this.websocket.on('default',this.handleScoringResponse.bind(this)); this.websocket.on('hint', this.showHint.bind(this)); this.websocket.on('exit', this.handleExitCommand.bind(this)); this.websocket.on('status', this.showStatus.bind(this)); }, initializeSocketForRunning: function(url) { this.initializeSocket(url); this.websocket.on('input',this.showPrompt.bind(this)); this.websocket.on('write', this.printWebsocketOutput.bind(this)); this.websocket.on('clear', this.clearOutput.bind(this)); this.websocket.on('turtle', this.handleTurtleCommand.bind(this)); this.websocket.on('turtlebatch', this.handleTurtlebatchCommand.bind(this)); this.websocket.on('render', this.printWebsocketOutput.bind(this)); this.websocket.on('exit', this.handleExitCommand.bind(this)); this.websocket.on('status', this.showStatus.bind(this)); this.websocket.on('hint', this.showHint.bind(this)); this.websocket.on('files', this.prepareFileDownloads.bind(this)); }, handleExitCommand: function() { this.killWebsocket(); this.handleStderrOutputForFlowr(); this.augmentStacktraceInOutput(); this.cleanUpTurtle(); this.cleanUpUI(); } };