@dodona/papyros 1.0.1 → 2.0.0-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (109) hide show
  1. package/LICENSE +0 -0
  2. package/README.md +0 -0
  3. package/dist/App.d.ts +1 -1
  4. package/dist/App.js +73 -0
  5. package/dist/App.js.map +1 -0
  6. package/dist/Backend.d.ts +0 -48
  7. package/dist/Backend.js +76 -0
  8. package/dist/Backend.js.map +1 -0
  9. package/dist/BackendEvent.d.ts +0 -0
  10. package/dist/BackendEvent.js +24 -0
  11. package/dist/BackendEvent.js.map +1 -0
  12. package/dist/BackendEventQueue.d.ts +0 -0
  13. package/dist/BackendEventQueue.js +135 -0
  14. package/dist/BackendEventQueue.js.map +1 -0
  15. package/dist/BackendManager.d.ts +1 -1
  16. package/dist/BackendManager.js +94 -0
  17. package/dist/BackendManager.js.map +1 -0
  18. package/dist/CodeRunner.d.ts +0 -0
  19. package/dist/CodeRunner.js +372 -0
  20. package/dist/CodeRunner.js.map +1 -0
  21. package/dist/Constants.d.ts +0 -0
  22. package/dist/Constants.js +36 -0
  23. package/dist/Constants.js.map +1 -0
  24. package/dist/InputManager.d.ts +0 -0
  25. package/dist/InputManager.js +102 -0
  26. package/dist/InputManager.js.map +1 -0
  27. package/dist/InputServiceWorker.d.ts +0 -0
  28. package/dist/InputServiceWorker.js +37 -0
  29. package/dist/InputServiceWorker.js.map +1 -0
  30. package/dist/Library.d.ts +2 -2
  31. package/dist/Library.js +9 -1
  32. package/dist/Library.js.map +1 -0
  33. package/dist/OutputManager.d.ts +0 -0
  34. package/dist/OutputManager.js +161 -0
  35. package/dist/OutputManager.js.map +1 -0
  36. package/dist/Papyros.css +563 -0
  37. package/dist/Papyros.d.ts +0 -1
  38. package/dist/Papyros.js +268 -0
  39. package/dist/Papyros.js.map +1 -0
  40. package/dist/ProgrammingLanguage.d.ts +0 -0
  41. package/dist/ProgrammingLanguage.js +9 -0
  42. package/dist/ProgrammingLanguage.js.map +1 -0
  43. package/dist/Translations.d.ts +74 -74
  44. package/dist/Translations.js +164 -0
  45. package/dist/Translations.js.map +1 -0
  46. package/dist/editor/BatchInputEditor.d.ts +0 -0
  47. package/dist/editor/BatchInputEditor.js +71 -0
  48. package/dist/editor/BatchInputEditor.js.map +1 -0
  49. package/dist/editor/CodeEditor.d.ts +0 -5
  50. package/dist/editor/CodeEditor.js +180 -0
  51. package/dist/editor/CodeEditor.js.map +1 -0
  52. package/dist/editor/CodeMirrorEditor.d.ts +0 -0
  53. package/dist/editor/CodeMirrorEditor.js +168 -0
  54. package/dist/editor/CodeMirrorEditor.js.map +1 -0
  55. package/dist/editor/DarkTheme.d.ts +0 -0
  56. package/dist/editor/DarkTheme.js +73 -0
  57. package/dist/editor/DarkTheme.js.map +1 -0
  58. package/dist/editor/Gutters.d.ts +0 -0
  59. package/dist/editor/Gutters.js +162 -0
  60. package/dist/editor/Gutters.js.map +1 -0
  61. package/dist/examples/Examples.d.ts +0 -0
  62. package/dist/examples/Examples.js +23 -0
  63. package/dist/examples/Examples.js.map +1 -0
  64. package/dist/examples/JavaScriptExamples.d.ts +0 -0
  65. package/dist/examples/JavaScriptExamples.js +16 -0
  66. package/dist/examples/JavaScriptExamples.js.map +1 -0
  67. package/dist/examples/PythonExamples.d.ts +0 -0
  68. package/dist/examples/PythonExamples.js +163 -0
  69. package/dist/examples/PythonExamples.js.map +1 -0
  70. package/dist/input/BatchInputHandler.d.ts +0 -0
  71. package/dist/input/BatchInputHandler.js +112 -0
  72. package/dist/input/BatchInputHandler.js.map +1 -0
  73. package/dist/input/InteractiveInputHandler.d.ts +0 -0
  74. package/dist/input/InteractiveInputHandler.js +90 -0
  75. package/dist/input/InteractiveInputHandler.js.map +1 -0
  76. package/dist/input/UserInputHandler.d.ts +0 -0
  77. package/dist/input/UserInputHandler.js +40 -0
  78. package/dist/input/UserInputHandler.js.map +1 -0
  79. package/dist/util/HTMLShapes.d.ts +0 -0
  80. package/dist/util/HTMLShapes.js +25 -0
  81. package/dist/util/HTMLShapes.js.map +1 -0
  82. package/dist/util/Logging.d.ts +0 -0
  83. package/dist/util/Logging.js +30 -0
  84. package/dist/util/Logging.js.map +1 -0
  85. package/dist/util/Rendering.d.ts +0 -0
  86. package/dist/util/Rendering.js +139 -0
  87. package/dist/util/Rendering.js.map +1 -0
  88. package/dist/util/Util.d.ts +1 -1
  89. package/dist/util/Util.js +148 -0
  90. package/dist/util/Util.js.map +1 -0
  91. package/dist/workers/input/InputWorker.d.ts +0 -0
  92. package/dist/workers/input/InputWorker.js +63 -1
  93. package/dist/workers/input/InputWorker.js.map +1 -0
  94. package/dist/workers/javascript/JavaScriptWorker.d.ts +39 -0
  95. package/dist/workers/javascript/JavaScriptWorker.js +148 -0
  96. package/dist/workers/javascript/JavaScriptWorker.js.map +1 -0
  97. package/dist/workers/javascript/worker.d.ts +1 -0
  98. package/dist/workers/javascript/worker.js +5 -0
  99. package/dist/workers/javascript/worker.js.map +1 -0
  100. package/dist/workers/python/PythonWorker.d.ts +31 -0
  101. package/dist/workers/python/PythonWorker.js +106 -0
  102. package/dist/workers/python/PythonWorker.js.map +1 -0
  103. package/dist/workers/python/python_package.tar.gz +0 -0
  104. package/dist/workers/python/worker.d.ts +1 -0
  105. package/dist/workers/python/worker.js +5 -0
  106. package/dist/workers/python/worker.js.map +1 -0
  107. package/package.json +45 -42
  108. package/dist/workers/javascript/JavaScriptWorker.worker.d.ts +0 -2
  109. package/dist/workers/python/PythonWorker.worker.d.ts +0 -2
