Skip to content

Commit bc86b03

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 e2eaca5 commit bc86b03

File tree

1 file changed

+41
-15
lines changed

1 file changed

+41
-15
lines changed

webapp/src/Twig/TwigExtension.php

Lines changed: 41 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,47 @@ 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+
* @return string The JavaScript source assignable to a model variable.
928+
*/
929+
public function getMonacoModel(SubmissionFile $file): string
930+
{
931+
if (array_key_exists($file->getSubmitfileid(), $this->renderedSources)) {
932+
return sprintf(
933+
<<<JS
934+
monaco.editor.getModel(monaco.Uri.parse("diff/%d/%s"));
935+
JS,
936+
$file->getSubmitfileid(),
937+
$file->getFilename(),
938+
);
939+
}
940+
$this->renderedSources[$file->getSubmitfileid()] = true;
941+
942+
return sprintf(
943+
<<<JS
944+
monaco.editor.createModel(
945+
"%s",
946+
undefined,
947+
monaco.Uri.parse("diff/%d/%s")
948+
);
949+
JS,
950+
$this->twig->getRuntime(EscaperRuntime::class)->escape($file->getSourcecode(), 'js'),
951+
$file->getSubmitfileid(),
952+
$file->getFilename(),
953+
);
954+
}
955+
920956
public function showDiff(string $id, SubmissionFile $newFile, SubmissionFile $oldFile): string
921957
{
922958
$editor = <<<HTML
923959
<div class="editor" id="__EDITOR__"></div>
924960
<script>
925961
$(function() {
926962
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-
);
963+
const originalModel = %s
964+
const modifiedModel = %s
937965
938966
const initialDiffMode = getDiffMode();
939967
const radios = $("#diffselect-__EDITOR__ > input[name='__EDITOR__-mode']");
@@ -988,10 +1016,8 @@ public function showDiff(string $id, SubmissionFile $newFile, SubmissionFile $ol
9881016

9891017
return sprintf(
9901018
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(),
1019+
$this->getMonacoModel($oldFile),
1020+
$this->getMonacoModel($newFile),
9951021
);
9961022
}
9971023

0 commit comments

Comments
 (0)