Skip to content

Backport fixes from aframe-inspector (batch 5)#1540

Merged
kfarr merged 8 commits into
mainfrom
backport-inspector-5
Apr 15, 2026
Merged

Backport fixes from aframe-inspector (batch 5)#1540
kfarr merged 8 commits into
mainfrom
backport-inspector-5

Conversation

@vincentfretin

@vincentfretin vincentfretin commented Apr 15, 2026

Copy link
Copy Markdown
Collaborator

Backport fixes from aframe-inspector (batch 5)

Previous sync: #1180

Changes

vincentfretin and others added 6 commits April 15, 2026 15:34
Backport from aframevr/aframe-inspector#822

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Move helper functions (getFilename, isValidId, getValidId, getUrlFromId,
getIdFromUrl) to assetsUtils.js. Detect already-loaded textures and show
error messages for duplicate/invalid asset names.

Backport from aframevr/aframe-inspector#824

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The pseudo-element selectors were missing :: prefix, making the rules
ineffective.

Backport from aframevr/aframe-inspector#826

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
THREE.ImageUtils was removed in newer Three.js versions, causing a
runtime warning.

Backport from aframevr/aframe-inspector#832

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…d to widgets

Replace componentname/entity propTypes with id prop on all widgets.
PropertyRow now generates and passes the id. Fix boolean label click by
using the id prop directly instead of constructing it in BooleanWidget.
Simplify PropertyRow type/value override logic.

Backport from aframevr/aframe-inspector#819

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Backport from aframevr/aframe-inspector#825

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@vincentfretin
vincentfretin requested a review from kfarr as a code owner April 15, 2026 13:56
vincentfretin and others added 2 commits April 15, 2026 15:59
Preserve world scale when reparenting by computing local scale relative
to the new parent. Remove rotation/scale attributes when they equal
default values (0 0 0 / 1 1 1) instead of always setting them.

Backport from c-frame/aframe-editor#62 and aframevr/aframe-inspector#63

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The animatetop keyframes were never defined, making the animation
rules ineffective.

Backport from aframevr/aframe-inspector#837

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@claude

claude Bot commented Apr 15, 2026

Copy link
Copy Markdown

Code Review — Backport fixes from aframe-inspector (batch 5)

Great batch of upstream fixes. The changes are well-scoped, clearly motivated, and generally clean. Here's a detailed look:


Overview

This PR backports 9 upstream fixes from aframe-inspector, covering: component ID validation, asset deduplication/error handling, CSS pseudo-element bugs, prop interface cleanup, boolean label click fix, world-scale preservation on reparent, and UX polish.


What's Well Done

  • CSS pseudo-element fix (index.scss) — The missing :: prefix on -webkit-color-swatch etc. was a legitimate rendering bug. Clean fix.
  • assetsUtils.js consolidation — Moving shared helpers out of ModalTextures and TextureWidget into a single module eliminates duplication and makes them testable in isolation.
  • a-assets auto-creation in insertNewAsset — Good defensive addition. Throwing a clear error when a-scene is also missing is better than a silent crash on null.appendChild.
  • crossOrigin = 'anonymous' always-on — Removing the conditional is safe here; every call site was passing true anyway, and the TextureWidget's private copy always set it unconditionally.
  • ID consistency fix for BooleanWidget — The root cause of the label-click bug was a separator mismatch: PropertyRow.render() used htmlFor={componentname + ':' + name} while BooleanWidget independently generated componentname + '.' + name. Centralizing the id in PropertyRow's constructor (this.id = props.componentname + ':' + props.name) and threading it through widgetProps fixes this cleanly.
  • isMap simplification in PropertyRow — Confirmed safe: A-Frame's material.src schema already has type: 'map'; only envMap has the wrong type string. The comment makes this clear.
  • Scale preservation in EntityReparentCommand — Correctly captures world scale before reparent and recomputes local scale relative to the new parent's world scale. The removeAttribute optimization for identity transforms is a nice touch.

Issues

1. Floating-point equality after trig operations — EntityReparentCommand.js:88-99

if (rotX === 0 && rotY === 0 && rotZ === 0) {
  entity.removeAttribute('rotation');
}
if (newLocalScale.x === 1 && newLocalScale.y === 1 && newLocalScale.z === 1) {
  entity.removeAttribute('scale');
}

