Closed Bug 229756 Opened 21 years ago Closed 14 years ago

Make SpiderMonkey's const extension JS2/ES4 compatible

Categories

(Core :: JavaScript Engine, defect, P2)

defect

Tracking

()

RESOLVED INVALID

People

(Reporter: brendan, Assigned: graydon)

References

Details

(Keywords: js1.5)

Attachments

(1 file, 1 obsolete file)

See bug 206199.  Currently, SpiderMonkey calls it an error (caught by the
compiler in the example) to declare a const twice.  It allows uninitialized
const, but does not allow one-time setting of same.  Neither of these appear to
be JS2/ES4 compatible to me.

Then there's the issue of exception-catching, which came up in 206199. 
http://www.mozilla.org/js/language/es4/formal/parser-semantics.html specifies a
ReferenceError from writeVariable, which would be catchable by wrapping the
initialized const, or the one-and-only assignment to an uninitialized const, in
a try block.  Currently, in SpiderMonkey, you can't catch a "redeclaration of
foo" error-as-exception in that way (you'd have to use eval of a const decl and
put the eval inside the try).

/be
Status: NEW → ASSIGNED
Priority: -- → P2
Target Milestone: --- → mozilla1.7alpha
Status: ASSIGNED → NEW
Target Milestone: mozilla1.7alpha → mozilla1.8alpha
Status: NEW → ASSIGNED
Target Milestone: mozilla1.8alpha1 → mozilla1.8beta2
Target Milestone: mozilla1.8beta2 → mozilla1.9alpha
Note also the lack of write-once enforcement means you can initialize a const many times in a loop and the last initializing assignment sticks:

js> var j
js> for (i = 0; i < 10; i++) {
const baz = j
if (i > 3) j = 7;
}
7
js> baz
7
js> baz=8
8
js> baz
7

/be
Just FYI, the Rhino const bug is bug 370400.

/be
QA Contact: pschwartau → general
Blocks: 383902
Hoping for clarity here before the next TG1 f2f.

/be
Blocks: js1.8
Target Milestone: mozilla1.9alpha1 → mozilla1.9 M11
Target Milestone: mozilla1.9beta3 → mozilla2.0
Rhino cloned SpiderMonkey, IIRC, and we still don't have agreement in Ecma TC39 on const declarations, so punting to moz2.

/be
No longer blocks: js1.8
Latest thinking, pretty solid, is that const, function, and let are block scoped and different from var (Waldemar cut the knot here, avoiding "let const" and "let function"). Under "use strict", you cannot refer to a const binding in its block before it has been evaluated. Still not sure what standard mode should do, trying to pin that down in es4-discuss now.

/be
Flags: wanted1.9.1?
Target Milestone: mozilla2.0 → mozilla1.9.1
Flags: wanted1.9.1? → wanted1.9.1+
Blocks: 443726
Depends on: 447713
Assignee: brendan → graydon
Status: ASSIGNED → NEW
This is just a sketch to show how I'm hoping to approach the bug. Notably it does not include support for the planned overloaded getter/setter write barrier semantics on general objects; it only handles the case of local let-style consts (and their decayed-to-var colleagues). Still, some feedback would be great. I've tried to be conservative / noninvasive, but this is the first time I've dug into the spidermonkey frontend at all, and I'm certain to have done a few things wrong.
I don't have a lot of substance to add here, I haven't done much with the compiler/emitter/parser myself.  But I can give some style hints:

+    JSBool constp;

I'm not sure about this LISPism (if that's what it is).  I can't think of a single place where a "p" is appended to a variable name in Spidermonkey.  I didn't look hard, so I can be swayed.  :)

+            switch (op) {
+            case JSOP_NAME:     op = JSOP_GETLOCALCONST; break;

in js/src, switch indentation should be like so:
+            switch (op) {
+              case JSOP_NAME:     op = JSOP_GETLOCALCONST; break;

Logic inside the case is indented another 2 spaces (not four):
       case PN_BINARY:
-- lots of stuff removed --
+          *answer = JS_TRUE;
+          break;

Should actually be:
       case PN_BINARY:
-- lots of stuff removed --
+        *answer = JS_TRUE;
+        break;


For my edification, why JSVAL_HOLE and not JSVAL_VOID?  Mustn't const objects be initialized with their declarations (and therefore never undefined?), or is "undefined" a valid initial value?

Haven't actually played with the patch yet, I'll take it out for a spin if I get a free moment.  Can't wait to see us get real const support though.

Will it be possible for us to fold "consts"?  I'm guessing no.
(In reply to comment #7)
> I don't have a lot of substance to add here, I haven't done much with the
> compiler/emitter/parser myself.  But I can give some style hints:
> 
> +    JSBool constp;
> 
> I'm not sure about this LISPism (if that's what it is).  I can't think of a
> single place where a "p" is appended to a variable name in Spidermonkey.  I
> didn't look hard, so I can be swayed.  :)

We append p, but it means "pointer":
jsapi.h:JS_ValueToObject(JSContext *cx, jsval v, JSObject **objp);
jsxml.h:js_FindXMLProperty(JSContext *cx, jsval nameval, JSObject **objp, jsid *idp);
etc.

I would recommend `JSBool isConst', but I've been in the wild west of jstracer.cpp for a while, so grain of salt is counselled.

> For my edification, why JSVAL_HOLE and not JSVAL_VOID?  Mustn't const objects
> be initialized with their declarations (and therefore never undefined?), or is
> "undefined" a valid initial value?

Undefined is a legal value.

const undefined = void(0);
const alsoUndefined;
alsoUndefined = void(0);

> Haven't actually played with the patch yet, I'll take it out for a spin if I
> get a free moment.  Can't wait to see us get real const support though.
> 
> Will it be possible for us to fold "consts"?  I'm guessing no.

Should be possible to fold and propagate consts, at least in cases where we can tell if we're before or after the initialization.  For `const magic = 5;' init-at-decl cases the let-like-hoisting behaviour makes it even easier than today, I think.
(In reply to comment #8)
> We append p, but it means "pointer":
> jsapi.h:JS_ValueToObject(JSContext *cx, jsval v, JSObject **objp);
> jsxml.h:js_FindXMLProperty(JSContext *cx, jsval nameval, JSObject **objp, jsid
> *idp);
> etc.

Errr, yeah.  I meant in the sense of a predicate.
Attached patch update to patchSplinter Review
Patch now implements both local and global variants of write-once const support. Various wrinkles exist: deleting is trapped on a global (it throws), but on a local is simply inhibited while emitting code (should it be a compile-time error?). Moreover, executing a const declaration statement lacking an initializer allocates the const but throws (post-throw it is still there and uninitialized, and can be written to exactly once as usual).

Further feedback appreciated. Existing comments incorporated. I believe this is inching towards the correct shape, but could probably still use more work.
Attachment #333480 - Attachment is obsolete: true
Target Milestone: mozilla1.9.1 → ---
The spec on this has moved on, see bug 611388
Status: NEW → RESOLVED
Closed: 14 years ago
Resolution: --- → INVALID
No longer blocks: 383902
No longer blocks: 443726
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: