Skip to content

Commit 46e5d58

Browse files
committed
Ensure unique Monaco models for diff sources
Monaco stores source code in a global service. The URIs of every source must be unique. As we are not editing the diff files anyway, we can make sure to only render them once and share them between diff viewers to reduce overhead.
1 parent 43ecaaa commit 46e5d58

File tree

1 file changed

+42
-15
lines changed

1 file changed

+42
-15
lines changed

webapp/src/Twig/TwigExtension.php

Lines changed: 42 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,9 @@
4343

4444
class TwigExtension extends AbstractExtension implements GlobalsInterface
4545
{
46+
/**
47+
* @param array<int, bool> $renderedSources
48+
*/
4649
public function __construct(
4750
protected readonly DOMJudgeService $dj,
4851
protected readonly ConfigurationService $config,
@@ -55,7 +58,8 @@ public function __construct(
5558
protected readonly AuthorizationCheckerInterface $authorizationChecker,
5659
protected readonly RouterInterface $router,
5760
#[Autowire('%kernel.project_dir%')]
58-
protected readonly string $projectDir
61+
protected readonly string $projectDir,
62+
protected array $renderedSources = []
5963
) {}
6064

6165
public function getFunctions(): array
@@ -917,23 +921,48 @@ public function codeEditor(
917921
sprintf($editor, $code, $editable ? 'false' : 'true', $mode, $extraForEdit));
918922
}
919923

924+
/**
925+
* Gets the JavaScript to get a Monaco model instance for the submission file.
926+
* Renders the source code of the file as Monaco model, if not already rendered.
927+
* @param SubmissionFile $file The submission file to render
928+
* @return string The JavaScript source assignable to a model variable.
929+
*/
930+
public function getMonacoModel(SubmissionFile $file): string
931+
{
932+
if (array_key_exists($file->getSubmitfileid(), $this->renderedSources)) {
933+
return sprintf(
934+
<<<JS
935+
monaco.editor.getModel(monaco.Uri.parse("diff/%d/%s"));
936+
JS,
937+
$file->getSubmitfileid(),
938+
$file->getFilename(),
939+
);
940+
}
941+
$this->renderedSources[$file->getSubmitfileid()] = true;
942+
943+
return sprintf(
944+
<<<JS
945+
monaco.editor.createModel(
946+
"%s",
947+
undefined,
948+
monaco.Uri.parse("diff/%d/%s")
949+
);
950+
JS,
951+
$this->twig->getRuntime(EscaperRuntime::class)->escape($file->getSourcecode(), 'js'),
952+
$file->getSubmitfileid(),
953+
$file->getFilename(),
954+
);
955+
}
956+
920957
public function showDiff(string $id, SubmissionFile $newFile, SubmissionFile $oldFile): string
921958
{
922959
$editor = <<<HTML
923960
<div class="editor" id="__EDITOR__"></div>
924961
<script>
925962
$(function() {
926963
require(['vs/editor/editor.main'], function () {
927-
const originalModel = monaco.editor.createModel(
928-
"%s",
929-
undefined,
930-
monaco.Uri.parse("diff-old/%s")
931-
);
932-
const modifiedModel = monaco.editor.createModel(
933-
"%s",
934-
undefined,
935-
monaco.Uri.parse("diff-new/%s")
936-
);
964+
const originalModel = %s
965+
const modifiedModel = %s
937966
938967
const initialDiffMode = getDiffMode();
939968
const radios = $("#diffselect-__EDITOR__ > input[name='__EDITOR__-mode']");
@@ -988,10 +1017,8 @@ public function showDiff(string $id, SubmissionFile $newFile, SubmissionFile $ol
9881017

9891018
return sprintf(
9901019
str_replace('__EDITOR__', $id, $editor),
991-
$this->twig->getRuntime(EscaperRuntime::class)->escape($oldFile->getSourcecode(), 'js'),
992-
$oldFile->getFilename(),
993-
$this->twig->getRuntime(EscaperRuntime::class)->escape($newFile->getSourcecode(), 'js'),
994-
$newFile->getFilename(),
1020+
$this->getMonacoModel($oldFile),
1021+
$this->getMonacoModel($newFile),
9951022
);
9961023
}
9971024

0 commit comments

Comments
 (0)