"const"

Harri Porten porten at froglogic.com
Sat Mar 20 18:56:42 CET 2004


Hello,

here's a patch that implements "const" a bit better than the quick
workaround I produced earlier for KDE 3.2.1.

Test case:

  const c = 11;
  shouldBe("c", "11");
  c = 22;
  shouldBe("c", "11");

What's missing is syntactic error checking. Looks like consts can't be
redeclared as opposed to vars.

Harri.
-------------- next part --------------
Index: ChangeLog
===================================================================
RCS file: /home/kde/kdelibs/kjs/ChangeLog,v
retrieving revision 1.41
retrieving revision 1.42
diff -u -3 -p -r1.41 -r1.42
--- ChangeLog	23 Feb 2004 12:18:28 -0000	1.41
+++ ChangeLog	20 Mar 2004 17:58:55 -0000	1.42
@@ -1,3 +1,7 @@
+2004-03-20  Harri Porten  <porten at kde.org>
+
+	* proper support for JavaScript 1.5 "const" keyword
+
 2004-02-23  Harri Porten  <porten at kde.org>
 
 	* keywords.table: for now, make "const" a synonym for "var". Not
Index: grammar.y
===================================================================
RCS file: /home/kde/kdelibs/kjs/grammar.y,v
retrieving revision 1.59
retrieving revision 1.60
diff -u -3 -p -r1.59 -r1.60
--- grammar.y	7 Nov 2003 09:48:43 -0000	1.59
+++ grammar.y	20 Mar 2004 17:58:55 -0000	1.60
@@ -74,6 +74,7 @@ using namespace KJS;
   PropertyNode        *pnode;
   CatchNode           *cnode;
   FinallyNode         *fnode;
+  VarStatementNode::Type vtype;
 }
 
 %start Program
@@ -87,7 +88,7 @@ using namespace KJS;
 %token STRING NUMBER
 
 /* keywords */
-%token BREAK CASE DEFAULT FOR NEW VAR CONTINUE
+%token BREAK CASE DEFAULT FOR NEW VAR CONST CONTINUE
 %token FUNCTION RETURN VOID DELETE
 %token IF THIS DO WHILE ELSE IN INSTANCEOF TYPEOF
 %token SWITCH WITH RESERVED
@@ -159,6 +160,7 @@ using namespace KJS;
 %type <elm>   ElementList
 %type <plist> PropertyNameAndValueList
 %type <pnode> PropertyName
+%type <vtype> Var
 
 %%
 
@@ -407,11 +409,16 @@ StatementList:
   | StatementList Statement        { $$ = new StatListNode($1, $2); }
 ;
 
+Var:
+    VAR                            { $$ = VarStatementNode::Variable; }
+  | CONST                          { $$ = VarStatementNode::Constant; }
+;
+
 VariableStatement:
