Copy link to clipboard
Copied
Hi everyone!
I think I found a bug in Extendscript.
As the docs says "any object has a reflect property.
So for example I wrote a function that returns array of strings that includes all the properties names of any object that are readonly:
function checkReadonlyValues(objToCheck) {
var readOnlyArr = [];
for (var i = 0; i < objToCheck.reflect.properties.length; i++) {
if (objToCheck.reflect.properties.type === 'readonly') {
readOnlyArr.push(objToCheck.reflect.properties.name);
}
}
return readOnlyArr;
}
If I call the function and pass it an `AfterEffects FolderItem` it doesn't return that numItems is a readonly properties.
Also in debug the property numItems type is `readwrite`.
But as you know, `numItems` is a readOnly property.
I checked it in both CS6 and CC15(13.5).
Someone knows why is this happen? or how to avoid it(not a workaround solution)? or just to report a bug, and wait for fix?(where should I post this bug?)
Copy link to clipboard
Copied
I had noticed this too and it is probably not a bug.
All properties of objects that belong to the After Effects Object Model seem to have type "readwrite", even though some can only be read.
An explanation can be (not sure) that all properties are created with that type, and then are being watched (with Object.prototype.watch).
Then when you try to set a property that is not supposed to be set by you (us), the watch function will throw an error telling that it is readonly, while on the javascript level it is actually readwrite.
Note that the type of core javascript properties is correct. For instance:
var r = new RegExp("");
alert(r.reflect.find("source").type); // alerts : "readonly" (the source of a regexp is readonly)
So if you want to know if a property is readonly, i think that the only way is to try to set the value:
function checkReadonlyValues(objToCheck) {
var readOnlyArr = [];
var name;
for (var i = 0; i < objToCheck.reflect.properties.length; i++) {
name = objToCheck.reflect.properties.name;
if (objToCheck.reflect.properties.type === "readonly"){
readOnlyArr.push(name);
}
else{
try{
objToCheck[name] = objToCheck[name];
}
catch(e){
readOnlyArr.push(name);
};
};
};
return readOnlyArr;
};
checkReadonlyValues(app.project.activeItem)
The problem is that it creates a bunch of history entries, so you'd have to wrap the whole thing into an undoGroup and use app.executeCommand(app.findMenuCommendId("Undo")) at the end to clean things. Not very nice...
Xavier
Copy link to clipboard
Copied
Thanks Xavier!
I'm aware for this option to check if property is readonly or not but it's still seems to me as workaround.
If you will check you can see that not only the JavaScript cores are right, but also File, and Folder etc. reflect object are right.
So it seems the problem is in After Effects(or maybe in other apps-I didn't check).
It looks like someone didn't do his job, because it's seems that every property type is readwrite(in the reflect object).
Copy link to clipboard
Copied
My answer was less about the workaround than the "explanation", although i'm not sure of it.
What i was trying to say is that as javascript properties, all properties in the AE Object Model are "writable", hence their type is "readwrite", it is no mistake, nobody failed, that's the way it is intended to work.
But agreed, it is confusing.
Copy link to clipboard
Copied
Just checked in Illustrator:
If you check `app.reflect.find('buildNumber').type` is readonly.
In AfterEffects the same code above returns readwrite.
So why there is a difference between them?
Copy link to clipboard
Copied
I don't know, as i only made an assumption about the after effects objects being watched.
So i'm not sure i should continue to answer, it would be nice if someone from the staff could clear this out.
But my bet is this ( ! )
i'd say that both teams have chosen different frameworks.
The ID team have defined readonly properties with "writable = false", while the AE team has defined everything with writable = true, but there is a watch function that can throw errors and prevent write access for properties that should not be written.
The ID way is less confusing, and the AE way more pedagogical (because of custom errors), at the cost of confusion for the nosy ones who inspect reflections...
Once again, that's only a bet.
Copy link to clipboard
Copied
I meant Illustrator, not ID.
By the way, what happens if you try this in illustrator ? (i dont have it)
app.buildNumber = 456;
In AE this throws the error: After Effects error: Unable to set "buildNumber". It is a readOnly attribute.
I imagine that in Illustrator, it is silently ignored (like when you try to set the source property of a regexp), unless you use 'use strict', in which case you would get not a Illustrator error but a javascript error.
Copy link to clipboard
Copied
I guess you are right..
In Illustrator unless you add `$.strict = true;` ExtendScript prints: 'Execution finished. Result: 456.
After you add `$.strict = true;` it's says: 'buildNumber is read only`(in try-catch it's throws a ReferenceError).
And in AE it always throws: 'After Effects Error: Unable to set "buildNumber". It is a readOnly attribute.' even if not in strict.
Copy link to clipboard
Copied
Thank you for testing.
And thanks for telling how to use 'use strict'. I could never figure out how to do it.
Strange that it is a $ property. Does this means that it is global and cannot be set locally ??
Xavier.
Copy link to clipboard
Copied
Glad to hear that I helped you!
It's only global but you can turn it on in the beginning of a function and turn it of at the end of the function.
Also there is an option to us `#strict on` but never tested so I don't know how it really works, but I guess it's works the same.
Copy link to clipboard
Copied
Turn on/off... big turn off! And actually, from the Scripting Guide:
($ object, 'strict' property:)
When true, any attempt to write to a read-only property causes a runtime
error. Some objects do not permit the creation of new properties when
true.
So it isnt exaclty the same as 'use strict', in particular it doesnt inlcude the feature i was interested in: prevent the creation of variables without the keyword var.
Eg:
$strict=true;
var comp = app.project.activeItem;
var myLayer;
/*
*/
myLayr = comp.layer(1);
// no error: it just creates a new global variable called myLayr
Nevermind !
Xavier.
Copy link to clipboard
Copied
Yes it's not the real use strict mode.
I assume it's because when ExtendScript was published, there wasn't use strict in the spec.
use strict was first released in EcmaScript 5(12/2009) and ExtendScript still relies on EcmaScript 3(12/1999).
I really hope that soon the ExtendScript team will decide to upgrade and change the ExtendScript engine to support the latest EcmaScript version, because there's a lot of programmers that writes non-short scripts, but longs.
I would be really happy to use some native EcmaScript 2015(and 2016 when released) features.
The decision not to upgrade, make it really hard to programmers (and artists that want to write some scripts) to write some scripts to Adobe programs. It's getting to hard to find some JavaScript code that is native JavaScript(EcmaScript 3).
Copy link to clipboard
Copied
I really hope that soon the ExtendScript team will decide to upgrade and change the ExtendScript engine to support the latest EcmaScript version, because there's a lot of programmers that writes non-short scripts, but longs.
Don't hold your breath. Talks I've had with reliable sources, have leaned towards that not happening. Hence Character Animator being a standalone app, and the introduction of HTML5 (CEP) panels in AE. Both have access to the more recent ECMA features. Bridges, not fixes unfortunately.
Get ready! An upgraded Adobe Community experience is coming in January.
Learn more