Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions src/components/common/DomListener.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import React, { Component } from "react";
import ReactDOM from "react-dom";

// no tests because js-dom doesn't support MutationObserver
// https://github.com/jsdom/jsdom/issues/639
Expand All @@ -24,15 +23,16 @@ export class DomListener extends Component<DomListenerProps> {
public observer: MutationObserver;
private readonly onResize: () => void;
private readonly onDomChange: () => void;
private readonly rootRef: React.RefObject<HTMLDivElement>;
constructor(props: DomListenerProps) {
super(props);
this.onResize = this.onUpdateHeight("resize").bind(this);
this.onDomChange = this.onUpdateHeight("domChange").bind(this);
this.observer = new MutationObserver(this.onDomChange);
this.rootRef = React.createRef<HTMLDivElement>();
}
componentDidMount(): void {
// eslint-disable-next-line react/no-find-dom-node
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

findDOMNode is legacy/deprecated behavior in modern React (especially with Strict Mode / React 18).

const rootNode = ReactDOM.findDOMNode(this);
const rootNode = this.rootRef.current;
if (rootNode) {
this.observer.observe(rootNode, { attributes: true, childList: true, subtree: true, characterData: true });
// need an initial trigger, make it run on next tick :shrug:
Expand All @@ -51,6 +51,6 @@ export class DomListener extends Component<DomListenerProps> {
}

render(): React.ReactNode {
return <div>{this.props.children}</div>;
return <div ref={this.rootRef}>{this.props.children}</div>;
}
}
5 changes: 4 additions & 1 deletion src/types.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import { ComponentType } from "react";
import { v2, WrappedDocument, OpenAttestationDocument, v3, SignedVerifiableCredential } from "@trustvc/trustvc";

export type Document = SignedVerifiableCredential | OpenAttestationDocument;
export type { OpenAttestationDocument, SignedVerifiableCredential } from "@trustvc/trustvc";

export type Attachment = v2.Attachment | v3.Attachment;
export interface Renderer {
attachment: Attachment;
Expand All @@ -9,7 +12,7 @@ export interface Renderer {
export interface TemplateProps<D extends OpenAttestationDocument | SignedVerifiableCredential> {
document: D;
wrappedDocument?: WrappedDocument<OpenAttestationDocument> | SignedVerifiableCredential;
handleObfuscation: (field: string) => void;
handleObfuscation?: (field: string) => void;
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Description: Find all usages of handleObfuscation that may need optional chaining

# Search for handleObfuscation calls without optional chaining
rg -n "handleObfuscation\s*\(" --type ts --type tsx -g '!*.d.ts' | grep -v "handleObfuscation?."

# Also check for destructuring of handleObfuscation from props
rg -n "handleObfuscation\s*}" --type ts --type tsx -g '!*.d.ts'

Repository: TrustVC/decentralized-renderer-react-components

Length of output: 1842


🏁 Script executed:

#!/bin/bash
# Search for handleObfuscation usages without null checks
rg "handleObfuscation" --type ts --type tsx -B 2 -A 2

Repository: TrustVC/decentralized-renderer-react-components

Length of output: 118


🌐 Web query:

TrustVC/decentralized-renderer-react-components handleObfuscation transcript.tsx

💡 Result:

The query refers to the handleObfuscation function in the context of the decentralized-renderer-react-components library (likely a fork or variant under TrustVC), specifically in a transcript.tsx file. This library is part of the OpenAttestation/TradeTrust ecosystem for rendering verifiable documents in iframes using React components. handleObfuscation is a mandatory prop provided to each configured Template React component (such as a Transcript template in transcript.tsx) when rendering a document. It is a function that triggers obfuscation (redaction/hiding) of sensitive fields in the document. Key details: - Signature/Usage: Called with a path string following lodash#get syntax, e.g., handleObfuscation('a[0].b.c'). - Behavior: Automatically sends a postMessage action { type: "OBFUSCATE", payload: path } to the iframe's decentralized renderer via components like FrameConnector or FramedDocumentRenderer. - Purpose: Allows templates to redact PII (e.g., names, IDs in transcripts) on demand, enhancing privacy in verifiable credential rendering. - Related components: ObfuscatableValue.js (976B in builds), used for rendering redactable values. No exact TrustVC repo found; closest are TradeTrust/decentralized-renderer-react-components (npm:@tradetrust-tt/decentralized-renderer-react-components v3.16.15, updated 2025) and Open-Attestation/decentralized-renderer-react-components. "Transcript" appears as an example template id/label alongside "certificate". @trustvc/trustvc is a dependency. Example in Template: const TranscriptTemplate = ({ document, handleObfuscation }) => (

<ObfuscatableValue value={get(document, 'sensitive.field')} path="sensitive.field" onObfuscate={handleObfuscation} />
); FramedDocumentRenderer auto-calls OBFUSCATE when requested by templates.

Citations:


🏁 Script executed:

#!/bin/bash
# Search for handleObfuscation usages in TypeScript/JavaScript files
rg "handleObfuscation" -B 2 -A 2 --type typescript --type javascript

Repository: TrustVC/decentralized-renderer-react-components

Length of output: 125


🏁 Script executed:

#!/bin/bash
# Find all files containing handleObfuscation
rg "handleObfuscation" -l --max-count=20

Repository: TrustVC/decentralized-renderer-react-components

Length of output: 314


🏁 Script executed:

#!/bin/bash
# List TypeScript/TSX files in the repo
fd -e ts -e tsx | head -20

Repository: TrustVC/decentralized-renderer-react-components

Length of output: 1304


🏁 Script executed:

#!/bin/bash
# Check the transcript.tsx file to see how handleObfuscation is used
cat example/decentralized-renderer/templates/govtechDemoCert/transcript.tsx

Repository: TrustVC/decentralized-renderer-react-components

Length of output: 7088


🏁 Script executed:

#!/bin/bash
# Check current state of src/types.ts
cat src/types.ts

Repository: TrustVC/decentralized-renderer-react-components

Length of output: 1395


🏁 Script executed:

#!/bin/bash
# Check all template files for handleObfuscation usage patterns
for file in $(find example/decentralized-renderer/templates -name "*.tsx" -type f); do
  if rg -q "handleObfuscation" "$file"; then
    echo "=== $file ==="
    rg -n "handleObfuscation" "$file" -A 1
  fi
done

Repository: TrustVC/decentralized-renderer-react-components

Length of output: 831


Breaking change: transcript.tsx template will throw at runtime when handleObfuscation is not provided.

Making handleObfuscation optional introduces a breaking change. The govtechDemoCert/transcript.tsx template destructures and calls handleObfuscation(...) without null checks at lines 35, 42, 49, 56, and 63. When a renderer omits this prop, these calls will throw TypeError: handleObfuscation is not a function at runtime.

Fix by updating the template to use optional chaining: handleObfuscation?.(\...`)`

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/types.ts` at line 15, The type change made handleObfuscation optional but
the govtechDemoCert/transcript.tsx template still destructures and invokes
handleObfuscation directly, causing runtime TypeError when the prop is omitted;
update the template so each invocation uses optional chaining (e.g., replace
calls to handleObfuscation(`...`) with handleObfuscation?.(`...`)) or
alternatively provide a default no-op in the component props destructure (e.g.,
handleObfuscation = () => {}) to ensure calls to handleObfuscation in the
template (the destructured prop used across multiple lines) are safe when not
supplied.

errorType?: string;
}

Expand Down
Loading