package/LICENSE CHANGED
File without changes
package/README.md CHANGED
File without changes
package/dist/App.d.ts CHANGED
@@ -1 +1 @@
1
- export {};
1
+ import "./Papyros.css";
package/dist/App.js ADDED
@@ -0,0 +1,73 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ import "./Papyros.css";
11
+ import { addPapyrosPrefix, DEFAULT_LOCALE, DEFAULT_PROGRAMMING_LANGUAGE, DEFAULT_SERVICE_WORKER } from "./Constants";
12
+ import { Papyros } from "./Papyros";
13
+ import { InputMode } from "./InputManager";
14
+ import { BatchInputHandler } from "./input/BatchInputHandler";
15
+ const LOCAL_STORAGE_KEYS = {
16
+ code: addPapyrosPrefix("previous-code"),
17
+ input: addPapyrosPrefix("previous-batch-input")
18
+ };
19
+ function setUpEditor(editor, storageKey) {
20
+ const previousValue = window.localStorage.getItem(storageKey);
21
+ if (previousValue) {
22
+ editor.setText(previousValue);
23
+ }
24
+ editor.onChange({
25
+ onChange: (text) => {
26
+ window.localStorage.setItem(storageKey, text);
27
+ },
28
+ delay: 0
29
+ });
30
+ }
31
+ function startPapyros() {
32
+ return __awaiter(this, void 0, void 0, function* () {
33
+ // Retrieve initial locale and programming language from URL
34
+ // This allows easier sharing of Papyros-related links with others
35
+ // While preventing loading an unwanted backend
36
+ const urlParams = new URLSearchParams(window.location.search);
37
+ const language = Papyros.toProgrammingLanguage(urlParams.get("language") ||
38
+ DEFAULT_PROGRAMMING_LANGUAGE);
39
+ const locale = urlParams.get("locale") || DEFAULT_LOCALE;
40
+ const config = {
41
+ standAlone: true,
42
+ programmingLanguage: language,
43
+ locale: locale,
44
+ inputMode: InputMode.Batch,
45
+ channelOptions: {
46
+ serviceWorkerName: DEFAULT_SERVICE_WORKER
47
+ }
48
+ };
49
+ const papyros = new Papyros(config);
50
+ let darkMode = false;
51
+ if (window.matchMedia) {
52
+ darkMode = window.matchMedia("(prefers-color-scheme: dark)").matches;
53
+ window.matchMedia("(prefers-color-scheme: dark)").addEventListener("change", e => {
54
+ papyros.setDarkMode(e.matches);
55
+ });
56
+ }
57
+ papyros.render({
58
+ standAloneOptions: {
59
+ parentElementId: "root"
60
+ },
61
+ darkMode: darkMode
62
+ });
63
+ setUpEditor(papyros.codeRunner.editor, LOCAL_STORAGE_KEYS.code);
64
+ papyros.codeRunner.editor.focus();
65
+ const handler = papyros.codeRunner.inputManager.getInputHandler(InputMode.Batch);
66
+ if (handler instanceof BatchInputHandler) {
67
+ setUpEditor(handler.batchEditor, LOCAL_STORAGE_KEYS.input);
68
+ }
69
+ yield papyros.launch();
70
+ });
71
+ }
72
+ startPapyros();
73
+ //# sourceMappingURL=App.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"App.js","sourceRoot":"","sources":["../src/App.ts"],"names":[],"mappings":"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"}
package/dist/Backend.d.ts CHANGED
@@ -1,40 +1,6 @@
1
- import { CompletionContext, CompletionResult } from "@codemirror/autocomplete";
2
1
  import { BackendEvent } from "./BackendEvent";