-    VAR VariableDeclarationList ';' { $$ = new VarStatementNode($2);
+    Var VariableDeclarationList ';' { $$ = new VarStatementNode($1, $2);
                                       DBG($$, @1, @3); }
-  | VAR VariableDeclarationList error { if (automatic()) {
-                                          $$ = new VarStatementNode($2);
+  | Var VariableDeclarationList error { if (automatic()) {
+                                          $$ = new VarStatementNode($1, $2);
 					  DBG($$, @1, @2);
                                         } else {
 					  YYABORT;
Index: keywords.table
===================================================================
RCS file: /home/kde/kdelibs/kjs/keywords.table,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -3 -p -r1.3 -r1.4
--- keywords.table	23 Feb 2004 12:14:14 -0000	1.3
+++ keywords.table	20 Mar 2004 17:58:55 -0000	1.4
@@ -8,6 +8,7 @@ false		FALSETOKEN
 break		BREAK
 case		CASE
 catch		CATCH
+const		CONST
 default		DEFAULT
 finally		FINALLY
 for		FOR
@@ -36,7 +37,6 @@ boolean		RESERVED
 byte		RESERVED
 char		RESERVED
 class		RESERVED
-const		VAR
 debugger	RESERVED
 double		RESERVED
 enum		RESERVED
Index: nodes.cpp
===================================================================
RCS file: /home/kde/kdelibs/kjs/nodes.cpp,v
retrieving revision 1.166
retrieving revision 1.167
diff -u -3 -p -r1.166 -r1.167
--- nodes.cpp	25 Jan 2004 16:53:07 -0000	1.166
+++ nodes.cpp	20 Mar 2004 17:58:55 -0000	1.167
@@ -1750,6 +1750,9 @@ bool VarDeclNode::deref()
   return Node::deref();
 }
 
+// global var/const flag
+static VarStatementNode::Type currentVarType;
+
 // ECMA 12.2
 Value VarDeclNode::evaluate(ExecState *exec) const
 {
@@ -1770,10 +1773,12 @@ Value VarDeclNode::evaluate(ExecState *e
 #endif
   // We use Internal to bypass all checks in derived objects, e.g. so that
   // "var location" creates a dynamic property instead of activating window.location.
-  if (exec->_context->type() == EvalCode)
-    variable.put(exec, ident, val, Internal);
-  else
-    variable.put(exec, ident, val, DontDelete | Internal);
+  int flags = Internal;
+  if (exec->_context->type() != EvalCode)
+    flags |= Internal;
+  if (currentVarType == VarStatementNode::Constant)
+    flags |= ReadOnly;
+  variable.put(exec, ident, val, flags);
 
   return String(ident.ustring());
 }
@@ -1781,8 +1786,15 @@ Value VarDeclNode::evaluate(ExecState *e
 void VarDeclNode::processVarDecls(ExecState *exec)
 {
   Object variable = exec->context().variableObject();
-  if ( !variable.hasProperty( exec, ident ) ) // already declared ?
-    variable.put(exec,ident, Undefined(), exec->_context->type() == EvalCode ? None : DontDelete);
+  if ( !variable.hasProperty( exec, ident ) ) { // already declared ?
+    int flags = Internal;
+    if (exec->_context->type() != EvalCode)
+      flags |= Internal;
+    if (currentVarType == VarStatementNode::Constant)
+      flags |= ReadOnly;
+    // TODO: check for forbidden redeclaration of consts
+    variable.put(exec,ident, Undefined(), flags);
+  }
   //else warning "variable %1 hides argument"
 }
 
@@ -1848,7 +1860,10 @@ Completion VarStatementNode::execute(Exe
 {
   KJS_BREAKPOINT;
 
-  (void) list->evaluate(exec); // returns 0L
+  // set global var/const flag
+  currentVarType = varType;
+
+  (void) list->evaluate(exec);
   KJS_CHECKEXCEPTION
 
   return Completion(Normal);
@@ -1856,6 +1871,9 @@ Completion VarStatementNode::execute(Exe
 
 void VarStatementNode::processVarDecls(ExecState *exec)
 {
+  // set global var/const flag
+  currentVarType = varType;
+
   list->processVarDecls(exec);
 }
 
Index: nodes.h
===================================================================
RCS file: /home/kde/kdelibs/kjs/nodes.h,v
retrieving revision 1.88
retrieving revision 1.89
diff -u -3 -p -r1.88 -r1.89
--- nodes.h	21 Feb 2004 20:47:56 -0000	1.88
+++ nodes.h	20 Mar 2004 17:58:55 -0000	1.89
@@ -707,13 +707,16 @@ namespace KJS {
 
   class VarStatementNode : public StatementNode {
   public:
-    VarStatementNode(VarDeclListNode *l) : list(l->list) { l->list = 0; }
+    enum Type { Variable, Constant };
+    VarStatementNode(Type t, VarDeclListNode *l)
+      : varType(t), list(l->list) { l->list = 0; }
     virtual void ref();
     virtual bool deref();
     virtual Completion execute(ExecState *exec);
     virtual void processVarDecls(ExecState *exec);
     virtual void streamTo(SourceStream &s) const;
   private:
+    Type varType;
     VarDeclListNode *list;
   };
 


More information about the Khtml-devel mailing list