After setFromQuaternionradToDeg and after world-scale division, these values will almost never be exactly 0 or 1 due to floating-point drift. An epsilon comparison (e.g. Math.abs(rotX) < 1e-5) would be more reliable. In practice this means attributes will often be written with near-zero/near-one values instead of being omitted — a minor inefficiency rather than a hard bug.

(This appears to be carried over from the upstream PRs, so not a blocker for this backport.)

2. Regex missing g flag in getValidIdassetsUtils.js:29-35

.replace(/\s/, '-')      // only replaces the FIRST space
.replace(/[\W]/, '')     // only replaces the FIRST non-word char

These were copied verbatim from the removed ModalTextures.js code, so this is a pre-existing bug, not introduced here. But since the function is now centralized and exported it's more visible. Consider fixing:

.replace(/\s+/g, '-')
.replace(/\W+/g, '')

3. CSS selector injection risk — assetsUtils.js:10

export function getIdFromUrl(url) {
  return document.querySelector("a-assets > [src='" + url + "']")?.id;
}

If url contains a single quote (e.g. a malformed or adversarial URL), this will break the querySelector call with a SyntaxError. URLs sourced from user-supplied input should be escaped. At minimum:

const escaped = url.replace(/'/g, "\\'");
return document.querySelector(`a-assets > [src='${escaped}']`)?.id;

The same issue exists in the pre-existing getUrlFromId which passes assetId directly to querySelector. Low severity since these are editor-only surfaces, but worth noting.

4. TextureWidget auto-registration removal — TextureWidget.js:140

The old onTextureModalSet called insertOrGetImageAsset for non-asset typed images, which would auto-register the image in a-assets and return a #id reference. This is now removed entirely. The new assumption is that ModalTextures.addNewAsset has already registered the asset before the event fires. Confirm that:

  • Selecting a registry image that is NOT yet in a-assets still results in it being registered before the texture value is set on the entity.
  • The event payload's value field for newly-added assets is #assetId (not url(...)) — looking at preview.value = 'url(' + src + ')' in ModalTextures, this may need verification.

5. onNameKeyUp inline handler recreated on each render — ModalTextures.js

Minor: the extracted inline onKeyUp arrow function closes over validAsset:

onKeyUp={(event) => {
  if (event.keyCode === 13 && validAsset) {
    this.addNewAsset();
  }
}}

This is fine functionally (the closure captures the correct value), but note event.keyCode is deprecated — event.key === 'Enter' is the modern equivalent.


Test Coverage

No new tests accompany this PR. The fixes are largely UI/behavioral (clicking labels, CORS attributes, CSS rendering, reparent math), so unit tests are harder to write — but EntityReparentCommand.updateLocalTransform with varying parent scales would be a good candidate for a Jest test, especially the floating-point equality edge case.


Summary

Good backport — the fixes address real bugs and the code is cleaner post-PR. The main things to double-check before merging:

  1. Manual test: drag-reparent an entity under a scaled parent and verify world position, rotation, and scale are preserved.
  2. Verify the TextureWidget/ModalTextures event flow for newly-added (non-asset) textures still works end-to-end.
  3. Optional: fix the g-flag regex in getValidId and the CSS selector injection in getIdFromUrl.

@github-project-automation github-project-automation Bot moved this to Backlog (Not Ready) in 3DStreet Dev Tracking Apr 15, 2026
@kfarr kfarr moved this from Backlog (Not Ready) to For Review in 3DStreet Dev Tracking Apr 15, 2026

@kfarr kfarr left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks @vincentfretin looks good. was able to test a few fixes but not everything since we don't support reparenting yet

@kfarr
kfarr merged commit 4739d21 into main Apr 15, 2026
3 checks passed
@kfarr
kfarr deleted the backport-inspector-5 branch April 15, 2026 23:20
@github-project-automation github-project-automation Bot moved this from For Review to Done in 3DStreet Dev Tracking Apr 15, 2026
@vincentfretin

Copy link
Copy Markdown
Collaborator Author

summary point 3 addressed in #1558

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

2 participants