Weird "use scripting additions" problem

I’ve been away from scripting for quite a long time, so I may have forgotten some intricacies AS. But I hope that someone can explain to me why the following simple thing does not work:

use AppleScript version "2.5" -- El Capitan (10.11) or later
use scripting additions
use framework "Foundation" --for ASObjC

tell application "Numbers"
	tell table 1 of sheet 1 of front document
		round (get value of cell 4 of row 5)
	end tell
end tell

I get the error “Can’t get value of cell 4 of row 5”.

If I remove the statement use framework "Foundation", then I get another error instead: “Can’t get row 5”.

But if I remove all the use statements, it does work, like a miracle!
Very strange! I thought no ‘use’ statements meant the latest AS and Standard Additions!? Not?

Also, with all the use statements in place, I can get it to work if I put the ‘round’ command on a separate line:

use AppleScript version "2.5" -- El Capitan (10.11) or later
use scripting additions
use framework "Foundation" --for ASObjC

tell application "Numbers"
	tell table 1 of sheet 1 of front document
		(get value of cell 4 of row 5)
		round result
	end tell
end tell

So, although I have this workaround, I don’t understand what’s going on, and it is extremely difficult to debug large scripts by random trial and error. I need to understand why certain things will not work.

I do note that ‘round’ comes from Standard Additions, and somehow it seems to clash with something, but Numbers does not have a ‘round’ command.
In theory, one should only have statements in tell blocks that target the app, but in practice, scripts become totally unwieldy if it jumps in and out of a myriad bog of tell statements making the script completely unreadable.

The existence of any use command alters the loading order and behavior of scripting additions. The errors you’re seeing aren’t very helpful and in theory shouldn’t happen, but they’re not surprising given the limitations of Coca scripting.

You’ll have fewer problems if you keep scripting addition commands (other than UI ones) out of tell blocks. And it doesn’t have to be unwieldy. For example:

use AppleScript version "2.5" -- El Capitan (10.11) or later
use scripting additions
use framework "Foundation" --for ASObjC

tell application "Numbers"
	tell table 1 of sheet 1 of front document
		my doRound(get value of cell 4 of row 5)
	end tell
end tell

on doRound(theVal)
	return round theVal
end doRound

(In the case of round, I’d just use this instead: ((get value of cell 4 of row 5) + 0.5) div 1. Apart from anything else, it’s a lot quicker.)

Thanks for your nice response.
I still do not know why round cause havoc inside the tell block, but only if it’s on the same line! Especially considering that Numbers does not have a round command. It is still “hidden obscure magic” to me!

Somewhat reluctantly, I may have “expel” scripting addition commands from tell blocks, even though I do not understand why. But if commands like round are detrimental inside a tell, I gather that UI commands could be equally detrimental(?)

As for using (aNumber + 0.5) div 1 as a rounding crutch, it does not do the same thing as Standard Additions round – different ways of treating half values, as the following shows:

set aNumber to 0.5
{(aNumber + 0.5) div 1, round aNumber}

-> {1, 0}

(And in my case, I wanted the latter, the “banker’s way”)

It goes back to security, to avoid code being injected into an application.

It’s a fair conclusion, but there is a difference. Perversely, now that I check, round is one you can use within a tell block. I’ve probably confused you by conflating two issues. You might want to read the section on scripting additions here:

https://developer.apple.com/library/archive/releasenotes/AppleScript/RN-AppleScript/RN-10_9/RN-10_9.html

It’s possible that the problem you’re seeing is a result of the optimization described there, with a reference being passed to round, rather than the result.

I think I have come to understand the weird behaviours I have seen (although I would disagree with the way they are treated).

In the document 10.6 Changes, section Scripting Addition Security, they say:

For security reasons, most scripting addition commands now return a “privilege violation” error when sent between application processes. In order to preserve compatibility with existing scripts, AppleScript redirects most of these commands to the current application, that is, the process running the script.

(Exceptions are commands such as display dialog, which must be handled within the target process to operate correctly.)

This is called “double-send”. Moreover:

If the event can be successfully redirected to the current process, then it didn’t need to be sent to the target process in the first place. You can eliminate the unnecessary double-send by moving the scripting addition command outside of the tell block, or by adding tell current application to the command.

The clean and efficient solution to my original script would be the following:

use AppleScript version "2.5" -- El Capitan (10.11) or later
use scripting additions
use framework "Foundation" --for ASObjC

tell application "Numbers"
	tell table 1 of sheet 1 of front document
		value of cell 4 of row 5
		tell current application to round result
	end tell
end tell

One could argue that AS should have worked anyway in my original script, by evaluating the get value of cell 4 of row 5 and then giving that to round, which would experience a double-send and execute it normally in the current app. And indeed, this is how my original script does behave if I remove all the use statements, just as I noticed by more or less random experiments!

Exactly this can be seen and noted in Script Debugger by checking for the Event log! It really shows the “privilege violation” and how round is being resent to the current app!

However, in 10.9 Changes, section Scripting Additions, they introduce “optimisations”:

In scripts that use use scripting additions, AppleScript can optimize Apple event sending for some scripting addition commands, automatically eliminating the double-send described in Scripting Addition Security.

It appears that this optimisation includes sending the whole line that starts with the round command to the current application! That does eliminate double-send, but in my original script it would mean that the current application is sent commands (or methods) regarding cell and row which it will not understand, so it throws an error!

Putting round on a separate line, without the tell current application to, will now send it directly to the current app without a double-send! Exactly this can be seen in the Event log!

I would disagree that this is good practice of “optimisation”, but that is what happens, and it is the reason why these use statements cause the original script to fail.

I will simply have to accept that any scripting addition command, apart from UI, must be on a separate line, preferably preceded by tell current application to unless I have use statements which would do this optimisation automatically.

2 Likes