3
2
  import { SyncExtras } from "comsync";
4
3
  import { BackendEventQueue } from "./BackendEventQueue";
5
- /**
6
- * Interface to represent the CodeMirror CompletionContext in a worker
7
- */
8
- export interface WorkerAutocompleteContext {
9
- /**
10
- * Whether the autocompletion was explicitly requested (using keybindings)
11
- */
12
- explicit: boolean;
13
- /**
14
- * The absolute position in the CodeMirror document
15
- */
16
- pos: number;
17
- /**
18
- * The line number of the cursor while completing (1-based)
19
- */
20
- line: number;
21
- /**
22
- * The column number of the cursor while completing (1-based)
23
- */
24
- column: number;
25
- /**
26
- * The full text to autocomplete for
27
- */
28
- text: string;
29
- /**
30
- * The match before the cursor (determined by a regex)
31
- */
32
- before: {
33
- from: number;
34
- to: number;
35
- text: string;
36
- } | null;
37
- }
38
4
  export interface WorkerDiagnostic {
39
5
  /**
40
6
  * 1-based index of the starting line containing the issue
@@ -111,20 +77,6 @@ export declare abstract class Backend<Extras extends SyncExtras = SyncExtras> {
111
77
  * @return {Promise<void>} Promise of execution
112
78
  */
113
79
  abstract runCode(extras: Extras, code: string, mode?: string): Promise<void>;
114
- /**
115
- * Converts the context to a cloneable object containing useful properties
116
- * to generate autocompletion suggestions with
117
- * Class instances are not passable to workers, so we extract the useful information
118
- * @param {CompletionContext} context Current context to autocomplete for
119
- * @param {RegExp} expr Expression to match the previous token with
120
- * @return {WorkerAutocompleteContext} Completion context that can be passed as a message
121
- */
122
- static convertCompletionContext(context: CompletionContext, expr?: RegExp): WorkerAutocompleteContext;
123
- /**
124
- * Generate autocompletion suggestions for the given context
125
- * @param {WorkerAutocompleteContext} context Context to autcomplete in
126
- */
127
- abstract autocomplete(context: WorkerAutocompleteContext): Promise<CompletionResult | null>;
128
80
  /**
129
81
  * Generate linting suggestions for the given code
130
82
  * @param {string} code The code to lint
@@ -0,0 +1,76 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ import { BackendEventType } from "./BackendEvent";
11
+ import { syncExpose } from "comsync";
12
+ import { BackendEventQueue } from "./BackendEventQueue";
13
+ export class Backend {
14
+ /**
15
+ * Constructor is limited as it is meant to be used as a WebWorker
16
+ * Proper initialization occurs in the launch method when the worker is started
17
+ * Synchronously exposing methods should be done here
18
+ */
19
+ constructor() {
20
+ this.extras = {};
21
+ this.onEvent = () => {
22
+ // Empty, initialized in launch
23
+ };
24
+ this.runCode = this.syncExpose()(this.runCode.bind(this));
25
+ this.queue = {};
26
+ }
27
+ /**
28
+ * @return {any} The function to expose methods for Comsync to allow interrupting
29
+ */
30
+ syncExpose() {
31
+ return syncExpose;
32
+ }
33
+ /**
34
+ * Initialize the backend by doing all setup-related work
35
+ * @param {function(BackendEvent):void} onEvent Callback for when events occur
36
+ * @param {function():void} onOverflow Callback for when overflow occurs
37
+ * @return {Promise<void>} Promise of launching
38
+ */
39
+ launch(onEvent, onOverflow) {
40
+ return __awaiter(this, void 0, void 0, function* () {
41
+ this.onEvent = (e) => {
42
+ onEvent(e);
43
+ if (e.type === BackendEventType.Sleep) {
44
+ return this.extras.syncSleep(e.data);
45
+ }
46
+ else if (e.type === BackendEventType.Input) {
47
+ return this.extras.readMessage();
48
+ }
49
+ };
50
+ this.queue = new BackendEventQueue(this.onEvent.bind(this), onOverflow);
51
+ return Promise.resolve();
52
+ });
53
+ }
54
+ /**
55
+ * Determine whether the modes supported by this Backend are active
56
+ * @param {string} code The current code in the editor
57
+ * @return {Array<RunMode>} The run modes of this Backend
58
+ */
59
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
60
+ runModes(code) {
61
+ return [];
62
+ }
63
+ /**
64
+ * @return {boolean} Whether too many output events were generated
65
+ */
66
+ hasOverflow() {
67
+ return this.queue.hasOverflow();
68
+ }
69
+ /**
70
+ * @return {Array<BackendEvent>} The events that happened after overflow
71
+ */
72
+ getOverflow() {
73
+ return this.queue.getOverflow();
74
+ }
75
+ }
76
+ //# sourceMappingURL=Backend.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Backend.js","sourceRoot":"","sources":["../src/Backend.ts"],"names":[],"mappings":";;;;;;;;;AAAA,OAAO,EAAgB,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAChE,OAAO,EAAE,UAAU,EAAc,MAAM,SAAS,CAAC;AACjD,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAmCxD,MAAM,OAAgB,OAAO;IAczB;;;;OAIG;IACH;QACI,IAAI,CAAC,MAAM,GAAG,EAAY,CAAC;QAC3B,IAAI,CAAC,OAAO,GAAG,GAAG,EAAE;YAChB,+BAA+B;QACnC,CAAC,CAAC;QACF,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,UAAU,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;QAC1D,IAAI,CAAC,KAAK,GAAG,EAAuB,CAAC;IACzC,CAAC;IAED;;OAEG;IACO,UAAU;QAChB,OAAO,UAAU,CAAC;IACtB,CAAC;IAED;;;;;OAKG;IACU,MAAM,CACf,OAAkC,EAClC,UAAsB;;YAEtB,IAAI,CAAC,OAAO,GAAG,CAAC,CAAe,EAAE,EAAE;gBAC/B,OAAO,CAAC,CAAC,CAAC,CAAC;gBACX,IAAI,CAAC,CAAC,IAAI,KAAK,gBAAgB,CAAC,KAAK,EAAE,CAAC;oBACpC,OAAO,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;gBACzC,CAAC;qBAAM,IAAI,CAAC,CAAC,IAAI,KAAK,gBAAgB,CAAC,KAAK,EAAE,CAAC;oBAC3C,OAAO,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC;gBACrC,CAAC;YACL,CAAC,CAAC;YACF,IAAI,CAAC,KAAK,GAAG,IAAI,iBAAiB,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,UAAU,CAAC,CAAC;YACxE,OAAO,OAAO,CAAC,OAAO,EAAE,CAAC;QAC7B,CAAC;KAAA;IAED;;;;OAIG;IACH,6DAA6D;IACtD,QAAQ,CAAC,IAAY;QACxB,OAAO,EAAE,CAAC;IACd,CAAC;IAiBD;;OAEG;IACI,WAAW;QACd,OAAO,IAAI,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC;IACpC,CAAC;IAED;;OAEG;IACI,WAAW;QACd,OAAO,IAAI,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC;IACpC,CAAC;CACJ"}
File without changes
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Enum representing all possible types for supported events
3
+ */
4
+ export var BackendEventType;
5
+ (function (BackendEventType) {
6
+ BackendEventType["Start"] = "start";
7
+ BackendEventType["End"] = "end";
8
+ BackendEventType["Input"] = "input";
9
+ BackendEventType["Output"] = "output";
10
+ BackendEventType["Sleep"] = "sleep";
11
+ BackendEventType["Error"] = "error";
12
+ BackendEventType["Interrupt"] = "interrupt";
13
+ BackendEventType["Loading"] = "loading";
14
+ })(BackendEventType || (BackendEventType = {}));
15
+ /**
16
+ * All possible types for ease of iteration
17
+ */
18
+ export const BACKEND_EVENT_TYPES = [
19
+ BackendEventType.Start, BackendEventType.End,
20
+ BackendEventType.Input, BackendEventType.Output,
21
+ BackendEventType.Sleep, BackendEventType.Error,
22
+ BackendEventType.Interrupt, BackendEventType.Loading
23
+ ];
24
+ //# sourceMappingURL=BackendEvent.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BackendEvent.js","sourceRoot":"","sources":["../src/BackendEvent.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,CAAN,IAAY,gBASX;AATD,WAAY,gBAAgB;IACxB,mCAAe,CAAA;IACf,+BAAW,CAAA;IACX,mCAAe,CAAA;IACf,qCAAiB,CAAA;IACjB,mCAAe,CAAA;IACf,mCAAe,CAAA;IACf,2CAAuB,CAAA;IACvB,uCAAmB,CAAA;AACvB,CAAC,EATW,gBAAgB,KAAhB,gBAAgB,QAS3B;AACD;;GAEG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG;IAC/B,gBAAgB,CAAC,KAAK,EAAE,gBAAgB,CAAC,GAAG;IAC5C,gBAAgB,CAAC,KAAK,EAAE,gBAAgB,CAAC,MAAM;IAC/C,gBAAgB,CAAC,KAAK,EAAE,gBAAgB,CAAC,KAAK;IAC9C,gBAAgB,CAAC,SAAS,EAAE,gBAAgB,CAAC,OAAO;CACvD,CAAC"}
File without changes
@@ -0,0 +1,135 @@
1
+ import { BackendEventType } from "./BackendEvent";
2
+ /**
3
+ * Queue to limit the amount of messages sent between threads
4
+ * This prevents communication issues which arise either in Comlink
5
+ * or in the WebWorker message passing code
6
+ */
7
+ export class BackendEventQueue {
8
+ /**
9
+ * @param {function(BackendEvent):void} callback Function to process events in the queue
10
+ * @param {function():void} onOverflow Callback for when overflow occurs
11
+ * @param {number} limit The maximal amount of output lines to send before overflowing
12
+ * @param {number} flushTime The time in milliseconds before sending events through
13
+ */
14
+ constructor(callback, onOverflow, limit = 1000, flushTime = 100) {
15
+ this.callback = callback;
16
+ this.limit = limit;
17
+ this.flushTime = flushTime;
18
+ this.queue = [];
19
+ this.overflow = [];
20
+ this.onOverflow = onOverflow;
21
+ this.overflown = false;
22
+ this.lastFlushTime = new Date().getTime();
23
+ this.sendCount = 0;
24
+ this.decoder = new TextDecoder();
25
+ }
26
+ /**
27
+ * Add an element to the queue
28
+ * @param {BackendEventType} type The type of the event
29
+ * @param {string | BufferSource} text The data for the event
30
+ * @param {string | any} extra Extra data for the event
31
+ * If string, interpreted as the contentType
32
+ * If anything else, it should contain a contentType
33
+ * If the contentType is not textual, an error is thrown
34
+ */
35
+ put(type, text, extra) {
36
+ let stringData = "";
37
+ if (typeof text !== "string") {
38
+ stringData = this.decoder.decode(text);
39
+ }
40
+ else {
41
+ stringData = text;
42
+ }
43
+ let extraArgs = {};
44
+ let contentType = "text/plain";
45
+ if (extra) {
46
+ if (typeof extra === "string") {
47
+ contentType = extra;
48
+ }
49
+ else {
50
+ contentType = extra["contentType"];
51
+ delete extra["contentType"];
52
+ extraArgs = extra;
53
+ }
54
+ }
55
+ if (this.queue.length === 0 ||
56
+ !contentType.startsWith("text") || // Non textual cannot be combined
57
+ this.queue[this.queue.length - 1].type !== type || // Different type
58
+ // Can't be combined if contentType doesn't match
59
+ this.queue[this.queue.length - 1].contentType !== contentType) {
60
+ this.queue.push(Object.assign({ type: type, data: stringData, contentType: contentType }, extraArgs));
61
+ }
62
+ else { // Same kind of event, combine into one
63
+ this.queue[this.queue.length - 1].data += stringData;
64
+ }
65
+ if (this.shouldFlush()) {
66
+ this.flush();
67
+ }
68
+ }
69
+ /**
70
+ * @return {boolean} Whether the queue contents should be flushed
71
+ */
72
+ shouldFlush() {
73
+ return this.queue.length > 1 || // different types of Events present
74
+ new Date().getTime() - this.lastFlushTime > this.flushTime;
75
+ }
76
+ /**
77
+ * Reset the queue contents for a new run
78
+ */
79
+ reset() {
80
+ this.queue = [];
81
+ this.overflow = [];
82
+ this.overflown = false;
83
+ this.lastFlushTime = new Date().getTime();
84
+ this.sendCount = 0;
85
+ }
86
+ /**
87
+ * @param {BackendEvent} e The event put in the queue
88
+ * @return {number} The amount of lines of data in the event
89
+ */
90
+ static lines(e) {
91
+ return (e.data.match(/\n/g) || []).length + 1;
92
+ }
93
+ /**
94
+ * Flush the queue contents using the callback
95
+ */
96
+ flush() {
97
+ this.queue.forEach(e => {
98
+ if (e.type === BackendEventType.Output) {
99
+ this.overflow.push(e);
100
+ if (this.sendCount < this.limit) {
101
+ this.sendCount += BackendEventQueue.lines(e);
102
+ this.callback(e);
103
+ }
104
+ else if (!this.overflown) {
105
+ this.overflown = true;
106
+ this.onOverflow();
107
+ }
108
+ }
109
+ else {
110
+ this.callback(e);
111
+ }
112
+ });
113
+ this.queue = [];
114
+ this.lastFlushTime = new Date().getTime();
115
+ }
116
+ /**
117
+ * @return {boolean} Whether too many output events were generated
118
+ */
119
+ hasOverflow() {
120
+ return this.overflown;
121
+ }
122
+ /**
123
+ * @return {Array<BackendEvent>} The events that happened after overflow
124
+ */
125
+ getOverflow() {
126
+ return this.overflow;
127
+ }
128
+ /**
129
+ * @param {Function} callback The event-consuming callback
130
+ */
131
+ setCallback(callback) {
132
+ this.callback = callback;
133
+ }
134
+ }
135
+ //# sourceMappingURL=BackendEventQueue.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BackendEventQueue.js","sourceRoot":"","sources":["../src/BackendEventQueue.ts"],"names":[],"mappings":"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"}
@@ -7,7 +7,7 @@ import { SyncClient } from "comsync";
7
7
  * Callback type definition for subscribers
