Bug 123529 - [KJS] Error compiling named FunctionExpression in ObjectLiteral
Summary: [KJS] Error compiling named FunctionExpression in ObjectLiteral
Status: RESOLVED FIXED
Alias: None
Product: konqueror
Classification: Applications
Component: kjs (show other bugs)
Version: unspecified
Platform: Debian testing Linux
: NOR normal
Target Milestone: ---
Assignee: Konqueror Developers
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2006-03-13 00:54 UTC by Thomas 'PointedEars' Lahn
Modified: 2007-04-21 00:11 UTC (History)
0 users

See Also:
Latest Commit:
Version Fixed In:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Thomas 'PointedEars' Lahn 2006-03-13 00:54:58 UTC
Version:            (using KDE KDE 3.5.1)
Installed from:    Debian testing/unstable Packages
OS:                Linux

This KJS version cannot compile a named FunctionExpression within an ObjectLiteral.  If you use that, you get a "read error" (de: "Einlesefehler in [resource], Zeile [line]") script error message (if debugging is enabled, otherwise compilation of the script silently fails, allowing code of following `script' elements to compile and execute.)

Loaded plugins: none.

Steps to reproduce the bug:

1. Include the following script code as content of the `script' element of an
   HTML document, or include it from an external script resource (e.g.
   resource.js) with

   <script type="text/javascript" src="resource.js">...</script>.

   a) Named FunctionExpression within an ObjectLiteral as right-hand side of an
      assignment:

        var x = {
          y: function z() {}
        };

   b) Named FunctionExpression within an ObjectLiteral that is passed as a
      function argument:

        // or use `var x = function() {};'
        function x() {};

        // The following line triggers a "read error" (message; if you have
        // enabled debugging)
        x({
          y: function z() {}
        });

2. Run the script by loading the HTML document that contains/includes it.

If you remove the `z' identifier in A) or B), thereby making the FunctionExpression anonymous, the error message described is not displayed, and everything works OK.

This behavior is not conforming to ECMAScript Edition 3 [1].  AFAIK it is not displayed by any version of JavaScript, JScript or the Opera script implementation that supports ObjectLiterals and FunctionExpressions I know of (AFAIK: JavaScript 1.3+, JScript 1.0+, Opera 6.0+ implementation).  Therefore, it makes script code break in Konqueror (and perhaps Apple Safari, too) that runs perfectly fine in NN 4.06+, Gecko M3+, IE 3+, and (at least) Opera 6.0+.

The relevant productions in the ECMAScript Specification are:

  Program :
    SourceElements

  SourceElements :
    SourceElement
    SourceElements SourceElement

  SourceElement :
    Statement
    FunctionDeclaration

  Statement --> ExpressionStatement

  ExpressionStatement :
    [lookahead !elementOf({{, function})] Expression ;

  Expression --> AssignmentExpression

  PrimaryExpression --> ObjectLiteral
  ObjectLiteral --> { PropertyNameAndValueList }
  PropertyNameAndValueList --> PropertyName: AssignmentExpression
  PropertyName --> Identifier

  AssignmentExpression
    --> LeftHandSideExpression AssignmentOperator AssignmentExpression

  AssignmentOperator : one of
      =      *=      /=     %= += -= <<= >>= >>>= &= ^= |=

  ConditionalExpression --> LogicalORExpression
  LogicalORExpression --> LogicalANDExpression
  LogicalANDExpression --> BitwiseORExpression
  BitwiseORExpression --> BitwiseXORExpression
  BitwiseXORExpression --> BitwiseANDExpression
  BitwiseANDExpression --> EqualityExpression
  EqualityExpression --> RelationalExpression
  RelationalExpression --> ShiftExpression
  ShiftExpression --> AdditiveExpression
  AdditiveExpression --> MultiplicativeExpression
  MultiplicativeExpression --> UnaryExpression
  UnaryExpression --> PostfixExpression
  PostfixExpression --> LeftHandSideExpression

  LeftHandSideExpression :
    NewExpression
    CallExpression

  NewExpression --> MemberExpression
  MemberExpression --> FunctionExpression

  CallExpression --> MemberExpression Arguments
  Arguments --> ( ArgumentList )
  ArgumentList --> AssignmentExpression

  FunctionExpression:
    function Identifier_opt ( FormalParameterList_opt ) { FunctionBody }
 
Meaning that a FunctionExpression is allowed right-hand side of an assignment or as a function argument, and the identifier in a FunctionExpression is optional.

Reproducible: always.

Expected behavior: Compile both the named and the anonymous FunctionExpression without error everywhere the specification allows it.


Regards,
PointedEars
___________
[1]
Older revision (December 1999) available as PDF document from
<URL:http://ecma-international.org/publications/standards/Ecma-262.htm>

Latest revision (March 2000) available as PDF or MS Word document from
<URL:http://mozilla.org/js/language/>
Comment 1 Thomas 'PointedEars' Lahn 2006-03-14 12:04:11 UTC
Sorry, while reformatting the bug report I snipped one important production that shows the connection between an AssignmentExpression, a ConditionalExpression, and therefore the rest of productions, allowing a FunctionExpression to be a function argument:

  AssignmentExpression :
    ConditionalExpression
    LeftHandSideExpression AssignmentOperator AssignmentExpression
Comment 2 Harri Porten 2007-04-21 00:11:17 UTC
SVN commit 656296 by porten:

extend named function expression hack to object literal property
values. See bug report #123529 and test added as rev 656295.

BUG: 123529


 M  +1 -1      lexer.cpp  


--- branches/KDE/3.5/kdelibs/kjs/lexer.cpp #656295:656296
@@ -566,7 +566,7 @@
     // There are lots of other uses, we really have to get this into the grammar
     if ( token == FUNCTION &&
          ( lastToken == '=' || lastToken == ',' || lastToken == '(' ||
-	   lastToken == RETURN ) )
+	   lastToken == ':' || lastToken == RETURN ) )
             convertNextIdentifier = true;
 
     if (token == CONTINUE || token == BREAK ||