Skip to content

Commit 80b6f55

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 80b6f55

File tree

1 file changed

+39
-15
lines changed

1 file changed

+39
-15
lines changed

webapp/src/Twig/TwigExtension.php

Lines changed: 39 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,8 @@ public function __construct(
5555
protected readonly AuthorizationCheckerInterface $authorizationChecker,
5656
protected readonly RouterInterface $router,
5757
#[Autowire('%kernel.project_dir%')]
58-
protected readonly string $projectDir
58+
protected readonly string $projectDir,
59+
protected array $renderedSources = []
5960
) {}
6061

6162
public function getFunctions(): array
@@ -917,23 +918,48 @@ public function codeEditor(
917918
sprintf($editor, $code, $editable ? 'false' : 'true', $mode, $extraForEdit));
918919
}
919920

921+
/**
922+
* Gets the JavaScript to get a Monaco model instance for the submission file.
923+
* Renders the source code of the file as Monaco model, if not already rendered.
924+
* @param SubmissionFile $file The submission file to render
925+
* @return string The JavaScript source assignable to a model variable.
926+
*/
927+
public function getMonacoModel(SubmissionFile $file): string
928+
{
929+
if (array_key_exists($file->getSubmitfileid(), $this->renderedSources)) {
930+
return sprintf(
931+
<<<JS
932+
monaco.editor.getModel(monaco.Uri.parse("diff/%d/%s"));
933+
JS,
934+
$file->getSubmitfileid(),
935+
$file->getFilename(),
936+
);
937+
}
938+
$this->renderedSources[$file->getSubmitfileid()] = true;
939+
940+
return sprintf(
941+
<<<JS
942+
monaco.editor.createModel(
943+
"%s",
944+
undefined,
945+
monaco.Uri.parse("diff/%d/%s")
946+
);
947+
JS,
948+
$this->twig->getRuntime(EscaperRuntime::class)->escape($file->getSourcecode(), 'js'),
949+
$file->getSubmitfileid(),
950+
$file->getFilename(),
951+
);
952+
}
953+
920954
public function showDiff(string $id, SubmissionFile $newFile, SubmissionFile $oldFile): string
921955
{
922956
$editor = <<<HTML
923957
<div class="editor" id="__EDITOR__"></div>
924958
<script>
925959
$(function() {
926960
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-
);
961+
const originalModel = %s
962+
const modifiedModel = %s
937963
938964
const initialDiffMode = getDiffMode();
939965
const radios = $("#diffselect-__EDITOR__ > input[name='__EDITOR__-mode']");
@@ -988,10 +1014,8 @@ public function showDiff(string $id, SubmissionFile $newFile, SubmissionFile $ol
9881014

9891015
return sprintf(
9901016
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(),
1017+
$this->getMonacoModel($oldFile),
1018+
$this->getMonacoModel($newFile),
9951019
);
9961020
}
9971021

0 commit comments

Comments
 (0)