On 17/12/2015 14:58, Chris Page wrote:
> I mean, once you know about
the issue -- and it is spelled out pretty clearly in the
ASLG -- it's hardly crippling.
Actually the ASLG's wording is extremely poor
(feel free to file a ticket on it). It completely fails to
state that the biggest risk is two completely unrelated
scripts can interfere with each other in heinously
unexpected and non-obvious ways if both happen to use the
same stageful library…
Well, I hope you read this before some of my other replies: I
thought you had complained about the *ability* to create
multiple component instances. Some of my replies on this
particular issue may now be tangental.
No. The problem with AS's library system is that it assumes
attachable apps create a new CI for every user script, whereas most
attachable apps, and even NSAppleScript, do not, because they've
never had to, and because they've never been told to. So they've
done what works for them, and work it did for 20 years. And you
can't realistically expect them all to change now.
As to your point about multiple clients seeing the same
library state: that's exactly how frameworks loaded into a
process work,
Chalk to cheese. Frameworks loaded into a process are used solely by
that process's own code. They aren't being shared by multiple
unrelated dependencies, so there isn't the. Problems _can_ arise if
the process also provides a plug-in interface for third-party
extensions that run in-process, but extension authors are
professional developers working in the same language as the host
application and are thoroughly schooled on just how dangerous it is
to be poking around another process's internals so develop their
code very, very, VERY carefully. (And still periodically cause the
host process to explode because they're sloppy or make an error.)
Same with device drivers that are loaded into the kernel process. If
you think that's a remotely acceptable standard of safety or user
experience for untrained amateurs writing AppleScript code for use
in other AppleScripts then you really need to ask yourself whose
needs you're really trying to serve here.
and, as far as I am aware, how libraries work in every other
scripting language.
Argumentum ad populum. Just because _most_ other scripting languages
(e.g. Python, Ruby) are sloppy amateurish hacks that aren't designed
to be internally safe and secure doesn't excuse you taking a
language that was (the usual caveats excepted) and turned it into
one that now isn't. And those languages are primarily intended to be
run out-of-process anyway, which is the traditional Unix way of
guaranteeing safe separation. Pointing at them simply shows you
haven't thought through *your* problem for yourself.
AS was primarily intended to run in-process, so has a very different
set of strictures and requirements to work within. _javascript_, which
was also designed to host multiple unrelated scripts in-process
certainly manages to provide unrelated scripts with independent
contexts. (Web browsers would've exploded years ago had it not.)
e.g. _javascript_Core's JSVirtualMachine vs JSContext arrangement is
not entirely unlike how CIs and SIs work in OSA; the key difference
being that browser developers who embed JS have _always_ known to
create a new VM for each new web page opened within the browser.
I suspect other scripting languages such as Lua that are
specifically intended for embedded use may well do the right thing
too. They may still cache for efficiency, of course (since that
eliminates subsequent file reading and parsing costs), but if
they've any sense they won't reuse library contexts.
And if you just use the default AppleScript instance it'll
work the same as them. And, like many other scripting/dynamic
languages, *if you want* you could create multiple runtime
instances to separate things if that fits your ideas about how
things should work better. Creating a new instance is
straightforward. You have the ability to get what you want—which
is the sort of flexibility it was intentionally designed to
offer.
20 years of established AppleScript *history* and *existing
infrastructure* doesn't give a crap. YOU need to accomodate IT, not
the other way around.
Look, I agree it would be a good thing if attachable apps _always_
loaded unrelated scripts into new CIs, but that just
ISN'T how things are done in the AS world. You can't just make a
unilateral decision to pull the rug from under 20 years of
assumptions and habits, and then claim it's not your problem when
users run into the problems that creates. As a professional product
maintainer you *should* have a duty of care to that product's users
not to break their stuff from under them. That means working within
the needs and limitations of the reality you HAVE, not the reality
you _wish_ you had.
..
The most straightforward and RELIABLE solution is not to reuse
cached modules across unrelated scripts by default, and _only_
enable it when _explicitly_ instructed to do so by the host process
(e.g. by creating a ComponentInstance with the appropriate flag).
For example, Xcode's AppleScript-based application project would do
this in its main.m file as it knows all libraries will have the same
owner. (The ASOC.framework itself would not do this as it ownership
is not its responsibility.) And, once this stuff is documented,
third-party developers whose apps already create a new CI for each
script could trivially update their code to set this flag too if
they need to.
This "safe-by-default" design ensures that existing attachable apps
that don't know about your *new* "one CI per user script"
recommendation can continue to operate as they've always done
without causing user's scripts to break. Of course, it'd be a lot
better if it had been done this way right from the start, but
realistically I'll take a mea culpa and willingness to fix it in the
OS next release.
Implementing this will require a little bit of work as you'll need
to build a dependency graph of modules as they're recursively loaded
by a particular user script. For example:
- If user script A loads libraries B and C, and library B also loads
library C, then A and B both need to use the same instance of C.
- However, when user script A requests library B it must receive a
new instance of B, NOT the same instance of B as A had, UNLESS the
process has already set the relevant flag to tell it that reuse is
allowed.
I'm not going to file the bug report, but I'm sure if you care about
your users then you'll have no problem writing it up and filing it
yourself. Leaving it to Stan or Shane or other users to write the
ticket for you isn't fair on them as they don't have the technical
insight needed, whereas you do. If you want them to dupe the ticket
to help bump it up the priority list, also post it on
<http://openradar.appspot.com> and hint to them they might
want to copy-paste it into Radar if they want it to be resolved
quickly.
Regards
has
|