8
8
  * @param {BackendEvent} e The published event
9
9
  */
10
- declare type BackendEventListener = (e: BackendEvent) => void;
10
+ type BackendEventListener = (e: BackendEvent) => void;
11
11
  /**
12
12
  * Abstract class to implement the singleton pattern
13
13
  * Static methods group functionality
@@ -0,0 +1,94 @@
1
+ import { ProgrammingLanguage } from "./ProgrammingLanguage";
2
+ import { BackendEventType } from "./BackendEvent";
3
+ import { LogType, papyrosLog } from "./util/Logging";
4
+ import { makeChannel } from "sync-message";
5
+ import { SyncClient } from "comsync";
6
+ import { PyodideClient } from "pyodide-worker-runner";
7
+ /**
8
+ * Abstract class to implement the singleton pattern
9
+ * Static methods group functionality
10
+ */
11
+ export class BackendManager {
12
+ /**
13
+ * @param {ProgrammingLanguage} language The language to support
14
+ * @param {Function} backendCreator The constructor for a SyncClient
15
+ */
16
+ static registerBackend(language, backendCreator) {
17
+ BackendManager.removeBackend(language);
18
+ BackendManager.createBackendMap.set(language, backendCreator);
19
+ }
20
+ /**
21
+ * Start a backend for the given language and cache for reuse
22
+ * @param {ProgrammingLanguage} language The programming language supported by the backend
23
+ * @return {SyncClient<Backend>} A SyncClient for the Backend
24
+ */
25
+ static getBackend(language) {
26
+ if (this.backendMap.has(language)) { // Cached
27
+ return this.backendMap.get(language);
28
+ }
29
+ else if (this.createBackendMap.has(language)) {
30
+ // Create and then cache
31
+ const syncClient = this.createBackendMap.get(language)();
32
+ this.backendMap.set(language, syncClient);
33
+ return syncClient;
34
+ }
35
+ else {
36
+ throw new Error(`${language} is not yet supported.`);
37
+ }
38
+ }
39
+ /**
40
+ * Remove a backend for the given language
41
+ * @param {ProgrammingLanguage} language The programming language supported by the backend
42
+ * @return {boolean} Whether the remove operation had any effect
43
+ */
44
+ static removeBackend(language) {
45
+ this.backendMap.delete(language);
46
+ return this.createBackendMap.delete(language);
47
+ }
48
+ /**
49
+ * Register a callback for when an event of a certain type is published
50
+ * @param {BackendEventType} type The type of event to subscribe to
51
+ * @param {BackendEventListener} subscriber Callback for when an event
52
+ * of the given type is published
53
+ */
54
+ static subscribe(type, subscriber) {
55
+ if (!this.subscriberMap.has(type)) {
56
+ this.subscriberMap.set(type, []);
57
+ }
58
+ const subscribers = this.subscriberMap.get(type);
59
+ if (!subscribers.includes(subscriber)) {
60
+ subscribers.push(subscriber);
61
+ }
62
+ }
63
+ /**
64
+ * Publish an event, notifying all listeners for its type
65
+ * @param {BackendEventType} e The event to publish
66
+ */
67
+ static publish(e) {
68
+ papyrosLog(LogType.Debug, "Publishing event: ", e);
69
+ if (e.type === BackendEventType.Start) {
70
+ BackendManager.halted = false;
71
+ }
72
+ if (!BackendManager.halted && this.subscriberMap.has(e.type)) {
73
+ this.subscriberMap.get(e.type).forEach(cb => cb(e));
74
+ }
75
+ }
76
+ static halt() {
77
+ BackendManager.halted = true;
78
+ }
79
+ }
80
+ /**
81
+ * Initialise the fields and setup the maps
82
+ */
83
+ (() => {
84
+ BackendManager.channel = makeChannel();
85
+ BackendManager.createBackendMap = new Map();
86
+ BackendManager.backendMap = new Map();
87
+ BackendManager.subscriberMap = new Map();
88
+ BackendManager.registerBackend(ProgrammingLanguage.Python, () => new PyodideClient(() => new Worker(new URL("./workers/python/worker", import.meta.url)), BackendManager.channel));
89
+ BackendManager.registerBackend(ProgrammingLanguage.JavaScript, () => new SyncClient(() => new Worker(new URL("./workers/javascript/worker", import.meta.url)), BackendManager.channel));
90
+ BackendManager.halted = false;
91
+ BackendManager.subscribe(BackendEventType.End, () => BackendManager.halt());
92
+ BackendManager.subscribe(BackendEventType.Interrupt, () => BackendManager.halt());
93
+ })();
94
+ //# sourceMappingURL=BackendManager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BackendManager.js","sourceRoot":"","sources":["../src/BackendManager.ts"],"names":[],"mappings":"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"}
File without changes