Controlling DontEnum (was: ES4 draft: Object)
lhansen at adobe.com
Thu Mar 13 16:36:14 PDT 2008
Speaking for myself, I should say from the outset that I am
not in favor of taking this much further than it has been
taken. The base language is ES3; we're trying to fix a
small problem in that language in the cheapest possible way.
I would rather backtrack to a solution that only fixes the
DontEnum problem than to go forward into an elaborate
design that attempts to fix various dodgy (or perceived as
dodgy) features in the base language.
Getters and setters should not be an issue. There is
no way in ES4 to add a getter or setter to an object after
the fact; getters and setters defined by an object initializer
or in a class are fixtures and hence not deletable.
(Some browsers have functions __defineGetter__ and
__defineSetter__ that allow getters and setters to be
added after the fact. Those are normally deletable.
I suggest that these browsers expand their API to match
that of __createProperty__.)
> -----Original Message-----
> From: Mark S. Miller [mailto:erights at google.com]
> Sent: 13. mars 2008 17:22
> To: Lars Hansen
> Cc: es4-discuss at mozilla.org
> Subject: Re: Controlling DontEnum (was: ES4 draft: Object)
> >> From: Neil Mix [mailto:nmix at pandora.com]
> >> function __createProperty__(name:EnumerableId,
> >> value:*,
> >> enumerable:boolean=true,
> >> removable:boolean=true,
> >> writable:boolean=true): void
> On Thu, Mar 13, 2008 at 2:21 PM, Lars Hansen
> <lhansen at adobe.com> wrote:
> > This feels like convergence. I'll hook this into the RI
> and write it
> > up in the next couple of days (barring further discussion, of
> > course).
> I've been following this discussion and am quite happy with
> the overall direction! With these changes, ES3.1 should be a
> much friendlier base to subset into a Caja-like secure
> language. I'm hopeful that the resulting Caja-like language
> could safely be a much larger subset of ES3.1 than with
> current Caja vs ES3. I haven't yet thought these issues
> through well, but I'll offer some half baked suggestions for now.
> * As someone pointed out, using positional boolean flag
> parameters (..., false, true, false, ...) makes call-site
> readability too hard.
> This point was raised earlier but seems to have been dropped. IIRC,
> *all* the other parameterization suggestions had better call
> site readability. My favorite was simply a list of strings.
> OTOH, an advantage of the bit-mask approach is that sensible
> combinations of flags can be named and used simply.
> * I love Neil's suggestion of moving towards names saying
> what's allowed, rather than saying what's denied. I'd like to
> go further and suggest that __createProperty__ adopt the
> security best-practice of
> default-deny: When a property is explicitly created by this
> mechanism, only those operations that are explicitly allowed
> are permitted. All others attributes default to denying
> permission. To maintain compatibility of course, a property
> created the old fashioned way is implicitly fully permissive.
> * As Brendan reminds us, an erroneous __createProperty__
> request should throw rather than failing silently or merely
> returning false.
> And a property access that fails because __createProperty__
> did not allow it should also fail with a throw rather than
> silently. If we want to be strictly legacy compatible, then
> these throws should only happen for properties created with
> __createProperty__. Unfortunately, that means the semantics
> and implementations would need to distinguish, for example,
> legacy silently non-writable properties from new noisily
> non-writable properties. Can we instead specify that all
> these failures will be noisy?
> * Kris raises, we need to think about the interaction of
> these attributes with the notion of virtual properties
> defined using getters and setters. In particular, how does
> one create a non-removable virtual property? Should virtual
> properties have deleters in addition to getters and setters?
> * Might there be a sensible way to extend this mechanism to
> distinguish public from non-public properties? Based on the
> Caja design, might we adopt the rule that non-public property
> foo can only be addressed as this.foo or this['foo']. In
> other words, x.foo would only work is foo is public or unrestricted.
> The general approach we're following here for properties is:
> default to legacy-compatible overly-permissive behavior, but
> allow restriction to a fail-stop subset of this behavior. We
> should prefer to make expressible those restrictions that
> contribute to reasoning about integrity. (This is the right
> criteria whether on not one is trying to define a secure subset.)
> We should apply this general approach to objects as well as
> individual properties of objects. The most important,
> borrowed from ES4, is fixture vs dynamic. The Caja concept
> "frozen" then becomes exactly:
> fixture + all existing properties are non-writable and non-removable.
> We can even use this approach to clean up the main source of
> confusion in ES3 while preserving compatibility: What is the
> intended behavior of a function? It would be great to
> explicitly restrict a function to be callable only as a
> function, or only as a method, or only as a constructor, or
> only as a final constructor. An unrestricted function could
> continue to be callable in all these ways, as with ES3
> functions. Moving these restrictions into the language would
> clear up a major source of vulnerability in the current Caja
> design: confused deputy dangers at the taming boundary
> between cajoled code and uncajoled code. If there's interest,
> I can expand on this issue.
More information about the Es4-discuss