mirror of
https://github.com/aphrody-labs/effectcraft.git
synced 2026-10-14 19:49:03 +00:00
Merge pull request #851 from Ni-zav/fix/811-script-object-identity-20261011
fix(script): preserve item and layer wrapper identity # Conflicts: # crates/script/src/tests.rs
This commit is contained in:
commit
6caa67971b
2 files changed
+69
-17
No files matched your search
@@ -6,8 +6,16 @@
|
||||
|
||||
var __ecGlobal = this;
|
||||
|
||||
// The scripting host keeps wrappers stable for each project item and comp/layer id.
|
||||
// Clear them when loading a different document, whose IDs may be reused.
|
||||
var __itemCache = Object.create(null), __layerCache = Object.create(null);
|
||||
function __clearIdentityCache() {
|
||||
__itemCache = Object.create(null);
|
||||
__layerCache = Object.create(null);
|
||||
}
|
||||
function __call(id, p) {
|
||||
var r = __exec(id, JSON.stringify(p || {}));
|
||||
if (id === "file.newProject" || id === "file.open" || id === "file.revert") __clearIdentityCache();
|
||||
return r === undefined || r === "" ? null : JSON.parse(r);
|
||||
}
|
||||
function __get(kind, a) {
|
||||
@@ -1056,14 +1064,18 @@ MarkerProperty.prototype = {
|
||||
|
||||
function __layer(compId, id) {
|
||||
if (id === null || id === undefined) return null;
|
||||
var i = __get("layer", { comp: compId, layer: id });
|
||||
var key = compId + ":" + id;
|
||||
if (Object.prototype.hasOwnProperty.call(__layerCache, key)) return __layerCache[key];
|
||||
var i = __get("layer", { comp: compId, layer: id }), layer;
|
||||
switch (i.kind) {
|
||||
case "text": return new TextLayer(compId, id);
|
||||
case "shape": return new ShapeLayer(compId, id);
|
||||
case "camera": return new CameraLayer(compId, id);
|
||||
case "light": return new LightLayer(compId, id);
|
||||
default: return new AVLayer(compId, id);
|
||||
case "text": layer = new TextLayer(compId, id); break;
|
||||
case "shape": layer = new ShapeLayer(compId, id); break;
|
||||
case "camera": layer = new CameraLayer(compId, id); break;
|
||||
case "light": layer = new LightLayer(compId, id); break;
|
||||
default: layer = new AVLayer(compId, id);
|
||||
}
|
||||
__layerCache[key] = layer;
|
||||
return layer;
|
||||
}
|
||||
|
||||
function Layer() {}
|
||||
@@ -1099,7 +1111,7 @@ Layer.prototype = {
|
||||
set name(v) { __call("layer.rename", this.__p1({ name: String(v) })); },
|
||||
get index() { return this.__info().index; },
|
||||
get matchName() { return this.__info().matchName; },
|
||||
get containingComp() { return new CompItem(this.__comp); },
|
||||
get containingComp() { return __item(this.__comp); },
|
||||
get propertyDepth() { return 0; },
|
||||
get propertyType() { return PropertyType.INDEXED_GROUP; },
|
||||
get parentProperty() { return null; },
|
||||
@@ -1370,7 +1382,7 @@ LayerCollection.prototype = {
|
||||
var ids = this.__ids(), sel = [];
|
||||
for (var i = 0; i < indices.length; i++) sel.push(ids[indices[i] - 1]);
|
||||
var r = __call("layer.precompose", { comp: this.__comp, layers: sel, name: String(name), mode: moveAllAttributes === false ? "leave" : "move" });
|
||||
return new CompItem(r.comp);
|
||||
return __item(r.comp);
|
||||
},
|
||||
byName: function (name) {
|
||||
var ids = this.__ids();
|
||||
@@ -1418,13 +1430,20 @@ ItemCollection.prototype = {
|
||||
|
||||
function __item(id) {
|
||||
if (id === null || id === undefined) return null;
|
||||
if (id === 0) return new FolderItem(0);
|
||||
var i = __get("item", { id: id });
|
||||
switch (i.kind) {
|
||||
case "comp": return new CompItem(id);
|
||||
case "folder": return new FolderItem(id);
|
||||
default: return new FootageItem(id);
|
||||
if (Object.prototype.hasOwnProperty.call(__itemCache, id)) return __itemCache[id];
|
||||
var item;
|
||||
if (id === 0) {
|
||||
item = new FolderItem(0);
|
||||
} else {
|
||||
var i = __get("item", { id: id });
|
||||
switch (i.kind) {
|
||||
case "comp": item = new CompItem(id); break;
|
||||
case "folder": item = new FolderItem(id); break;
|
||||
default: item = new FootageItem(id);
|
||||
}
|
||||
}
|
||||
__itemCache[id] = item;
|
||||
return item;
|
||||
}
|
||||
|
||||
function Item() {}
|
||||
@@ -1454,7 +1473,7 @@ Item.prototype = {
|
||||
__call("project.select", { items: selection.filter(function (item) { return item !== id; }) });
|
||||
}
|
||||
},
|
||||
get usedIn() { return this.__info().usedIn.map(function (c) { return new CompItem(c); }); },
|
||||
get usedIn() { return this.__info().usedIn.map(function (c) { return __item(c); }); },
|
||||
remove: function () { __call("project.delete", { items: [this.__id] }); },
|
||||
};
|
||||
|
||||
@@ -1681,7 +1700,7 @@ RenderQueueItem.prototype = {
|
||||
for (var i = 0; i < l.length; i++) if (l[i].id === this.__id) return l[i];
|
||||
throw __err("the render queue item no longer exists");
|
||||
},
|
||||
get comp() { return new CompItem(this.__info().comp); },
|
||||
get comp() { return __item(this.__info().comp); },
|
||||
get status() {
|
||||
var s = this.__info().statusLabel;
|
||||
for (var k in __rqStatus) if (s.indexOf(k) === 0) return __rqStatus[k];
|
||||
@@ -1783,7 +1802,7 @@ Project.prototype = {
|
||||
__info: function () { return __get("project"); },
|
||||
get items() { return new ItemCollection(0); },
|
||||
get numItems() { return this.__info().items.length; },
|
||||
get rootFolder() { return new FolderItem(0); },
|
||||
get rootFolder() { return __item(0); },
|
||||
get activeItem() { return __item(this.__info().active); },
|
||||
get selection() { return this.__info().selection.map(__item); },
|
||||
get file() { var p = this.__info().path; return p ? new File(p) : null; },
|
||||
|
||||
@@ -930,3 +930,36 @@ fn import_options_preserve_layered_psd_compositions() {
|
||||
assert_eq!(bad.result, json!(false));
|
||||
let _ = std::fs::remove_dir_all(&dir);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn script_item_and_layer_identity_survives_repeated_access() {
|
||||
let mut s = session();
|
||||
let o = ok(
|
||||
&mut s,
|
||||
r#"
|
||||
var c = app.project.items.addComp("Identity", 120, 80, 1, 3, 25);
|
||||
var parent = c.layers.addNull(), child = c.layers.addNull();
|
||||
child.parent = parent;
|
||||
[
|
||||
parent.containingComp === c,
|
||||
c.layer(1) === c.layer(1),
|
||||
child.parent === parent,
|
||||
app.project.item(1) === app.project.item(1),
|
||||
app.project.item(1) === c,
|
||||
app.project.itemByID(c.id) === c
|
||||
]
|
||||
"#,
|
||||
);
|
||||
assert_eq!(o.result, json!([true, true, true, true, true, true]));
|
||||
// Reusing item and layer IDs in a new project must not alias old wrappers.
|
||||
let o = ok(
|
||||
&mut s,
|
||||
r#"
|
||||
var old = app.project.item(1);
|
||||
app.newProject();
|
||||
var next = app.project.items.addComp("New", 120, 80, 1, 3, 25);
|
||||
[old !== next, app.project.item(1) === next]
|
||||
"#,
|
||||
);
|
||||
assert_eq!(o.result, json!([true, true]));
|
||||
}
|
||||
Reference in new issue
Block a user