This is an automated email from the ASF dual-hosted git repository.

rusackas pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/superset.git


The following commit(s) were added to refs/heads/master by this push:
     new 2875c76d55a chore(deps): bump react-ace from 14.0.1 to 15.0.0 in 
/superset-frontend (#42833)
2875c76d55a is described below

commit 2875c76d55a3da9dae369724e55bb38daad11b17
Author: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
AuthorDate: Tue Sep 8 17:52:09 2026 -0700

    chore(deps): bump react-ace from 14.0.1 to 15.0.0 in /superset-frontend 
(#42833)
    
    Signed-off-by: dependabot[bot] <[email protected]>
    Co-authored-by: dependabot[bot] 
<49699333+dependabot[bot]@users.noreply.github.com>
    Co-authored-by: Claude Code <[email protected]>
---
 superset-frontend/package-lock.json                | 17 +++----
 .../packages/superset-ui-core/package.json         |  2 +-
 .../AsyncAceEditor/AsyncAceEditor.test.tsx         | 55 ++++++++++++++++++++++
 3 files changed, 65 insertions(+), 9 deletions(-)

diff --git a/superset-frontend/package-lock.json 
b/superset-frontend/package-lock.json
index 92dc5cd0769..f979f6512fa 100644
--- a/superset-frontend/package-lock.json
+++ b/superset-frontend/package-lock.json
@@ -32288,7 +32288,8 @@
       "version": "4.4.2",
       "resolved": 
"https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz";,
       "integrity": 
"sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==",
-      "license": "MIT"
+      "license": "MIT",
+      "peer": true
     },
     "node_modules/lodash.isempty": {
       "version": "4.4.0",
@@ -32300,7 +32301,8 @@
       "version": "4.5.0",
       "resolved": 
"https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz";,
       "integrity": 
"sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==",
-      "license": "MIT"
+      "license": "MIT",
+      "peer": true
     },
     "node_modules/lodash.isplainobject": {
       "version": "4.0.6",
@@ -47102,7 +47104,7 @@
         "math-expression-evaluator": "^2.0.7",
         "parse-ms": "^4.0.0",
         "re-resizable": "^6.11.2",
-        "react-ace": "^14.0.1",
+        "react-ace": "^15.0.0",
         "react-draggable": "^4.7.1",
         "react-error-boundary": "^6.1.4",
         "react-js-cron": "^6.0.2",
@@ -47203,15 +47205,14 @@
       }
     },
     "packages/superset-ui-core/node_modules/react-ace": {
-      "version": "14.0.1",
-      "resolved": 
"https://registry.npmjs.org/react-ace/-/react-ace-14.0.1.tgz";,
-      "integrity": 
"sha512-z6YAZ20PNf/FqmYEic//G/UK6uw0rn21g58ASgHJHl9rfE4nITQLqthr9rHMVQK4ezwohJbp2dGrZpkq979PYQ==",
+      "version": "15.0.0",
+      "resolved": 
"https://registry.npmjs.org/react-ace/-/react-ace-15.0.0.tgz";,
+      "integrity": 
"sha512-gdmS5ftF0hsbkcrAjZQqYbXwFg5JrHuxjki8mP6Bn9kfa6lHKfZk9sU9EfS0ifQ1CpGCmRxF/VC7GRvlJMBuZw==",
       "license": "MIT",
       "dependencies": {
         "ace-builds": "^1.36.3",
         "diff-match-patch": "^1.0.5",
-        "lodash.get": "^4.4.2",
-        "lodash.isequal": "^4.5.0",
+        "fast-equals": "^5.3.3",
         "prop-types": "^15.8.1"
       },
       "peerDependencies": {
diff --git a/superset-frontend/packages/superset-ui-core/package.json 
b/superset-frontend/packages/superset-ui-core/package.json
index d2f1ab64520..a766aa9f982 100644
--- a/superset-frontend/packages/superset-ui-core/package.json
+++ b/superset-frontend/packages/superset-ui-core/package.json
@@ -78,7 +78,7 @@
     "math-expression-evaluator": "^2.0.7",
     "parse-ms": "^4.0.0",
     "re-resizable": "^6.11.2",
-    "react-ace": "^14.0.1",
+    "react-ace": "^15.0.0",
     "react-draggable": "^4.7.1",
     "react-error-boundary": "^6.1.4",
     "react-js-cron": "^6.0.2",
diff --git 
a/superset-frontend/packages/superset-ui-core/src/components/AsyncAceEditor/AsyncAceEditor.test.tsx
 
b/superset-frontend/packages/superset-ui-core/src/components/AsyncAceEditor/AsyncAceEditor.test.tsx
index db5ac8da798..0af0e62cff2 100644
--- 
a/superset-frontend/packages/superset-ui-core/src/components/AsyncAceEditor/AsyncAceEditor.test.tsx
+++ 
b/superset-frontend/packages/superset-ui-core/src/components/AsyncAceEditor/AsyncAceEditor.test.tsx
@@ -604,6 +604,61 @@ test('cleans up event listeners on unmount', async () => {
   offSpy.mockRestore();
 });
 
+test('re-applies annotations only when their content actually changes across 
renders (react-ace 15 fast-equals regression guard)', async () => {
+  // react-ace's componentDidUpdate decides whether to call
+  // session.setAnnotations() by deep-comparing the new/old `annotations`
+  // prop (lib/ace.js, using an internal deep-equality helper -- lodash's
+  // isEqual through react-ace 14.x, fast-equals's deepEqual from 15.0.0
+  // onward). Superset's own AceEditorProvider/EditorWrapper always pass a
+  // freshly `.map()`-derived annotations array on every render, so this
+  // guards the actual behavior Superset relies on: a same-content-but-
+  // different-reference array must NOT re-trigger setAnnotations (or the
+  // editor would thrash on every keystroke-driven re-render), while a
+  // genuinely different array must still update the editor.
+  const ref = createRef<AceEditor>();
+  const annotationsV1 = [{ row: 0, column: 0, type: 'error', text: 'oops' }];
+
+  const { rerender, container } = render(
+    <SQLEditor ref={ref as React.Ref<never>} annotations={annotationsV1} />,
+  );
+
+  await waitFor(() => {
+    expect(container.querySelector(selector)).toBeInTheDocument();
+  });
+
+  const session = ref.current?.editor?.getSession();
+  expect(session).toBeDefined();
+  if (!session) return;
+
+  // The initial mount already applies annotations via componentDidMount,
+  // not componentDidUpdate, so start observing only from the first update.
+  const setAnnotationsSpy = jest.spyOn(session, 'setAnnotations');
+
+  // Same content, new array/object references -- must be a no-op.
+  const annotationsV1SameContent = [
+    { row: 0, column: 0, type: 'error', text: 'oops' },
+  ];
+  rerender(
+    <SQLEditor
+      ref={ref as React.Ref<never>}
+      annotations={annotationsV1SameContent}
+    />,
+  );
+  expect(setAnnotationsSpy).not.toHaveBeenCalled();
+
+  // Genuinely different content -- must update, with the new value.
+  const annotationsV2 = [
+    { row: 1, column: 2, type: 'warning', text: 'different' },
+  ];
+  rerender(
+    <SQLEditor ref={ref as React.Ref<never>} annotations={annotationsV2} />,
+  );
+  expect(setAnnotationsSpy).toHaveBeenCalledTimes(1);
+  expect(setAnnotationsSpy).toHaveBeenCalledWith(annotationsV2);
+
+  setAnnotationsSpy.mockRestore();
+});
+
 test('does not move autocomplete popup if target container is document.body', 
async () => {
   const ref = createRef<AceEditor>();
   const { container } = render(<SQLEditor ref={ref as React.Ref<never>} />);

Reply via email to