DefaultRelativeUrlPropSource does not sort properties keys for comparison
>>> [!note] Migrated issue <!-- Drupal.org comment --> <!-- Migrated from issue #3550165. --> Reported by: [mglaman](https://www.drupal.org/user/2416470) Related to !187 >>> <h3 id="overview">Overview</h3> <p>When using a code component with a prop of image or video you cannot publish a page using the default prop values. If you do, you get:</p> <pre>Error 500: Extraneous JSON Schema information detected: { "properties": { "src": { "type": "string", "format": "uri-reference", "pattern": "^(\/|https?:\/\/)?(?!.*\\:\/\/)[^\\s]+$", "contentMediaType": "video\/*" }, "poster": { "type": "string", "format": "uri-reference", "pattern": "^(\/|https?:\/\/)?(?!.*\\:\/\/)[^\\s]+$", "contentMediaType": "image\/*" } }, "required": [ "src" ], "type": "object" }&nbsp; should have been just { "properties": { "src": { "type": "string", "contentMediaType": "video\/*", "format": "uri-reference", "pattern": "^(\/|https?:\/\/)?(?!.*\\:\/\/)[^\\s]+$" }, "poster": { "type": "string", "contentMediaType": "image\/*", "format": "uri-reference", "pattern": "^(\/|https?:\/\/)?(?!.*\\:\/\/)[^\\s]+$" } }, "required": [ "src" ], "type": "object" }.</pre><p>That's because the comparison logic doesn't sort recursively through the JSON schema.</p> <pre>&nbsp;&nbsp;&nbsp; ksort($sdc_prop_source['jsonSchema']);<br>&nbsp;&nbsp;&nbsp; ksort($minimal);<br>&nbsp;&nbsp;&nbsp; if ($sdc_prop_source['jsonSchema'] !== $minimal) {</pre><p>The <code>properties</code> keys are not sorted the same.</p> <h4>Steps to reproduce</h4> <p>1. Create a <em>VideoCC</em> code component in the code editor with</p> <pre>const Component = ({<br>&nbsp; video,<br>}) =&gt; {<br>&nbsp; return (<br>&nbsp;&nbsp;&nbsp; &lt;div className="text-3xl"&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;video controls width="250" poster={ video?.poster }&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;source src={ video.src } type="video/mp4"/&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/video&gt;<br>&nbsp;&nbsp;&nbsp; &lt;/div&gt;<br>&nbsp; );<br>};<br><br>export default Component;</pre><p>2. Ensure you add a <em>Video</em> prop with type <code>video</code>.<br> 3. Promote to available components in the library.<br> 4. Create a new page with that video. Link to a video from your media library. It works.<br> 5. Remove the video so it uses the defaults and save.<br> 6. The preview fails.<br> 7. If you manually go to <code>/canvas/api/v0/layout/canvas_page/1</code> you'll see the stacktrace:</p> <pre>file: "/var/www/html/web/modules/contrib/canvas/src/PropSource/DefaultRelativeUrlPropSource.php",<br>line: 101,<br>trace: [<br>{<br>file: "/var/www/html/web/modules/contrib/canvas/src/PropSource/PropSource.php",<br>line: 33,<br>function: "parse",<br>class: "Drupal\canvas\PropSource\DefaultRelativeUrlPropSource",<br>type: "::"<br>},<br>{<br>file: "/var/www/html/web/modules/contrib/canvas/src/Plugin/Canvas/ComponentSource/GeneratedFieldExplicitInputUxComponentSourceBase.php",<br>line: 1263,<br>function: "parse",<br>class: "Drupal\canvas\PropSource\PropSource",<br>type: "::"<br>},<br>{<br>file: "/var/www/html/web/modules/contrib/canvas/src/Plugin/Canvas/ComponentSource/GeneratedFieldExplicitInputUxComponentSourceBase.php",<br>line: 342,<br>function: "uncollapse",<br>class: "Drupal\canvas\Plugin\Canvas\ComponentSource\GeneratedFieldExplicitInputUxComponentSourceBase",<br>type: "-&gt;"<br>},<br>{<br>file: "/var/www/html/web/modules/contrib/canvas/src/Plugin/Field/FieldType/ComponentTreeItemList.php",<br>line: 99,<br>function: "getExplicitInput",<br>class: "Drupal\canvas\Plugin\Canvas\ComponentSource\GeneratedFieldExplicitInputUxComponentSourceBase",<br>type: "-&gt;"<br>},</pre><h3 id="proposed-resolution">Proposed resolution</h3> <p>Drupal doesn't have a recursive ksort, so hack it like</p> <pre>&nbsp;&nbsp;&nbsp; ksort($sdc_prop_source['jsonSchema']);<br>&nbsp;&nbsp;&nbsp; foreach (array_keys($sdc_prop_source['jsonSchema']['properties']) as $property_key) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ksort($sdc_prop_source['jsonSchema']['properties'][$property_key]);<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; ksort($minimal);<br>&nbsp;&nbsp;&nbsp; foreach (array_keys($minimal['properties']) as $property_key) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ksort($minimal['properties'][$property_key]);<br>&nbsp;&nbsp;&nbsp; }</pre><h3 id="ui-changes">User interface changes</h3> > Related issue: [Issue #3556987](https://www.drupal.org/node/3556987)
issue