@remotion/studio-server 4.0.476 → 4.0.477

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -515,10 +515,15 @@ const createStringAttribute = (name, value) => {
515
515
  const createBooleanAttribute = (name, value) => {
516
516
  return recast.types.builders.jsxAttribute(recast.types.builders.jsxIdentifier(name), recast.types.builders.jsxExpressionContainer(recast.types.builders.booleanLiteral(value)));
517
517
  };
518
- const createPositionAbsoluteStyleAttribute = () => {
519
- return recast.types.builders.jsxAttribute(recast.types.builders.jsxIdentifier('style'), recast.types.builders.jsxExpressionContainer(recast.types.builders.objectExpression([
518
+ const formatTranslateValue = ({ x, y }) => `${x}px ${y}px`;
519
+ const createPositionAbsoluteStyleAttribute = (position) => {
520
+ const properties = [
520
521
  recast.types.builders.objectProperty(recast.types.builders.identifier('position'), recast.types.builders.stringLiteral('absolute')),
521
- ])));
522
+ ];
523
+ if (position) {
524
+ properties.push(recast.types.builders.objectProperty(recast.types.builders.identifier('translate'), recast.types.builders.stringLiteral(formatTranslateValue(position))));
525
+ }
526
+ return recast.types.builders.jsxAttribute(recast.types.builders.jsxIdentifier('style'), recast.types.builders.jsxExpressionContainer(recast.types.builders.objectExpression(properties)));
522
527
  };
523
528
  const createStaticFileSrcAttribute = ({ staticFileLocalName, src, }) => {
524
529
  return recast.types.builders.jsxAttribute(recast.types.builders.jsxIdentifier('src'), recast.types.builders.jsxExpressionContainer(recast.types.builders.callExpression(recast.types.builders.identifier(staticFileLocalName), [recast.types.builders.stringLiteral(src)])));
@@ -535,25 +540,27 @@ const createComponentProp = ({ name, value, }) => {
535
540
  const createStringSrcAttribute = (src) => {
536
541
  return recast.types.builders.jsxAttribute(recast.types.builders.jsxIdentifier('src'), recast.types.builders.stringLiteral(src));
537
542
  };
538
- const createSolidElement = ({ localName, width, height, }) => {
543
+ const createSolidElement = ({ localName, width, height, position, }) => {
539
544
  return recast.types.builders.jsxElement(recast.types.builders.jsxOpeningElement(recast.types.builders.jsxIdentifier(localName), [
540
545
  createNumberAttribute('width', width),
541
546
  createNumberAttribute('height', height),
542
- createPositionAbsoluteStyleAttribute(),
547
+ createPositionAbsoluteStyleAttribute(position),
543
548
  ], true), null, []);
544
549
  };
545
- const createComponentElement = ({ localName, props, }) => {
550
+ const createComponentElement = ({ localName, props, position, }) => {
546
551
  return recast.types.builders.jsxElement(recast.types.builders.jsxOpeningElement(recast.types.builders.jsxIdentifier(localName), [
547
552
  ...props.map(createComponentProp),
548
- createPositionAbsoluteStyleAttribute(),
553
+ createPositionAbsoluteStyleAttribute(position),
549
554
  ], true), null, []);
550
555
  };
551
- const createAssetElement = ({ addPositionStyle, localName, staticFileLocalName, src, dimensions, }) => {
556
+ const createAssetElement = ({ addPositionStyle, localName, staticFileLocalName, src, dimensions, position, }) => {
552
557
  return recast.types.builders.jsxElement(recast.types.builders.jsxOpeningElement(recast.types.builders.jsxIdentifier(localName), [
553
558
  staticFileLocalName === null
554
559
  ? createStringSrcAttribute(src)
555
560
  : createStaticFileSrcAttribute({ staticFileLocalName, src }),
556
- ...(addPositionStyle ? [createPositionAbsoluteStyleAttribute()] : []),
561
+ ...(addPositionStyle
562
+ ? [createPositionAbsoluteStyleAttribute(position)]
563
+ : []),
557
564
  ...(dimensions
558
565
  ? [
559
566
  createNumberAttribute('width', dimensions.width),
@@ -1007,6 +1014,7 @@ const createInsertableJsxElement = ({ ast, element, }) => {
1007
1014
  localName: solidLocalName,
1008
1015
  width: element.width,
1009
1016
  height: element.height,
1017
+ position: element.position,
1010
1018
  });
1011
1019
  }
1012
1020
  if (element.type === 'component') {
@@ -1019,6 +1027,7 @@ const createInsertableJsxElement = ({ ast, element, }) => {
1019
1027
  return createComponentElement({
1020
1028
  localName: componentLocalName,
1021
1029
  props: element.props,
1030
+ position: element.position,
1022
1031
  });
1023
1032
  }
1024
1033
  if (element.type === 'asset') {
@@ -1048,6 +1057,7 @@ const createInsertableJsxElement = ({ ast, element, }) => {
1048
1057
  staticFileLocalName,
1049
1058
  src: element.src,
1050
1059
  dimensions: element.dimensions,
1060
+ position: element.position,
1051
1061
  });
1052
1062
  }
1053
1063
  throw new Error('Unsupported element type');
@@ -0,0 +1,12 @@
1
+ import type { File, JSXOpeningElement } from '@babel/types';
2
+ export declare class JsxElementIdentityMismatchError extends Error {
3
+ constructor();
4
+ }
5
+ export declare const getJsxComponentIdentity: ({ ast, jsxElement, }: {
6
+ ast: File;
7
+ jsxElement: JSXOpeningElement;
8
+ }) => string | null;
9
+ export declare const jsxComponentIdentitiesMatch: ({ expected, actual, }: {
10
+ expected: string | null;
11
+ actual: string | null;
12
+ }) => boolean;
@@ -0,0 +1,126 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.jsxComponentIdentitiesMatch = exports.getJsxComponentIdentity = exports.JsxElementIdentityMismatchError = void 0;
4
+ const imports_1 = require("../helpers/imports");
5
+ class JsxElementIdentityMismatchError extends Error {
6
+ constructor() {
7
+ super('JSX element identity changed');
8
+ }
9
+ }
10
+ exports.JsxElementIdentityMismatchError = JsxElementIdentityMismatchError;
11
+ const jsxMemberToString = (expr) => {
12
+ if (expr.type === 'JSXIdentifier') {
13
+ return expr.name;
14
+ }
15
+ return `${jsxMemberToString(expr.object)}.${expr.property.name}`;
16
+ };
17
+ const getJsxRootIdentifier = (expr) => {
18
+ if (expr.type === 'JSXIdentifier') {
19
+ return expr;
20
+ }
21
+ return getJsxRootIdentifier(expr.object);
22
+ };
23
+ const getTagName = (node) => {
24
+ if (node.name.type === 'JSXIdentifier') {
25
+ return node.name.name;
26
+ }
27
+ if (node.name.type === 'JSXMemberExpression') {
28
+ return jsxMemberToString(node.name);
29
+ }
30
+ return null;
31
+ };
32
+ const getMemberPath = (tagName) => {
33
+ const dotIndex = tagName.indexOf('.');
34
+ return dotIndex === -1 ? '' : tagName.slice(dotIndex + 1);
35
+ };
36
+ const getMemberPathAfterImportName = ({ tagName, importName, }) => {
37
+ const parts = tagName.split('.');
38
+ const importNameIndex = parts.indexOf(importName);
39
+ if (importNameIndex === -1) {
40
+ return getMemberPath(tagName);
41
+ }
42
+ return parts.slice(importNameIndex + 1).join('.');
43
+ };
44
+ const sourcePathToIdentityPrefix = (sourcePath) => {
45
+ if (sourcePath === 'remotion') {
46
+ return 'dev.remotion.remotion';
47
+ }
48
+ if (sourcePath.startsWith('@remotion/')) {
49
+ const packageName = sourcePath
50
+ .slice('@remotion/'.length)
51
+ .replace(/-([a-z])/g, (_, char) => char.toUpperCase());
52
+ return `dev.remotion.${packageName}`;
53
+ }
54
+ return null;
55
+ };
56
+ const makeImportedIdentity = ({ sourcePath, importName, memberPath, }) => {
57
+ const prefix = sourcePathToIdentityPrefix(sourcePath);
58
+ if (prefix === null) {
59
+ return null;
60
+ }
61
+ return [prefix, importName, memberPath].filter(Boolean).join('.');
62
+ };
63
+ const getJsxComponentIdentity = ({ ast, jsxElement, }) => {
64
+ var _a;
65
+ const tagName = getTagName(jsxElement);
66
+ if (tagName === null) {
67
+ return null;
68
+ }
69
+ const rootIdentifier = jsxElement.name.type === 'JSXIdentifier'
70
+ ? jsxElement.name
71
+ : jsxElement.name.type === 'JSXMemberExpression'
72
+ ? getJsxRootIdentifier(jsxElement.name)
73
+ : null;
74
+ if (rootIdentifier === null) {
75
+ return tagName;
76
+ }
77
+ for (const node of ast.program.body) {
78
+ if (node.type !== 'ImportDeclaration') {
79
+ continue;
80
+ }
81
+ const sourcePath = String(node.source.value);
82
+ for (const specifier of node.specifiers) {
83
+ if (specifier.type === 'ImportSpecifier' &&
84
+ ((_a = specifier.local) === null || _a === void 0 ? void 0 : _a.name) === rootIdentifier.name) {
85
+ const importName = (0, imports_1.getImportedName)(specifier);
86
+ return makeImportedIdentity({
87
+ sourcePath,
88
+ importName,
89
+ memberPath: getMemberPath(tagName),
90
+ });
91
+ }
92
+ if (specifier.type === 'ImportNamespaceSpecifier' &&
93
+ specifier.local.name === rootIdentifier.name) {
94
+ const [importName, ...members] = getMemberPath(tagName).split('.');
95
+ if (!importName) {
96
+ return null;
97
+ }
98
+ return makeImportedIdentity({
99
+ sourcePath,
100
+ importName,
101
+ memberPath: members.join('.'),
102
+ });
103
+ }
104
+ if (specifier.type === 'ImportDefaultSpecifier' &&
105
+ specifier.local.name === rootIdentifier.name) {
106
+ return makeImportedIdentity({
107
+ sourcePath,
108
+ importName: 'default',
109
+ memberPath: getMemberPathAfterImportName({
110
+ tagName,
111
+ importName: rootIdentifier.name,
112
+ }),
113
+ });
114
+ }
115
+ }
116
+ }
117
+ return tagName;
118
+ };
119
+ exports.getJsxComponentIdentity = getJsxComponentIdentity;
120
+ const jsxComponentIdentitiesMatch = ({ expected, actual, }) => {
121
+ if (expected === null) {
122
+ return true;
123
+ }
124
+ return expected === actual;
125
+ };
126
+ exports.jsxComponentIdentitiesMatch = jsxComponentIdentitiesMatch;
@@ -74,6 +74,7 @@ const addSequenceKeyframeHandler = ({ input: { fileName, nodePath, key, frame, v
74
74
  fileContents: output,
75
75
  keys: (0, studio_shared_1.getAllSchemaKeys)(schema),
76
76
  nodePath: updatedNodePath,
77
+ componentIdentity: null,
77
78
  effects: [],
78
79
  });
79
80
  const updatedSubscriptionKey = { ...nodePath, nodePath: updatedNodePath };
@@ -10,22 +10,25 @@ export declare const getComputedStatus: (node: Expression, ast: File) => CanUpda
10
10
  export declare const findJsxElementAtNodePath: (ast: File, nodePath: SequenceNodePath) => JSXOpeningElement | null;
11
11
  export declare const findNodePathForJsxElement: (ast: File, target: JSXOpeningElement) => SequenceNodePath | null;
12
12
  export declare const lineColumnToNodePath: (ast: File, targetLine: number) => SequenceNodePath | null;
13
- export declare const computeSequencePropsStatusFromContent: ({ fileContents, nodePath, keys, effects, }: {
13
+ export declare const computeSequencePropsStatusFromContent: ({ fileContents, nodePath, componentIdentity, keys, effects, }: {
14
14
  fileContents: string;
15
15
  nodePath: SequenceNodePath;
16
+ componentIdentity: string | null;
16
17
  keys: string[];
17
18
  effects: string[][];
18
19
  }) => CanUpdateSequencePropsResponseTrue;
19
- export declare const computeSequencePropsStatus: ({ fileName, nodePath, keys, effects, remotionRoot, }: {
20
+ export declare const computeSequencePropsStatus: ({ fileName, nodePath, componentIdentity, keys, effects, remotionRoot, }: {
20
21
  fileName: string;
21
22
  nodePath: SequenceNodePath;
23
+ componentIdentity: string | null;
22
24
  keys: string[];
23
25
  effects: string[][];
24
26
  remotionRoot: string;
25
27
  }) => CanUpdateSequencePropsResponseTrue;
26
- export declare const computeSequencePropsStatusFromFilenameByLine: ({ fileName, line, keys, effects, remotionRoot, logLevel, }: {
28
+ export declare const computeSequencePropsStatusFromFilenameByLine: ({ fileName, line, componentIdentity, keys, effects, remotionRoot, logLevel, }: {
27
29
  fileName: string;
28
30
  line: number;
31
+ componentIdentity: string | null;
29
32
  keys: string[];
30
33
  effects: string[][];
31
34
  remotionRoot: string;
@@ -43,6 +43,7 @@ const parse_ast_1 = require("../../codemods/parse-ast");
43
43
  const get_ast_node_path_1 = require("../../helpers/get-ast-node-path");
44
44
  const import_agnostic_node_path_1 = require("../../helpers/import-agnostic-node-path");
45
45
  const resolve_file_inside_project_1 = require("../../helpers/resolve-file-inside-project");
46
+ const jsx_component_identity_1 = require("../jsx-component-identity");
46
47
  const jsx_element_not_found_at_location_error_1 = require("../jsx-element-not-found-at-location-error");
47
48
  const can_update_effect_props_1 = require("./can-update-effect-props");
48
49
  const staticStatus = (codeValue) => ({
@@ -353,6 +354,25 @@ const getInterpolationKeyframes = (node, ast) => {
353
354
  if (node.type === 'TSAsExpression') {
354
355
  return getInterpolationKeyframes(node.expression, ast);
355
356
  }
357
+ if (node.type === 'CallExpression' &&
358
+ node.callee.type === 'Identifier' &&
359
+ node.callee.name === 'String' &&
360
+ node.arguments.length === 1 &&
361
+ node.arguments[0].type !== 'ArgumentPlaceholder' &&
362
+ node.arguments[0].type !== 'JSXNamespacedName' &&
363
+ node.arguments[0].type !== 'SpreadElement') {
364
+ const interpolation = getInterpolationKeyframes(node.arguments[0], ast);
365
+ if (!interpolation) {
366
+ return undefined;
367
+ }
368
+ return {
369
+ ...interpolation,
370
+ keyframes: interpolation.keyframes.map((keyframe) => ({
371
+ ...keyframe,
372
+ value: String(keyframe.value),
373
+ })),
374
+ };
375
+ }
356
376
  if (node.type !== 'CallExpression') {
357
377
  return undefined;
358
378
  }
@@ -627,12 +647,18 @@ const computeSequenceOnlyPropsRecord = ({ jsxElement, ast, keys, }) => {
627
647
  }
628
648
  return filteredProps;
629
649
  };
630
- const computeSequencePropsStatusFromContent = ({ fileContents, nodePath, keys, effects, }) => {
650
+ const computeSequencePropsStatusFromContent = ({ fileContents, nodePath, componentIdentity, keys, effects, }) => {
631
651
  const ast = (0, parse_ast_1.parseAst)(fileContents);
632
652
  const jsxElement = (0, exports.findJsxElementAtNodePath)(ast, nodePath);
633
653
  if (!jsxElement) {
634
654
  throw new jsx_element_not_found_at_location_error_1.JsxElementNotFoundAtLocationError();
635
655
  }
656
+ if (!(0, jsx_component_identity_1.jsxComponentIdentitiesMatch)({
657
+ expected: componentIdentity,
658
+ actual: (0, jsx_component_identity_1.getJsxComponentIdentity)({ ast, jsxElement }),
659
+ })) {
660
+ throw new jsx_component_identity_1.JsxElementIdentityMismatchError();
661
+ }
636
662
  const filteredProps = computeSequenceOnlyPropsRecord({ jsxElement, ast, keys });
637
663
  const effectsStatuses = computeEffectsForJsx({ ast, jsxElement, effects });
638
664
  return {
@@ -642,7 +668,7 @@ const computeSequencePropsStatusFromContent = ({ fileContents, nodePath, keys, e
642
668
  };
643
669
  };
644
670
  exports.computeSequencePropsStatusFromContent = computeSequencePropsStatusFromContent;
645
- const computeSequencePropsStatus = ({ fileName, nodePath, keys, effects, remotionRoot, }) => {
671
+ const computeSequencePropsStatus = ({ fileName, nodePath, componentIdentity, keys, effects, remotionRoot, }) => {
646
672
  const { absolutePath } = (0, resolve_file_inside_project_1.resolveFileInsideProject)({
647
673
  remotionRoot,
648
674
  fileName,
@@ -652,12 +678,13 @@ const computeSequencePropsStatus = ({ fileName, nodePath, keys, effects, remotio
652
678
  return (0, exports.computeSequencePropsStatusFromContent)({
653
679
  fileContents,
654
680
  nodePath,
681
+ componentIdentity,
655
682
  keys,
656
683
  effects,
657
684
  });
658
685
  };
659
686
  exports.computeSequencePropsStatus = computeSequencePropsStatus;
660
- const computeSequencePropsStatusFromFilenameByLine = ({ fileName, line, keys, effects, remotionRoot, logLevel, }) => {
687
+ const computeSequencePropsStatusFromFilenameByLine = ({ fileName, line, componentIdentity, keys, effects, remotionRoot, logLevel, }) => {
661
688
  try {
662
689
  const { absolutePath } = (0, resolve_file_inside_project_1.resolveFileInsideProject)({
663
690
  remotionRoot,
@@ -680,6 +707,7 @@ const computeSequencePropsStatusFromFilenameByLine = ({ fileName, line, keys, ef
680
707
  status: (0, exports.computeSequencePropsStatus)({
681
708
  fileName,
682
709
  nodePath: resolvedNodePath,
710
+ componentIdentity,
683
711
  keys,
684
712
  effects,
685
713
  remotionRoot,
@@ -215,6 +215,7 @@ const deleteKeyframes = async ({ sequenceKeyframes, effectKeyframes, clientId, r
215
215
  fileContents: output,
216
216
  keys: (0, studio_shared_1.getAllSchemaKeys)(keyframe.schema),
217
217
  nodePath: keyframe.nodePath.nodePath,
218
+ componentIdentity: null,
218
219
  effects: [],
219
220
  });
220
221
  return {
@@ -257,6 +257,7 @@ const downloadRemoteAssetHandler = async ({ input, publicDir, request }) => {
257
257
  src: assetPath,
258
258
  srcType: 'static',
259
259
  dimensions: fileType.dimensions,
260
+ position: null,
260
261
  };
261
262
  return {
262
263
  assetPath,
@@ -14,7 +14,16 @@ const validateDimension = (name, value) => {
14
14
  throw new Error(`${name} must be a positive number`);
15
15
  }
16
16
  };
17
+ const validatePosition = (position) => {
18
+ if (position === null) {
19
+ return;
20
+ }
21
+ if (!Number.isFinite(position.x) || !Number.isFinite(position.y)) {
22
+ throw new Error('Position must be finite');
23
+ }
24
+ };
17
25
  const validateElement = (element) => {
26
+ validatePosition(element.position);
18
27
  if (element.type === 'solid') {
19
28
  validateDimension('width', element.width);
20
29
  validateDimension('height', element.height);
@@ -145,6 +145,7 @@ const saveSequencePropsHandler = ({ input: { edits, clientId, undoLabel, redoLab
145
145
  fileContents: output,
146
146
  keys: (0, studio_shared_1.getAllSchemaKeys)(edit.schema),
147
147
  nodePath: edit.nodePath.nodePath,
148
+ componentIdentity: null,
148
149
  effects: [],
149
150
  });
150
151
  return {
@@ -2,12 +2,13 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.subscribeToSequenceProps = void 0;
4
4
  const sequence_props_watchers_1 = require("../sequence-props-watchers");
5
- const subscribeToSequenceProps = ({ input: { fileName, line, column, nodePath, keys, effects, clientId }, remotionRoot, logLevel, }) => {
5
+ const subscribeToSequenceProps = ({ input: { fileName, line, column, nodePath, componentIdentity, keys, effects, clientId, }, remotionRoot, logLevel, }) => {
6
6
  const result = (0, sequence_props_watchers_1.subscribeToSequencePropsWatchers)({
7
7
  fileName,
8
8
  line,
9
9
  column,
10
10
  nodePath,
11
+ componentIdentity,
11
12
  keys,
12
13
  effects,
13
14
  remotionRoot,
@@ -77,6 +77,7 @@ const updateSequenceKeyframeSettingsHandler = ({ input: { fileName, nodePath, ke
77
77
  fileContents: output,
78
78
  keys: (0, studio_shared_1.getAllSchemaKeys)(schema),
79
79
  nodePath: updatedNodePath,
80
+ componentIdentity: null,
80
81
  effects: [],
81
82
  });
82
83
  const updatedSubscriptionKey = { ...nodePath, nodePath: updatedNodePath };
@@ -1,10 +1,11 @@
1
1
  import { type SubscribeToSequencePropsResponse } from '@remotion/studio-shared';
2
2
  import type { SequenceNodePath } from 'remotion';
3
- export declare const subscribeToSequencePropsWatchers: ({ fileName, line, column, nodePath: preferredNodePath, keys, effects, remotionRoot, clientId, logLevel, }: {
3
+ export declare const subscribeToSequencePropsWatchers: ({ fileName, line, column, nodePath: preferredNodePath, componentIdentity, keys, effects, remotionRoot, clientId, logLevel, }: {
4
4
  fileName: string;
5
5
  line: number;
6
6
  column: number;
7
7
  nodePath: SequenceNodePath | null;
8
+ componentIdentity: string | null;
8
9
  keys: string[];
9
10
  effects: string[][];
10
11
  remotionRoot: string;
@@ -8,42 +8,64 @@ const node_path_1 = __importDefault(require("node:path"));
8
8
  const renderer_1 = require("@remotion/renderer");
9
9
  const studio_shared_1 = require("@remotion/studio-shared");
10
10
  const file_watcher_1 = require("../file-watcher");
11
+ const jsx_component_identity_1 = require("./jsx-component-identity");
11
12
  const jsx_element_not_found_at_location_error_1 = require("./jsx-element-not-found-at-location-error");
12
13
  const live_events_1 = require("./live-events");
13
14
  const node_path_cache_1 = require("./node-path-cache");
14
15
  const can_update_sequence_props_1 = require("./routes/can-update-sequence-props");
15
16
  const sequencePropsWatchers = {};
16
- const getSequencePropsStatus = ({ fileName, line, column, preferredNodePath, keys, effects, remotionRoot, logLevel, }) => {
17
+ const getSequencePropsStatus = ({ fileName, line, column, preferredNodePath, componentIdentity, keys, effects, remotionRoot, logLevel, }) => {
17
18
  if (preferredNodePath) {
18
- const fromNodePath = (0, can_update_sequence_props_1.computeSequencePropsStatus)({
19
- fileName,
20
- nodePath: preferredNodePath,
21
- keys,
22
- effects,
23
- remotionRoot,
24
- });
25
- return {
26
- status: fromNodePath,
27
- nodePath: {
28
- absolutePath: node_path_1.default.resolve(remotionRoot, fileName),
19
+ try {
20
+ const fromNodePath = (0, can_update_sequence_props_1.computeSequencePropsStatus)({
21
+ fileName,
29
22
  nodePath: preferredNodePath,
30
- sequenceKeys: keys,
31
- effectKeys: effects,
32
- },
33
- success: true,
34
- };
23
+ componentIdentity,
24
+ keys,
25
+ effects,
26
+ remotionRoot,
27
+ });
28
+ return {
29
+ status: fromNodePath,
30
+ nodePath: {
31
+ absolutePath: node_path_1.default.resolve(remotionRoot, fileName),
32
+ nodePath: preferredNodePath,
33
+ sequenceKeys: keys,
34
+ effectKeys: effects,
35
+ },
36
+ success: true,
37
+ };
38
+ }
39
+ catch (error) {
40
+ if (!(error instanceof jsx_component_identity_1.JsxElementIdentityMismatchError ||
41
+ error instanceof jsx_element_not_found_at_location_error_1.JsxElementNotFoundAtLocationError)) {
42
+ throw error;
43
+ }
44
+ }
35
45
  }
36
46
  // Try cached nodePath first (handles stale source maps after suppressed rebuilds)
37
47
  const cachedNodePath = (0, node_path_cache_1.getCachedNodePath)(fileName, line, column);
38
48
  if (cachedNodePath) {
39
- const cachedResult = (0, can_update_sequence_props_1.computeSequencePropsStatus)({
40
- fileName,
41
- nodePath: cachedNodePath,
42
- keys,
43
- effects,
44
- remotionRoot,
45
- });
46
- if (cachedResult.canUpdate) {
49
+ const cachedResult = (() => {
50
+ try {
51
+ return (0, can_update_sequence_props_1.computeSequencePropsStatus)({
52
+ fileName,
53
+ nodePath: cachedNodePath,
54
+ componentIdentity,
55
+ keys,
56
+ effects,
57
+ remotionRoot,
58
+ });
59
+ }
60
+ catch (error) {
61
+ if (error instanceof jsx_component_identity_1.JsxElementIdentityMismatchError ||
62
+ error instanceof jsx_element_not_found_at_location_error_1.JsxElementNotFoundAtLocationError) {
63
+ return null;
64
+ }
65
+ throw error;
66
+ }
67
+ })();
68
+ if (cachedResult === null || cachedResult === void 0 ? void 0 : cachedResult.canUpdate) {
47
69
  return {
48
70
  status: cachedResult,
49
71
  nodePath: {
@@ -59,6 +81,7 @@ const getSequencePropsStatus = ({ fileName, line, column, preferredNodePath, key
59
81
  const status = (0, can_update_sequence_props_1.computeSequencePropsStatusFromFilenameByLine)({
60
82
  fileName,
61
83
  line,
84
+ componentIdentity,
62
85
  keys,
63
86
  effects,
64
87
  remotionRoot,
@@ -66,13 +89,14 @@ const getSequencePropsStatus = ({ fileName, line, column, preferredNodePath, key
66
89
  });
67
90
  return status;
68
91
  };
69
- const subscribeToSequencePropsWatchers = ({ fileName, line, column, nodePath: preferredNodePath, keys, effects, remotionRoot, clientId, logLevel, }) => {
92
+ const subscribeToSequencePropsWatchers = ({ fileName, line, column, nodePath: preferredNodePath, componentIdentity, keys, effects, remotionRoot, clientId, logLevel, }) => {
70
93
  var _a;
71
94
  const initialResult = getSequencePropsStatus({
72
95
  fileName,
73
96
  line,
74
97
  column,
75
98
  preferredNodePath,
99
+ componentIdentity,
76
100
  keys,
77
101
  effects,
78
102
  remotionRoot,
@@ -105,6 +129,7 @@ const subscribeToSequencePropsWatchers = ({ fileName, line, column, nodePath: pr
105
129
  const result = (0, can_update_sequence_props_1.computeSequencePropsStatusFromContent)({
106
130
  fileContents: event.content,
107
131
  nodePath: nodePath.nodePath,
132
+ componentIdentity,
108
133
  keys,
109
134
  effects,
110
135
  });
@@ -125,7 +150,8 @@ const subscribeToSequencePropsWatchers = ({ fileName, line, column, nodePath: pr
125
150
  });
126
151
  }
127
152
  catch (error) {
128
- if (error instanceof jsx_element_not_found_at_location_error_1.JsxElementNotFoundAtLocationError) {
153
+ if (error instanceof jsx_element_not_found_at_location_error_1.JsxElementNotFoundAtLocationError ||
154
+ error instanceof jsx_component_identity_1.JsxElementIdentityMismatchError) {
129
155
  (0, live_events_1.waitForLiveEventsListener)().then((listener) => {
130
156
  listener.sendEventToClientId(clientId, {
131
157
  type: 'lost-node-path',
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "url": "https://github.com/remotion-dev/remotion/tree/main/packages/studio-server"
4
4
  },
5
5
  "name": "@remotion/studio-server",
6
- "version": "4.0.476",
6
+ "version": "4.0.477",
7
7
  "description": "Run a Remotion Studio with a server backend",
8
8
  "main": "dist",
9
9
  "scripts": {
@@ -27,11 +27,11 @@
27
27
  "@babel/parser": "7.24.1",
28
28
  "semver": "7.5.3",
29
29
  "prettier": "3.8.1",
30
- "remotion": "4.0.476",
30
+ "remotion": "4.0.477",
31
31
  "recast": "0.23.11",
32
- "@remotion/bundler": "4.0.476",
33
- "@remotion/renderer": "4.0.476",
34
- "@remotion/studio-shared": "4.0.476",
32
+ "@remotion/bundler": "4.0.477",
33
+ "@remotion/renderer": "4.0.477",
34
+ "@remotion/studio-shared": "4.0.477",
35
35
  "memfs": "3.4.3",
36
36
  "open": "8.4.2"
37
37
  },
@@ -39,7 +39,7 @@
39
39
  "ast-types": "0.16.1",
40
40
  "react": "19.2.3",
41
41
  "@types/semver": "7.5.3",
42
- "@remotion/eslint-config-internal": "4.0.476",
42
+ "@remotion/eslint-config-internal": "4.0.477",
43
43
  "eslint": "9.19.0",
44
44
  "@types/node": "20.12.14",
45
45
  "@typescript/native-preview": "7.0.0-dev.20260217.1"