diff options
author | zsfelfoldi <zsfelfoldi@gmail.com> | 2015-03-20 20:22:01 +0800 |
---|---|---|
committer | zsfelfoldi <zsfelfoldi@gmail.com> | 2015-03-20 20:22:01 +0800 |
commit | 8324b683b4e557e6c5c9d572d01f933b3e074185 (patch) | |
tree | 8c6a8c34d87f808c3979875642d4ca38844ad22d | |
parent | 91f9f355b2e334214e38e1827c624cdcc23c5130 (diff) | |
download | go-tangerine-8324b683b4e557e6c5c9d572d01f933b3e074185.tar.gz go-tangerine-8324b683b4e557e6c5c9d572d01f933b3e074185.tar.zst go-tangerine-8324b683b4e557e6c5c9d572d01f933b3e074185.zip |
using robertkrimen/otto, godeps updated
144 files changed, 4986 insertions, 13116 deletions
diff --git a/Godeps/Godeps.json b/Godeps/Godeps.json index e6eab504d..56d67522d 100644 --- a/Godeps/Godeps.json +++ b/Godeps/Godeps.json @@ -47,8 +47,8 @@ "Rev": "ccfcd0245381f0c94c68f50626665eed3c6b726a" }, { - "ImportPath": "github.com/obscuren/otto", - "Rev": "cf13cc4228c5e5ce0fe27a7aea90bc10091c4f19" + "ImportPath": "github.com/robertkrimen/otto", + "Rev": "dea31a3d392779af358ec41f77a07fcc7e9d04ba" }, { "ImportPath": "github.com/obscuren/qml", diff --git a/Godeps/_workspace/src/github.com/obscuren/otto/ast/README.markdown b/Godeps/_workspace/src/github.com/obscuren/otto/ast/README.markdown deleted file mode 100644 index a12e048d5..000000000 --- a/Godeps/_workspace/src/github.com/obscuren/otto/ast/README.markdown +++ /dev/null @@ -1,1066 +0,0 @@ -# ast --- - import "github.com/robertkrimen/otto/ast" - -Package ast declares types representing a JavaScript AST. - - -### Warning - -The parser and AST interfaces are still works-in-progress (particularly where -node types are concerned) and may change in the future. - -## Usage - -#### type ArrayLiteral - -```go -type ArrayLiteral struct { - LeftBracket file.Idx - RightBracket file.Idx - Value []Expression -} -``` - - -#### func (*ArrayLiteral) Idx0 - -```go -func (self *ArrayLiteral) Idx0() file.Idx -``` - -#### func (*ArrayLiteral) Idx1 - -```go -func (self *ArrayLiteral) Idx1() file.Idx -``` - -#### type AssignExpression - -```go -type AssignExpression struct { - Operator token.Token - Left Expression - Right Expression -} -``` - - -#### func (*AssignExpression) Idx0 - -```go -func (self *AssignExpression) Idx0() file.Idx -``` - -#### func (*AssignExpression) Idx1 - -```go -func (self *AssignExpression) Idx1() file.Idx -``` - -#### type BadExpression - -```go -type BadExpression struct { - From file.Idx - To file.Idx -} -``` - - -#### func (*BadExpression) Idx0 - -```go -func (self *BadExpression) Idx0() file.Idx -``` - -#### func (*BadExpression) Idx1 - -```go -func (self *BadExpression) Idx1() file.Idx -``` - -#### type BadStatement - -```go -type BadStatement struct { - From file.Idx - To file.Idx -} -``` - - -#### func (*BadStatement) Idx0 - -```go -func (self *BadStatement) Idx0() file.Idx -``` - -#### func (*BadStatement) Idx1 - -```go -func (self *BadStatement) Idx1() file.Idx -``` - -#### type BinaryExpression - -```go -type BinaryExpression struct { - Operator token.Token - Left Expression - Right Expression - Comparison bool -} -``` - - -#### func (*BinaryExpression) Idx0 - -```go -func (self *BinaryExpression) Idx0() file.Idx -``` - -#### func (*BinaryExpression) Idx1 - -```go -func (self *BinaryExpression) Idx1() file.Idx -``` - -#### type BlockStatement - -```go -type BlockStatement struct { - LeftBrace file.Idx - List []Statement - RightBrace file.Idx -} -``` - - -#### func (*BlockStatement) Idx0 - -```go -func (self *BlockStatement) Idx0() file.Idx -``` - -#### func (*BlockStatement) Idx1 - -```go -func (self *BlockStatement) Idx1() file.Idx -``` - -#### type BooleanLiteral - -```go -type BooleanLiteral struct { - Idx file.Idx - Literal string - Value bool -} -``` - - -#### func (*BooleanLiteral) Idx0 - -```go -func (self *BooleanLiteral) Idx0() file.Idx -``` - -#### func (*BooleanLiteral) Idx1 - -```go -func (self *BooleanLiteral) Idx1() file.Idx -``` - -#### type BracketExpression - -```go -type BracketExpression struct { - Left Expression - Member Expression - LeftBracket file.Idx - RightBracket file.Idx -} -``` - - -#### func (*BracketExpression) Idx0 - -```go -func (self *BracketExpression) Idx0() file.Idx -``` - -#### func (*BracketExpression) Idx1 - -```go -func (self *BracketExpression) Idx1() file.Idx -``` - -#### type BranchStatement - -```go -type BranchStatement struct { - Idx file.Idx - Token token.Token - Label *Identifier -} -``` - - -#### func (*BranchStatement) Idx0 - -```go -func (self *BranchStatement) Idx0() file.Idx -``` - -#### func (*BranchStatement) Idx1 - -```go -func (self *BranchStatement) Idx1() file.Idx -``` - -#### type CallExpression - -```go -type CallExpression struct { - Callee Expression - LeftParenthesis file.Idx - ArgumentList []Expression - RightParenthesis file.Idx -} -``` - - -#### func (*CallExpression) Idx0 - -```go -func (self *CallExpression) Idx0() file.Idx -``` - -#### func (*CallExpression) Idx1 - -```go -func (self *CallExpression) Idx1() file.Idx -``` - -#### type CaseStatement - -```go -type CaseStatement struct { - Case file.Idx - Test Expression - Consequent []Statement -} -``` - - -#### func (*CaseStatement) Idx0 - -```go -func (self *CaseStatement) Idx0() file.Idx -``` - -#### func (*CaseStatement) Idx1 - -```go -func (self *CaseStatement) Idx1() file.Idx -``` - -#### type CatchStatement - -```go -type CatchStatement struct { - Catch file.Idx - Parameter *Identifier - Body Statement -} -``` - - -#### func (*CatchStatement) Idx0 - -```go -func (self *CatchStatement) Idx0() file.Idx -``` - -#### func (*CatchStatement) Idx1 - -```go -func (self *CatchStatement) Idx1() file.Idx -``` - -#### type ConditionalExpression - -```go -type ConditionalExpression struct { - Test Expression - Consequent Expression - Alternate Expression -} -``` - - -#### func (*ConditionalExpression) Idx0 - -```go -func (self *ConditionalExpression) Idx0() file.Idx -``` - -#### func (*ConditionalExpression) Idx1 - -```go -func (self *ConditionalExpression) Idx1() file.Idx -``` - -#### type DebuggerStatement - -```go -type DebuggerStatement struct { - Debugger file.Idx -} -``` - - -#### func (*DebuggerStatement) Idx0 - -```go -func (self *DebuggerStatement) Idx0() file.Idx -``` - -#### func (*DebuggerStatement) Idx1 - -```go -func (self *DebuggerStatement) Idx1() file.Idx -``` - -#### type Declaration - -```go -type Declaration interface { - // contains filtered or unexported methods -} -``` - -All declaration nodes implement the Declaration interface. - -#### type DoWhileStatement - -```go -type DoWhileStatement struct { - Do file.Idx - Test Expression - Body Statement -} -``` - - -#### func (*DoWhileStatement) Idx0 - -```go -func (self *DoWhileStatement) Idx0() file.Idx -``` - -#### func (*DoWhileStatement) Idx1 - -```go -func (self *DoWhileStatement) Idx1() file.Idx -``` - -#### type DotExpression - -```go -type DotExpression struct { - Left Expression - Identifier Identifier -} -``` - - -#### func (*DotExpression) Idx0 - -```go -func (self *DotExpression) Idx0() file.Idx -``` - -#### func (*DotExpression) Idx1 - -```go -func (self *DotExpression) Idx1() file.Idx -``` - -#### type EmptyStatement - -```go -type EmptyStatement struct { - Semicolon file.Idx -} -``` - - -#### func (*EmptyStatement) Idx0 - -```go -func (self *EmptyStatement) Idx0() file.Idx -``` - -#### func (*EmptyStatement) Idx1 - -```go -func (self *EmptyStatement) Idx1() file.Idx -``` - -#### type Expression - -```go -type Expression interface { - Node - // contains filtered or unexported methods -} -``` - -All expression nodes implement the Expression interface. - -#### type ExpressionStatement - -```go -type ExpressionStatement struct { - Expression Expression -} -``` - - -#### func (*ExpressionStatement) Idx0 - -```go -func (self *ExpressionStatement) Idx0() file.Idx -``` - -#### func (*ExpressionStatement) Idx1 - -```go -func (self *ExpressionStatement) Idx1() file.Idx -``` - -#### type ForInStatement - -```go -type ForInStatement struct { - For file.Idx - Into Expression - Source Expression - Body Statement -} -``` - - -#### func (*ForInStatement) Idx0 - -```go -func (self *ForInStatement) Idx0() file.Idx -``` - -#### func (*ForInStatement) Idx1 - -```go -func (self *ForInStatement) Idx1() file.Idx -``` - -#### type ForStatement - -```go -type ForStatement struct { - For file.Idx - Initializer Expression - Update Expression - Test Expression - Body Statement -} -``` - - -#### func (*ForStatement) Idx0 - -```go -func (self *ForStatement) Idx0() file.Idx -``` - -#### func (*ForStatement) Idx1 - -```go -func (self *ForStatement) Idx1() file.Idx -``` - -#### type FunctionDeclaration - -```go -type FunctionDeclaration struct { - Function *FunctionLiteral -} -``` - - -#### type FunctionLiteral - -```go -type FunctionLiteral struct { - Function file.Idx - Name *Identifier - ParameterList *ParameterList - Body Statement - Source string - - DeclarationList []Declaration -} -``` - - -#### func (*FunctionLiteral) Idx0 - -```go -func (self *FunctionLiteral) Idx0() file.Idx -``` - -#### func (*FunctionLiteral) Idx1 - -```go -func (self *FunctionLiteral) Idx1() file.Idx -``` - -#### type Identifier - -```go -type Identifier struct { - Name string - Idx file.Idx -} -``` - - -#### func (*Identifier) Idx0 - -```go -func (self *Identifier) Idx0() file.Idx -``` - -#### func (*Identifier) Idx1 - -```go -func (self *Identifier) Idx1() file.Idx -``` - -#### type IfStatement - -```go -type IfStatement struct { - If file.Idx - Test Expression - Consequent Statement - Alternate Statement -} -``` - - -#### func (*IfStatement) Idx0 - -```go -func (self *IfStatement) Idx0() file.Idx -``` - -#### func (*IfStatement) Idx1 - -```go -func (self *IfStatement) Idx1() file.Idx -``` - -#### type LabelledStatement - -```go -type LabelledStatement struct { - Label *Identifier - Colon file.Idx - Statement Statement -} -``` - - -#### func (*LabelledStatement) Idx0 - -```go -func (self *LabelledStatement) Idx0() file.Idx -``` - -#### func (*LabelledStatement) Idx1 - -```go -func (self *LabelledStatement) Idx1() file.Idx -``` - -#### type NewExpression - -```go -type NewExpression struct { - New file.Idx - Callee Expression - LeftParenthesis file.Idx - ArgumentList []Expression - RightParenthesis file.Idx -} -``` - - -#### func (*NewExpression) Idx0 - -```go -func (self *NewExpression) Idx0() file.Idx -``` - -#### func (*NewExpression) Idx1 - -```go -func (self *NewExpression) Idx1() file.Idx -``` - -#### type Node - -```go -type Node interface { - Idx0() file.Idx // The index of the first character belonging to the node - Idx1() file.Idx // The index of the first character immediately after the node -} -``` - -All nodes implement the Node interface. - -#### type NullLiteral - -```go -type NullLiteral struct { - Idx file.Idx - Literal string -} -``` - - -#### func (*NullLiteral) Idx0 - -```go -func (self *NullLiteral) Idx0() file.Idx -``` - -#### func (*NullLiteral) Idx1 - -```go -func (self *NullLiteral) Idx1() file.Idx -``` - -#### type NumberLiteral - -```go -type NumberLiteral struct { - Idx file.Idx - Literal string - Value interface{} -} -``` - - -#### func (*NumberLiteral) Idx0 - -```go -func (self *NumberLiteral) Idx0() file.Idx -``` - -#### func (*NumberLiteral) Idx1 - -```go -func (self *NumberLiteral) Idx1() file.Idx -``` - -#### type ObjectLiteral - -```go -type ObjectLiteral struct { - LeftBrace file.Idx - RightBrace file.Idx - Value []Property -} -``` - - -#### func (*ObjectLiteral) Idx0 - -```go -func (self *ObjectLiteral) Idx0() file.Idx -``` - -#### func (*ObjectLiteral) Idx1 - -```go -func (self *ObjectLiteral) Idx1() file.Idx -``` - -#### type ParameterList - -```go -type ParameterList struct { - Opening file.Idx - List []*Identifier - Closing file.Idx -} -``` - - -#### type Program - -```go -type Program struct { - Body []Statement - - DeclarationList []Declaration -} -``` - - -#### func (*Program) Idx0 - -```go -func (self *Program) Idx0() file.Idx -``` - -#### func (*Program) Idx1 - -```go -func (self *Program) Idx1() file.Idx -``` - -#### type Property - -```go -type Property struct { - Key string - Kind string - Value Expression -} -``` - - -#### type RegExpLiteral - -```go -type RegExpLiteral struct { - Idx file.Idx - Literal string - Pattern string - Flags string - Value string -} -``` - - -#### func (*RegExpLiteral) Idx0 - -```go -func (self *RegExpLiteral) Idx0() file.Idx -``` - -#### func (*RegExpLiteral) Idx1 - -```go -func (self *RegExpLiteral) Idx1() file.Idx -``` - -#### type ReturnStatement - -```go -type ReturnStatement struct { - Return file.Idx - Argument Expression -} -``` - - -#### func (*ReturnStatement) Idx0 - -```go -func (self *ReturnStatement) Idx0() file.Idx -``` - -#### func (*ReturnStatement) Idx1 - -```go -func (self *ReturnStatement) Idx1() file.Idx -``` - -#### type SequenceExpression - -```go -type SequenceExpression struct { - Sequence []Expression -} -``` - - -#### func (*SequenceExpression) Idx0 - -```go -func (self *SequenceExpression) Idx0() file.Idx -``` - -#### func (*SequenceExpression) Idx1 - -```go -func (self *SequenceExpression) Idx1() file.Idx -``` - -#### type Statement - -```go -type Statement interface { - Node - // contains filtered or unexported methods -} -``` - -All statement nodes implement the Statement interface. - -#### type StringLiteral - -```go -type StringLiteral struct { - Idx file.Idx - Literal string - Value string -} -``` - - -#### func (*StringLiteral) Idx0 - -```go -func (self *StringLiteral) Idx0() file.Idx -``` - -#### func (*StringLiteral) Idx1 - -```go -func (self *StringLiteral) Idx1() file.Idx -``` - -#### type SwitchStatement - -```go -type SwitchStatement struct { - Switch file.Idx - Discriminant Expression - Default int - Body []*CaseStatement -} -``` - - -#### func (*SwitchStatement) Idx0 - -```go -func (self *SwitchStatement) Idx0() file.Idx -``` - -#### func (*SwitchStatement) Idx1 - -```go -func (self *SwitchStatement) Idx1() file.Idx -``` - -#### type ThisExpression - -```go -type ThisExpression struct { - Idx file.Idx -} -``` - - -#### func (*ThisExpression) Idx0 - -```go -func (self *ThisExpression) Idx0() file.Idx -``` - -#### func (*ThisExpression) Idx1 - -```go -func (self *ThisExpression) Idx1() file.Idx -``` - -#### type ThrowStatement - -```go -type ThrowStatement struct { - Throw file.Idx - Argument Expression -} -``` - - -#### func (*ThrowStatement) Idx0 - -```go -func (self *ThrowStatement) Idx0() file.Idx -``` - -#### func (*ThrowStatement) Idx1 - -```go -func (self *ThrowStatement) Idx1() file.Idx -``` - -#### type TryStatement - -```go -type TryStatement struct { - Try file.Idx - Body Statement - Catch *CatchStatement - Finally Statement -} -``` - - -#### func (*TryStatement) Idx0 - -```go -func (self *TryStatement) Idx0() file.Idx -``` - -#### func (*TryStatement) Idx1 - -```go -func (self *TryStatement) Idx1() file.Idx -``` - -#### type UnaryExpression - -```go -type UnaryExpression struct { - Operator token.Token - Idx file.Idx // If a prefix operation - Operand Expression - Postfix bool -} -``` - - -#### func (*UnaryExpression) Idx0 - -```go -func (self *UnaryExpression) Idx0() file.Idx -``` - -#### func (*UnaryExpression) Idx1 - -```go -func (self *UnaryExpression) Idx1() file.Idx -``` - -#### type VariableDeclaration - -```go -type VariableDeclaration struct { - Var file.Idx - List []*VariableExpression -} -``` - - -#### type VariableExpression - -```go -type VariableExpression struct { - Name string - Idx file.Idx - Initializer Expression -} -``` - - -#### func (*VariableExpression) Idx0 - -```go -func (self *VariableExpression) Idx0() file.Idx -``` - -#### func (*VariableExpression) Idx1 - -```go -func (self *VariableExpression) Idx1() file.Idx -``` - -#### type VariableStatement - -```go -type VariableStatement struct { - Var file.Idx - List []Expression -} -``` - - -#### func (*VariableStatement) Idx0 - -```go -func (self *VariableStatement) Idx0() file.Idx -``` - -#### func (*VariableStatement) Idx1 - -```go -func (self *VariableStatement) Idx1() file.Idx -``` - -#### type WhileStatement - -```go -type WhileStatement struct { - While file.Idx - Test Expression - Body Statement -} -``` - - -#### func (*WhileStatement) Idx0 - -```go -func (self *WhileStatement) Idx0() file.Idx -``` - -#### func (*WhileStatement) Idx1 - -```go -func (self *WhileStatement) Idx1() file.Idx -``` - -#### type WithStatement - -```go -type WithStatement struct { - With file.Idx - Object Expression - Body Statement -} -``` - - -#### func (*WithStatement) Idx0 - -```go -func (self *WithStatement) Idx0() file.Idx -``` - -#### func (*WithStatement) Idx1 - -```go -func (self *WithStatement) Idx1() file.Idx -``` - --- -**godocdown** http://github.com/robertkrimen/godocdown diff --git a/Godeps/_workspace/src/github.com/obscuren/otto/ast/node.go b/Godeps/_workspace/src/github.com/obscuren/otto/ast/node.go deleted file mode 100644 index c8b3cb04e..000000000 --- a/Godeps/_workspace/src/github.com/obscuren/otto/ast/node.go +++ /dev/null @@ -1,496 +0,0 @@ -/* -Package ast declares types representing a JavaScript AST. - -Warning - -The parser and AST interfaces are still works-in-progress (particularly where -node types are concerned) and may change in the future. - -*/ -package ast - -import ( - "github.com/robertkrimen/otto/file" - "github.com/robertkrimen/otto/token" -) - -// All nodes implement the Node interface. -type Node interface { - Idx0() file.Idx // The index of the first character belonging to the node - Idx1() file.Idx // The index of the first character immediately after the node -} - -// ========== // -// Expression // -// ========== // - -type ( - // All expression nodes implement the Expression interface. - Expression interface { - Node - _expressionNode() - } - - ArrayLiteral struct { - LeftBracket file.Idx - RightBracket file.Idx - Value []Expression - } - - AssignExpression struct { - Operator token.Token - Left Expression - Right Expression - } - - BadExpression struct { - From file.Idx - To file.Idx - } - - BinaryExpression struct { - Operator token.Token - Left Expression - Right Expression - Comparison bool - } - - BooleanLiteral struct { - Idx file.Idx - Literal string - Value bool - } - - BracketExpression struct { - Left Expression - Member Expression - LeftBracket file.Idx - RightBracket file.Idx - } - - CallExpression struct { - Callee Expression - LeftParenthesis file.Idx - ArgumentList []Expression - RightParenthesis file.Idx - } - - ConditionalExpression struct { - Test Expression - Consequent Expression - Alternate Expression - } - - DotExpression struct { - Left Expression - Identifier Identifier - } - - FunctionLiteral struct { - Function file.Idx - Name *Identifier - ParameterList *ParameterList - Body Statement - Source string - - DeclarationList []Declaration - } - - Identifier struct { - Name string - Idx file.Idx - } - - NewExpression struct { - New file.Idx - Callee Expression - LeftParenthesis file.Idx - ArgumentList []Expression - RightParenthesis file.Idx - } - - NullLiteral struct { - Idx file.Idx - Literal string - } - - NumberLiteral struct { - Idx file.Idx - Literal string - Value interface{} - } - - ObjectLiteral struct { - LeftBrace file.Idx - RightBrace file.Idx - Value []Property - } - - ParameterList struct { - Opening file.Idx - List []*Identifier - Closing file.Idx - } - - Property struct { - Key string - Kind string - Value Expression - } - - RegExpLiteral struct { - Idx file.Idx - Literal string - Pattern string - Flags string - Value string - } - - SequenceExpression struct { - Sequence []Expression - } - - StringLiteral struct { - Idx file.Idx - Literal string - Value string - } - - ThisExpression struct { - Idx file.Idx - } - - UnaryExpression struct { - Operator token.Token - Idx file.Idx // If a prefix operation - Operand Expression - Postfix bool - } - - VariableExpression struct { - Name string - Idx file.Idx - Initializer Expression - } -) - -// _expressionNode - -func (*ArrayLiteral) _expressionNode() {} -func (*AssignExpression) _expressionNode() {} -func (*BadExpression) _expressionNode() {} -func (*BinaryExpression) _expressionNode() {} -func (*BooleanLiteral) _expressionNode() {} -func (*BracketExpression) _expressionNode() {} -func (*CallExpression) _expressionNode() {} -func (*ConditionalExpression) _expressionNode() {} -func (*DotExpression) _expressionNode() {} -func (*FunctionLiteral) _expressionNode() {} -func (*Identifier) _expressionNode() {} -func (*NewExpression) _expressionNode() {} -func (*NullLiteral) _expressionNode() {} -func (*NumberLiteral) _expressionNode() {} -func (*ObjectLiteral) _expressionNode() {} -func (*RegExpLiteral) _expressionNode() {} -func (*SequenceExpression) _expressionNode() {} -func (*StringLiteral) _expressionNode() {} -func (*ThisExpression) _expressionNode() {} -func (*UnaryExpression) _expressionNode() {} -func (*VariableExpression) _expressionNode() {} - -// ========= // -// Statement // -// ========= // - -type ( - // All statement nodes implement the Statement interface. - Statement interface { - Node - _statementNode() - } - - BadStatement struct { - From file.Idx - To file.Idx - } - - BlockStatement struct { - LeftBrace file.Idx - List []Statement - RightBrace file.Idx - } - - BranchStatement struct { - Idx file.Idx - Token token.Token - Label *Identifier - } - - CaseStatement struct { - Case file.Idx - Test Expression - Consequent []Statement - } - - CatchStatement struct { - Catch file.Idx - Parameter *Identifier - Body Statement - } - - DebuggerStatement struct { - Debugger file.Idx - } - - DoWhileStatement struct { - Do file.Idx - Test Expression - Body Statement - } - - EmptyStatement struct { - Semicolon file.Idx - } - - ExpressionStatement struct { - Expression Expression - } - - ForInStatement struct { - For file.Idx - Into Expression - Source Expression - Body Statement - } - - ForStatement struct { - For file.Idx - Initializer Expression - Update Expression - Test Expression - Body Statement - } - - IfStatement struct { - If file.Idx - Test Expression - Consequent Statement - Alternate Statement - } - - LabelledStatement struct { - Label *Identifier - Colon file.Idx - Statement Statement - } - - ReturnStatement struct { - Return file.Idx - Argument Expression - } - - SwitchStatement struct { - Switch file.Idx - Discriminant Expression - Default int - Body []*CaseStatement - } - - ThrowStatement struct { - Throw file.Idx - Argument Expression - } - - TryStatement struct { - Try file.Idx - Body Statement - Catch *CatchStatement - Finally Statement - } - - VariableStatement struct { - Var file.Idx - List []Expression - } - - WhileStatement struct { - While file.Idx - Test Expression - Body Statement - } - - WithStatement struct { - With file.Idx - Object Expression - Body Statement - } -) - -// _statementNode - -func (*BadStatement) _statementNode() {} -func (*BlockStatement) _statementNode() {} -func (*BranchStatement) _statementNode() {} -func (*CaseStatement) _statementNode() {} -func (*CatchStatement) _statementNode() {} -func (*DebuggerStatement) _statementNode() {} -func (*DoWhileStatement) _statementNode() {} -func (*EmptyStatement) _statementNode() {} -func (*ExpressionStatement) _statementNode() {} -func (*ForInStatement) _statementNode() {} -func (*ForStatement) _statementNode() {} -func (*IfStatement) _statementNode() {} -func (*LabelledStatement) _statementNode() {} -func (*ReturnStatement) _statementNode() {} -func (*SwitchStatement) _statementNode() {} -func (*ThrowStatement) _statementNode() {} -func (*TryStatement) _statementNode() {} -func (*VariableStatement) _statementNode() {} -func (*WhileStatement) _statementNode() {} -func (*WithStatement) _statementNode() {} - -// =========== // -// Declaration // -// =========== // - -type ( - // All declaration nodes implement the Declaration interface. - Declaration interface { - _declarationNode() - } - - FunctionDeclaration struct { - Function *FunctionLiteral - } - - VariableDeclaration struct { - Var file.Idx - List []*VariableExpression - } -) - -// _declarationNode - -func (*FunctionDeclaration) _declarationNode() {} -func (*VariableDeclaration) _declarationNode() {} - -// ==== // -// Node // -// ==== // - -type Program struct { - Body []Statement - - DeclarationList []Declaration -} - -// ==== // -// Idx0 // -// ==== // - -func (self *ArrayLiteral) Idx0() file.Idx { return self.LeftBracket } -func (self *AssignExpression) Idx0() file.Idx { return self.Left.Idx0() } -func (self *BadExpression) Idx0() file.Idx { return self.From } -func (self *BinaryExpression) Idx0() file.Idx { return self.Left.Idx0() } -func (self *BooleanLiteral) Idx0() file.Idx { return self.Idx } -func (self *BracketExpression) Idx0() file.Idx { return self.Left.Idx0() } -func (self *CallExpression) Idx0() file.Idx { return self.Callee.Idx0() } -func (self *ConditionalExpression) Idx0() file.Idx { return self.Test.Idx0() } -func (self *DotExpression) Idx0() file.Idx { return self.Left.Idx0() } -func (self *FunctionLiteral) Idx0() file.Idx { return self.Function } -func (self *Identifier) Idx0() file.Idx { return self.Idx } -func (self *NewExpression) Idx0() file.Idx { return self.New } -func (self *NullLiteral) Idx0() file.Idx { return self.Idx } -func (self *NumberLiteral) Idx0() file.Idx { return self.Idx } -func (self *ObjectLiteral) Idx0() file.Idx { return self.LeftBrace } -func (self *RegExpLiteral) Idx0() file.Idx { return self.Idx } -func (self *SequenceExpression) Idx0() file.Idx { return self.Sequence[0].Idx0() } -func (self *StringLiteral) Idx0() file.Idx { return self.Idx } -func (self *ThisExpression) Idx0() file.Idx { return self.Idx } -func (self *UnaryExpression) Idx0() file.Idx { return self.Idx } -func (self *VariableExpression) Idx0() file.Idx { return self.Idx } - -func (self *BadStatement) Idx0() file.Idx { return self.From } -func (self *BlockStatement) Idx0() file.Idx { return self.LeftBrace } -func (self *BranchStatement) Idx0() file.Idx { return self.Idx } -func (self *CaseStatement) Idx0() file.Idx { return self.Case } -func (self *CatchStatement) Idx0() file.Idx { return self.Catch } -func (self *DebuggerStatement) Idx0() file.Idx { return self.Debugger } -func (self *DoWhileStatement) Idx0() file.Idx { return self.Do } -func (self *EmptyStatement) Idx0() file.Idx { return self.Semicolon } -func (self *ExpressionStatement) Idx0() file.Idx { return self.Expression.Idx0() } -func (self *ForInStatement) Idx0() file.Idx { return self.For } -func (self *ForStatement) Idx0() file.Idx { return self.For } -func (self *IfStatement) Idx0() file.Idx { return self.If } -func (self *LabelledStatement) Idx0() file.Idx { return self.Label.Idx0() } -func (self *Program) Idx0() file.Idx { return self.Body[0].Idx0() } -func (self *ReturnStatement) Idx0() file.Idx { return self.Return } -func (self *SwitchStatement) Idx0() file.Idx { return self.Switch } -func (self *ThrowStatement) Idx0() file.Idx { return self.Throw } -func (self *TryStatement) Idx0() file.Idx { return self.Try } -func (self *VariableStatement) Idx0() file.Idx { return self.Var } -func (self *WhileStatement) Idx0() file.Idx { return self.While } -func (self *WithStatement) Idx0() file.Idx { return self.With } - -// ==== // -// Idx1 // -// ==== // - -func (self *ArrayLiteral) Idx1() file.Idx { return self.RightBracket } -func (self *AssignExpression) Idx1() file.Idx { return self.Right.Idx1() } -func (self *BadExpression) Idx1() file.Idx { return self.To } -func (self *BinaryExpression) Idx1() file.Idx { return self.Right.Idx1() } -func (self *BooleanLiteral) Idx1() file.Idx { return file.Idx(int(self.Idx) + len(self.Literal)) } -func (self *BracketExpression) Idx1() file.Idx { return self.RightBracket + 1 } -func (self *CallExpression) Idx1() file.Idx { return self.RightParenthesis + 1 } -func (self *ConditionalExpression) Idx1() file.Idx { return self.Test.Idx1() } -func (self *DotExpression) Idx1() file.Idx { return self.Identifier.Idx1() } -func (self *FunctionLiteral) Idx1() file.Idx { return self.Body.Idx1() } -func (self *Identifier) Idx1() file.Idx { return file.Idx(int(self.Idx) + len(self.Name)) } -func (self *NewExpression) Idx1() file.Idx { return self.RightParenthesis + 1 } -func (self *NullLiteral) Idx1() file.Idx { return file.Idx(int(self.Idx) + 4) } // "null" -func (self *NumberLiteral) Idx1() file.Idx { return file.Idx(int(self.Idx) + len(self.Literal)) } -func (self *ObjectLiteral) Idx1() file.Idx { return self.RightBrace } -func (self *RegExpLiteral) Idx1() file.Idx { return file.Idx(int(self.Idx) + len(self.Literal)) } -func (self *SequenceExpression) Idx1() file.Idx { return self.Sequence[0].Idx1() } -func (self *StringLiteral) Idx1() file.Idx { return file.Idx(int(self.Idx) + len(self.Literal)) } -func (self *ThisExpression) Idx1() file.Idx { return self.Idx } -func (self *UnaryExpression) Idx1() file.Idx { - if self.Postfix { - return self.Operand.Idx1() + 2 // ++ -- - } - return self.Operand.Idx1() -} -func (self *VariableExpression) Idx1() file.Idx { - if self.Initializer == nil { - return file.Idx(int(self.Idx) + len(self.Name) + 1) - } - return self.Initializer.Idx1() -} - -func (self *BadStatement) Idx1() file.Idx { return self.To } -func (self *BlockStatement) Idx1() file.Idx { return self.RightBrace + 1 } -func (self *BranchStatement) Idx1() file.Idx { return self.Idx } -func (self *CaseStatement) Idx1() file.Idx { return self.Consequent[len(self.Consequent)-1].Idx1() } -func (self *CatchStatement) Idx1() file.Idx { return self.Body.Idx1() } -func (self *DebuggerStatement) Idx1() file.Idx { return self.Debugger + 8 } -func (self *DoWhileStatement) Idx1() file.Idx { return self.Test.Idx1() } -func (self *EmptyStatement) Idx1() file.Idx { return self.Semicolon + 1 } -func (self *ExpressionStatement) Idx1() file.Idx { return self.Expression.Idx1() } -func (self *ForInStatement) Idx1() file.Idx { return self.Body.Idx1() } -func (self *ForStatement) Idx1() file.Idx { return self.Body.Idx1() } -func (self *IfStatement) Idx1() file.Idx { - if self.Alternate != nil { - return self.Alternate.Idx1() - } - return self.Consequent.Idx1() -} -func (self *LabelledStatement) Idx1() file.Idx { return self.Colon + 1 } -func (self *Program) Idx1() file.Idx { return self.Body[len(self.Body)-1].Idx1() } -func (self *ReturnStatement) Idx1() file.Idx { return self.Return } -func (self *SwitchStatement) Idx1() file.Idx { return self.Body[len(self.Body)-1].Idx1() } -func (self *ThrowStatement) Idx1() file.Idx { return self.Throw } -func (self *TryStatement) Idx1() file.Idx { return self.Try } -func (self *VariableStatement) Idx1() file.Idx { return self.List[len(self.List)-1].Idx1() } -func (self *WhileStatement) Idx1() file.Idx { return self.Body.Idx1() } -func (self *WithStatement) Idx1() file.Idx { return self.Body.Idx1() } diff --git a/Godeps/_workspace/src/github.com/obscuren/otto/builtin_error.go b/Godeps/_workspace/src/github.com/obscuren/otto/builtin_error.go deleted file mode 100644 index effd7f698..000000000 --- a/Godeps/_workspace/src/github.com/obscuren/otto/builtin_error.go +++ /dev/null @@ -1,85 +0,0 @@ -package otto - -func (runtime *_runtime) newEvalError(message Value) *_object { - self := runtime.newErrorObject(message) - self.prototype = runtime.Global.EvalErrorPrototype - return self -} - -func builtinEvalError(call FunctionCall) Value { - return toValue_object(call.runtime.newEvalError(call.Argument(0))) -} - -func builtinNewEvalError(self *_object, _ Value, argumentList []Value) Value { - return toValue_object(self.runtime.newEvalError(valueOfArrayIndex(argumentList, 0))) -} - -func (runtime *_runtime) newTypeError(message Value) *_object { - self := runtime.newErrorObject(message) - self.prototype = runtime.Global.TypeErrorPrototype - return self -} - -func builtinTypeError(call FunctionCall) Value { - return toValue_object(call.runtime.newTypeError(call.Argument(0))) -} - -func builtinNewTypeError(self *_object, _ Value, argumentList []Value) Value { - return toValue_object(self.runtime.newTypeError(valueOfArrayIndex(argumentList, 0))) -} - -func (runtime *_runtime) newRangeError(message Value) *_object { - self := runtime.newErrorObject(message) - self.prototype = runtime.Global.RangeErrorPrototype - return self -} - -func builtinRangeError(call FunctionCall) Value { - return toValue_object(call.runtime.newRangeError(call.Argument(0))) -} - -func builtinNewRangeError(self *_object, _ Value, argumentList []Value) Value { - return toValue_object(self.runtime.newRangeError(valueOfArrayIndex(argumentList, 0))) -} - -func (runtime *_runtime) newURIError(message Value) *_object { - self := runtime.newErrorObject(message) - self.prototype = runtime.Global.URIErrorPrototype - return self -} - -func (runtime *_runtime) newReferenceError(message Value) *_object { - self := runtime.newErrorObject(message) - self.prototype = runtime.Global.ReferenceErrorPrototype - return self -} - -func builtinReferenceError(call FunctionCall) Value { - return toValue_object(call.runtime.newReferenceError(call.Argument(0))) -} - -func builtinNewReferenceError(self *_object, _ Value, argumentList []Value) Value { - return toValue_object(self.runtime.newReferenceError(valueOfArrayIndex(argumentList, 0))) -} - -func (runtime *_runtime) newSyntaxError(message Value) *_object { - self := runtime.newErrorObject(message) - self.prototype = runtime.Global.SyntaxErrorPrototype - return self -} - -func builtinSyntaxError(call FunctionCall) Value { - return toValue_object(call.runtime.newSyntaxError(call.Argument(0))) -} - -func builtinNewSyntaxError(self *_object, _ Value, argumentList []Value) Value { - return toValue_object(self.runtime.newSyntaxError(valueOfArrayIndex(argumentList, 0))) -} - -func builtinURIError(call FunctionCall) Value { - return toValue_object(call.runtime.newURIError(call.Argument(0))) -} - -func builtinNewURIError(self *_object, _ Value, argumentList []Value) Value { - return toValue_object(self.runtime.newURIError(valueOfArrayIndex(argumentList, 0))) -} diff --git a/Godeps/_workspace/src/github.com/obscuren/otto/clone.go b/Godeps/_workspace/src/github.com/obscuren/otto/clone.go deleted file mode 100644 index fbdde81c2..000000000 --- a/Godeps/_workspace/src/github.com/obscuren/otto/clone.go +++ /dev/null @@ -1,144 +0,0 @@ -package otto - -import ( - "fmt" -) - -type _clone struct { - runtime *_runtime - stash struct { - object map[*_object]*_object - objectEnvironment map[*_objectEnvironment]*_objectEnvironment - declarativeEnvironment map[*_declarativeEnvironment]*_declarativeEnvironment - } -} - -func (runtime *_runtime) clone() *_runtime { - - self := &_runtime{} - clone := &_clone{ - runtime: self, - } - clone.stash.object = make(map[*_object]*_object) - clone.stash.objectEnvironment = make(map[*_objectEnvironment]*_objectEnvironment) - clone.stash.declarativeEnvironment = make(map[*_declarativeEnvironment]*_declarativeEnvironment) - - globalObject := clone.object(runtime.GlobalObject) - self.GlobalEnvironment = self.newObjectEnvironment(globalObject, nil) - self.GlobalObject = globalObject - self.Global = _global{ - clone.object(runtime.Global.Object), - clone.object(runtime.Global.Function), - clone.object(runtime.Global.Array), - clone.object(runtime.Global.String), - clone.object(runtime.Global.Boolean), - clone.object(runtime.Global.Number), - clone.object(runtime.Global.Math), - clone.object(runtime.Global.Date), - clone.object(runtime.Global.RegExp), - clone.object(runtime.Global.Error), - clone.object(runtime.Global.EvalError), - clone.object(runtime.Global.TypeError), - clone.object(runtime.Global.RangeError), - clone.object(runtime.Global.ReferenceError), - clone.object(runtime.Global.SyntaxError), - clone.object(runtime.Global.URIError), - clone.object(runtime.Global.JSON), - - clone.object(runtime.Global.ObjectPrototype), - clone.object(runtime.Global.FunctionPrototype), - clone.object(runtime.Global.ArrayPrototype), - clone.object(runtime.Global.StringPrototype), - clone.object(runtime.Global.BooleanPrototype), - clone.object(runtime.Global.NumberPrototype), - clone.object(runtime.Global.DatePrototype), - clone.object(runtime.Global.RegExpPrototype), - clone.object(runtime.Global.ErrorPrototype), - clone.object(runtime.Global.EvalErrorPrototype), - clone.object(runtime.Global.TypeErrorPrototype), - clone.object(runtime.Global.RangeErrorPrototype), - clone.object(runtime.Global.ReferenceErrorPrototype), - clone.object(runtime.Global.SyntaxErrorPrototype), - clone.object(runtime.Global.URIErrorPrototype), - } - - self.EnterGlobalExecutionContext() - - self.eval = self.GlobalObject.property["eval"].value.(Value).value.(*_object) - self.GlobalObject.prototype = self.Global.ObjectPrototype - - return self -} -func (clone *_clone) object(self0 *_object) *_object { - if self1, exists := clone.stash.object[self0]; exists { - return self1 - } - self1 := &_object{} - clone.stash.object[self0] = self1 - return self0.objectClass.clone(self0, self1, clone) -} - -func (clone *_clone) declarativeEnvironment(self0 *_declarativeEnvironment) (*_declarativeEnvironment, bool) { - if self1, exists := clone.stash.declarativeEnvironment[self0]; exists { - return self1, true - } - self1 := &_declarativeEnvironment{} - clone.stash.declarativeEnvironment[self0] = self1 - return self1, false -} - -func (clone *_clone) objectEnvironment(self0 *_objectEnvironment) (*_objectEnvironment, bool) { - if self1, exists := clone.stash.objectEnvironment[self0]; exists { - return self1, true - } - self1 := &_objectEnvironment{} - clone.stash.objectEnvironment[self0] = self1 - return self1, false -} - -func (clone *_clone) value(self0 Value) Value { - self1 := self0 - switch value := self0.value.(type) { - case *_object: - self1.value = clone.object(value) - } - return self1 -} - -func (clone *_clone) valueArray(self0 []Value) []Value { - self1 := make([]Value, len(self0)) - for index, value := range self0 { - self1[index] = clone.value(value) - } - return self1 -} - -func (clone *_clone) environment(self0 _environment) _environment { - if self0 == nil { - return nil - } - return self0.clone(clone) -} - -func (clone *_clone) property(self0 _property) _property { - self1 := self0 - if value, valid := self0.value.(Value); valid { - self1.value = clone.value(value) - } else { - panic(fmt.Errorf("self0.value.(Value) != true")) - } - return self1 -} - -func (clone *_clone) declarativeProperty(self0 _declarativeProperty) _declarativeProperty { - self1 := self0 - self1.value = clone.value(self0.value) - return self1 -} - -func (clone *_clone) callFunction(self0 _callFunction) _callFunction { - if self0 == nil { - return nil - } - return self0.clone(clone) -} diff --git a/Godeps/_workspace/src/github.com/obscuren/otto/cmpl_function.go b/Godeps/_workspace/src/github.com/obscuren/otto/cmpl_function.go deleted file mode 100644 index 0c8a9df14..000000000 --- a/Godeps/_workspace/src/github.com/obscuren/otto/cmpl_function.go +++ /dev/null @@ -1,46 +0,0 @@ -package otto - -// _cmpl_nodeCallFunction -type _cmpl_nodeCallFunction struct { - node *_nodeFunctionLiteral - scopeEnvironment _environment // Can be either Lexical or Variable -} - -func new_nodeCallFunction(node *_nodeFunctionLiteral, scopeEnvironment _environment) *_cmpl_nodeCallFunction { - self := &_cmpl_nodeCallFunction{ - node: node, - } - self.scopeEnvironment = scopeEnvironment - return self -} - -func (self _cmpl_nodeCallFunction) Dispatch(function *_object, environment *_functionEnvironment, runtime *_runtime, this Value, argumentList []Value, _ bool) Value { - return runtime.cmpl_call_nodeFunction(function, environment, self.node, this, argumentList) -} - -func (self _cmpl_nodeCallFunction) ScopeEnvironment() _environment { - return self.scopeEnvironment -} - -func (self _cmpl_nodeCallFunction) Source(object *_object) string { - return self.node.source -} - -func (self0 _cmpl_nodeCallFunction) clone(clone *_clone) _callFunction { - return _cmpl_nodeCallFunction{ - node: self0.node, - scopeEnvironment: clone.environment(self0.scopeEnvironment), - } -} - -// --- - -func (runtime *_runtime) newNodeFunctionObject(node *_nodeFunctionLiteral, scopeEnvironment _environment) *_object { - self := runtime.newClassObject("Function") - self.value = _functionObject{ - call: new_nodeCallFunction(node, scopeEnvironment), - construct: defaultConstructFunction, - } - self.defineProperty("length", toValue_int(len(node.parameterList)), 0000, false) - return self -} diff --git a/Godeps/_workspace/src/github.com/obscuren/otto/dbg/dbg.go b/Godeps/_workspace/src/github.com/obscuren/otto/dbg/dbg.go deleted file mode 100644 index 83bf6c573..000000000 --- a/Godeps/_workspace/src/github.com/obscuren/otto/dbg/dbg.go +++ /dev/null @@ -1,387 +0,0 @@ -// This file was AUTOMATICALLY GENERATED by dbg-import (smuggol) from github.com/robertkrimen/dbg - -/* -Package dbg is a println/printf/log-debugging utility library. - - import ( - Dbg "github.com/robertkrimen/dbg" - ) - - dbg, dbgf := Dbg.New() - - dbg("Emit some debug stuff", []byte{120, 121, 122, 122, 121}, math.Pi) - # "2013/01/28 16:50:03 Emit some debug stuff [120 121 122 122 121] 3.141592653589793" - - dbgf("With a %s formatting %.2f", "little", math.Pi) - # "2013/01/28 16:51:55 With a little formatting (3.14)" - - dbgf("%/fatal//A fatal debug statement: should not be here") - # "A fatal debug statement: should not be here" - # ...and then, os.Exit(1) - - dbgf("%/panic//Can also panic %s", "this") - # "Can also panic this" - # ...as a panic, equivalent to: panic("Can also panic this") - - dbgf("Any %s arguments without a corresponding %%", "extra", "are treated like arguments to dbg()") - # "2013/01/28 17:14:40 Any extra arguments (without a corresponding %) are treated like arguments to dbg()" - - dbgf("%d %d", 1, 2, 3, 4, 5) - # "2013/01/28 17:16:32 Another example: 1 2 3 4 5" - - dbgf("%@: Include the function name for a little context (via %s)", "%@") - # "2013... github.com/robertkrimen/dbg.TestSynopsis: Include the function name for a little context (via %@)" - -By default, dbg uses log (log.Println, log.Printf, log.Panic, etc.) for output. -However, you can also provide your own output destination by invoking dbg.New with -a customization function: - - import ( - "bytes" - Dbg "github.com/robertkrimen/dbg" - "os" - ) - - # dbg to os.Stderr - dbg, dbgf := Dbg.New(func(dbgr *Dbgr) { - dbgr.SetOutput(os.Stderr) - }) - - # A slightly contrived example: - var buffer bytes.Buffer - dbg, dbgf := New(func(dbgr *Dbgr) { - dbgr.SetOutput(&buffer) - }) - -*/ -package dbg - -import ( - "bytes" - "fmt" - "io" - "log" - "os" - "regexp" - "runtime" - "strings" - "unicode" -) - -type _frmt struct { - ctl string - format string - operandCount int - panic bool - fatal bool - check bool -} - -var ( - ctlTest = regexp.MustCompile(`^\s*%/`) - ctlScan = regexp.MustCompile(`%?/(panic|fatal|check)(?:\s|$)`) -) - -func operandCount(format string) int { - count := 0 - end := len(format) - for at := 0; at < end; { - for at < end && format[at] != '%' { - at++ - } - at++ - if at < end { - if format[at] != '%' && format[at] != '@' { - count++ - } - at++ - } - } - return count -} - -func parseFormat(format string) (frmt _frmt) { - if ctlTest.MatchString(format) { - format = strings.TrimLeftFunc(format, unicode.IsSpace) - index := strings.Index(format, "//") - if index != -1 { - frmt.ctl = format[0:index] - format = format[index+2:] // Skip the second slash via +2 (instead of +1) - } else { - frmt.ctl = format - format = "" - } - for _, tmp := range ctlScan.FindAllStringSubmatch(frmt.ctl, -1) { - for _, value := range tmp[1:] { - switch value { - case "panic": - frmt.panic = true - case "fatal": - frmt.fatal = true - case "check": - frmt.check = true - } - } - } - } - frmt.format = format - frmt.operandCount = operandCount(format) - return -} - -type Dbgr struct { - emit _emit -} - -type DbgFunction func(values ...interface{}) - -func NewDbgr() *Dbgr { - self := &Dbgr{} - return self -} - -/* -New will create and return a pair of debugging functions. You can customize where -they output to by passing in an (optional) customization function: - - import ( - Dbg "github.com/robertkrimen/dbg" - "os" - ) - - # dbg to os.Stderr - dbg, dbgf := Dbg.New(func(dbgr *Dbgr) { - dbgr.SetOutput(os.Stderr) - }) - -*/ -func New(options ...interface{}) (dbg DbgFunction, dbgf DbgFunction) { - dbgr := NewDbgr() - if len(options) > 0 { - if fn, ok := options[0].(func(*Dbgr)); ok { - fn(dbgr) - } - } - return dbgr.DbgDbgf() -} - -func (self Dbgr) Dbg(values ...interface{}) { - self.getEmit().emit(_frmt{}, "", values...) -} - -func (self Dbgr) Dbgf(values ...interface{}) { - self.dbgf(values...) -} - -func (self Dbgr) DbgDbgf() (dbg DbgFunction, dbgf DbgFunction) { - dbg = func(vl ...interface{}) { - self.Dbg(vl...) - } - dbgf = func(vl ...interface{}) { - self.dbgf(vl...) - } - return dbg, dbgf // Redundant, but... -} - -func (self Dbgr) dbgf(values ...interface{}) { - - var frmt _frmt - if len(values) > 0 { - tmp := fmt.Sprint(values[0]) - frmt = parseFormat(tmp) - values = values[1:] - } - - buffer_f := bytes.Buffer{} - format := frmt.format - end := len(format) - for at := 0; at < end; { - last := at - for at < end && format[at] != '%' { - at++ - } - if at > last { - buffer_f.WriteString(format[last:at]) - } - if at >= end { - break - } - // format[at] == '%' - at++ - // format[at] == ? - if format[at] == '@' { - depth := 2 - pc, _, _, _ := runtime.Caller(depth) - name := runtime.FuncForPC(pc).Name() - buffer_f.WriteString(name) - } else { - buffer_f.WriteString(format[at-1 : at+1]) - } - at++ - } - - //values_f := append([]interface{}{}, values[0:frmt.operandCount]...) - values_f := values[0:frmt.operandCount] - values_dbg := values[frmt.operandCount:] - if len(values_dbg) > 0 { - // Adjust frmt.format: - // (%v instead of %s because: frmt.check) - { - tmp := format - if len(tmp) > 0 { - if unicode.IsSpace(rune(tmp[len(tmp)-1])) { - buffer_f.WriteString("%v") - } else { - buffer_f.WriteString(" %v") - } - } else if frmt.check { - // Performing a check, so no output - } else { - buffer_f.WriteString("%v") - } - } - - // Adjust values_f: - if !frmt.check { - tmp := []string{} - for _, value := range values_dbg { - tmp = append(tmp, fmt.Sprintf("%v", value)) - } - // First, make a copy of values_f, so we avoid overwriting values_dbg when appending - values_f = append([]interface{}{}, values_f...) - values_f = append(values_f, strings.Join(tmp, " ")) - } - } - - format = buffer_f.String() - if frmt.check { - // We do not actually emit to the log, but panic if - // a non-nil value is detected (e.g. a non-nil error) - for _, value := range values_dbg { - if value != nil { - if format == "" { - panic(value) - } else { - panic(fmt.Sprintf(format, append(values_f, value)...)) - } - } - } - } else { - self.getEmit().emit(frmt, format, values_f...) - } -} - -// Idiot-proof &Dbgr{}, etc. -func (self *Dbgr) getEmit() _emit { - if self.emit == nil { - self.emit = standardEmit() - } - return self.emit -} - -// SetOutput will accept the following as a destination for output: -// -// *log.Logger Print*/Panic*/Fatal* of the logger -// io.Writer - -// nil Reset to the default output (os.Stderr) -// "log" Print*/Panic*/Fatal* via the "log" package -// -func (self *Dbgr) SetOutput(output interface{}) { - if output == nil { - self.emit = standardEmit() - return - } - switch output := output.(type) { - case *log.Logger: - self.emit = _emitLogger{ - logger: output, - } - return - case io.Writer: - self.emit = _emitWriter{ - writer: output, - } - return - case string: - if output == "log" { - self.emit = _emitLog{} - return - } - } - panic(output) -} - -// ======== // -// = emit = // -// ======== // - -func standardEmit() _emit { - return _emitWriter{ - writer: os.Stderr, - } -} - -func ln(tmp string) string { - length := len(tmp) - if length > 0 && tmp[length-1] != '\n' { - return tmp + "\n" - } - return tmp -} - -type _emit interface { - emit(_frmt, string, ...interface{}) -} - -type _emitWriter struct { - writer io.Writer -} - -func (self _emitWriter) emit(frmt _frmt, format string, values ...interface{}) { - if format == "" { - fmt.Fprintln(self.writer, values...) - } else { - if frmt.panic { - panic(fmt.Sprintf(format, values...)) - } - fmt.Fprintf(self.writer, ln(format), values...) - if frmt.fatal { - os.Exit(1) - } - } -} - -type _emitLogger struct { - logger *log.Logger -} - -func (self _emitLogger) emit(frmt _frmt, format string, values ...interface{}) { - if format == "" { - self.logger.Println(values...) - } else { - if frmt.panic { - self.logger.Panicf(format, values...) - } else if frmt.fatal { - self.logger.Fatalf(format, values...) - } else { - self.logger.Printf(format, values...) - } - } -} - -type _emitLog struct { -} - -func (self _emitLog) emit(frmt _frmt, format string, values ...interface{}) { - if format == "" { - log.Println(values...) - } else { - if frmt.panic { - log.Panicf(format, values...) - } else if frmt.fatal { - log.Fatalf(format, values...) - } else { - log.Printf(format, values...) - } - } -} diff --git a/Godeps/_workspace/src/github.com/obscuren/otto/environment.go b/Godeps/_workspace/src/github.com/obscuren/otto/environment.go deleted file mode 100644 index 891a3c9af..000000000 --- a/Godeps/_workspace/src/github.com/obscuren/otto/environment.go +++ /dev/null @@ -1,280 +0,0 @@ -package otto - -import ( - "fmt" -) - -// _environment - -type _environment interface { - HasBinding(string) bool - - CreateMutableBinding(string, bool) - SetMutableBinding(string, Value, bool) - // SetMutableBinding with Lazy CreateMutableBinding(..., true) - SetValue(string, Value, bool) - - GetBindingValue(string, bool) Value - GetValue(string, bool) Value // GetBindingValue - DeleteBinding(string) bool - ImplicitThisValue() *_object - - Outer() _environment - - newReference(string, bool) _reference - clone(clone *_clone) _environment - runtimeOf() *_runtime -} - -// _functionEnvironment - -type _functionEnvironment struct { - _declarativeEnvironment - arguments *_object - indexOfArgumentName map[string]string -} - -func (runtime *_runtime) newFunctionEnvironment(outer _environment) *_functionEnvironment { - return &_functionEnvironment{ - _declarativeEnvironment: _declarativeEnvironment{ - runtime: runtime, - outer: outer, - property: map[string]_declarativeProperty{}, - }, - } -} - -func (self0 _functionEnvironment) clone(clone *_clone) _environment { - return &_functionEnvironment{ - *(self0._declarativeEnvironment.clone(clone).(*_declarativeEnvironment)), - clone.object(self0.arguments), - self0.indexOfArgumentName, - } -} - -func (self _functionEnvironment) runtimeOf() *_runtime { - return self._declarativeEnvironment.runtimeOf() -} - -// _objectEnvironment - -type _objectEnvironment struct { - runtime *_runtime - outer _environment - Object *_object - ProvideThis bool -} - -func (self *_objectEnvironment) runtimeOf() *_runtime { - return self.runtime -} - -func (runtime *_runtime) newObjectEnvironment(object *_object, outer _environment) *_objectEnvironment { - if object == nil { - object = runtime.newBaseObject() - object.class = "environment" - } - return &_objectEnvironment{ - runtime: runtime, - outer: outer, - Object: object, - } -} - -func (self0 *_objectEnvironment) clone(clone *_clone) _environment { - self1, exists := clone.objectEnvironment(self0) - if exists { - return self1 - } - *self1 = _objectEnvironment{ - clone.runtime, - clone.environment(self0.outer), - clone.object(self0.Object), - self0.ProvideThis, - } - return self1 -} - -func (self *_objectEnvironment) HasBinding(name string) bool { - return self.Object.hasProperty(name) -} - -func (self *_objectEnvironment) CreateMutableBinding(name string, deletable bool) { - if self.Object.hasProperty(name) { - panic(hereBeDragons()) - } - mode := _propertyMode(0111) - if !deletable { - mode = _propertyMode(0110) - } - // TODO False? - self.Object.defineProperty(name, UndefinedValue(), mode, false) -} - -func (self *_objectEnvironment) SetMutableBinding(name string, value Value, strict bool) { - self.Object.put(name, value, strict) -} - -func (self *_objectEnvironment) SetValue(name string, value Value, throw bool) { - if !self.HasBinding(name) { - self.CreateMutableBinding(name, true) // Configurable by default - } - self.SetMutableBinding(name, value, throw) -} - -func (self *_objectEnvironment) GetBindingValue(name string, strict bool) Value { - if self.Object.hasProperty(name) { - return self.Object.get(name) - } - if strict { - panic(newReferenceError("Not Defined", name)) - } - return UndefinedValue() -} - -func (self *_objectEnvironment) GetValue(name string, throw bool) Value { - return self.GetBindingValue(name, throw) -} - -func (self *_objectEnvironment) DeleteBinding(name string) bool { - return self.Object.delete(name, false) -} - -func (self *_objectEnvironment) ImplicitThisValue() *_object { - if self.ProvideThis { - return self.Object - } - return nil -} - -func (self *_objectEnvironment) Outer() _environment { - return self.outer -} - -func (self *_objectEnvironment) newReference(name string, strict bool) _reference { - return newPropertyReference(self.Object, name, strict) -} - -// _declarativeEnvironment - -func (runtime *_runtime) newDeclarativeEnvironment(outer _environment) *_declarativeEnvironment { - return &_declarativeEnvironment{ - runtime: runtime, - outer: outer, - property: map[string]_declarativeProperty{}, - } -} - -func (self0 *_declarativeEnvironment) clone(clone *_clone) _environment { - self1, exists := clone.declarativeEnvironment(self0) - if exists { - return self1 - } - property := make(map[string]_declarativeProperty, len(self0.property)) - for index, value := range self0.property { - property[index] = clone.declarativeProperty(value) - } - *self1 = _declarativeEnvironment{ - clone.runtime, - clone.environment(self0.outer), - property, - } - return self1 -} - -type _declarativeProperty struct { - value Value - mutable bool - deletable bool - readable bool -} - -type _declarativeEnvironment struct { - runtime *_runtime - outer _environment - property map[string]_declarativeProperty -} - -func (self *_declarativeEnvironment) HasBinding(name string) bool { - _, exists := self.property[name] - return exists -} - -func (self *_declarativeEnvironment) runtimeOf() *_runtime { - return self.runtime -} - -func (self *_declarativeEnvironment) CreateMutableBinding(name string, deletable bool) { - _, exists := self.property[name] - if exists { - panic(fmt.Errorf("CreateMutableBinding: %s: already exists", name)) - } - self.property[name] = _declarativeProperty{ - value: UndefinedValue(), - mutable: true, - deletable: deletable, - readable: false, - } -} - -func (self *_declarativeEnvironment) SetMutableBinding(name string, value Value, strict bool) { - property, exists := self.property[name] - if !exists { - panic(fmt.Errorf("SetMutableBinding: %s: missing", name)) - } - if property.mutable { - property.value = value - self.property[name] = property - } else { - typeErrorResult(strict) - } -} - -func (self *_declarativeEnvironment) SetValue(name string, value Value, throw bool) { - if !self.HasBinding(name) { - self.CreateMutableBinding(name, false) // NOT deletable by default - } - self.SetMutableBinding(name, value, throw) -} - -func (self *_declarativeEnvironment) GetBindingValue(name string, strict bool) Value { - property, exists := self.property[name] - if !exists { - panic(fmt.Errorf("GetBindingValue: %s: missing", name)) - } - if !property.mutable && !property.readable { - if strict { - panic(newTypeError()) - } - return UndefinedValue() - } - return property.value -} - -func (self *_declarativeEnvironment) GetValue(name string, throw bool) Value { - return self.GetBindingValue(name, throw) -} - -func (self *_declarativeEnvironment) DeleteBinding(name string) bool { - property, exists := self.property[name] - if !exists { - return true - } - if !property.deletable { - return false - } - delete(self.property, name) - return true -} - -func (self *_declarativeEnvironment) ImplicitThisValue() *_object { - return nil -} - -func (self *_declarativeEnvironment) Outer() _environment { - return self.outer -} - -func (self *_declarativeEnvironment) newReference(name string, strict bool) _reference { - return newEnvironmentReference(self, name, strict, nil) -} diff --git a/Godeps/_workspace/src/github.com/obscuren/otto/error.go b/Godeps/_workspace/src/github.com/obscuren/otto/error.go deleted file mode 100644 index 887b954bd..000000000 --- a/Godeps/_workspace/src/github.com/obscuren/otto/error.go +++ /dev/null @@ -1,152 +0,0 @@ -package otto - -import ( - "errors" - "fmt" - - "github.com/robertkrimen/otto/ast" -) - -type _exception struct { - value interface{} -} - -func newException(value interface{}) *_exception { - return &_exception{ - value: value, - } -} - -func (self *_exception) eject() interface{} { - value := self.value - self.value = nil // Prevent Go from holding on to the value, whatever it is - return value -} - -type _error struct { - Name string - Message string - - Line int // Hackish -- line where the error/exception occurred -} - -var messageDetail map[string]string = map[string]string{ - "notDefined": "%v is not defined", -} - -func messageFromDescription(description string, argumentList ...interface{}) string { - message := messageDetail[description] - if message == "" { - message = description - } - message = fmt.Sprintf(message, argumentList...) - return message -} - -func (self _error) MessageValue() Value { - if self.Message == "" { - return UndefinedValue() - } - return toValue_string(self.Message) -} - -func (self _error) String() string { - if len(self.Name) == 0 { - return self.Message - } - if len(self.Message) == 0 { - return self.Name - } - return fmt.Sprintf("%s: %s", self.Name, self.Message) -} - -func newError(name string, argumentList ...interface{}) _error { - description := "" - var node ast.Node = nil - length := len(argumentList) - if length > 0 { - if node, _ = argumentList[length-1].(ast.Node); node != nil || argumentList[length-1] == nil { - argumentList = argumentList[0 : length-1] - length -= 1 - } - if length > 0 { - description, argumentList = argumentList[0].(string), argumentList[1:] - } - } - return _error{ - Name: name, - Message: messageFromDescription(description, argumentList...), - Line: -1, - } - //error := _error{ - // Name: name, - // Message: messageFromDescription(description, argumentList...), - // Line: -1, - //} - //if node != nil { - // error.Line = ast.position() - //} - //return error -} - -func newReferenceError(argumentList ...interface{}) _error { - return newError("ReferenceError", argumentList...) -} - -func newTypeError(argumentList ...interface{}) _error { - return newError("TypeError", argumentList...) -} - -func newRangeError(argumentList ...interface{}) _error { - return newError("RangeError", argumentList...) -} - -func newSyntaxError(argumentList ...interface{}) _error { - return newError("SyntaxError", argumentList...) -} - -func newURIError(argumentList ...interface{}) _error { - return newError("URIError", argumentList...) -} - -func typeErrorResult(throw bool) bool { - if throw { - panic(newTypeError()) - } - return false -} - -func catchPanic(function func()) (err error) { - // FIXME - defer func() { - if caught := recover(); caught != nil { - if exception, ok := caught.(*_exception); ok { - caught = exception.eject() - } - switch caught := caught.(type) { - //case *_syntaxError: - // err = errors.New(fmt.Sprintf("%s (line %d)", caught.String(), caught.Line+0)) - // return - case _error: - if caught.Line == -1 { - err = errors.New(caught.String()) - } else { - // We're 0-based (for now), hence the + 1 - err = errors.New(fmt.Sprintf("%s (line %d)", caught.String(), caught.Line+1)) - } - return - case Value: - err = errors.New(toString(caught)) - return - //case string: - // if strings.HasPrefix(caught, "SyntaxError:") { - // err = errors.New(caught) - // return - // } - } - panic(caught) - } - }() - function() - return nil -} diff --git a/Godeps/_workspace/src/github.com/obscuren/otto/error_test.go b/Godeps/_workspace/src/github.com/obscuren/otto/error_test.go deleted file mode 100644 index d0580c618..000000000 --- a/Godeps/_workspace/src/github.com/obscuren/otto/error_test.go +++ /dev/null @@ -1,62 +0,0 @@ -package otto - -import ( - "testing" -) - -func TestError(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(` - [ Error.prototype.name, Error.prototype.message, Error.prototype.hasOwnProperty("message") ]; - `, "Error,,true") - }) -} - -func TestError_instanceof(t *testing.T) { - tt(t, func() { - test, _ := test() - - test(`(new TypeError()) instanceof Error`, true) - }) -} - -func TestPanicValue(t *testing.T) { - tt(t, func() { - test, vm := test() - - vm.Set("abc", func(call FunctionCall) Value { - value, err := call.Otto.Run(`({ def: 3.14159 })`) - is(err, nil) - panic(value) - }) - - test(` - try { - abc(); - } - catch (err) { - error = err; - } - [ error instanceof Error, error.message, error.def ]; - `, "false,,3.14159") - }) -} - -func Test_catchPanic(t *testing.T) { - tt(t, func() { - vm := New() - - _, err := vm.Run(` - A syntax error that - does not define - var; - abc; - `) - is(err, "!=", nil) - - _, err = vm.Call(`abc.def`, nil) - is(err, "!=", nil) - }) -} diff --git a/Godeps/_workspace/src/github.com/obscuren/otto/execution_context.go b/Godeps/_workspace/src/github.com/obscuren/otto/execution_context.go deleted file mode 100644 index 07d891022..000000000 --- a/Godeps/_workspace/src/github.com/obscuren/otto/execution_context.go +++ /dev/null @@ -1,40 +0,0 @@ -package otto - -type _executionContext struct { - LexicalEnvironment _environment - VariableEnvironment _environment - this *_object - eval bool // Replace this with kind? -} - -func newExecutionContext(lexical _environment, variable _environment, this *_object) *_executionContext { - return &_executionContext{ - LexicalEnvironment: lexical, - VariableEnvironment: variable, - this: this, - } -} - -func (self *_executionContext) getValue(name string) Value { - strict := false - return self.LexicalEnvironment.GetValue(name, strict) -} - -func (self *_executionContext) setValue(name string, value Value, throw bool) { - self.LexicalEnvironment.SetValue(name, value, throw) -} - -func (self *_executionContext) newLexicalEnvironment(object *_object) (_environment, *_objectEnvironment) { - // Get runtime from the object (for now) - runtime := object.runtime - previousLexical := self.LexicalEnvironment - newLexical := runtime.newObjectEnvironment(object, self.LexicalEnvironment) - self.LexicalEnvironment = newLexical - return previousLexical, newLexical -} - -func (self *_executionContext) newDeclarativeEnvironment(runtime *_runtime) _environment { - previousLexical := self.LexicalEnvironment - self.LexicalEnvironment = runtime.newDeclarativeEnvironment(self.LexicalEnvironment) - return previousLexical -} diff --git a/Godeps/_workspace/src/github.com/obscuren/otto/file/README.markdown b/Godeps/_workspace/src/github.com/obscuren/otto/file/README.markdown deleted file mode 100644 index 72bbdb1fd..000000000 --- a/Godeps/_workspace/src/github.com/obscuren/otto/file/README.markdown +++ /dev/null @@ -1,72 +0,0 @@ -# file --- - import "github.com/robertkrimen/otto/file" - -Package file encapsulates the file abstractions used by the ast & parser. - -## Usage - -#### type FileSet - -```go -type FileSet struct { -} -``` - -A FileSet represents a set of source files. - -#### func (*FileSet) AddFile - -```go -func (self *FileSet) AddFile(filename, src string) int -``` -AddFile adds a new file with the given filename and src. - -This an internal method, but exported for cross-package use. - -#### func (*FileSet) Position - -```go -func (self *FileSet) Position(idx Idx) *Position -``` -Position converts an Idx in the FileSet into a Position. - -#### type Idx - -```go -type Idx int -``` - -Idx is a compact encoding of a source position within a file set. It can be -converted into a Position for a more convenient, but much larger, -representation. - -#### type Position - -```go -type Position struct { - Filename string // The filename where the error occurred, if any - Offset int // The src offset - Line int // The line number, starting at 1 - Column int // The column number, starting at 1 (The character count) - -} -``` - -Position describes an arbitrary source position including the filename, line, -and column location. - -#### func (*Position) String - -```go -func (self *Position) String() string -``` -String returns a string in one of several forms: - - file:line:column A valid position with filename - line:column A valid position without filename - file An invalid position with filename - - An invalid position without filename - --- -**godocdown** http://github.com/robertkrimen/godocdown diff --git a/Godeps/_workspace/src/github.com/obscuren/otto/file/file.go b/Godeps/_workspace/src/github.com/obscuren/otto/file/file.go deleted file mode 100644 index 5e893d819..000000000 --- a/Godeps/_workspace/src/github.com/obscuren/otto/file/file.go +++ /dev/null @@ -1,106 +0,0 @@ -// Package file encapsulates the file abstractions used by the ast & parser. -// -package file - -import ( - "fmt" - "strings" -) - -// Idx is a compact encoding of a source position within a file set. -// It can be converted into a Position for a more convenient, but much -// larger, representation. -type Idx int - -// Position describes an arbitrary source position -// including the filename, line, and column location. -type Position struct { - Filename string // The filename where the error occurred, if any - Offset int // The src offset - Line int // The line number, starting at 1 - Column int // The column number, starting at 1 (The character count) - -} - -// A Position is valid if the line number is > 0. - -func (self *Position) isValid() bool { - return self.Line > 0 -} - -// String returns a string in one of several forms: -// -// file:line:column A valid position with filename -// line:column A valid position without filename -// file An invalid position with filename -// - An invalid position without filename -// -func (self *Position) String() string { - str := self.Filename - if self.isValid() { - if str != "" { - str += ":" - } - str += fmt.Sprintf("%d:%d", self.Line, self.Column) - } - if str == "" { - str = "-" - } - return str -} - -// FileSet - -// A FileSet represents a set of source files. -type FileSet struct { - files []*_file - last *_file -} - -// AddFile adds a new file with the given filename and src. -// -// This an internal method, but exported for cross-package use. -func (self *FileSet) AddFile(filename, src string) int { - base := self.nextBase() - file := &_file{ - filename: filename, - src: src, - base: base, - } - self.files = append(self.files, file) - self.last = file - return base -} - -func (self *FileSet) nextBase() int { - if self.last == nil { - return 1 - } - return self.last.base + len(self.last.src) + 1 -} - -// Position converts an Idx in the FileSet into a Position. -func (self *FileSet) Position(idx Idx) *Position { - position := &Position{} - for _, file := range self.files { - if idx <= Idx(file.base+len(file.src)) { - offset := int(idx) - file.base - src := file.src[:offset] - position.Filename = file.filename - position.Offset = offset - position.Line = 1 + strings.Count(src, "\n") - if index := strings.LastIndex(src, "\n"); index >= 0 { - position.Column = offset - index - } else { - position.Column = 1 + len(src) - } - } - } - return position -} - -type _file struct { - filename string - src string - base int // This will always be 1 or greater -} diff --git a/Godeps/_workspace/src/github.com/obscuren/otto/parser/Makefile b/Godeps/_workspace/src/github.com/obscuren/otto/parser/Makefile deleted file mode 100644 index 766fd4d0b..000000000 --- a/Godeps/_workspace/src/github.com/obscuren/otto/parser/Makefile +++ /dev/null @@ -1,4 +0,0 @@ -.PHONY: test - -test: - go test diff --git a/Godeps/_workspace/src/github.com/obscuren/otto/parser/README.markdown b/Godeps/_workspace/src/github.com/obscuren/otto/parser/README.markdown deleted file mode 100644 index c3cae5b60..000000000 --- a/Godeps/_workspace/src/github.com/obscuren/otto/parser/README.markdown +++ /dev/null @@ -1,190 +0,0 @@ -# parser --- - import "github.com/robertkrimen/otto/parser" - -Package parser implements a parser for JavaScript. - - import ( - "github.com/robertkrimen/otto/parser" - ) - -Parse and return an AST - - filename := "" // A filename is optional - src := ` - // Sample xyzzy example - (function(){ - if (3.14159 > 0) { - console.log("Hello, World."); - return; - } - - var xyzzy = NaN; - console.log("Nothing happens."); - return xyzzy; - })(); - ` - - // Parse some JavaScript, yielding a *ast.Program and/or an ErrorList - program, err := parser.ParseFile(nil, filename, src, 0) - - -### Warning - -The parser and AST interfaces are still works-in-progress (particularly where -node types are concerned) and may change in the future. - -## Usage - -#### func ParseFile - -```go -func ParseFile(fileSet *file.FileSet, filename string, src interface{}, mode Mode) (*ast.Program, error) -``` -ParseFile parses the source code of a single JavaScript/ECMAScript source file -and returns the corresponding ast.Program node. - -If fileSet == nil, ParseFile parses source without a FileSet. If fileSet != nil, -ParseFile first adds filename and src to fileSet. - -The filename argument is optional and is used for labelling errors, etc. - -src may be a string, a byte slice, a bytes.Buffer, or an io.Reader, but it MUST -always be in UTF-8. - - // Parse some JavaScript, yielding a *ast.Program and/or an ErrorList - program, err := parser.ParseFile(nil, "", `if (abc > 1) {}`, 0) - -#### func ParseFunction - -```go -func ParseFunction(parameterList, body string) (*ast.FunctionLiteral, error) -``` -ParseFunction parses a given parameter list and body as a function and returns -the corresponding ast.FunctionLiteral node. - -The parameter list, if any, should be a comma-separated list of identifiers. - -#### func ReadSource - -```go -func ReadSource(filename string, src interface{}) ([]byte, error) -``` - -#### func TransformRegExp - -```go -func TransformRegExp(pattern string) (string, error) -``` -TransformRegExp transforms a JavaScript pattern into a Go "regexp" pattern. - -re2 (Go) cannot do backtracking, so the presence of a lookahead (?=) (?!) or -backreference (\1, \2, ...) will cause an error. - -re2 (Go) has a different definition for \s: [\t\n\f\r ]. The JavaScript -definition, on the other hand, also includes \v, Unicode "Separator, Space", -etc. - -If the pattern is invalid (not valid even in JavaScript), then this function -returns the empty string and an error. - -If the pattern is valid, but incompatible (contains a lookahead or -backreference), then this function returns the transformation (a non-empty -string) AND an error. - -#### type Error - -```go -type Error struct { - Position file.Position - Message string -} -``` - -An Error represents a parsing error. It includes the position where the error -occurred and a message/description. - -#### func (Error) Error - -```go -func (self Error) Error() string -``` - -#### type ErrorList - -```go -type ErrorList []*Error -``` - -ErrorList is a list of *Errors. - -#### func (*ErrorList) Add - -```go -func (self *ErrorList) Add(position file.Position, msg string) -``` -Add adds an Error with given position and message to an ErrorList. - -#### func (ErrorList) Err - -```go -func (self ErrorList) Err() error -``` -Err returns an error equivalent to this ErrorList. If the list is empty, Err -returns nil. - -#### func (ErrorList) Error - -```go -func (self ErrorList) Error() string -``` -Error implements the Error interface. - -#### func (ErrorList) Len - -```go -func (self ErrorList) Len() int -``` - -#### func (ErrorList) Less - -```go -func (self ErrorList) Less(i, j int) bool -``` - -#### func (*ErrorList) Reset - -```go -func (self *ErrorList) Reset() -``` -Reset resets an ErrorList to no errors. - -#### func (ErrorList) Sort - -```go -func (self ErrorList) Sort() -``` - -#### func (ErrorList) Swap - -```go -func (self ErrorList) Swap(i, j int) -``` - -#### type Mode - -```go -type Mode uint -``` - -A Mode value is a set of flags (or 0). They control optional parser -functionality. - -```go -const ( - IgnoreRegExpErrors Mode = 1 << iota // Ignore RegExp compatibility errors (allow backtracking) -) -``` - --- -**godocdown** http://github.com/robertkrimen/godocdown diff --git a/Godeps/_workspace/src/github.com/obscuren/otto/parser/dbg.go b/Godeps/_workspace/src/github.com/obscuren/otto/parser/dbg.go deleted file mode 100644 index 3c5f2f698..000000000 --- a/Godeps/_workspace/src/github.com/obscuren/otto/parser/dbg.go +++ /dev/null @@ -1,9 +0,0 @@ -// This file was AUTOMATICALLY GENERATED by dbg-import (smuggol) for github.com/robertkrimen/dbg - -package parser - -import ( - Dbg "github.com/robertkrimen/otto/dbg" -) - -var dbg, dbgf = Dbg.New() diff --git a/Godeps/_workspace/src/github.com/obscuren/otto/parser/error.go b/Godeps/_workspace/src/github.com/obscuren/otto/parser/error.go deleted file mode 100644 index 39ea75132..000000000 --- a/Godeps/_workspace/src/github.com/obscuren/otto/parser/error.go +++ /dev/null @@ -1,175 +0,0 @@ -package parser - -import ( - "fmt" - "sort" - - "github.com/robertkrimen/otto/file" - "github.com/robertkrimen/otto/token" -) - -const ( - err_UnexpectedToken = "Unexpected token %v" - err_UnexpectedEndOfInput = "Unexpected end of input" - err_UnexpectedEscape = "Unexpected escape" -) - -// UnexpectedNumber: 'Unexpected number', -// UnexpectedString: 'Unexpected string', -// UnexpectedIdentifier: 'Unexpected identifier', -// UnexpectedReserved: 'Unexpected reserved word', -// NewlineAfterThrow: 'Illegal newline after throw', -// InvalidRegExp: 'Invalid regular expression', -// UnterminatedRegExp: 'Invalid regular expression: missing /', -// InvalidLHSInAssignment: 'Invalid left-hand side in assignment', -// InvalidLHSInForIn: 'Invalid left-hand side in for-in', -// MultipleDefaultsInSwitch: 'More than one default clause in switch statement', -// NoCatchOrFinally: 'Missing catch or finally after try', -// UnknownLabel: 'Undefined label \'%0\'', -// Redeclaration: '%0 \'%1\' has already been declared', -// IllegalContinue: 'Illegal continue statement', -// IllegalBreak: 'Illegal break statement', -// IllegalReturn: 'Illegal return statement', -// StrictModeWith: 'Strict mode code may not include a with statement', -// StrictCatchVariable: 'Catch variable may not be eval or arguments in strict mode', -// StrictVarName: 'Variable name may not be eval or arguments in strict mode', -// StrictParamName: 'Parameter name eval or arguments is not allowed in strict mode', -// StrictParamDupe: 'Strict mode function may not have duplicate parameter names', -// StrictFunctionName: 'Function name may not be eval or arguments in strict mode', -// StrictOctalLiteral: 'Octal literals are not allowed in strict mode.', -// StrictDelete: 'Delete of an unqualified identifier in strict mode.', -// StrictDuplicateProperty: 'Duplicate data property in object literal not allowed in strict mode', -// AccessorDataProperty: 'Object literal may not have data and accessor property with the same name', -// AccessorGetSet: 'Object literal may not have multiple get/set accessors with the same name', -// StrictLHSAssignment: 'Assignment to eval or arguments is not allowed in strict mode', -// StrictLHSPostfix: 'Postfix increment/decrement may not have eval or arguments operand in strict mode', -// StrictLHSPrefix: 'Prefix increment/decrement may not have eval or arguments operand in strict mode', -// StrictReservedWord: 'Use of future reserved word in strict mode' - -// A SyntaxError is a description of an ECMAScript syntax error. - -// An Error represents a parsing error. It includes the position where the error occurred and a message/description. -type Error struct { - Position file.Position - Message string -} - -// FXIME Should this be "SyntaxError"? - -func (self Error) Error() string { - filename := self.Position.Filename - if filename == "" { - filename = "(anonymous)" - } - return fmt.Sprintf("%s: Line %d:%d %s", - filename, - self.Position.Line, - self.Position.Column, - self.Message, - ) -} - -func (self *_parser) error(place interface{}, msg string, msgValues ...interface{}) *Error { - idx := file.Idx(0) - switch place := place.(type) { - case int: - idx = self.idxOf(place) - case file.Idx: - if place == 0 { - idx = self.idxOf(self.chrOffset) - } else { - idx = place - } - default: - panic(fmt.Errorf("error(%T, ...)", place)) - } - - position := self.position(idx) - msg = fmt.Sprintf(msg, msgValues...) - self.errors.Add(position, msg) - return self.errors[len(self.errors)-1] -} - -func (self *_parser) errorUnexpected(idx file.Idx, chr rune) error { - if chr == -1 { - return self.error(idx, err_UnexpectedEndOfInput) - } - return self.error(idx, err_UnexpectedToken, token.ILLEGAL) -} - -func (self *_parser) errorUnexpectedToken(tkn token.Token) error { - switch tkn { - case token.EOF: - return self.error(file.Idx(0), err_UnexpectedEndOfInput) - } - value := tkn.String() - switch tkn { - case token.BOOLEAN, token.NULL: - value = self.literal - case token.IDENTIFIER: - return self.error(self.idx, "Unexpected identifier") - case token.KEYWORD: - // TODO Might be a future reserved word - return self.error(self.idx, "Unexpected reserved word") - case token.NUMBER: - return self.error(self.idx, "Unexpected number") - case token.STRING: - return self.error(self.idx, "Unexpected string") - } - return self.error(self.idx, err_UnexpectedToken, value) -} - -// ErrorList is a list of *Errors. -// -type ErrorList []*Error - -// Add adds an Error with given position and message to an ErrorList. -func (self *ErrorList) Add(position file.Position, msg string) { - *self = append(*self, &Error{position, msg}) -} - -// Reset resets an ErrorList to no errors. -func (self *ErrorList) Reset() { *self = (*self)[0:0] } - -func (self ErrorList) Len() int { return len(self) } -func (self ErrorList) Swap(i, j int) { self[i], self[j] = self[j], self[i] } -func (self ErrorList) Less(i, j int) bool { - x := &self[i].Position - y := &self[j].Position - if x.Filename < y.Filename { - return true - } - if x.Filename == y.Filename { - if x.Line < y.Line { - return true - } - if x.Line == y.Line { - return x.Column < y.Column - } - } - return false -} - -func (self ErrorList) Sort() { - sort.Sort(self) -} - -// Error implements the Error interface. -func (self ErrorList) Error() string { - switch len(self) { - case 0: - return "no errors" - case 1: - return self[0].Error() - } - return fmt.Sprintf("%s (and %d more errors)", self[0].Error(), len(self)-1) -} - -// Err returns an error equivalent to this ErrorList. -// If the list is empty, Err returns nil. -func (self ErrorList) Err() error { - if len(self) == 0 { - return nil - } - return self -} diff --git a/Godeps/_workspace/src/github.com/obscuren/otto/parser/expression.go b/Godeps/_workspace/src/github.com/obscuren/otto/parser/expression.go deleted file mode 100644 index dc397b5cb..000000000 --- a/Godeps/_workspace/src/github.com/obscuren/otto/parser/expression.go +++ /dev/null @@ -1,815 +0,0 @@ -package parser - -import ( - "regexp" - - "github.com/robertkrimen/otto/ast" - "github.com/robertkrimen/otto/file" - "github.com/robertkrimen/otto/token" -) - -func (self *_parser) parseIdentifier() *ast.Identifier { - literal := self.literal - idx := self.idx - self.next() - return &ast.Identifier{ - Name: literal, - Idx: idx, - } -} - -func (self *_parser) parsePrimaryExpression() ast.Expression { - literal := self.literal - idx := self.idx - switch self.token { - case token.IDENTIFIER: - self.next() - if len(literal) > 1 { - tkn, strict := token.IsKeyword(literal) - if tkn == token.KEYWORD { - if !strict { - self.error(idx, "Unexpected reserved word") - } - } - } - return &ast.Identifier{ - Name: literal, - Idx: idx, - } - case token.NULL: - self.next() - return &ast.NullLiteral{ - Idx: idx, - Literal: literal, - } - case token.BOOLEAN: - self.next() - value := false - switch literal { - case "true": - value = true - case "false": - value = false - default: - self.error(idx, "Illegal boolean literal") - } - return &ast.BooleanLiteral{ - Idx: idx, - Literal: literal, - Value: value, - } - case token.STRING: - self.next() - value, err := parseStringLiteral(literal[1 : len(literal)-1]) - if err != nil { - self.error(idx, err.Error()) - } - return &ast.StringLiteral{ - Idx: idx, - Literal: literal, - Value: value, - } - case token.NUMBER: - self.next() - value, err := parseNumberLiteral(literal) - if err != nil { - self.error(idx, err.Error()) - value = 0 - } - return &ast.NumberLiteral{ - Idx: idx, - Literal: literal, - Value: value, - } - case token.SLASH, token.QUOTIENT_ASSIGN: - return self.parseRegExpLiteral() - case token.LEFT_BRACE: - return self.parseObjectLiteral() - case token.LEFT_BRACKET: - return self.parseArrayLiteral() - case token.LEFT_PARENTHESIS: - self.expect(token.LEFT_PARENTHESIS) - expression := self.parseExpression() - self.expect(token.RIGHT_PARENTHESIS) - return expression - case token.THIS: - self.next() - return &ast.ThisExpression{ - Idx: idx, - } - case token.FUNCTION: - return self.parseFunction(false) - } - - self.errorUnexpectedToken(self.token) - self.nextStatement() - return &ast.BadExpression{From: idx, To: self.idx} -} - -func (self *_parser) parseRegExpLiteral() *ast.RegExpLiteral { - - offset := self.chrOffset - 1 // Opening slash already gotten - if self.token == token.QUOTIENT_ASSIGN { - offset -= 1 // = - } - idx := self.idxOf(offset) - - pattern, err := self.scanString(offset) - endOffset := self.chrOffset - - self.next() - if err == nil { - pattern = pattern[1 : len(pattern)-1] - } - - flags := "" - if self.token == token.IDENTIFIER { // gim - - flags = self.literal - self.next() - endOffset = self.chrOffset - 1 - } - - var value string - // TODO 15.10 - { - // Test during parsing that this is a valid regular expression - // Sorry, (?=) and (?!) are invalid (for now) - pattern, err := TransformRegExp(pattern) - if err != nil { - if pattern == "" || self.mode&IgnoreRegExpErrors == 0 { - self.error(idx, "Invalid regular expression: %s", err.Error()) - } - } else { - _, err = regexp.Compile(pattern) - if err != nil { - // We should not get here, ParseRegExp should catch any errors - self.error(idx, "Invalid regular expression: %s", err.Error()[22:]) // Skip redundant "parse regexp error" - } else { - value = pattern - } - } - } - - literal := self.str[offset:endOffset] - - return &ast.RegExpLiteral{ - Idx: idx, - Literal: literal, - Pattern: pattern, - Flags: flags, - Value: value, - } -} - -func (self *_parser) parseVariableDeclaration(declarationList *[]*ast.VariableExpression) ast.Expression { - - if self.token != token.IDENTIFIER { - idx := self.expect(token.IDENTIFIER) - self.nextStatement() - return &ast.BadExpression{From: idx, To: self.idx} - } - - literal := self.literal - idx := self.idx - self.next() - node := &ast.VariableExpression{ - Name: literal, - Idx: idx, - } - - if declarationList != nil { - *declarationList = append(*declarationList, node) - } - - if self.token == token.ASSIGN { - self.next() - node.Initializer = self.parseAssignmentExpression() - } - - return node -} - -func (self *_parser) parseVariableDeclarationList(var_ file.Idx) []ast.Expression { - - var declarationList []*ast.VariableExpression // Avoid bad expressions - var list []ast.Expression - - for { - list = append(list, self.parseVariableDeclaration(&declarationList)) - if self.token != token.COMMA { - break - } - self.next() - } - - self.scope.declare(&ast.VariableDeclaration{ - Var: var_, - List: declarationList, - }) - - return list -} - -func (self *_parser) parseObjectPropertyKey() (string, string) { - idx, tkn, literal := self.idx, self.token, self.literal - value := "" - self.next() - switch tkn { - case token.IDENTIFIER: - value = literal - case token.NUMBER: - var err error - _, err = parseNumberLiteral(literal) - if err != nil { - self.error(idx, err.Error()) - } else { - value = literal - } - case token.STRING: - var err error - value, err = parseStringLiteral(literal[1 : len(literal)-1]) - if err != nil { - self.error(idx, err.Error()) - } - default: - // null, false, class, etc. - if matchIdentifier.MatchString(literal) { - value = literal - } - } - return literal, value -} - -func (self *_parser) parseObjectProperty() ast.Property { - - literal, value := self.parseObjectPropertyKey() - if literal == "get" && self.token != token.COLON { - idx := self.idx - _, value := self.parseObjectPropertyKey() - parameterList := self.parseFunctionParameterList() - - node := &ast.FunctionLiteral{ - Function: idx, - ParameterList: parameterList, - } - self.parseFunctionBlock(node) - return ast.Property{ - Key: value, - Kind: "get", - Value: node, - } - } else if literal == "set" && self.token != token.COLON { - idx := self.idx - _, value := self.parseObjectPropertyKey() - parameterList := self.parseFunctionParameterList() - - node := &ast.FunctionLiteral{ - Function: idx, - ParameterList: parameterList, - } - self.parseFunctionBlock(node) - return ast.Property{ - Key: value, - Kind: "set", - Value: node, - } - } - - self.expect(token.COLON) - - return ast.Property{ - Key: value, - Kind: "value", - Value: self.parseAssignmentExpression(), - } -} - -func (self *_parser) parseObjectLiteral() ast.Expression { - var value []ast.Property - idx0 := self.expect(token.LEFT_BRACE) - for self.token != token.RIGHT_BRACE && self.token != token.EOF { - property := self.parseObjectProperty() - value = append(value, property) - if self.token == token.COMMA { - self.next() - continue - } - } - idx1 := self.expect(token.RIGHT_BRACE) - - return &ast.ObjectLiteral{ - LeftBrace: idx0, - RightBrace: idx1, - Value: value, - } -} - -func (self *_parser) parseArrayLiteral() ast.Expression { - - idx0 := self.expect(token.LEFT_BRACKET) - var value []ast.Expression - for self.token != token.RIGHT_BRACKET && self.token != token.EOF { - if self.token == token.COMMA { - self.next() - value = append(value, nil) - continue - } - value = append(value, self.parseAssignmentExpression()) - if self.token != token.RIGHT_BRACKET { - self.expect(token.COMMA) - } - } - idx1 := self.expect(token.RIGHT_BRACKET) - - return &ast.ArrayLiteral{ - LeftBracket: idx0, - RightBracket: idx1, - Value: value, - } -} - -func (self *_parser) parseArgumentList() (argumentList []ast.Expression, idx0, idx1 file.Idx) { - idx0 = self.expect(token.LEFT_PARENTHESIS) - if self.token != token.RIGHT_PARENTHESIS { - for { - argumentList = append(argumentList, self.parseAssignmentExpression()) - if self.token != token.COMMA { - break - } - self.next() - } - } - idx1 = self.expect(token.RIGHT_PARENTHESIS) - return -} - -func (self *_parser) parseCallExpression(left ast.Expression) ast.Expression { - argumentList, idx0, idx1 := self.parseArgumentList() - return &ast.CallExpression{ - Callee: left, - LeftParenthesis: idx0, - ArgumentList: argumentList, - RightParenthesis: idx1, - } -} - -func (self *_parser) parseDotMember(left ast.Expression) ast.Expression { - period := self.expect(token.PERIOD) - - literal := self.literal - idx := self.idx - - if !matchIdentifier.MatchString(literal) { - self.expect(token.IDENTIFIER) - self.nextStatement() - return &ast.BadExpression{From: period, To: self.idx} - } - - self.next() - - return &ast.DotExpression{ - Left: left, - Identifier: ast.Identifier{ - Idx: idx, - Name: literal, - }, - } -} - -func (self *_parser) parseBracketMember(left ast.Expression) ast.Expression { - idx0 := self.expect(token.LEFT_BRACKET) - member := self.parseExpression() - idx1 := self.expect(token.RIGHT_BRACKET) - return &ast.BracketExpression{ - LeftBracket: idx0, - Left: left, - Member: member, - RightBracket: idx1, - } -} - -func (self *_parser) parseNewExpression() ast.Expression { - idx := self.expect(token.NEW) - callee := self.parseLeftHandSideExpression() - node := &ast.NewExpression{ - New: idx, - Callee: callee, - } - if self.token == token.LEFT_PARENTHESIS { - argumentList, idx0, idx1 := self.parseArgumentList() - node.ArgumentList = argumentList - node.LeftParenthesis = idx0 - node.RightParenthesis = idx1 - } - return node -} - -func (self *_parser) parseLeftHandSideExpression() ast.Expression { - - var left ast.Expression - if self.token == token.NEW { - left = self.parseNewExpression() - } else { - left = self.parsePrimaryExpression() - } - - for { - if self.token == token.PERIOD { - left = self.parseDotMember(left) - } else if self.token == token.LEFT_BRACE { - left = self.parseBracketMember(left) - } else { - break - } - } - - return left -} - -func (self *_parser) parseLeftHandSideExpressionAllowCall() ast.Expression { - - allowIn := self.scope.allowIn - self.scope.allowIn = true - defer func() { - self.scope.allowIn = allowIn - }() - - var left ast.Expression - if self.token == token.NEW { - left = self.parseNewExpression() - } else { - left = self.parsePrimaryExpression() - } - - for { - if self.token == token.PERIOD { - left = self.parseDotMember(left) - } else if self.token == token.LEFT_BRACKET { - left = self.parseBracketMember(left) - } else if self.token == token.LEFT_PARENTHESIS { - left = self.parseCallExpression(left) - } else { - break - } - } - - return left -} - -func (self *_parser) parsePostfixExpression() ast.Expression { - operand := self.parseLeftHandSideExpressionAllowCall() - - switch self.token { - case token.INCREMENT, token.DECREMENT: - // Make sure there is no line terminator here - if self.implicitSemicolon { - break - } - tkn := self.token - idx := self.idx - self.next() - switch operand.(type) { - case *ast.Identifier, *ast.DotExpression, *ast.BracketExpression: - default: - self.error(idx, "Invalid left-hand side in assignment") - self.nextStatement() - return &ast.BadExpression{From: idx, To: self.idx} - } - return &ast.UnaryExpression{ - Operator: tkn, - Idx: idx, - Operand: operand, - Postfix: true, - } - } - - return operand -} - -func (self *_parser) parseUnaryExpression() ast.Expression { - - switch self.token { - case token.PLUS, token.MINUS, token.NOT, token.BITWISE_NOT: - fallthrough - case token.DELETE, token.VOID, token.TYPEOF: - tkn := self.token - idx := self.idx - self.next() - return &ast.UnaryExpression{ - Operator: tkn, - Idx: idx, - Operand: self.parseUnaryExpression(), - } - case token.INCREMENT, token.DECREMENT: - tkn := self.token - idx := self.idx - self.next() - operand := self.parseUnaryExpression() - switch operand.(type) { - case *ast.Identifier, *ast.DotExpression, *ast.BracketExpression: - default: - self.error(idx, "Invalid left-hand side in assignment") - self.nextStatement() - return &ast.BadExpression{From: idx, To: self.idx} - } - return &ast.UnaryExpression{ - Operator: tkn, - Idx: idx, - Operand: operand, - } - } - - return self.parsePostfixExpression() -} - -func (self *_parser) parseMultiplicativeExpression() ast.Expression { - next := self.parseUnaryExpression - left := next() - - for self.token == token.MULTIPLY || self.token == token.SLASH || - self.token == token.REMAINDER { - tkn := self.token - self.next() - left = &ast.BinaryExpression{ - Operator: tkn, - Left: left, - Right: next(), - } - } - - return left -} - -func (self *_parser) parseAdditiveExpression() ast.Expression { - next := self.parseMultiplicativeExpression - left := next() - - for self.token == token.PLUS || self.token == token.MINUS { - tkn := self.token - self.next() - left = &ast.BinaryExpression{ - Operator: tkn, - Left: left, - Right: next(), - } - } - - return left -} - -func (self *_parser) parseShiftExpression() ast.Expression { - next := self.parseAdditiveExpression - left := next() - - for self.token == token.SHIFT_LEFT || self.token == token.SHIFT_RIGHT || - self.token == token.UNSIGNED_SHIFT_RIGHT { - tkn := self.token - self.next() - left = &ast.BinaryExpression{ - Operator: tkn, - Left: left, - Right: next(), - } - } - - return left -} - -func (self *_parser) parseRelationalExpression() ast.Expression { - next := self.parseShiftExpression - left := next() - - allowIn := self.scope.allowIn - self.scope.allowIn = true - defer func() { - self.scope.allowIn = allowIn - }() - - switch self.token { - case token.LESS, token.LESS_OR_EQUAL, token.GREATER, token.GREATER_OR_EQUAL: - tkn := self.token - self.next() - return &ast.BinaryExpression{ - Operator: tkn, - Left: left, - Right: self.parseRelationalExpression(), - Comparison: true, - } - case token.INSTANCEOF: - tkn := self.token - self.next() - return &ast.BinaryExpression{ - Operator: tkn, - Left: left, - Right: self.parseRelationalExpression(), - } - case token.IN: - if !allowIn { - return left - } - tkn := self.token - self.next() - return &ast.BinaryExpression{ - Operator: tkn, - Left: left, - Right: self.parseRelationalExpression(), - } - } - - return left -} - -func (self *_parser) parseEqualityExpression() ast.Expression { - next := self.parseRelationalExpression - left := next() - - for self.token == token.EQUAL || self.token == token.NOT_EQUAL || - self.token == token.STRICT_EQUAL || self.token == token.STRICT_NOT_EQUAL { - tkn := self.token - self.next() - left = &ast.BinaryExpression{ - Operator: tkn, - Left: left, - Right: next(), - Comparison: true, - } - } - - return left -} - -func (self *_parser) parseBitwiseAndExpression() ast.Expression { - next := self.parseEqualityExpression - left := next() - - for self.token == token.AND { - tkn := self.token - self.next() - left = &ast.BinaryExpression{ - Operator: tkn, - Left: left, - Right: next(), - } - } - - return left -} - -func (self *_parser) parseBitwiseExclusiveOrExpression() ast.Expression { - next := self.parseBitwiseAndExpression - left := next() - - for self.token == token.EXCLUSIVE_OR { - tkn := self.token - self.next() - left = &ast.BinaryExpression{ - Operator: tkn, - Left: left, - Right: next(), - } - } - - return left -} - -func (self *_parser) parseBitwiseOrExpression() ast.Expression { - next := self.parseBitwiseExclusiveOrExpression - left := next() - - for self.token == token.OR { - tkn := self.token - self.next() - left = &ast.BinaryExpression{ - Operator: tkn, - Left: left, - Right: next(), - } - } - - return left -} - -func (self *_parser) parseLogicalAndExpression() ast.Expression { - next := self.parseBitwiseOrExpression - left := next() - - for self.token == token.LOGICAL_AND { - tkn := self.token - self.next() - left = &ast.BinaryExpression{ - Operator: tkn, - Left: left, - Right: next(), - } - } - - return left -} - -func (self *_parser) parseLogicalOrExpression() ast.Expression { - next := self.parseLogicalAndExpression - left := next() - - for self.token == token.LOGICAL_OR { - tkn := self.token - self.next() - left = &ast.BinaryExpression{ - Operator: tkn, - Left: left, - Right: next(), - } - } - - return left -} - -func (self *_parser) parseConditionlExpression() ast.Expression { - left := self.parseLogicalOrExpression() - - if self.token == token.QUESTION_MARK { - self.next() - consequent := self.parseAssignmentExpression() - self.expect(token.COLON) - return &ast.ConditionalExpression{ - Test: left, - Consequent: consequent, - Alternate: self.parseAssignmentExpression(), - } - } - - return left -} - -func (self *_parser) parseAssignmentExpression() ast.Expression { - left := self.parseConditionlExpression() - var operator token.Token - switch self.token { - case token.ASSIGN: - operator = self.token - case token.ADD_ASSIGN: - operator = token.PLUS - case token.SUBTRACT_ASSIGN: - operator = token.MINUS - case token.MULTIPLY_ASSIGN: - operator = token.MULTIPLY - case token.QUOTIENT_ASSIGN: - operator = token.SLASH - case token.REMAINDER_ASSIGN: - operator = token.REMAINDER - case token.AND_ASSIGN: - operator = token.AND - case token.AND_NOT_ASSIGN: - operator = token.AND_NOT - case token.OR_ASSIGN: - operator = token.OR - case token.EXCLUSIVE_OR_ASSIGN: - operator = token.EXCLUSIVE_OR - case token.SHIFT_LEFT_ASSIGN: - operator = token.SHIFT_LEFT - case token.SHIFT_RIGHT_ASSIGN: - operator = token.SHIFT_RIGHT - case token.UNSIGNED_SHIFT_RIGHT_ASSIGN: - operator = token.UNSIGNED_SHIFT_RIGHT - } - - if operator != 0 { - idx := self.idx - self.next() - switch left.(type) { - case *ast.Identifier, *ast.DotExpression, *ast.BracketExpression: - default: - self.error(left.Idx0(), "Invalid left-hand side in assignment") - self.nextStatement() - return &ast.BadExpression{From: idx, To: self.idx} - } - return &ast.AssignExpression{ - Left: left, - Operator: operator, - Right: self.parseAssignmentExpression(), - } - } - - return left -} - -func (self *_parser) parseExpression() ast.Expression { - next := self.parseAssignmentExpression - left := next() - - if self.token == token.COMMA { - sequence := []ast.Expression{left} - for { - if self.token != token.COMMA { - break - } - self.next() - sequence = append(sequence, next()) - } - return &ast.SequenceExpression{ - Sequence: sequence, - } - } - - return left -} diff --git a/Godeps/_workspace/src/github.com/obscuren/otto/parser/lexer.go b/Godeps/_workspace/src/github.com/obscuren/otto/parser/lexer.go deleted file mode 100644 index bc3e74f77..000000000 --- a/Godeps/_workspace/src/github.com/obscuren/otto/parser/lexer.go +++ /dev/null @@ -1,819 +0,0 @@ -package parser - -import ( - "bytes" - "errors" - "fmt" - "regexp" - "strconv" - "strings" - "unicode" - "unicode/utf8" - - "github.com/robertkrimen/otto/file" - "github.com/robertkrimen/otto/token" -) - -type _chr struct { - value rune - width int -} - -var matchIdentifier = regexp.MustCompile(`^[$_\p{L}][$_\p{L}\d}]*$`) - -func isDecimalDigit(chr rune) bool { - return '0' <= chr && chr <= '9' -} - -func digitValue(chr rune) int { - switch { - case '0' <= chr && chr <= '9': - return int(chr - '0') - case 'a' <= chr && chr <= 'f': - return int(chr - 'a' + 10) - case 'A' <= chr && chr <= 'F': - return int(chr - 'A' + 10) - } - return 16 // Larger than any legal digit value -} - -func isDigit(chr rune, base int) bool { - return digitValue(chr) < base -} - -func isIdentifierStart(chr rune) bool { - return chr == '$' || chr == '_' || chr == '\\' || - 'a' <= chr && chr <= 'z' || 'A' <= chr && chr <= 'Z' || - chr >= utf8.RuneSelf && unicode.IsLetter(chr) -} - -func isIdentifierPart(chr rune) bool { - return chr == '$' || chr == '_' || chr == '\\' || - 'a' <= chr && chr <= 'z' || 'A' <= chr && chr <= 'Z' || - '0' <= chr && chr <= '9' || - chr >= utf8.RuneSelf && (unicode.IsLetter(chr) || unicode.IsDigit(chr)) -} - -func (self *_parser) scanIdentifier() (string, error) { - offset := self.chrOffset - parse := false - for isIdentifierPart(self.chr) { - if self.chr == '\\' { - distance := self.chrOffset - offset - self.read() - if self.chr != 'u' { - return "", fmt.Errorf("Invalid identifier escape character: %c (%s)", self.chr, string(self.chr)) - } - parse = true - var value rune - for j := 0; j < 4; j++ { - self.read() - decimal, ok := hex2decimal(byte(self.chr)) - if !ok { - return "", fmt.Errorf("Invalid identifier escape character: %c (%s)", self.chr, string(self.chr)) - } - value = value<<4 | decimal - } - if value == '\\' { - return "", fmt.Errorf("Invalid identifier escape value: %c (%s)", value, string(value)) - } else if distance == 0 { - if !isIdentifierStart(value) { - return "", fmt.Errorf("Invalid identifier escape value: %c (%s)", value, string(value)) - } - } else if distance > 0 { - if !isIdentifierPart(value) { - return "", fmt.Errorf("Invalid identifier escape value: %c (%s)", value, string(value)) - } - } - } - self.read() - } - literal := string(self.str[offset:self.chrOffset]) - if parse { - return parseStringLiteral(literal) - } - return literal, nil -} - -// 7.2 -func isLineWhiteSpace(chr rune) bool { - switch chr { - case '\u0009', '\u000b', '\u000c', '\u0020', '\u00a0', '\ufeff': - return true - case '\u000a', '\u000d', '\u2028', '\u2029': - return false - case '\u0085': - return false - } - return unicode.IsSpace(chr) -} - -// 7.3 -func isLineTerminator(chr rune) bool { - switch chr { - case '\u000a', '\u000d', '\u2028', '\u2029': - return true - } - return false -} - -func (self *_parser) scan() (tkn token.Token, literal string, idx file.Idx) { - - self.implicitSemicolon = false - - for { - self.skipWhiteSpace() - - idx = self.idxOf(self.chrOffset) - insertSemicolon := false - - switch chr := self.chr; { - case isIdentifierStart(chr): - var err error - literal, err = self.scanIdentifier() - if err != nil { - tkn = token.ILLEGAL - break - } - if len(literal) > 1 { - // Keywords are longer than 1 character, avoid lookup otherwise - var strict bool - tkn, strict = token.IsKeyword(literal) - - switch tkn { - - case 0: // Not a keyword - if literal == "true" || literal == "false" { - self.insertSemicolon = true - tkn = token.BOOLEAN - return - } else if literal == "null" { - self.insertSemicolon = true - tkn = token.NULL - return - } - - case token.KEYWORD: - tkn = token.KEYWORD - if strict { - // TODO If strict and in strict mode, then this is not a break - break - } - return - - case - token.THIS, - token.BREAK, - token.THROW, // A newline after a throw is not allowed, but we need to detect it - token.RETURN, - token.CONTINUE, - token.DEBUGGER: - self.insertSemicolon = true - return - - default: - return - - } - } - self.insertSemicolon = true - tkn = token.IDENTIFIER - return - case '0' <= chr && chr <= '9': - self.insertSemicolon = true - tkn, literal = self.scanNumericLiteral(false) - return - default: - self.read() - switch chr { - case -1: - if self.insertSemicolon { - self.insertSemicolon = false - self.implicitSemicolon = true - } - tkn = token.EOF - case '\r', '\n', '\u2028', '\u2029': - self.insertSemicolon = false - self.implicitSemicolon = true - continue - case ':': - tkn = token.COLON - case '.': - if digitValue(self.chr) < 10 { - insertSemicolon = true - tkn, literal = self.scanNumericLiteral(true) - } else { - tkn = token.PERIOD - } - case ',': - tkn = token.COMMA - case ';': - tkn = token.SEMICOLON - case '(': - tkn = token.LEFT_PARENTHESIS - case ')': - tkn = token.RIGHT_PARENTHESIS - insertSemicolon = true - case '[': - tkn = token.LEFT_BRACKET - case ']': - tkn = token.RIGHT_BRACKET - insertSemicolon = true - case '{': - tkn = token.LEFT_BRACE - case '}': - tkn = token.RIGHT_BRACE - insertSemicolon = true - case '+': - tkn = self.switch3(token.PLUS, token.ADD_ASSIGN, '+', token.INCREMENT) - if tkn == token.INCREMENT { - insertSemicolon = true - } - case '-': - tkn = self.switch3(token.MINUS, token.SUBTRACT_ASSIGN, '-', token.DECREMENT) - if tkn == token.DECREMENT { - insertSemicolon = true - } - case '*': - tkn = self.switch2(token.MULTIPLY, token.MULTIPLY_ASSIGN) - case '/': - if self.chr == '/' { - self.skipSingleLineComment() - continue - } else if self.chr == '*' { - self.skipMultiLineComment() - continue - } else { - // Could be division, could be RegExp literal - tkn = self.switch2(token.SLASH, token.QUOTIENT_ASSIGN) - insertSemicolon = true - } - case '%': - tkn = self.switch2(token.REMAINDER, token.REMAINDER_ASSIGN) - case '^': - tkn = self.switch2(token.EXCLUSIVE_OR, token.EXCLUSIVE_OR_ASSIGN) - case '<': - tkn = self.switch4(token.LESS, token.LESS_OR_EQUAL, '<', token.SHIFT_LEFT, token.SHIFT_LEFT_ASSIGN) - case '>': - tkn = self.switch6(token.GREATER, token.GREATER_OR_EQUAL, '>', token.SHIFT_RIGHT, token.SHIFT_RIGHT_ASSIGN, '>', token.UNSIGNED_SHIFT_RIGHT, token.UNSIGNED_SHIFT_RIGHT_ASSIGN) - case '=': - tkn = self.switch2(token.ASSIGN, token.EQUAL) - if tkn == token.EQUAL && self.chr == '=' { - self.read() - tkn = token.STRICT_EQUAL - } - case '!': - tkn = self.switch2(token.NOT, token.NOT_EQUAL) - if tkn == token.NOT_EQUAL && self.chr == '=' { - self.read() - tkn = token.STRICT_NOT_EQUAL - } - case '&': - if self.chr == '^' { - self.read() - tkn = self.switch2(token.AND_NOT, token.AND_NOT_ASSIGN) - } else { - tkn = self.switch3(token.AND, token.AND_ASSIGN, '&', token.LOGICAL_AND) - } - case '|': - tkn = self.switch3(token.OR, token.OR_ASSIGN, '|', token.LOGICAL_OR) - case '~': - tkn = token.BITWISE_NOT - case '?': - tkn = token.QUESTION_MARK - case '"', '\'': - insertSemicolon = true - tkn = token.STRING - var err error - literal, err = self.scanString(self.chrOffset - 1) - if err != nil { - tkn = token.ILLEGAL - } - default: - self.errorUnexpected(idx, chr) - tkn = token.ILLEGAL - } - } - self.insertSemicolon = insertSemicolon - return - } -} - -func (self *_parser) switch2(tkn0, tkn1 token.Token) token.Token { - if self.chr == '=' { - self.read() - return tkn1 - } - return tkn0 -} - -func (self *_parser) switch3(tkn0, tkn1 token.Token, chr2 rune, tkn2 token.Token) token.Token { - if self.chr == '=' { - self.read() - return tkn1 - } - if self.chr == chr2 { - self.read() - return tkn2 - } - return tkn0 -} - -func (self *_parser) switch4(tkn0, tkn1 token.Token, chr2 rune, tkn2, tkn3 token.Token) token.Token { - if self.chr == '=' { - self.read() - return tkn1 - } - if self.chr == chr2 { - self.read() - if self.chr == '=' { - self.read() - return tkn3 - } - return tkn2 - } - return tkn0 -} - -func (self *_parser) switch6(tkn0, tkn1 token.Token, chr2 rune, tkn2, tkn3 token.Token, chr3 rune, tkn4, tkn5 token.Token) token.Token { - if self.chr == '=' { - self.read() - return tkn1 - } - if self.chr == chr2 { - self.read() - if self.chr == '=' { - self.read() - return tkn3 - } - if self.chr == chr3 { - self.read() - if self.chr == '=' { - self.read() - return tkn5 - } - return tkn4 - } - return tkn2 - } - return tkn0 -} - -func (self *_parser) chrAt(index int) _chr { - value, width := utf8.DecodeRuneInString(self.str[index:]) - return _chr{ - value: value, - width: width, - } -} - -func (self *_parser) _peek() rune { - if self.offset+1 < self.length { - return rune(self.str[self.offset+1]) - } - return -1 -} - -func (self *_parser) read() { - if self.offset < self.length { - self.chrOffset = self.offset - chr, width := rune(self.str[self.offset]), 1 - if chr >= utf8.RuneSelf { // !ASCII - chr, width = utf8.DecodeRuneInString(self.str[self.offset:]) - if chr == utf8.RuneError && width == 1 { - self.error(self.chrOffset, "Invalid UTF-8 character") - } - } - self.offset += width - self.chr = chr - } else { - self.chrOffset = self.length - self.chr = -1 // EOF - } -} - -// This is here since the functions are so similar -func (self *_RegExp_parser) read() { - if self.offset < self.length { - self.chrOffset = self.offset - chr, width := rune(self.str[self.offset]), 1 - if chr >= utf8.RuneSelf { // !ASCII - chr, width = utf8.DecodeRuneInString(self.str[self.offset:]) - if chr == utf8.RuneError && width == 1 { - self.error(self.chrOffset, "Invalid UTF-8 character") - } - } - self.offset += width - self.chr = chr - } else { - self.chrOffset = self.length - self.chr = -1 // EOF - } -} - -func (self *_parser) skipSingleLineComment() { - for self.chr != -1 { - self.read() - if isLineTerminator(self.chr) { - return - } - } -} - -func (self *_parser) skipMultiLineComment() { - self.read() - for self.chr >= 0 { - chr := self.chr - self.read() - if chr == '*' && self.chr == '/' { - self.read() - return - } - } - - self.errorUnexpected(0, self.chr) -} - -func (self *_parser) skipWhiteSpace() { - for { - switch self.chr { - case ' ', '\t', '\f', '\v', '\u00a0', '\ufeff': - self.read() - continue - case '\r': - if self._peek() == '\n' { - self.read() - } - fallthrough - case '\u2028', '\u2029', '\n': - if self.insertSemicolon { - return - } - self.read() - continue - } - if self.chr >= utf8.RuneSelf { - if unicode.IsSpace(self.chr) { - self.read() - continue - } - } - break - } -} - -func (self *_parser) skipLineWhiteSpace() { - for isLineWhiteSpace(self.chr) { - self.read() - } -} - -func (self *_parser) scanMantissa(base int) { - for digitValue(self.chr) < base { - self.read() - } -} - -func (self *_parser) scanEscape(quote rune) { - - var length, base uint32 - switch self.chr { - //case '0', '1', '2', '3', '4', '5', '6', '7': - // Octal: - // length, base, limit = 3, 8, 255 - case 'a', 'b', 'f', 'n', 'r', 't', 'v', '\\', '"', '\'', '0': - self.read() - return - case '\r', '\n', '\u2028', '\u2029': - self.scanNewline() - return - case 'x': - self.read() - length, base = 2, 16 - case 'u': - self.read() - length, base = 4, 16 - default: - self.read() // Always make progress - return - } - - var value uint32 - for ; length > 0 && self.chr != quote && self.chr >= 0; length-- { - digit := uint32(digitValue(self.chr)) - if digit >= base { - break - } - value = value*base + digit - self.read() - } -} - -func (self *_parser) scanString(offset int) (string, error) { - // " ' / - quote := rune(self.str[offset]) - - for self.chr != quote { - chr := self.chr - if chr == '\n' || chr == '\r' || chr == '\u2028' || chr == '\u2029' || chr < 0 { - goto newline - } - self.read() - if chr == '\\' { - if quote == '/' { - if self.chr == '\n' || self.chr == '\r' || self.chr == '\u2028' || self.chr == '\u2029' || self.chr < 0 { - goto newline - } - self.read() - } else { - self.scanEscape(quote) - } - } else if chr == '[' && quote == '/' { - // Allow a slash (/) in a bracket character class ([...]) - // TODO Fix this, this is hacky... - quote = -1 - } else if chr == ']' && quote == -1 { - quote = '/' - } - } - - // " ' / - self.read() - - return string(self.str[offset:self.chrOffset]), nil - -newline: - self.scanNewline() - err := "String not terminated" - if quote == '/' { - err = "Invalid regular expression: missing /" - self.error(self.idxOf(offset), err) - } - return "", errors.New(err) -} - -func (self *_parser) scanNewline() { - if self.chr == '\r' { - self.read() - if self.chr != '\n' { - return - } - } - self.read() -} - -func hex2decimal(chr byte) (value rune, ok bool) { - { - chr := rune(chr) - switch { - case '0' <= chr && chr <= '9': - return chr - '0', true - case 'a' <= chr && chr <= 'f': - return chr - 'a' + 10, true - case 'A' <= chr && chr <= 'F': - return chr - 'A' + 10, true - } - return - } -} - -func parseNumberLiteral(literal string) (value interface{}, err error) { - // TODO Is Uint okay? What about -MAX_UINT - value, err = strconv.ParseInt(literal, 0, 64) - if err == nil { - return - } - - parseIntErr := err // Save this first error, just in case - - value, err = strconv.ParseFloat(literal, 64) - if err == nil { - return - } else if err.(*strconv.NumError).Err == strconv.ErrRange { - // Infinity, etc. - return value, nil - } - - err = parseIntErr - - if err.(*strconv.NumError).Err == strconv.ErrRange { - if len(literal) > 2 && literal[0] == '0' && (literal[1] == 'X' || literal[1] == 'x') { - // Could just be a very large number (e.g. 0x8000000000000000) - var value float64 - literal = literal[2:] - for _, chr := range literal { - digit := digitValue(chr) - if digit >= 16 { - goto error - } - value = value*16 + float64(digit) - } - return value, nil - } - } - -error: - return nil, errors.New("Illegal numeric literal") -} - -func parseStringLiteral(literal string) (string, error) { - // Best case scenario... - if literal == "" { - return "", nil - } - - // Slightly less-best case scenario... - if !strings.ContainsRune(literal, '\\') { - return literal, nil - } - - str := literal - buffer := bytes.NewBuffer(make([]byte, 0, 3*len(literal)/2)) - - for len(str) > 0 { - switch chr := str[0]; { - // We do not explicitly handle the case of the quote - // value, which can be: " ' / - // This assumes we're already passed a partially well-formed literal - case chr >= utf8.RuneSelf: - chr, size := utf8.DecodeRuneInString(str) - buffer.WriteRune(chr) - str = str[size:] - continue - case chr != '\\': - buffer.WriteByte(chr) - str = str[1:] - continue - } - - if len(str) <= 1 { - panic("len(str) <= 1") - } - chr := str[1] - var value rune - if chr >= utf8.RuneSelf { - str = str[1:] - var size int - value, size = utf8.DecodeRuneInString(str) - str = str[size:] // \ + <character> - } else { - str = str[2:] // \<character> - switch chr { - case 'b': - value = '\b' - case 'f': - value = '\f' - case 'n': - value = '\n' - case 'r': - value = '\r' - case 't': - value = '\t' - case 'v': - value = '\v' - case 'x', 'u': - size := 0 - switch chr { - case 'x': - size = 2 - case 'u': - size = 4 - } - if len(str) < size { - return "", fmt.Errorf("invalid escape: \\%s: len(%q) != %d", string(chr), str, size) - } - for j := 0; j < size; j++ { - decimal, ok := hex2decimal(str[j]) - if !ok { - return "", fmt.Errorf("invalid escape: \\%s: %q", string(chr), str[:size]) - } - value = value<<4 | decimal - } - str = str[size:] - if chr == 'x' { - break - } - if value > utf8.MaxRune { - panic("value > utf8.MaxRune") - } - case '0': - if len(str) == 0 || '0' > str[0] || str[0] > '7' { - value = 0 - break - } - fallthrough - case '1', '2', '3', '4', '5', '6', '7': - // TODO strict - value = rune(chr) - '0' - j := 0 - for ; j < 2; j++ { - if len(str) < j+1 { - break - } - chr := str[j] - if '0' > chr || chr > '7' { - break - } - decimal := rune(str[j]) - '0' - value = (value << 3) | decimal - } - str = str[j:] - case '\\': - value = '\\' - case '\'', '"': - value = rune(chr) - case '\r': - if len(str) > 0 { - if str[0] == '\n' { - str = str[1:] - } - } - fallthrough - case '\n': - continue - default: - value = rune(chr) - } - } - buffer.WriteRune(value) - } - - return buffer.String(), nil -} - -func (self *_parser) scanNumericLiteral(decimalPoint bool) (token.Token, string) { - - offset := self.chrOffset - tkn := token.NUMBER - - if decimalPoint { - offset-- - self.scanMantissa(10) - goto exponent - } - - if self.chr == '0' { - offset := self.chrOffset - self.read() - if self.chr == 'x' || self.chr == 'X' { - // Hexadecimal - self.read() - if isDigit(self.chr, 16) { - self.read() - } else { - return token.ILLEGAL, self.str[offset:self.chrOffset] - } - self.scanMantissa(16) - - if self.chrOffset-offset <= 2 { - // Only "0x" or "0X" - self.error(0, "Illegal hexadecimal number") - } - - goto hexadecimal - } else if self.chr == '.' { - // Float - goto float - } else { - // Octal, Float - if self.chr == 'e' || self.chr == 'E' { - goto exponent - } - self.scanMantissa(8) - if self.chr == '8' || self.chr == '9' { - return token.ILLEGAL, self.str[offset:self.chrOffset] - } - goto octal - } - } - - self.scanMantissa(10) - -float: - if self.chr == '.' { - self.read() - self.scanMantissa(10) - } - -exponent: - if self.chr == 'e' || self.chr == 'E' { - self.read() - if self.chr == '-' || self.chr == '+' { - self.read() - } - if isDecimalDigit(self.chr) { - self.read() - self.scanMantissa(10) - } else { - return token.ILLEGAL, self.str[offset:self.chrOffset] - } - } - -hexadecimal: -octal: - if isIdentifierStart(self.chr) || isDecimalDigit(self.chr) { - return token.ILLEGAL, self.str[offset:self.chrOffset] - } - - return tkn, self.str[offset:self.chrOffset] -} diff --git a/Godeps/_workspace/src/github.com/obscuren/otto/parser/lexer_test.go b/Godeps/_workspace/src/github.com/obscuren/otto/parser/lexer_test.go deleted file mode 100644 index 37eb7a464..000000000 --- a/Godeps/_workspace/src/github.com/obscuren/otto/parser/lexer_test.go +++ /dev/null @@ -1,380 +0,0 @@ -package parser - -import ( - "../terst" - "testing" - - "github.com/robertkrimen/otto/file" - "github.com/robertkrimen/otto/token" -) - -var tt = terst.Terst -var is = terst.Is - -func TestLexer(t *testing.T) { - tt(t, func() { - setup := func(src string) *_parser { - parser := newParser("", src) - return parser - } - - test := func(src string, test ...interface{}) { - parser := setup(src) - for len(test) > 0 { - tkn, literal, idx := parser.scan() - if len(test) > 0 { - is(tkn, test[0].(token.Token)) - test = test[1:] - } - if len(test) > 0 { - is(literal, test[0].(string)) - test = test[1:] - } - if len(test) > 0 { - // FIXME terst, Fix this so that cast to file.Idx is not necessary? - is(idx, file.Idx(test[0].(int))) - test = test[1:] - } - } - } - - test("", - token.EOF, "", 1, - ) - - test("1", - token.NUMBER, "1", 1, - token.EOF, "", 2, - ) - - test(".0", - token.NUMBER, ".0", 1, - token.EOF, "", 3, - ) - - test("abc", - token.IDENTIFIER, "abc", 1, - token.EOF, "", 4, - ) - - test("abc(1)", - token.IDENTIFIER, "abc", 1, - token.LEFT_PARENTHESIS, "", 4, - token.NUMBER, "1", 5, - token.RIGHT_PARENTHESIS, "", 6, - token.EOF, "", 7, - ) - - test(".", - token.PERIOD, "", 1, - token.EOF, "", 2, - ) - - test("===.", - token.STRICT_EQUAL, "", 1, - token.PERIOD, "", 4, - token.EOF, "", 5, - ) - - test(">>>=.0", - token.UNSIGNED_SHIFT_RIGHT_ASSIGN, "", 1, - token.NUMBER, ".0", 5, - token.EOF, "", 7, - ) - - test(">>>=0.0.", - token.UNSIGNED_SHIFT_RIGHT_ASSIGN, "", 1, - token.NUMBER, "0.0", 5, - token.PERIOD, "", 8, - token.EOF, "", 9, - ) - - test("\"abc\"", - token.STRING, "\"abc\"", 1, - token.EOF, "", 6, - ) - - test("abc = //", - token.IDENTIFIER, "abc", 1, - token.ASSIGN, "", 5, - token.EOF, "", 9, - ) - - test("abc = 1 / 2", - token.IDENTIFIER, "abc", 1, - token.ASSIGN, "", 5, - token.NUMBER, "1", 7, - token.SLASH, "", 9, - token.NUMBER, "2", 11, - token.EOF, "", 12, - ) - - test("xyzzy = 'Nothing happens.'", - token.IDENTIFIER, "xyzzy", 1, - token.ASSIGN, "", 7, - token.STRING, "'Nothing happens.'", 9, - token.EOF, "", 27, - ) - - test("abc = !false", - token.IDENTIFIER, "abc", 1, - token.ASSIGN, "", 5, - token.NOT, "", 7, - token.BOOLEAN, "false", 8, - token.EOF, "", 13, - ) - - test("abc = !!true", - token.IDENTIFIER, "abc", 1, - token.ASSIGN, "", 5, - token.NOT, "", 7, - token.NOT, "", 8, - token.BOOLEAN, "true", 9, - token.EOF, "", 13, - ) - - test("abc *= 1", - token.IDENTIFIER, "abc", 1, - token.MULTIPLY_ASSIGN, "", 5, - token.NUMBER, "1", 8, - token.EOF, "", 9, - ) - - test("if 1 else", - token.IF, "if", 1, - token.NUMBER, "1", 4, - token.ELSE, "else", 6, - token.EOF, "", 10, - ) - - test("null", - token.NULL, "null", 1, - token.EOF, "", 5, - ) - - test(`"\u007a\x79\u000a\x78"`, - token.STRING, "\"\\u007a\\x79\\u000a\\x78\"", 1, - token.EOF, "", 23, - ) - - test(`"[First line \ -Second line \ - Third line\ -. ]" - `, - token.STRING, "\"[First line \\\nSecond line \\\n Third line\\\n. ]\"", 1, - token.EOF, "", 53, - ) - - test("/", - token.SLASH, "", 1, - token.EOF, "", 2, - ) - - test("var abc = \"abc\uFFFFabc\"", - token.VAR, "var", 1, - token.IDENTIFIER, "abc", 5, - token.ASSIGN, "", 9, - token.STRING, "\"abc\uFFFFabc\"", 11, - token.EOF, "", 22, - ) - - test(`'\t' === '\r'`, - token.STRING, "'\\t'", 1, - token.STRICT_EQUAL, "", 6, - token.STRING, "'\\r'", 10, - token.EOF, "", 14, - ) - - test(`var \u0024 = 1`, - token.VAR, "var", 1, - token.IDENTIFIER, "$", 5, - token.ASSIGN, "", 12, - token.NUMBER, "1", 14, - token.EOF, "", 15, - ) - - test("10e10000", - token.NUMBER, "10e10000", 1, - token.EOF, "", 9, - ) - - test(`var if var class`, - token.VAR, "var", 1, - token.IF, "if", 5, - token.VAR, "var", 8, - token.KEYWORD, "class", 12, - token.EOF, "", 17, - ) - - test(`-0`, - token.MINUS, "", 1, - token.NUMBER, "0", 2, - token.EOF, "", 3, - ) - - test(`.01`, - token.NUMBER, ".01", 1, - token.EOF, "", 4, - ) - - test(`.01e+2`, - token.NUMBER, ".01e+2", 1, - token.EOF, "", 7, - ) - - test(";", - token.SEMICOLON, "", 1, - token.EOF, "", 2, - ) - - test(";;", - token.SEMICOLON, "", 1, - token.SEMICOLON, "", 2, - token.EOF, "", 3, - ) - - test("//", - token.EOF, "", 3, - ) - - test(";;//", - token.SEMICOLON, "", 1, - token.SEMICOLON, "", 2, - token.EOF, "", 5, - ) - - test("1", - token.NUMBER, "1", 1, - ) - - test("12 123", - token.NUMBER, "12", 1, - token.NUMBER, "123", 4, - ) - - test("1.2 12.3", - token.NUMBER, "1.2", 1, - token.NUMBER, "12.3", 5, - ) - - test("/ /=", - token.SLASH, "", 1, - token.QUOTIENT_ASSIGN, "", 3, - ) - - test(`"abc"`, - token.STRING, `"abc"`, 1, - ) - - test(`'abc'`, - token.STRING, `'abc'`, 1, - ) - - test("++", - token.INCREMENT, "", 1, - ) - - test(">", - token.GREATER, "", 1, - ) - - test(">=", - token.GREATER_OR_EQUAL, "", 1, - ) - - test(">>", - token.SHIFT_RIGHT, "", 1, - ) - - test(">>=", - token.SHIFT_RIGHT_ASSIGN, "", 1, - ) - - test(">>>", - token.UNSIGNED_SHIFT_RIGHT, "", 1, - ) - - test(">>>=", - token.UNSIGNED_SHIFT_RIGHT_ASSIGN, "", 1, - ) - - test("1 \"abc\"", - token.NUMBER, "1", 1, - token.STRING, "\"abc\"", 3, - ) - - test(",", - token.COMMA, "", 1, - ) - - test("1, \"abc\"", - token.NUMBER, "1", 1, - token.COMMA, "", 2, - token.STRING, "\"abc\"", 4, - ) - - test("new abc(1, 3.14159);", - token.NEW, "new", 1, - token.IDENTIFIER, "abc", 5, - token.LEFT_PARENTHESIS, "", 8, - token.NUMBER, "1", 9, - token.COMMA, "", 10, - token.NUMBER, "3.14159", 12, - token.RIGHT_PARENTHESIS, "", 19, - token.SEMICOLON, "", 20, - ) - - test("1 == \"1\"", - token.NUMBER, "1", 1, - token.EQUAL, "", 3, - token.STRING, "\"1\"", 6, - ) - - test("1\n[]\n", - token.NUMBER, "1", 1, - token.LEFT_BRACKET, "", 3, - token.RIGHT_BRACKET, "", 4, - ) - - test("1\ufeff[]\ufeff", - token.NUMBER, "1", 1, - token.LEFT_BRACKET, "", 5, - token.RIGHT_BRACKET, "", 6, - ) - - // ILLEGAL - - test(`3ea`, - token.ILLEGAL, "3e", 1, - token.IDENTIFIER, "a", 3, - token.EOF, "", 4, - ) - - test(`3in`, - token.ILLEGAL, "3", 1, - token.IN, "in", 2, - token.EOF, "", 4, - ) - - test("\"Hello\nWorld\"", - token.ILLEGAL, "", 1, - token.IDENTIFIER, "World", 8, - token.ILLEGAL, "", 13, - token.EOF, "", 14, - ) - - test("\u203f = 10", - token.ILLEGAL, "", 1, - token.ASSIGN, "", 5, - token.NUMBER, "10", 7, - token.EOF, "", 9, - ) - - test(`"\x0G"`, - token.STRING, "\"\\x0G\"", 1, - token.EOF, "", 7, - ) - - }) -} diff --git a/Godeps/_workspace/src/github.com/obscuren/otto/parser/marshal_test.go b/Godeps/_workspace/src/github.com/obscuren/otto/parser/marshal_test.go deleted file mode 100644 index f54cd2d4f..000000000 --- a/Godeps/_workspace/src/github.com/obscuren/otto/parser/marshal_test.go +++ /dev/null @@ -1,930 +0,0 @@ -package parser - -import ( - "bytes" - "encoding/json" - "fmt" - "os" - "reflect" - "strings" - "testing" - - "github.com/robertkrimen/otto/ast" -) - -func marshal(name string, children ...interface{}) interface{} { - if len(children) == 1 { - if name == "" { - return testMarshalNode(children[0]) - } - return map[string]interface{}{ - name: children[0], - } - } - map_ := map[string]interface{}{} - length := len(children) / 2 - for i := 0; i < length; i++ { - name := children[i*2].(string) - value := children[i*2+1] - map_[name] = value - } - if name == "" { - return map_ - } - return map[string]interface{}{ - name: map_, - } -} - -func testMarshalNode(node interface{}) interface{} { - switch node := node.(type) { - - // Expression - - case *ast.ArrayLiteral: - return marshal("Array", testMarshalNode(node.Value)) - - case *ast.AssignExpression: - return marshal("Assign", - "Left", testMarshalNode(node.Left), - "Right", testMarshalNode(node.Right), - ) - - case *ast.BinaryExpression: - return marshal("BinaryExpression", - "Operator", node.Operator.String(), - "Left", testMarshalNode(node.Left), - "Right", testMarshalNode(node.Right), - ) - - case *ast.BooleanLiteral: - return marshal("Literal", node.Value) - - case *ast.CallExpression: - return marshal("Call", - "Callee", testMarshalNode(node.Callee), - "ArgumentList", testMarshalNode(node.ArgumentList), - ) - - case *ast.ConditionalExpression: - return marshal("Conditional", - "Test", testMarshalNode(node.Test), - "Consequent", testMarshalNode(node.Consequent), - "Alternate", testMarshalNode(node.Alternate), - ) - - case *ast.DotExpression: - return marshal("Dot", - "Left", testMarshalNode(node.Left), - "Member", node.Identifier.Name, - ) - - case *ast.NewExpression: - return marshal("New", - "Callee", testMarshalNode(node.Callee), - "ArgumentList", testMarshalNode(node.ArgumentList), - ) - - case *ast.NullLiteral: - return marshal("Literal", nil) - - case *ast.NumberLiteral: - return marshal("Literal", node.Value) - - case *ast.ObjectLiteral: - return marshal("Object", testMarshalNode(node.Value)) - - case *ast.RegExpLiteral: - return marshal("Literal", node.Literal) - - case *ast.StringLiteral: - return marshal("Literal", node.Literal) - - case *ast.VariableExpression: - return []interface{}{node.Name, testMarshalNode(node.Initializer)} - - // Statement - - case *ast.Program: - return testMarshalNode(node.Body) - - case *ast.BlockStatement: - return marshal("BlockStatement", testMarshalNode(node.List)) - - case *ast.EmptyStatement: - return "EmptyStatement" - - case *ast.ExpressionStatement: - return testMarshalNode(node.Expression) - - case *ast.ForInStatement: - return marshal("ForIn", - "Into", marshal("", node.Into), - "Source", marshal("", node.Source), - "Body", marshal("", node.Body), - ) - - case *ast.FunctionLiteral: - return marshal("Function", testMarshalNode(node.Body)) - - case *ast.Identifier: - return marshal("Identifier", node.Name) - - case *ast.IfStatement: - if_ := marshal("", - "Test", testMarshalNode(node.Test), - "Consequent", testMarshalNode(node.Consequent), - ).(map[string]interface{}) - if node.Alternate != nil { - if_["Alternate"] = testMarshalNode(node.Alternate) - } - return marshal("If", if_) - - case *ast.LabelledStatement: - return marshal("Label", - "Name", node.Label.Name, - "Statement", testMarshalNode(node.Statement), - ) - case ast.Property: - return marshal("", - "Key", node.Key, - "Value", testMarshalNode(node.Value), - ) - - case *ast.ReturnStatement: - return marshal("Return", testMarshalNode(node.Argument)) - - case *ast.SequenceExpression: - return marshal("Sequence", testMarshalNode(node.Sequence)) - - case *ast.ThrowStatement: - return marshal("Throw", testMarshalNode(node.Argument)) - - case *ast.VariableStatement: - return marshal("Var", testMarshalNode(node.List)) - - } - - { - value := reflect.ValueOf(node) - if value.Kind() == reflect.Slice { - tmp0 := []interface{}{} - for index := 0; index < value.Len(); index++ { - tmp0 = append(tmp0, testMarshalNode(value.Index(index).Interface())) - } - return tmp0 - } - } - - if node != nil { - fmt.Fprintf(os.Stderr, "testMarshalNode(%T)\n", node) - } - - return nil -} - -func testMarshal(node interface{}) string { - value, err := json.Marshal(testMarshalNode(node)) - if err != nil { - panic(err) - } - return string(value) -} - -func TestParserAST(t *testing.T) { - tt(t, func() { - - test := func(inputOutput string) { - match := matchBeforeAfterSeparator.FindStringIndex(inputOutput) - input := strings.TrimSpace(inputOutput[0:match[0]]) - wantOutput := strings.TrimSpace(inputOutput[match[1]:]) - _, program, err := testParse(input) - is(err, nil) - haveOutput := testMarshal(program) - tmp0, tmp1 := bytes.Buffer{}, bytes.Buffer{} - json.Indent(&tmp0, []byte(haveOutput), "\t\t", " ") - json.Indent(&tmp1, []byte(wantOutput), "\t\t", " ") - is("\n\t\t"+tmp0.String(), "\n\t\t"+tmp1.String()) - } - - test(` - --- -[] - `) - - test(` - ; - --- -[ - "EmptyStatement" -] - `) - - test(` - ;;; - --- -[ - "EmptyStatement", - "EmptyStatement", - "EmptyStatement" -] - `) - - test(` - 1; true; abc; "abc"; null; - --- -[ - { - "Literal": 1 - }, - { - "Literal": true - }, - { - "Identifier": "abc" - }, - { - "Literal": "\"abc\"" - }, - { - "Literal": null - } -] - `) - - test(` - { 1; null; 3.14159; ; } - --- -[ - { - "BlockStatement": [ - { - "Literal": 1 - }, - { - "Literal": null - }, - { - "Literal": 3.14159 - }, - "EmptyStatement" - ] - } -] - `) - - test(` - new abc(); - --- -[ - { - "New": { - "ArgumentList": [], - "Callee": { - "Identifier": "abc" - } - } - } -] - `) - - test(` - new abc(1, 3.14159) - --- -[ - { - "New": { - "ArgumentList": [ - { - "Literal": 1 - }, - { - "Literal": 3.14159 - } - ], - "Callee": { - "Identifier": "abc" - } - } - } -] - `) - - test(` - true ? false : true - --- -[ - { - "Conditional": { - "Alternate": { - "Literal": true - }, - "Consequent": { - "Literal": false - }, - "Test": { - "Literal": true - } - } - } -] - `) - - test(` - true || false - --- -[ - { - "BinaryExpression": { - "Left": { - "Literal": true - }, - "Operator": "||", - "Right": { - "Literal": false - } - } - } -] - `) - - test(` - 0 + { abc: true } - --- -[ - { - "BinaryExpression": { - "Left": { - "Literal": 0 - }, - "Operator": "+", - "Right": { - "Object": [ - { - "Key": "abc", - "Value": { - "Literal": true - } - } - ] - } - } - } -] - `) - - test(` - 1 == "1" - --- -[ - { - "BinaryExpression": { - "Left": { - "Literal": 1 - }, - "Operator": "==", - "Right": { - "Literal": "\"1\"" - } - } - } -] - `) - - test(` - abc(1) - --- -[ - { - "Call": { - "ArgumentList": [ - { - "Literal": 1 - } - ], - "Callee": { - "Identifier": "abc" - } - } - } -] - `) - - test(` - Math.pow(3, 2) - --- -[ - { - "Call": { - "ArgumentList": [ - { - "Literal": 3 - }, - { - "Literal": 2 - } - ], - "Callee": { - "Dot": { - "Left": { - "Identifier": "Math" - }, - "Member": "pow" - } - } - } - } -] - `) - - test(` - 1, 2, 3 - --- -[ - { - "Sequence": [ - { - "Literal": 1 - }, - { - "Literal": 2 - }, - { - "Literal": 3 - } - ] - } -] - `) - - test(` - / abc / gim; - --- -[ - { - "Literal": "/ abc / gim" - } -] - `) - - test(` - if (0) - 1; - --- -[ - { - "If": { - "Consequent": { - "Literal": 1 - }, - "Test": { - "Literal": 0 - } - } - } -] - `) - - test(` - 0+function(){ - return; - } - --- -[ - { - "BinaryExpression": { - "Left": { - "Literal": 0 - }, - "Operator": "+", - "Right": { - "Function": { - "BlockStatement": [ - { - "Return": null - } - ] - } - } - } - } -] - `) - - test(` - xyzzy // Ignore it - // Ignore this - // And this - /* And all.. - - - - ... of this! - */ - "Nothing happens." - // And finally this - --- -[ - { - "Identifier": "xyzzy" - }, - { - "Literal": "\"Nothing happens.\"" - } -] - `) - - test(` - ((x & (x = 1)) !== 0) - --- -[ - { - "BinaryExpression": { - "Left": { - "BinaryExpression": { - "Left": { - "Identifier": "x" - }, - "Operator": "\u0026", - "Right": { - "Assign": { - "Left": { - "Identifier": "x" - }, - "Right": { - "Literal": 1 - } - } - } - } - }, - "Operator": "!==", - "Right": { - "Literal": 0 - } - } - } -] - `) - - test(` - { abc: 'def' } - --- -[ - { - "BlockStatement": [ - { - "Label": { - "Name": "abc", - "Statement": { - "Literal": "'def'" - } - } - } - ] - } -] - `) - - test(` - // This is not an object, this is a string literal with a label! - ({ abc: 'def' }) - --- -[ - { - "Object": [ - { - "Key": "abc", - "Value": { - "Literal": "'def'" - } - } - ] - } -] - `) - - test(` - [,] - --- -[ - { - "Array": [ - null - ] - } -] - `) - - test(` - [,,] - --- -[ - { - "Array": [ - null, - null - ] - } -] - `) - - test(` - ({ get abc() {} }) - --- -[ - { - "Object": [ - { - "Key": "abc", - "Value": { - "Function": { - "BlockStatement": [] - } - } - } - ] - } -] - `) - - test(` - /abc/.source - --- -[ - { - "Dot": { - "Left": { - "Literal": "/abc/" - }, - "Member": "source" - } - } -] - `) - - test(` - xyzzy - - throw new TypeError("Nothing happens.") - --- -[ - { - "Identifier": "xyzzy" - }, - { - "Throw": { - "New": { - "ArgumentList": [ - { - "Literal": "\"Nothing happens.\"" - } - ], - "Callee": { - "Identifier": "TypeError" - } - } - } - } -] - `) - - // When run, this will call a type error to be thrown - // This is essentially the same as: - // - // var abc = 1(function(){})() - // - test(` - var abc = 1 - (function(){ - })() - --- -[ - { - "Var": [ - [ - "abc", - { - "Call": { - "ArgumentList": [], - "Callee": { - "Call": { - "ArgumentList": [ - { - "Function": { - "BlockStatement": [] - } - } - ], - "Callee": { - "Literal": 1 - } - } - } - } - } - ] - ] - } -] - `) - - test(` - "use strict" - --- -[ - { - "Literal": "\"use strict\"" - } -] - `) - - test(` - "use strict" - abc = 1 + 2 + 11 - --- -[ - { - "Literal": "\"use strict\"" - }, - { - "Assign": { - "Left": { - "Identifier": "abc" - }, - "Right": { - "BinaryExpression": { - "Left": { - "BinaryExpression": { - "Left": { - "Literal": 1 - }, - "Operator": "+", - "Right": { - "Literal": 2 - } - } - }, - "Operator": "+", - "Right": { - "Literal": 11 - } - } - } - } - } -] - `) - - test(` - abc = function() { 'use strict' } - --- -[ - { - "Assign": { - "Left": { - "Identifier": "abc" - }, - "Right": { - "Function": { - "BlockStatement": [ - { - "Literal": "'use strict'" - } - ] - } - } - } - } -] - `) - - test(` - for (var abc in def) { - } - --- -[ - { - "ForIn": { - "Body": { - "BlockStatement": [] - }, - "Into": [ - "abc", - null - ], - "Source": { - "Identifier": "def" - } - } - } -] - `) - - test(` - abc = { - '"': "'", - "'": '"', - } - --- -[ - { - "Assign": { - "Left": { - "Identifier": "abc" - }, - "Right": { - "Object": [ - { - "Key": "\"", - "Value": { - "Literal": "\"'\"" - } - }, - { - "Key": "'", - "Value": { - "Literal": "'\"'" - } - } - ] - } - } - } -] - `) - - return - - test(` - if (!abc && abc.jkl(def) && abc[0] === +abc[0] && abc.length < ghi) { - } - --- -[ - { - "If": { - "Consequent": { - "BlockStatement": [] - }, - "Test": { - "BinaryExpression": { - "Left": { - "BinaryExpression": { - "Left": { - "BinaryExpression": { - "Left": null, - "Operator": "\u0026\u0026", - "Right": { - "Call": { - "ArgumentList": [ - { - "Identifier": "def" - } - ], - "Callee": { - "Dot": { - "Left": { - "Identifier": "abc" - }, - "Member": "jkl" - } - } - } - } - } - }, - "Operator": "\u0026\u0026", - "Right": { - "BinaryExpression": { - "Left": null, - "Operator": "===", - "Right": null - } - } - } - }, - "Operator": "\u0026\u0026", - "Right": { - "BinaryExpression": { - "Left": { - "Dot": { - "Left": { - "Identifier": "abc" - }, - "Member": "length" - } - }, - "Operator": "\u003c", - "Right": { - "Identifier": "ghi" - } - } - } - } - } - } - } -] - `) - }) -} diff --git a/Godeps/_workspace/src/github.com/obscuren/otto/parser/parser.go b/Godeps/_workspace/src/github.com/obscuren/otto/parser/parser.go deleted file mode 100644 index 37146aee9..000000000 --- a/Godeps/_workspace/src/github.com/obscuren/otto/parser/parser.go +++ /dev/null @@ -1,270 +0,0 @@ -/* -Package parser implements a parser for JavaScript. - - import ( - "github.com/robertkrimen/otto/parser" - ) - -Parse and return an AST - - filename := "" // A filename is optional - src := ` - // Sample xyzzy example - (function(){ - if (3.14159 > 0) { - console.log("Hello, World."); - return; - } - - var xyzzy = NaN; - console.log("Nothing happens."); - return xyzzy; - })(); - ` - - // Parse some JavaScript, yielding a *ast.Program and/or an ErrorList - program, err := parser.ParseFile(nil, filename, src, 0) - -Warning - -The parser and AST interfaces are still works-in-progress (particularly where -node types are concerned) and may change in the future. - -*/ -package parser - -import ( - "bytes" - "errors" - "io" - "io/ioutil" - - "github.com/robertkrimen/otto/ast" - "github.com/robertkrimen/otto/file" - "github.com/robertkrimen/otto/token" -) - -// A Mode value is a set of flags (or 0). They control optional parser functionality. -type Mode uint - -const ( - IgnoreRegExpErrors Mode = 1 << iota // Ignore RegExp compatibility errors (allow backtracking) -) - -type _parser struct { - filename string - str string - length int - base int - - chr rune // The current character - chrOffset int // The offset of current character - offset int // The offset after current character (may be greater than 1) - - idx file.Idx // The index of token - token token.Token // The token - literal string // The literal of the token, if any - - scope *_scope - insertSemicolon bool // If we see a newline, then insert an implicit semicolon - implicitSemicolon bool // An implicit semicolon exists - - errors ErrorList - - recover struct { - // Scratch when trying to seek to the next statement, etc. - idx file.Idx - count int - } - - mode Mode -} - -func _newParser(filename, src string, base int) *_parser { - return &_parser{ - chr: ' ', // This is set so we can start scanning by skipping whitespace - str: src, - length: len(src), - base: base, - } -} - -func newParser(filename, src string) *_parser { - return _newParser(filename, src, 1) -} - -func ReadSource(filename string, src interface{}) ([]byte, error) { - if src != nil { - switch src := src.(type) { - case string: - return []byte(src), nil - case []byte: - return src, nil - case *bytes.Buffer: - if src != nil { - return src.Bytes(), nil - } - case io.Reader: - var bfr bytes.Buffer - if _, err := io.Copy(&bfr, src); err != nil { - return nil, err - } - return bfr.Bytes(), nil - } - return nil, errors.New("invalid source") - } - return ioutil.ReadFile(filename) -} - -// ParseFile parses the source code of a single JavaScript/ECMAScript source file and returns -// the corresponding ast.Program node. -// -// If fileSet == nil, ParseFile parses source without a FileSet. -// If fileSet != nil, ParseFile first adds filename and src to fileSet. -// -// The filename argument is optional and is used for labelling errors, etc. -// -// src may be a string, a byte slice, a bytes.Buffer, or an io.Reader, but it MUST always be in UTF-8. -// -// // Parse some JavaScript, yielding a *ast.Program and/or an ErrorList -// program, err := parser.ParseFile(nil, "", `if (abc > 1) {}`, 0) -// -func ParseFile(fileSet *file.FileSet, filename string, src interface{}, mode Mode) (*ast.Program, error) { - str, err := ReadSource(filename, src) - if err != nil { - return nil, err - } - { - str := string(str) - - base := 1 - if fileSet != nil { - base = fileSet.AddFile(filename, str) - } - - parser := _newParser(filename, str, base) - parser.mode = mode - return parser.parse() - } -} - -// ParseFunction parses a given parameter list and body as a function and returns the -// corresponding ast.FunctionLiteral node. -// -// The parameter list, if any, should be a comma-separated list of identifiers. -// -func ParseFunction(parameterList, body string) (*ast.FunctionLiteral, error) { - - src := "(function(" + parameterList + ") {\n" + body + "\n})" - - parser := _newParser("", src, 1) - program, err := parser.parse() - if err != nil { - return nil, err - } - - return program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.FunctionLiteral), nil -} - -func (self *_parser) slice(idx0, idx1 file.Idx) string { - from := int(idx0) - self.base - to := int(idx1) - self.base - if from >= 0 && to <= len(self.str) { - return self.str[from:to] - } - - return "" -} - -func (self *_parser) parse() (*ast.Program, error) { - self.next() - program := self.parseProgram() - if false { - self.errors.Sort() - } - return program, self.errors.Err() -} - -func (self *_parser) next() { - self.token, self.literal, self.idx = self.scan() -} - -func (self *_parser) optionalSemicolon() { - if self.token == token.SEMICOLON { - self.next() - return - } - - if self.implicitSemicolon { - self.implicitSemicolon = false - return - } - - if self.token != token.EOF && self.token != token.RIGHT_BRACE { - self.expect(token.SEMICOLON) - } -} - -func (self *_parser) semicolon() { - if self.token != token.RIGHT_PARENTHESIS && self.token != token.RIGHT_BRACE { - if self.implicitSemicolon { - self.implicitSemicolon = false - return - } - - self.expect(token.SEMICOLON) - } -} - -func (self *_parser) idxOf(offset int) file.Idx { - return file.Idx(self.base + offset) -} - -func (self *_parser) expect(value token.Token) file.Idx { - idx := self.idx - if self.token != value { - self.errorUnexpectedToken(self.token) - } - self.next() - return idx -} - -func lineCount(str string) (int, int) { - line, last := 0, -1 - pair := false - for index, chr := range str { - switch chr { - case '\r': - line += 1 - last = index - pair = true - continue - case '\n': - if !pair { - line += 1 - } - last = index - case '\u2028', '\u2029': - line += 1 - last = index + 2 - } - pair = false - } - return line, last -} - -func (self *_parser) position(idx file.Idx) file.Position { - position := file.Position{} - offset := int(idx) - self.base - str := self.str[:offset] - position.Filename = self.filename - line, last := lineCount(str) - position.Line = 1 + line - if last >= 0 { - position.Column = offset - last - } else { - position.Column = 1 + len(str) - } - - return position -} diff --git a/Godeps/_workspace/src/github.com/obscuren/otto/parser/parser_test.go b/Godeps/_workspace/src/github.com/obscuren/otto/parser/parser_test.go deleted file mode 100644 index 8f9457745..000000000 --- a/Godeps/_workspace/src/github.com/obscuren/otto/parser/parser_test.go +++ /dev/null @@ -1,1004 +0,0 @@ -package parser - -import ( - "errors" - "regexp" - "strings" - "testing" - - "github.com/robertkrimen/otto/ast" - "github.com/robertkrimen/otto/file" -) - -func firstErr(err error) error { - switch err := err.(type) { - case ErrorList: - return err[0] - } - return err -} - -var matchBeforeAfterSeparator = regexp.MustCompile(`(?m)^[ \t]*---$`) - -func testParse(src string) (parser *_parser, program *ast.Program, err error) { - defer func() { - if tmp := recover(); tmp != nil { - switch tmp := tmp.(type) { - case string: - if strings.HasPrefix(tmp, "SyntaxError:") { - parser = nil - program = nil - err = errors.New(tmp) - return - } - } - panic(tmp) - } - }() - parser = newParser("", src) - program, err = parser.parse() - return -} - -func TestParseFile(t *testing.T) { - tt(t, func() { - _, err := ParseFile(nil, "", `/abc/`, 0) - is(err, nil) - - _, err = ParseFile(nil, "", `/(?!def)abc/`, IgnoreRegExpErrors) - is(err, nil) - - _, err = ParseFile(nil, "", `/(?!def)abc/`, 0) - is(err, "(anonymous): Line 1:1 Invalid regular expression: re2: Invalid (?!) <lookahead>") - - _, err = ParseFile(nil, "", `/(?!def)abc/; return`, IgnoreRegExpErrors) - is(err, "(anonymous): Line 1:15 Illegal return statement") - }) -} - -func TestParseFunction(t *testing.T) { - tt(t, func() { - test := func(prm, bdy string, expect interface{}) *ast.FunctionLiteral { - function, err := ParseFunction(prm, bdy) - is(firstErr(err), expect) - return function - } - - test("a, b,c,d", "", nil) - - test("a, b;,c,d", "", "(anonymous): Line 1:15 Unexpected token ;") - - test("this", "", "(anonymous): Line 1:11 Unexpected token this") - - test("a, b, c, null", "", "(anonymous): Line 1:20 Unexpected token null") - - test("a, b,c,d", "return;", nil) - - test("a, b,c,d", "break;", "(anonymous): Line 2:1 Illegal break statement") - - test("a, b,c,d", "{}", nil) - }) -} - -func TestParserErr(t *testing.T) { - tt(t, func() { - test := func(input string, expect interface{}) (*ast.Program, *_parser) { - parser := newParser("", input) - program, err := parser.parse() - is(firstErr(err), expect) - return program, parser - } - - program, parser := test("", nil) - - program, parser = test(` - var abc; - break; do { - } while(true); - `, "(anonymous): Line 3:9 Illegal break statement") - { - stmt := program.Body[1].(*ast.BadStatement) - is(parser.position(stmt.From).Column, 9) - is(parser.position(stmt.To).Column, 16) - is(parser.slice(stmt.From, stmt.To), "break; ") - } - - test("{", "(anonymous): Line 1:2 Unexpected end of input") - - test("}", "(anonymous): Line 1:1 Unexpected token }") - - test("3ea", "(anonymous): Line 1:1 Unexpected token ILLEGAL") - - test("3in", "(anonymous): Line 1:1 Unexpected token ILLEGAL") - - test("3in []", "(anonymous): Line 1:1 Unexpected token ILLEGAL") - - test("3e", "(anonymous): Line 1:1 Unexpected token ILLEGAL") - - test("3e+", "(anonymous): Line 1:1 Unexpected token ILLEGAL") - - test("3e-", "(anonymous): Line 1:1 Unexpected token ILLEGAL") - - test("3x", "(anonymous): Line 1:1 Unexpected token ILLEGAL") - - test("3x0", "(anonymous): Line 1:1 Unexpected token ILLEGAL") - - test("0x", "(anonymous): Line 1:1 Unexpected token ILLEGAL") - - test("09", "(anonymous): Line 1:1 Unexpected token ILLEGAL") - - test("018", "(anonymous): Line 1:1 Unexpected token ILLEGAL") - - test("01.0", "(anonymous): Line 1:3 Unexpected number") - - test("01a", "(anonymous): Line 1:1 Unexpected token ILLEGAL") - - test("0x3in[]", "(anonymous): Line 1:1 Unexpected token ILLEGAL") - - test("\"Hello\nWorld\"", "(anonymous): Line 1:1 Unexpected token ILLEGAL") - - test("\u203f = 10", "(anonymous): Line 1:1 Unexpected token ILLEGAL") - - test("x\\", "(anonymous): Line 1:1 Unexpected token ILLEGAL") - - test("x\\\\", "(anonymous): Line 1:1 Unexpected token ILLEGAL") - - test("x\\u005c", "(anonymous): Line 1:1 Unexpected token ILLEGAL") - - test("x\\u002a", "(anonymous): Line 1:1 Unexpected token ILLEGAL") - - test("x\\\\u002a", "(anonymous): Line 1:1 Unexpected token ILLEGAL") - - test("/\n", "(anonymous): Line 1:1 Invalid regular expression: missing /") - - test("var x = /(s/g", "(anonymous): Line 1:9 Invalid regular expression: Unterminated group") - - test("0 = 1", "(anonymous): Line 1:1 Invalid left-hand side in assignment") - - test("func() = 1", "(anonymous): Line 1:1 Invalid left-hand side in assignment") - - test("(1 + 1) = 2", "(anonymous): Line 1:2 Invalid left-hand side in assignment") - - test("1++", "(anonymous): Line 1:2 Invalid left-hand side in assignment") - - test("1--", "(anonymous): Line 1:2 Invalid left-hand side in assignment") - - test("--1", "(anonymous): Line 1:1 Invalid left-hand side in assignment") - - test("for((1 + 1) in abc) def();", "(anonymous): Line 1:1 Invalid left-hand side in for-in") - - test("[", "(anonymous): Line 1:2 Unexpected end of input") - - test("[,", "(anonymous): Line 1:3 Unexpected end of input") - - test("1 + {", "(anonymous): Line 1:6 Unexpected end of input") - - test("1 + { abc:abc", "(anonymous): Line 1:14 Unexpected end of input") - - test("1 + { abc:abc,", "(anonymous): Line 1:15 Unexpected end of input") - - test("var abc = /\n/", "(anonymous): Line 1:11 Invalid regular expression: missing /") - - test("var abc = \"\n", "(anonymous): Line 1:11 Unexpected token ILLEGAL") - - test("var if = 0", "(anonymous): Line 1:5 Unexpected token if") - - test("abc + 0 = 1", "(anonymous): Line 1:1 Invalid left-hand side in assignment") - - test("+abc = 1", "(anonymous): Line 1:1 Invalid left-hand side in assignment") - - test("1 + (", "(anonymous): Line 1:6 Unexpected end of input") - - test("\n\n\n{", "(anonymous): Line 4:2 Unexpected end of input") - - test("\n/* Some multiline\ncomment */\n)", "(anonymous): Line 4:1 Unexpected token )") - - // TODO - //{ set 1 } - //{ get 2 } - //({ set: s(if) { } }) - //({ set s(.) { } }) - //({ set: s() { } }) - //({ set: s(a, b) { } }) - //({ get: g(d) { } }) - //({ get i() { }, i: 42 }) - //({ i: 42, get i() { } }) - //({ set i(x) { }, i: 42 }) - //({ i: 42, set i(x) { } }) - //({ get i() { }, get i() { } }) - //({ set i(x) { }, set i(x) { } }) - - test("function abc(if) {}", "(anonymous): Line 1:14 Unexpected token if") - - test("function abc(true) {}", "(anonymous): Line 1:14 Unexpected token true") - - test("function abc(false) {}", "(anonymous): Line 1:14 Unexpected token false") - - test("function abc(null) {}", "(anonymous): Line 1:14 Unexpected token null") - - test("function null() {}", "(anonymous): Line 1:10 Unexpected token null") - - test("function true() {}", "(anonymous): Line 1:10 Unexpected token true") - - test("function false() {}", "(anonymous): Line 1:10 Unexpected token false") - - test("function if() {}", "(anonymous): Line 1:10 Unexpected token if") - - test("a b;", "(anonymous): Line 1:3 Unexpected identifier") - - test("if.a", "(anonymous): Line 1:3 Unexpected token .") - - test("a if", "(anonymous): Line 1:3 Unexpected token if") - - test("a class", "(anonymous): Line 1:3 Unexpected reserved word") - - test("break\n", "(anonymous): Line 1:1 Illegal break statement") - - test("break 1;", "(anonymous): Line 1:7 Unexpected number") - - test("for (;;) { break 1; }", "(anonymous): Line 1:18 Unexpected number") - - test("continue\n", "(anonymous): Line 1:1 Illegal continue statement") - - test("continue 1;", "(anonymous): Line 1:10 Unexpected number") - - test("for (;;) { continue 1; }", "(anonymous): Line 1:21 Unexpected number") - - test("throw", "(anonymous): Line 1:1 Unexpected end of input") - - test("throw;", "(anonymous): Line 1:6 Unexpected token ;") - - test("throw \n", "(anonymous): Line 1:1 Unexpected end of input") - - test("for (var abc, def in {});", "(anonymous): Line 1:19 Unexpected token in") - - test("for ((abc in {});;);", nil) - - test("for ((abc in {}));", "(anonymous): Line 1:17 Unexpected token )") - - test("for (+abc in {});", "(anonymous): Line 1:1 Invalid left-hand side in for-in") - - test("if (false)", "(anonymous): Line 1:11 Unexpected end of input") - - test("if (false) abc(); else", "(anonymous): Line 1:23 Unexpected end of input") - - test("do", "(anonymous): Line 1:3 Unexpected end of input") - - test("while (false)", "(anonymous): Line 1:14 Unexpected end of input") - - test("for (;;)", "(anonymous): Line 1:9 Unexpected end of input") - - test("with (abc)", "(anonymous): Line 1:11 Unexpected end of input") - - test("try {}", "(anonymous): Line 1:1 Missing catch or finally after try") - - test("try {} catch {}", "(anonymous): Line 1:14 Unexpected token {") - - test("try {} catch () {}", "(anonymous): Line 1:15 Unexpected token )") - - test("\u203f = 1", "(anonymous): Line 1:1 Unexpected token ILLEGAL") - - // TODO - // const x = 12, y; - // const x, y = 12; - // const x; - // if(true) let a = 1; - // if(true) const a = 1; - - test(`new abc()."def"`, "(anonymous): Line 1:11 Unexpected string") - - test("/*", "(anonymous): Line 1:3 Unexpected end of input") - - test("/**", "(anonymous): Line 1:4 Unexpected end of input") - - test("/*\n\n\n", "(anonymous): Line 4:1 Unexpected end of input") - - test("/*\n\n\n*", "(anonymous): Line 4:2 Unexpected end of input") - - test("/*abc", "(anonymous): Line 1:6 Unexpected end of input") - - test("/*abc *", "(anonymous): Line 1:9 Unexpected end of input") - - test("\n]", "(anonymous): Line 2:1 Unexpected token ]") - - test("\r\n]", "(anonymous): Line 2:1 Unexpected token ]") - - test("\n\r]", "(anonymous): Line 3:1 Unexpected token ]") - - test("//\r\n]", "(anonymous): Line 2:1 Unexpected token ]") - - test("//\n\r]", "(anonymous): Line 3:1 Unexpected token ]") - - test("/abc\\\n/", "(anonymous): Line 1:1 Invalid regular expression: missing /") - - test("//\r \n]", "(anonymous): Line 3:1 Unexpected token ]") - - test("/*\r\n*/]", "(anonymous): Line 2:3 Unexpected token ]") - - test("/*\r \n*/]", "(anonymous): Line 3:3 Unexpected token ]") - - test("\\\\", "(anonymous): Line 1:1 Unexpected token ILLEGAL") - - test("\\u005c", "(anonymous): Line 1:1 Unexpected token ILLEGAL") - - test("\\abc", "(anonymous): Line 1:1 Unexpected token ILLEGAL") - - test("\\u0000", "(anonymous): Line 1:1 Unexpected token ILLEGAL") - - test("\\u200c = []", "(anonymous): Line 1:1 Unexpected token ILLEGAL") - - test("\\u200D = []", "(anonymous): Line 1:1 Unexpected token ILLEGAL") - - test(`"\`, "(anonymous): Line 1:1 Unexpected token ILLEGAL") - - test(`"\u`, "(anonymous): Line 1:1 Unexpected token ILLEGAL") - - test("return", "(anonymous): Line 1:1 Illegal return statement") - - test("continue", "(anonymous): Line 1:1 Illegal continue statement") - - test("break", "(anonymous): Line 1:1 Illegal break statement") - - test("switch (abc) { default: continue; }", "(anonymous): Line 1:25 Illegal continue statement") - - test("do { abc } *", "(anonymous): Line 1:12 Unexpected token *") - - test("while (true) { break abc; }", "(anonymous): Line 1:16 Undefined label 'abc'") - - test("while (true) { continue abc; }", "(anonymous): Line 1:16 Undefined label 'abc'") - - test("abc: while (true) { (function(){ break abc; }); }", "(anonymous): Line 1:34 Undefined label 'abc'") - - test("abc: while (true) { (function(){ abc: break abc; }); }", nil) - - test("abc: while (true) { (function(){ continue abc; }); }", "(anonymous): Line 1:34 Undefined label 'abc'") - - test(`abc: if (0) break abc; else {}`, nil) - - test(`abc: if (0) { break abc; } else {}`, nil) - - test(`abc: if (0) { break abc } else {}`, nil) - - test("abc: while (true) { abc: while (true) {} }", "(anonymous): Line 1:21 Label 'abc' already exists") - - if false { - // TODO When strict mode is implemented - test("(function () { 'use strict'; delete abc; }())", "") - } - - test("_: _: while (true) {]", "(anonymous): Line 1:4 Label '_' already exists") - - test("_:\n_:\nwhile (true) {]", "(anonymous): Line 2:1 Label '_' already exists") - - test("_:\n _:\nwhile (true) {]", "(anonymous): Line 2:4 Label '_' already exists") - - test("/Xyzzy(?!Nothing happens)/", - "(anonymous): Line 1:1 Invalid regular expression: re2: Invalid (?!) <lookahead>") - - test("function(){}", "(anonymous): Line 1:9 Unexpected token (") - - test("\n/*/", "(anonymous): Line 2:4 Unexpected end of input") - - test("/*/.source", "(anonymous): Line 1:11 Unexpected end of input") - - test("/\\1/.source", "(anonymous): Line 1:1 Invalid regular expression: re2: Invalid \\1 <backreference>") - - test("var class", "(anonymous): Line 1:5 Unexpected reserved word") - - test("var if", "(anonymous): Line 1:5 Unexpected token if") - - test("object Object", "(anonymous): Line 1:8 Unexpected identifier") - - test("[object Object]", "(anonymous): Line 1:9 Unexpected identifier") - - test("\\u0xyz", "(anonymous): Line 1:1 Unexpected token ILLEGAL") - - test(`for (var abc, def in {}) {}`, "(anonymous): Line 1:19 Unexpected token in") - - test(`for (abc, def in {}) {}`, "(anonymous): Line 1:1 Invalid left-hand side in for-in") - - test(`for (var abc=def, ghi=("abc" in {}); true;) {}`, nil) - - { - // Semicolon insertion - - test("this\nif (1);", nil) - - test("while (1) { break\nif (1); }", nil) - - test("throw\nif (1);", "(anonymous): Line 1:1 Illegal newline after throw") - - test("(function(){ return\nif (1); })", nil) - - test("while (1) { continue\nif (1); }", nil) - - test("debugger\nif (1);", nil) - } - - { // Reserved words - - test("class", "(anonymous): Line 1:1 Unexpected reserved word") - test("abc.class = 1", nil) - test("var class;", "(anonymous): Line 1:5 Unexpected reserved word") - - test("const", "(anonymous): Line 1:1 Unexpected reserved word") - test("abc.const = 1", nil) - test("var const;", "(anonymous): Line 1:5 Unexpected reserved word") - - test("enum", "(anonymous): Line 1:1 Unexpected reserved word") - test("abc.enum = 1", nil) - test("var enum;", "(anonymous): Line 1:5 Unexpected reserved word") - - test("export", "(anonymous): Line 1:1 Unexpected reserved word") - test("abc.export = 1", nil) - test("var export;", "(anonymous): Line 1:5 Unexpected reserved word") - - test("extends", "(anonymous): Line 1:1 Unexpected reserved word") - test("abc.extends = 1", nil) - test("var extends;", "(anonymous): Line 1:5 Unexpected reserved word") - - test("import", "(anonymous): Line 1:1 Unexpected reserved word") - test("abc.import = 1", nil) - test("var import;", "(anonymous): Line 1:5 Unexpected reserved word") - - test("super", "(anonymous): Line 1:1 Unexpected reserved word") - test("abc.super = 1", nil) - test("var super;", "(anonymous): Line 1:5 Unexpected reserved word") - } - - { // Reserved words (strict) - - test(`implements`, nil) - test(`abc.implements = 1`, nil) - test(`var implements;`, nil) - - test(`interface`, nil) - test(`abc.interface = 1`, nil) - test(`var interface;`, nil) - - test(`let`, nil) - test(`abc.let = 1`, nil) - test(`var let;`, nil) - - test(`package`, nil) - test(`abc.package = 1`, nil) - test(`var package;`, nil) - - test(`private`, nil) - test(`abc.private = 1`, nil) - test(`var private;`, nil) - - test(`protected`, nil) - test(`abc.protected = 1`, nil) - test(`var protected;`, nil) - - test(`public`, nil) - test(`abc.public = 1`, nil) - test(`var public;`, nil) - - test(`static`, nil) - test(`abc.static = 1`, nil) - test(`var static;`, nil) - - test(`yield`, nil) - test(`abc.yield = 1`, nil) - test(`var yield;`, nil) - } - }) -} - -func TestParser(t *testing.T) { - tt(t, func() { - test := func(source string, chk interface{}) *ast.Program { - _, program, err := testParse(source) - is(firstErr(err), chk) - return program - } - - test(` - abc - -- - [] - `, "(anonymous): Line 3:13 Invalid left-hand side in assignment") - - test(` - abc-- - [] - `, nil) - - test("1\n[]\n", "(anonymous): Line 2:2 Unexpected token ]") - - test(` - function abc() { - } - abc() - `, nil) - - program := test("", nil) - - test("//", nil) - - test("/* */", nil) - - test("/** **/", nil) - - test("/*****/", nil) - - test("/*", "(anonymous): Line 1:3 Unexpected end of input") - - test("#", "(anonymous): Line 1:1 Unexpected token ILLEGAL") - - test("/**/#", "(anonymous): Line 1:5 Unexpected token ILLEGAL") - - test("new +", "(anonymous): Line 1:5 Unexpected token +") - - program = test(";", nil) - is(len(program.Body), 1) - is(program.Body[0].(*ast.EmptyStatement).Semicolon, file.Idx(1)) - - program = test(";;", nil) - is(len(program.Body), 2) - is(program.Body[0].(*ast.EmptyStatement).Semicolon, file.Idx(1)) - is(program.Body[1].(*ast.EmptyStatement).Semicolon, file.Idx(2)) - - program = test("1.2", nil) - is(len(program.Body), 1) - is(program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.NumberLiteral).Literal, "1.2") - - program = test("/* */1.2", nil) - is(len(program.Body), 1) - is(program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.NumberLiteral).Literal, "1.2") - - program = test("\n", nil) - is(len(program.Body), 0) - - test(` - if (0) { - abc = 0 - } - else abc = 0 - `, nil) - - test("if (0) abc = 0 else abc = 0", "(anonymous): Line 1:16 Unexpected token else") - - test(` - if (0) { - abc = 0 - } else abc = 0 - `, nil) - - test(` - if (0) { - abc = 1 - } else { - } - `, nil) - - test(` - do { - } while (true) - `, nil) - - test(` - try { - } finally { - } - `, nil) - - test(` - try { - } catch (abc) { - } finally { - } - `, nil) - - test(` - try { - } - catch (abc) { - } - finally { - } - `, nil) - - test(`try {} catch (abc) {} finally {}`, nil) - - test(` - do { - do { - } while (0) - } while (0) - `, nil) - - test(` - (function(){ - try { - if ( - 1 - ) { - return 1 - } - return 0 - } finally { - } - })() - `, nil) - - test("abc = ''\ndef", nil) - - test("abc = 1\ndef", nil) - - test("abc = Math\ndef", nil) - - test(`"\'"`, nil) - - test(` - abc = function(){ - } - abc = 0 - `, nil) - - test("abc.null = 0", nil) - - test("0x41", nil) - - test(`"\d"`, nil) - - test(`(function(){return this})`, nil) - - test(` - Object.defineProperty(Array.prototype, "0", { - value: 100, - writable: false, - configurable: true - }); - abc = [101]; - abc.hasOwnProperty("0") && abc[0] === 101; - `, nil) - - test(`new abc()`, nil) - test(`new {}`, nil) - - test(` - limit = 4 - result = 0 - while (limit) { - limit = limit - 1 - if (limit) { - } - else { - break - } - result = result + 1 - } - `, nil) - - test(` - while (0) { - if (0) { - continue - } - } - `, nil) - - test("var \u0061\u0062\u0063 = 0", nil) - - // 7_3_1 - test("var test7_3_1\nabc = 66;", nil) - test("var test7_3_1\u2028abc = 66;", nil) - - // 7_3_3 - test("//\u2028 =;", "(anonymous): Line 2:2 Unexpected token =") - - // 7_3_10 - test("var abc = \u2029;", "(anonymous): Line 2:1 Unexpected token ;") - test("var abc = \\u2029;", "(anonymous): Line 1:11 Unexpected token ILLEGAL") - test("var \\u0061\\u0062\\u0063 = 0;", nil) - - test("'", "(anonymous): Line 1:1 Unexpected token ILLEGAL") - - test("'\nstr\ning\n'", "(anonymous): Line 1:1 Unexpected token ILLEGAL") - - // S7.6_A4.3_T1 - test(`var $\u0030 = 0;`, nil) - - // S7.6.1.1_A1.1 - test(`switch = 1`, "(anonymous): Line 1:8 Unexpected token =") - - // S7.8.3_A2.1_T1 - test(`.0 === 0.0`, nil) - - // 7.8.5-1 - test("var regExp = /\\\rn/;", "(anonymous): Line 1:14 Invalid regular expression: missing /") - - // S7.8.5_A1.1_T2 - test("var regExp = /=/;", nil) - - // S7.8.5_A1.2_T1 - test("/*/", "(anonymous): Line 1:4 Unexpected end of input") - - // Sbp_7.9_A9_T3 - test(` - do { - ; - } while (false) true - `, nil) - - // S7.9_A10_T10 - test(` - {a:1 - } 3 - `, nil) - - test(` - abc - ++def - `, nil) - - // S7.9_A5.2_T1 - test(` - for(false;false - ) { - break; - } - `, "(anonymous): Line 3:13 Unexpected token )") - - // S7.9_A9_T8 - test(` - do {}; - while (false) - `, "(anonymous): Line 2:18 Unexpected token ;") - - // S8.4_A5 - test(` - "x\0y" - `, nil) - - // S9.3.1_A6_T1 - test(` - 10e10000 - `, nil) - - // 10.4.2-1-5 - test(` - "abc\ - def" - `, nil) - - test("'\\\n'", nil) - - test("'\\\r\n'", nil) - - //// 11.13.1-1-1 - test("42 = 42;", "(anonymous): Line 1:1 Invalid left-hand side in assignment") - - // S11.13.2_A4.2_T1.3 - test(` - abc /= "1" - `, nil) - - // 12.1-1 - test(` - try{};catch(){} - `, "(anonymous): Line 2:13 Missing catch or finally after try") - - // 12.1-3 - test(` - try{};finally{} - `, "(anonymous): Line 2:13 Missing catch or finally after try") - - // S12.6.3_A11.1_T3 - test(` - while (true) { - break abc; - } - `, "(anonymous): Line 3:17 Undefined label 'abc'") - - // S15.3_A2_T1 - test(`var x / = 1;`, "(anonymous): Line 1:7 Unexpected token /") - - test(` - function abc() { - if (0) - return; - else { - } - } - `, nil) - - test("//\u2028 var =;", "(anonymous): Line 2:6 Unexpected token =") - - test(` - throw - {} - `, "(anonymous): Line 2:13 Illegal newline after throw") - - // S7.6.1.1_A1.11 - test(` - function = 1 - `, "(anonymous): Line 2:22 Unexpected token =") - - // S7.8.3_A1.2_T1 - test(`0e1`, nil) - - test("abc = 1; abc\n++", "(anonymous): Line 2:3 Unexpected end of input") - - // --- - - test("({ get abc() {} })", nil) - - test(`for (abc.def in {}) {}`, nil) - - test(`while (true) { break }`, nil) - - test(`while (true) { continue }`, nil) - - test(`abc=/^(?:(\w+:)\/{2}(\w+(?:\.\w+)*\/?)|(.{0,2}\/{1}))?([/.]*?(?:[^?]+)?\/)?((?:[^/?]+)\.(\w+))(?:\?(\S+)?)?$/,def=/^(?:(\w+:)\/{2})|(.{0,2}\/{1})?([/.]*?(?:[^?]+)?\/?)?$/`, nil) - - test(`(function() { try {} catch (err) {} finally {} return })`, nil) - - test(`0xde0b6b3a7640080.toFixed(0)`, nil) - - test(`/[^-._0-9A-Za-z\xb7\xc0-\xd6\xd8-\xf6\xf8-\u037d\u37f-\u1fff\u200c-\u200d\u203f\u2040\u2070-\u218f]/`, nil) - - test(`/[\u0000-\u0008\u000B-\u000C\u000E-\u001F\uD800-\uDFFF\uFFFE-\uFFFF]/`, nil) - - test("var abc = 1;\ufeff", nil) - - test("\ufeff/* var abc = 1; */", nil) - - test(`if (-0x8000000000000000<=abc&&abc<=0x8000000000000000) {}`, nil) - - test(`(function(){debugger;return this;})`, nil) - - test(` - - `, nil) - - test(` - var abc = "" - debugger - `, nil) - - test(` - var abc = /\[\]$/ - debugger - `, nil) - - test(` - var abc = 1 / - 2 - debugger - `, nil) - }) -} - -func Test_parseStringLiteral(t *testing.T) { - tt(t, func() { - test := func(have, want string) { - have, err := parseStringLiteral(have) - is(err, nil) - is(have, want) - } - - test("", "") - - test("1(\\\\d+)", "1(\\d+)") - - test("\\u2029", "\u2029") - - test("abc\\uFFFFabc", "abc\uFFFFabc") - - test("[First line \\\nSecond line \\\n Third line\\\n. ]", - "[First line Second line Third line. ]") - - test("\\u007a\\x79\\u000a\\x78", "zy\nx") - - // S7.8.4_A4.2_T3 - test("\\a", "a") - test("\u0410", "\u0410") - - // S7.8.4_A5.1_T1 - test("\\0", "\u0000") - - // S8.4_A5 - test("\u0000", "\u0000") - - // 15.5.4.20 - test("'abc'\\\n'def'", "'abc''def'") - - // 15.5.4.20-4-1 - test("'abc'\\\r\n'def'", "'abc''def'") - - // Octal - test("\\0", "\000") - test("\\00", "\000") - test("\\000", "\000") - test("\\09", "\0009") - test("\\009", "\0009") - test("\\0009", "\0009") - test("\\1", "\001") - test("\\01", "\001") - test("\\001", "\001") - test("\\0011", "\0011") - test("\\1abc", "\001abc") - - test("\\\u4e16", "\u4e16") - - // err - test = func(have, want string) { - have, err := parseStringLiteral(have) - is(err.Error(), want) - is(have, "") - } - - test(`\u`, `invalid escape: \u: len("") != 4`) - test(`\u0`, `invalid escape: \u: len("0") != 4`) - test(`\u00`, `invalid escape: \u: len("00") != 4`) - test(`\u000`, `invalid escape: \u: len("000") != 4`) - - test(`\x`, `invalid escape: \x: len("") != 2`) - test(`\x0`, `invalid escape: \x: len("0") != 2`) - test(`\x0`, `invalid escape: \x: len("0") != 2`) - }) -} - -func Test_parseNumberLiteral(t *testing.T) { - tt(t, func() { - test := func(input string, expect interface{}) { - result, err := parseNumberLiteral(input) - is(err, nil) - is(result, expect) - } - - test("0", 0) - - test("0x8000000000000000", float64(9.223372036854776e+18)) - }) -} - -func TestPosition(t *testing.T) { - tt(t, func() { - parser := newParser("", "// Lorem ipsum") - - // Out of range, idx0 (error condition) - is(parser.slice(0, 1), "") - is(parser.slice(0, 10), "") - - // Out of range, idx1 (error condition) - is(parser.slice(1, 128), "") - - is(parser.str[0:0], "") - is(parser.slice(1, 1), "") - - is(parser.str[0:1], "/") - is(parser.slice(1, 2), "/") - - is(parser.str[0:14], "// Lorem ipsum") - is(parser.slice(1, 15), "// Lorem ipsum") - - parser = newParser("", "(function(){ return 0; })") - program, err := parser.parse() - is(err, nil) - - var node ast.Node - node = program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.FunctionLiteral) - is(node.Idx0(), file.Idx(2)) - is(node.Idx1(), file.Idx(25)) - is(parser.slice(node.Idx0(), node.Idx1()), "function(){ return 0; }") - is(parser.slice(node.Idx0(), node.Idx1()+1), "function(){ return 0; })") - is(parser.slice(node.Idx0(), node.Idx1()+2), "") - is(node.(*ast.FunctionLiteral).Source, "function(){ return 0; }") - - node = program - is(node.Idx0(), file.Idx(2)) - is(node.Idx1(), file.Idx(25)) - is(parser.slice(node.Idx0(), node.Idx1()), "function(){ return 0; }") - - parser = newParser("", "(function(){ return abc; })") - program, err = parser.parse() - is(err, nil) - node = program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.FunctionLiteral) - is(node.(*ast.FunctionLiteral).Source, "function(){ return abc; }") - }) -} diff --git a/Godeps/_workspace/src/github.com/obscuren/otto/parser/regexp.go b/Godeps/_workspace/src/github.com/obscuren/otto/parser/regexp.go deleted file mode 100644 index f614dae74..000000000 --- a/Godeps/_workspace/src/github.com/obscuren/otto/parser/regexp.go +++ /dev/null @@ -1,358 +0,0 @@ -package parser - -import ( - "bytes" - "fmt" - "strconv" -) - -type _RegExp_parser struct { - str string - length int - - chr rune // The current character - chrOffset int // The offset of current character - offset int // The offset after current character (may be greater than 1) - - errors []error - invalid bool // The input is an invalid JavaScript RegExp - - goRegexp *bytes.Buffer -} - -// TransformRegExp transforms a JavaScript pattern into a Go "regexp" pattern. -// -// re2 (Go) cannot do backtracking, so the presence of a lookahead (?=) (?!) or -// backreference (\1, \2, ...) will cause an error. -// -// re2 (Go) has a different definition for \s: [\t\n\f\r ]. -// The JavaScript definition, on the other hand, also includes \v, Unicode "Separator, Space", etc. -// -// If the pattern is invalid (not valid even in JavaScript), then this function -// returns the empty string and an error. -// -// If the pattern is valid, but incompatible (contains a lookahead or backreference), -// then this function returns the transformation (a non-empty string) AND an error. -func TransformRegExp(pattern string) (string, error) { - - if pattern == "" { - return "", nil - } - - // TODO If without \, if without (?=, (?!, then another shortcut - - parser := _RegExp_parser{ - str: pattern, - length: len(pattern), - goRegexp: bytes.NewBuffer(make([]byte, 0, 3*len(pattern)/2)), - } - parser.read() // Pull in the first character - parser.scan() - var err error - if len(parser.errors) > 0 { - err = parser.errors[0] - } - if parser.invalid { - return "", err - } - - // Might not be re2 compatible, but is still a valid JavaScript RegExp - return parser.goRegexp.String(), err -} - -func (self *_RegExp_parser) scan() { - for self.chr != -1 { - switch self.chr { - case '\\': - self.read() - self.scanEscape(false) - case '(': - self.pass() - self.scanGroup() - case '[': - self.pass() - self.scanBracket() - case ')': - self.error(-1, "Unmatched ')'") - self.invalid = true - self.pass() - default: - self.pass() - } - } -} - -// (...) -func (self *_RegExp_parser) scanGroup() { - str := self.str[self.chrOffset:] - if len(str) > 1 { // A possibility of (?= or (?! - if str[0] == '?' { - if str[1] == '=' || str[1] == '!' { - self.error(-1, "re2: Invalid (%s) <lookahead>", self.str[self.chrOffset:self.chrOffset+2]) - } - } - } - for self.chr != -1 && self.chr != ')' { - switch self.chr { - case '\\': - self.read() - self.scanEscape(false) - case '(': - self.pass() - self.scanGroup() - case '[': - self.pass() - self.scanBracket() - default: - self.pass() - continue - } - } - if self.chr != ')' { - self.error(-1, "Unterminated group") - self.invalid = true - return - } - self.pass() -} - -// [...] -func (self *_RegExp_parser) scanBracket() { - for self.chr != -1 { - if self.chr == ']' { - break - } else if self.chr == '\\' { - self.read() - self.scanEscape(true) - continue - } - self.pass() - } - if self.chr != ']' { - self.error(-1, "Unterminated character class") - self.invalid = true - return - } - self.pass() -} - -// \... -func (self *_RegExp_parser) scanEscape(inClass bool) { - offset := self.chrOffset - - var length, base uint32 - switch self.chr { - - case '0', '1', '2', '3', '4', '5', '6', '7': - var value int64 - size := 0 - for { - digit := int64(digitValue(self.chr)) - if digit >= 8 { - // Not a valid digit - break - } - value = value*8 + digit - self.read() - size += 1 - } - if size == 1 { // The number of characters read - _, err := self.goRegexp.Write([]byte{'\\', byte(value) + '0'}) - if err != nil { - self.errors = append(self.errors, err) - } - if value != 0 { - // An invalid backreference - self.error(-1, "re2: Invalid \\%d <backreference>", value) - } - return - } - tmp := []byte{'\\', 'x', '0', 0} - if value >= 16 { - tmp = tmp[0:2] - } else { - tmp = tmp[0:3] - } - tmp = strconv.AppendInt(tmp, value, 16) - _, err := self.goRegexp.Write(tmp) - if err != nil { - self.errors = append(self.errors, err) - } - return - - case '8', '9': - size := 0 - for { - digit := digitValue(self.chr) - if digit >= 10 { - // Not a valid digit - break - } - self.read() - size += 1 - } - err := self.goRegexp.WriteByte('\\') - if err != nil { - self.errors = append(self.errors, err) - } - _, err = self.goRegexp.WriteString(self.str[offset:self.chrOffset]) - if err != nil { - self.errors = append(self.errors, err) - } - self.error(-1, "re2: Invalid \\%s <backreference>", self.str[offset:self.chrOffset]) - return - - case 'x': - self.read() - length, base = 2, 16 - - case 'u': - self.read() - length, base = 4, 16 - - case 'b': - if inClass { - _, err := self.goRegexp.Write([]byte{'\\', 'x', '0', '8'}) - if err != nil { - self.errors = append(self.errors, err) - } - self.read() - return - } - fallthrough - - case 'B': - fallthrough - - case 'd', 'D', 's', 'S', 'w', 'W': - // This is slightly broken, because ECMAScript - // includes \v in \s, \S, while re2 does not - fallthrough - - case '\\': - fallthrough - - case 'f', 'n', 'r', 't', 'v': - err := self.goRegexp.WriteByte('\\') - if err != nil { - self.errors = append(self.errors, err) - } - self.pass() - return - - case 'c': - self.read() - var value int64 - if 'a' <= self.chr && self.chr <= 'z' { - value = int64(self.chr) - 'a' + 1 - } else if 'A' <= self.chr && self.chr <= 'Z' { - value = int64(self.chr) - 'A' + 1 - } else { - err := self.goRegexp.WriteByte('c') - if err != nil { - self.errors = append(self.errors, err) - } - return - } - tmp := []byte{'\\', 'x', '0', 0} - if value >= 16 { - tmp = tmp[0:2] - } else { - tmp = tmp[0:3] - } - tmp = strconv.AppendInt(tmp, value, 16) - _, err := self.goRegexp.Write(tmp) - if err != nil { - self.errors = append(self.errors, err) - } - self.read() - return - - default: - // $ is an identifier character, so we have to have - // a special case for it here - if self.chr == '$' || !isIdentifierPart(self.chr) { - // A non-identifier character needs escaping - err := self.goRegexp.WriteByte('\\') - if err != nil { - self.errors = append(self.errors, err) - } - } else { - // Unescape the character for re2 - } - self.pass() - return - } - - // Otherwise, we're a \u.... or \x... - valueOffset := self.chrOffset - - var value uint32 - { - length := length - for ; length > 0; length-- { - digit := uint32(digitValue(self.chr)) - if digit >= base { - // Not a valid digit - goto skip - } - value = value*base + digit - self.read() - } - } - - if length == 4 { - _, err := self.goRegexp.Write([]byte{ - '\\', - 'x', - '{', - self.str[valueOffset+0], - self.str[valueOffset+1], - self.str[valueOffset+2], - self.str[valueOffset+3], - '}', - }) - if err != nil { - self.errors = append(self.errors, err) - } - } else if length == 2 { - _, err := self.goRegexp.Write([]byte{ - '\\', - 'x', - self.str[valueOffset+0], - self.str[valueOffset+1], - }) - if err != nil { - self.errors = append(self.errors, err) - } - } else { - // Should never, ever get here... - self.error(-1, "re2: Illegal branch in scanEscape") - goto skip - } - - return - -skip: - _, err := self.goRegexp.WriteString(self.str[offset:self.chrOffset]) - if err != nil { - self.errors = append(self.errors, err) - } -} - -func (self *_RegExp_parser) pass() { - if self.chr != -1 { - _, err := self.goRegexp.WriteRune(self.chr) - if err != nil { - self.errors = append(self.errors, err) - } - } - self.read() -} - -// TODO Better error reporting, use the offset, etc. -func (self *_RegExp_parser) error(offset int, msg string, msgValues ...interface{}) error { - err := fmt.Errorf(msg, msgValues...) - self.errors = append(self.errors, err) - return err -} diff --git a/Godeps/_workspace/src/github.com/obscuren/otto/parser/regexp_test.go b/Godeps/_workspace/src/github.com/obscuren/otto/parser/regexp_test.go deleted file mode 100644 index 3222db1a7..000000000 --- a/Godeps/_workspace/src/github.com/obscuren/otto/parser/regexp_test.go +++ /dev/null @@ -1,149 +0,0 @@ -package parser - -import ( - "regexp" - "testing" -) - -func TestRegExp(t *testing.T) { - tt(t, func() { - { - // err - test := func(input string, expect interface{}) { - _, err := TransformRegExp(input) - is(err, expect) - } - - test("[", "Unterminated character class") - - test("(", "Unterminated group") - - test("(?=)", "re2: Invalid (?=) <lookahead>") - - test("(?=)", "re2: Invalid (?=) <lookahead>") - - test("(?!)", "re2: Invalid (?!) <lookahead>") - - // An error anyway - test("(?=", "re2: Invalid (?=) <lookahead>") - - test("\\1", "re2: Invalid \\1 <backreference>") - - test("\\90", "re2: Invalid \\90 <backreference>") - - test("\\9123456789", "re2: Invalid \\9123456789 <backreference>") - - test("\\(?=)", "Unmatched ')'") - - test(")", "Unmatched ')'") - } - - { - // err - test := func(input, expect string, expectErr interface{}) { - output, err := TransformRegExp(input) - is(output, expect) - is(err, expectErr) - } - - test("(?!)", "(?!)", "re2: Invalid (?!) <lookahead>") - - test(")", "", "Unmatched ')'") - - test("(?!))", "", "re2: Invalid (?!) <lookahead>") - - test("\\0", "\\0", nil) - - test("\\1", "\\1", "re2: Invalid \\1 <backreference>") - - test("\\9123456789", "\\9123456789", "re2: Invalid \\9123456789 <backreference>") - } - - { - // err - test := func(input string, expect string) { - result, err := TransformRegExp(input) - is(err, nil) - if is(result, expect) { - _, err := regexp.Compile(result) - if !is(err, nil) { - t.Log(result) - } - } - } - - test("", "") - - test("abc", "abc") - - test(`\abc`, `abc`) - - test(`\a\b\c`, `a\bc`) - - test(`\x`, `x`) - - test(`\c`, `c`) - - test(`\cA`, `\x01`) - - test(`\cz`, `\x1a`) - - test(`\ca`, `\x01`) - - test(`\cj`, `\x0a`) - - test(`\ck`, `\x0b`) - - test(`\+`, `\+`) - - test(`[\b]`, `[\x08]`) - - test(`\u0z01\x\undefined`, `u0z01xundefined`) - - test(`\\|'|\r|\n|\t|\u2028|\u2029`, `\\|'|\r|\n|\t|\x{2028}|\x{2029}`) - - test("]", "]") - - test("}", "}") - - test("%", "%") - - test("(%)", "(%)") - - test("(?:[%\\s])", "(?:[%\\s])") - - test("[[]", "[[]") - - test("\\101", "\\x41") - - test("\\51", "\\x29") - - test("\\051", "\\x29") - - test("\\175", "\\x7d") - - test("\\04", "\\x04") - - test(`<%([\s\S]+?)%>`, `<%([\s\S]+?)%>`) - - test(`(.)^`, "(.)^") - - test(`<%-([\s\S]+?)%>|<%=([\s\S]+?)%>|<%([\s\S]+?)%>|$`, `<%-([\s\S]+?)%>|<%=([\s\S]+?)%>|<%([\s\S]+?)%>|$`) - - test(`\$`, `\$`) - - test(`[G-b]`, `[G-b]`) - - test(`[G-b\0]`, `[G-b\0]`) - } - }) -} - -func TestTransformRegExp(t *testing.T) { - tt(t, func() { - pattern, err := TransformRegExp(`\s+abc\s+`) - is(err, nil) - is(pattern, `\s+abc\s+`) - is(regexp.MustCompile(pattern).MatchString("\t abc def"), true) - }) -} diff --git a/Godeps/_workspace/src/github.com/obscuren/otto/parser/scope.go b/Godeps/_workspace/src/github.com/obscuren/otto/parser/scope.go deleted file mode 100644 index e1dbdda13..000000000 --- a/Godeps/_workspace/src/github.com/obscuren/otto/parser/scope.go +++ /dev/null @@ -1,44 +0,0 @@ -package parser - -import ( - "github.com/robertkrimen/otto/ast" -) - -type _scope struct { - outer *_scope - allowIn bool - inIteration bool - inSwitch bool - inFunction bool - declarationList []ast.Declaration - - labels []string -} - -func (self *_parser) openScope() { - self.scope = &_scope{ - outer: self.scope, - allowIn: true, - } -} - -func (self *_parser) closeScope() { - self.scope = self.scope.outer -} - -func (self *_scope) declare(declaration ast.Declaration) { - self.declarationList = append(self.declarationList, declaration) -} - -func (self *_scope) hasLabel(name string) bool { - for _, label := range self.labels { - if label == name { - return true - } - } - if self.outer != nil && !self.inFunction { - // Crossing a function boundary to look for a label is verboten - return self.outer.hasLabel(name) - } - return false -} diff --git a/Godeps/_workspace/src/github.com/obscuren/otto/parser/statement.go b/Godeps/_workspace/src/github.com/obscuren/otto/parser/statement.go deleted file mode 100644 index 4c08b523c..000000000 --- a/Godeps/_workspace/src/github.com/obscuren/otto/parser/statement.go +++ /dev/null @@ -1,662 +0,0 @@ -package parser - -import ( - "github.com/robertkrimen/otto/ast" - "github.com/robertkrimen/otto/token" -) - -func (self *_parser) parseBlockStatement() *ast.BlockStatement { - node := &ast.BlockStatement{} - node.LeftBrace = self.expect(token.LEFT_BRACE) - node.List = self.parseStatementList() - node.RightBrace = self.expect(token.RIGHT_BRACE) - - return node -} - -func (self *_parser) parseEmptyStatement() ast.Statement { - idx := self.expect(token.SEMICOLON) - return &ast.EmptyStatement{Semicolon: idx} -} - -func (self *_parser) parseStatementList() (list []ast.Statement) { - for self.token != token.RIGHT_BRACE && self.token != token.EOF { - list = append(list, self.parseStatement()) - } - - return -} - -func (self *_parser) parseStatement() ast.Statement { - - if self.token == token.EOF { - self.errorUnexpectedToken(self.token) - return &ast.BadStatement{From: self.idx, To: self.idx + 1} - } - - switch self.token { - case token.SEMICOLON: - return self.parseEmptyStatement() - case token.LEFT_BRACE: - return self.parseBlockStatement() - case token.IF: - return self.parseIfStatement() - case token.DO: - return self.parseDoWhileStatement() - case token.WHILE: - return self.parseWhileStatement() - case token.FOR: - return self.parseForOrForInStatement() - case token.BREAK: - return self.parseBreakStatement() - case token.CONTINUE: - return self.parseContinueStatement() - case token.DEBUGGER: - return self.parseDebuggerStatement() - case token.WITH: - return self.parseWithStatement() - case token.VAR: - return self.parseVariableStatement() - case token.FUNCTION: - self.parseFunction(true) - // FIXME - return &ast.EmptyStatement{} - case token.SWITCH: - return self.parseSwitchStatement() - case token.RETURN: - return self.parseReturnStatement() - case token.THROW: - return self.parseThrowStatement() - case token.TRY: - return self.parseTryStatement() - } - - expression := self.parseExpression() - - if identifier, isIdentifier := expression.(*ast.Identifier); isIdentifier && self.token == token.COLON { - // LabelledStatement - colon := self.idx - self.next() // : - label := identifier.Name - for _, value := range self.scope.labels { - if label == value { - self.error(identifier.Idx0(), "Label '%s' already exists", label) - } - } - self.scope.labels = append(self.scope.labels, label) // Push the label - statement := self.parseStatement() - self.scope.labels = self.scope.labels[:len(self.scope.labels)-1] // Pop the label - return &ast.LabelledStatement{ - Label: identifier, - Colon: colon, - Statement: statement, - } - } - - self.optionalSemicolon() - - return &ast.ExpressionStatement{ - Expression: expression, - } -} - -func (self *_parser) parseTryStatement() ast.Statement { - - node := &ast.TryStatement{ - Try: self.expect(token.TRY), - Body: self.parseBlockStatement(), - } - - if self.token == token.CATCH { - catch := self.idx - self.next() - self.expect(token.LEFT_PARENTHESIS) - if self.token != token.IDENTIFIER { - self.expect(token.IDENTIFIER) - self.nextStatement() - return &ast.BadStatement{From: catch, To: self.idx} - } else { - identifier := self.parseIdentifier() - self.expect(token.RIGHT_PARENTHESIS) - node.Catch = &ast.CatchStatement{ - Catch: catch, - Parameter: identifier, - Body: self.parseBlockStatement(), - } - } - } - - if self.token == token.FINALLY { - self.next() - node.Finally = self.parseBlockStatement() - } - - if node.Catch == nil && node.Finally == nil { - self.error(node.Try, "Missing catch or finally after try") - return &ast.BadStatement{From: node.Try, To: node.Body.Idx1()} - } - - return node -} - -func (self *_parser) parseFunctionParameterList() *ast.ParameterList { - opening := self.expect(token.LEFT_PARENTHESIS) - var list []*ast.Identifier - for self.token != token.RIGHT_PARENTHESIS && self.token != token.EOF { - if self.token != token.IDENTIFIER { - self.expect(token.IDENTIFIER) - } else { - list = append(list, self.parseIdentifier()) - } - if self.token != token.RIGHT_PARENTHESIS { - self.expect(token.COMMA) - } - } - closing := self.expect(token.RIGHT_PARENTHESIS) - - return &ast.ParameterList{ - Opening: opening, - List: list, - Closing: closing, - } -} - -func (self *_parser) parseParameterList() (list []string) { - for self.token != token.EOF { - if self.token != token.IDENTIFIER { - self.expect(token.IDENTIFIER) - } - list = append(list, self.literal) - self.next() - if self.token != token.EOF { - self.expect(token.COMMA) - } - } - return -} - -func (self *_parser) parseFunction(declaration bool) *ast.FunctionLiteral { - - node := &ast.FunctionLiteral{ - Function: self.expect(token.FUNCTION), - } - - var name *ast.Identifier - if self.token == token.IDENTIFIER { - name = self.parseIdentifier() - if declaration { - self.scope.declare(&ast.FunctionDeclaration{ - Function: node, - }) - } - } else if declaration { - // Use expect error handling - self.expect(token.IDENTIFIER) - } - node.Name = name - node.ParameterList = self.parseFunctionParameterList() - self.parseFunctionBlock(node) - node.Source = self.slice(node.Idx0(), node.Idx1()) - - return node -} - -func (self *_parser) parseFunctionBlock(node *ast.FunctionLiteral) { - { - self.openScope() - inFunction := self.scope.inFunction - self.scope.inFunction = true - defer func() { - self.scope.inFunction = inFunction - self.closeScope() - }() - node.Body = self.parseBlockStatement() - node.DeclarationList = self.scope.declarationList - } -} - -func (self *_parser) parseDebuggerStatement() ast.Statement { - idx := self.expect(token.DEBUGGER) - - node := &ast.DebuggerStatement{ - Debugger: idx, - } - - self.semicolon() - - return node -} - -func (self *_parser) parseReturnStatement() ast.Statement { - idx := self.expect(token.RETURN) - - if !self.scope.inFunction { - self.error(idx, "Illegal return statement") - self.nextStatement() - return &ast.BadStatement{From: idx, To: self.idx} - } - - node := &ast.ReturnStatement{ - Return: idx, - } - - if !self.implicitSemicolon && self.token != token.SEMICOLON && self.token != token.RIGHT_BRACE && self.token != token.EOF { - node.Argument = self.parseExpression() - } - - self.semicolon() - - return node -} - -func (self *_parser) parseThrowStatement() ast.Statement { - idx := self.expect(token.THROW) - - if self.implicitSemicolon { - if self.chr == -1 { // Hackish - self.error(idx, "Unexpected end of input") - } else { - self.error(idx, "Illegal newline after throw") - } - self.nextStatement() - return &ast.BadStatement{From: idx, To: self.idx} - } - - node := &ast.ThrowStatement{ - Argument: self.parseExpression(), - } - - self.semicolon() - - return node -} - -func (self *_parser) parseSwitchStatement() ast.Statement { - self.expect(token.SWITCH) - self.expect(token.LEFT_PARENTHESIS) - node := &ast.SwitchStatement{ - Discriminant: self.parseExpression(), - Default: -1, - } - self.expect(token.RIGHT_PARENTHESIS) - - self.expect(token.LEFT_BRACE) - - inSwitch := self.scope.inSwitch - self.scope.inSwitch = true - defer func() { - self.scope.inSwitch = inSwitch - }() - - for index := 0; self.token != token.EOF; index++ { - if self.token == token.RIGHT_BRACE { - self.next() - break - } - - clause := self.parseCaseStatement() - if clause.Test == nil { - if node.Default != -1 { - self.error(clause.Case, "Already saw a default in switch") - } - node.Default = index - } - node.Body = append(node.Body, clause) - } - - return node -} - -func (self *_parser) parseWithStatement() ast.Statement { - self.expect(token.WITH) - self.expect(token.LEFT_PARENTHESIS) - node := &ast.WithStatement{ - Object: self.parseExpression(), - } - self.expect(token.RIGHT_PARENTHESIS) - - node.Body = self.parseStatement() - - return node -} - -func (self *_parser) parseCaseStatement() *ast.CaseStatement { - - node := &ast.CaseStatement{ - Case: self.idx, - } - if self.token == token.DEFAULT { - self.next() - } else { - self.expect(token.CASE) - node.Test = self.parseExpression() - } - self.expect(token.COLON) - - for { - if self.token == token.EOF || - self.token == token.RIGHT_BRACE || - self.token == token.CASE || - self.token == token.DEFAULT { - break - } - node.Consequent = append(node.Consequent, self.parseStatement()) - - } - - return node -} - -func (self *_parser) parseIterationStatement() ast.Statement { - inIteration := self.scope.inIteration - self.scope.inIteration = true - defer func() { - self.scope.inIteration = inIteration - }() - return self.parseStatement() -} - -func (self *_parser) parseForIn(into ast.Expression) *ast.ForInStatement { - - // Already have consumed "<into> in" - - source := self.parseExpression() - self.expect(token.RIGHT_PARENTHESIS) - - return &ast.ForInStatement{ - Into: into, - Source: source, - Body: self.parseIterationStatement(), - } -} - -func (self *_parser) parseFor(initializer ast.Expression) *ast.ForStatement { - - // Already have consumed "<initializer> ;" - - var test, update ast.Expression - - if self.token != token.SEMICOLON { - test = self.parseExpression() - } - self.expect(token.SEMICOLON) - - if self.token != token.RIGHT_PARENTHESIS { - update = self.parseExpression() - } - self.expect(token.RIGHT_PARENTHESIS) - - return &ast.ForStatement{ - Initializer: initializer, - Test: test, - Update: update, - Body: self.parseIterationStatement(), - } -} - -func (self *_parser) parseForOrForInStatement() ast.Statement { - idx := self.expect(token.FOR) - self.expect(token.LEFT_PARENTHESIS) - - var left []ast.Expression - - forIn := false - if self.token != token.SEMICOLON { - - allowIn := self.scope.allowIn - self.scope.allowIn = false - if self.token == token.VAR { - var_ := self.idx - self.next() - list := self.parseVariableDeclarationList(var_) - if len(list) == 1 && self.token == token.IN { - self.next() // in - forIn = true - left = []ast.Expression{list[0]} // There is only one declaration - } else { - left = list - } - } else { - left = append(left, self.parseExpression()) - if self.token == token.IN { - self.next() - forIn = true - } - } - self.scope.allowIn = allowIn - } - - if forIn { - switch left[0].(type) { - case *ast.Identifier, *ast.DotExpression, *ast.BracketExpression, *ast.VariableExpression: - // These are all acceptable - default: - self.error(idx, "Invalid left-hand side in for-in") - self.nextStatement() - return &ast.BadStatement{From: idx, To: self.idx} - } - return self.parseForIn(left[0]) - } - - self.expect(token.SEMICOLON) - return self.parseFor(&ast.SequenceExpression{Sequence: left}) -} - -func (self *_parser) parseVariableStatement() *ast.VariableStatement { - - idx := self.expect(token.VAR) - - list := self.parseVariableDeclarationList(idx) - self.semicolon() - - return &ast.VariableStatement{ - Var: idx, - List: list, - } -} - -func (self *_parser) parseDoWhileStatement() ast.Statement { - inIteration := self.scope.inIteration - self.scope.inIteration = true - defer func() { - self.scope.inIteration = inIteration - }() - - self.expect(token.DO) - node := &ast.DoWhileStatement{} - if self.token == token.LEFT_BRACE { - node.Body = self.parseBlockStatement() - } else { - node.Body = self.parseStatement() - } - - self.expect(token.WHILE) - self.expect(token.LEFT_PARENTHESIS) - node.Test = self.parseExpression() - self.expect(token.RIGHT_PARENTHESIS) - - return node -} - -func (self *_parser) parseWhileStatement() ast.Statement { - self.expect(token.WHILE) - self.expect(token.LEFT_PARENTHESIS) - node := &ast.WhileStatement{ - Test: self.parseExpression(), - } - self.expect(token.RIGHT_PARENTHESIS) - node.Body = self.parseIterationStatement() - - return node -} - -func (self *_parser) parseIfStatement() ast.Statement { - self.expect(token.IF) - self.expect(token.LEFT_PARENTHESIS) - node := &ast.IfStatement{ - Test: self.parseExpression(), - } - self.expect(token.RIGHT_PARENTHESIS) - - if self.token == token.LEFT_BRACE { - node.Consequent = self.parseBlockStatement() - } else { - node.Consequent = self.parseStatement() - } - - if self.token == token.ELSE { - self.next() - node.Alternate = self.parseStatement() - } - - return node -} - -func (self *_parser) parseSourceElement() ast.Statement { - return self.parseStatement() -} - -func (self *_parser) parseSourceElements() []ast.Statement { - body := []ast.Statement(nil) - - for { - if self.token != token.STRING { - break - } - - body = append(body, self.parseSourceElement()) - } - - for self.token != token.EOF { - body = append(body, self.parseSourceElement()) - } - - return body -} - -func (self *_parser) parseProgram() *ast.Program { - self.openScope() - defer self.closeScope() - return &ast.Program{ - Body: self.parseSourceElements(), - DeclarationList: self.scope.declarationList, - } -} - -func (self *_parser) parseBreakStatement() ast.Statement { - idx := self.expect(token.BREAK) - semicolon := self.implicitSemicolon - if self.token == token.SEMICOLON { - semicolon = true - self.next() - } - - if semicolon || self.token == token.RIGHT_BRACE { - self.implicitSemicolon = false - if !self.scope.inIteration && !self.scope.inSwitch { - goto illegal - } - return &ast.BranchStatement{ - Idx: idx, - Token: token.BREAK, - } - } - - if self.token == token.IDENTIFIER { - identifier := self.parseIdentifier() - if !self.scope.hasLabel(identifier.Name) { - self.error(idx, "Undefined label '%s'", identifier.Name) - return &ast.BadStatement{From: idx, To: identifier.Idx1()} - } - self.semicolon() - return &ast.BranchStatement{ - Idx: idx, - Token: token.BREAK, - Label: identifier, - } - } - - self.expect(token.IDENTIFIER) - -illegal: - self.error(idx, "Illegal break statement") - self.nextStatement() - return &ast.BadStatement{From: idx, To: self.idx} -} - -func (self *_parser) parseContinueStatement() ast.Statement { - idx := self.expect(token.CONTINUE) - semicolon := self.implicitSemicolon - if self.token == token.SEMICOLON { - semicolon = true - self.next() - } - - if semicolon || self.token == token.RIGHT_BRACE { - self.implicitSemicolon = false - if !self.scope.inIteration { - goto illegal - } - return &ast.BranchStatement{ - Idx: idx, - Token: token.CONTINUE, - } - } - - if self.token == token.IDENTIFIER { - identifier := self.parseIdentifier() - if !self.scope.hasLabel(identifier.Name) { - self.error(idx, "Undefined label '%s'", identifier.Name) - return &ast.BadStatement{From: idx, To: identifier.Idx1()} - } - if !self.scope.inIteration { - goto illegal - } - self.semicolon() - return &ast.BranchStatement{ - Idx: idx, - Token: token.CONTINUE, - Label: identifier, - } - } - - self.expect(token.IDENTIFIER) - -illegal: - self.error(idx, "Illegal continue statement") - self.nextStatement() - return &ast.BadStatement{From: idx, To: self.idx} -} - -// Find the next statement after an error (recover) -func (self *_parser) nextStatement() { - for { - switch self.token { - case token.BREAK, token.CONTINUE, - token.FOR, token.IF, token.RETURN, token.SWITCH, - token.VAR, token.DO, token.TRY, token.WITH, - token.WHILE, token.THROW, token.CATCH, token.FINALLY: - // Return only if parser made some progress since last - // sync or if it has not reached 10 next calls without - // progress. Otherwise consume at least one token to - // avoid an endless parser loop - if self.idx == self.recover.idx && self.recover.count < 10 { - self.recover.count++ - return - } - if self.idx > self.recover.idx { - self.recover.idx = self.idx - self.recover.count = 0 - return - } - // Reaching here indicates a parser bug, likely an - // incorrect token list in this function, but it only - // leads to skipping of possibly correct code if a - // previous error is present, and thus is preferred - // over a non-terminating parse. - case token.EOF: - return - } - self.next() - } -} diff --git a/Godeps/_workspace/src/github.com/obscuren/otto/registry/README.markdown b/Godeps/_workspace/src/github.com/obscuren/otto/registry/README.markdown deleted file mode 100644 index ba2d38909..000000000 --- a/Godeps/_workspace/src/github.com/obscuren/otto/registry/README.markdown +++ /dev/null @@ -1,51 +0,0 @@ -# registry --- - import "github.com/robertkrimen/otto/registry" - -Package registry is an expirmental package to facillitate altering the otto -runtime via import. - -This interface can change at any time. - -## Usage - -#### func Apply - -```go -func Apply(callback func(Entry)) -``` - -#### type Entry - -```go -type Entry struct { -} -``` - - -#### func Register - -```go -func Register(source func() string) *Entry -``` - -#### func (*Entry) Disable - -```go -func (self *Entry) Disable() -``` - -#### func (*Entry) Enable - -```go -func (self *Entry) Enable() -``` - -#### func (Entry) Source - -```go -func (self Entry) Source() string -``` - --- -**godocdown** http://github.com/robertkrimen/godocdown diff --git a/Godeps/_workspace/src/github.com/obscuren/otto/registry/registry.go b/Godeps/_workspace/src/github.com/obscuren/otto/registry/registry.go deleted file mode 100644 index 966638ac4..000000000 --- a/Godeps/_workspace/src/github.com/obscuren/otto/registry/registry.go +++ /dev/null @@ -1,47 +0,0 @@ -/* -Package registry is an expirmental package to facillitate altering the otto runtime via import. - -This interface can change at any time. -*/ -package registry - -var registry []*Entry = make([]*Entry, 0) - -type Entry struct { - active bool - source func() string -} - -func newEntry(source func() string) *Entry { - return &Entry{ - active: true, - source: source, - } -} - -func (self *Entry) Enable() { - self.active = true -} - -func (self *Entry) Disable() { - self.active = false -} - -func (self Entry) Source() string { - return self.source() -} - -func Apply(callback func(Entry)) { - for _, entry := range registry { - if !entry.active { - continue - } - callback(*entry) - } -} - -func Register(source func() string) *Entry { - entry := newEntry(source) - registry = append(registry, entry) - return entry -} diff --git a/Godeps/_workspace/src/github.com/obscuren/otto/token/Makefile b/Godeps/_workspace/src/github.com/obscuren/otto/token/Makefile deleted file mode 100644 index 1e85c7348..000000000 --- a/Godeps/_workspace/src/github.com/obscuren/otto/token/Makefile +++ /dev/null @@ -1,2 +0,0 @@ -token_const.go: tokenfmt - ./$^ | gofmt > $@ diff --git a/Godeps/_workspace/src/github.com/obscuren/otto/token/README.markdown b/Godeps/_workspace/src/github.com/obscuren/otto/token/README.markdown deleted file mode 100644 index 1865f23cc..000000000 --- a/Godeps/_workspace/src/github.com/obscuren/otto/token/README.markdown +++ /dev/null @@ -1,171 +0,0 @@ -# token --- - import "github.com/robertkrimen/otto/token" - -Package token defines constants representing the lexical tokens of JavaScript -(ECMA5). - -## Usage - -```go -const ( - ILLEGAL - EOF - COMMENT - KEYWORD - - STRING - BOOLEAN - NULL - NUMBER - IDENTIFIER - - PLUS // + - MINUS // - - MULTIPLY // * - SLASH // / - REMAINDER // % - - AND // & - OR // | - EXCLUSIVE_OR // ^ - SHIFT_LEFT // << - SHIFT_RIGHT // >> - UNSIGNED_SHIFT_RIGHT // >>> - AND_NOT // &^ - - ADD_ASSIGN // += - SUBTRACT_ASSIGN // -= - MULTIPLY_ASSIGN // *= - QUOTIENT_ASSIGN // /= - REMAINDER_ASSIGN // %= - - AND_ASSIGN // &= - OR_ASSIGN // |= - EXCLUSIVE_OR_ASSIGN // ^= - SHIFT_LEFT_ASSIGN // <<= - SHIFT_RIGHT_ASSIGN // >>= - UNSIGNED_SHIFT_RIGHT_ASSIGN // >>>= - AND_NOT_ASSIGN // &^= - - LOGICAL_AND // && - LOGICAL_OR // || - INCREMENT // ++ - DECREMENT // -- - - EQUAL // == - STRICT_EQUAL // === - LESS // < - GREATER // > - ASSIGN // = - NOT // ! - - BITWISE_NOT // ~ - - NOT_EQUAL // != - STRICT_NOT_EQUAL // !== - LESS_OR_EQUAL // <= - GREATER_OR_EQUAL // <= - - LEFT_PARENTHESIS // ( - LEFT_BRACKET // [ - LEFT_BRACE // { - COMMA // , - PERIOD // . - - RIGHT_PARENTHESIS // ) - RIGHT_BRACKET // ] - RIGHT_BRACE // } - SEMICOLON // ; - COLON // : - QUESTION_MARK // ? - - IF - IN - DO - - VAR - FOR - NEW - TRY - - THIS - ELSE - CASE - VOID - WITH - - WHILE - BREAK - CATCH - THROW - - RETURN - TYPEOF - DELETE - SWITCH - - DEFAULT - FINALLY - - FUNCTION - CONTINUE - DEBUGGER - - INSTANCEOF -) -``` - -#### type Token - -```go -type Token int -``` - -Token is the set of lexical tokens in JavaScript (ECMA5). - -#### func IsKeyword - -```go -func IsKeyword(literal string) (Token, bool) -``` -IsKeyword returns the keyword token if literal is a keyword, a KEYWORD token if -the literal is a future keyword (const, let, class, super, ...), or 0 if the -literal is not a keyword. - -If the literal is a keyword, IsKeyword returns a second value indicating if the -literal is considered a future keyword in strict-mode only. - -7.6.1.2 Future Reserved Words: - - const - class - enum - export - extends - import - super - -7.6.1.2 Future Reserved Words (strict): - - implements - interface - let - package - private - protected - public - static - -#### func (Token) String - -```go -func (tkn Token) String() string -``` -String returns the string corresponding to the token. For operators, delimiters, -and keywords the string is the actual token string (e.g., for the token PLUS, -the String() is "+"). For all other tokens the string corresponds to the token -name (e.g. for the token IDENTIFIER, the string is "IDENTIFIER"). - --- -**godocdown** http://github.com/robertkrimen/godocdown diff --git a/Godeps/_workspace/src/github.com/obscuren/otto/token/token.go b/Godeps/_workspace/src/github.com/obscuren/otto/token/token.go deleted file mode 100644 index 0e941ac96..000000000 --- a/Godeps/_workspace/src/github.com/obscuren/otto/token/token.go +++ /dev/null @@ -1,116 +0,0 @@ -// Package token defines constants representing the lexical tokens of JavaScript (ECMA5). -package token - -import ( - "strconv" -) - -// Token is the set of lexical tokens in JavaScript (ECMA5). -type Token int - -// String returns the string corresponding to the token. -// For operators, delimiters, and keywords the string is the actual -// token string (e.g., for the token PLUS, the String() is -// "+"). For all other tokens the string corresponds to the token -// name (e.g. for the token IDENTIFIER, the string is "IDENTIFIER"). -// -func (tkn Token) String() string { - if 0 == tkn { - return "UNKNOWN" - } - if tkn < Token(len(token2string)) { - return token2string[tkn] - } - return "token(" + strconv.Itoa(int(tkn)) + ")" -} - -// This is not used for anything -func (tkn Token) precedence(in bool) int { - - switch tkn { - case LOGICAL_OR: - return 1 - - case LOGICAL_AND: - return 2 - - case OR, OR_ASSIGN: - return 3 - - case EXCLUSIVE_OR: - return 4 - - case AND, AND_ASSIGN, AND_NOT, AND_NOT_ASSIGN: - return 5 - - case EQUAL, - NOT_EQUAL, - STRICT_EQUAL, - STRICT_NOT_EQUAL: - return 6 - - case LESS, GREATER, LESS_OR_EQUAL, GREATER_OR_EQUAL, INSTANCEOF: - return 7 - - case IN: - if in { - return 7 - } - return 0 - - case SHIFT_LEFT, SHIFT_RIGHT, UNSIGNED_SHIFT_RIGHT: - fallthrough - case SHIFT_LEFT_ASSIGN, SHIFT_RIGHT_ASSIGN, UNSIGNED_SHIFT_RIGHT_ASSIGN: - return 8 - - case PLUS, MINUS, ADD_ASSIGN, SUBTRACT_ASSIGN: - return 9 - - case MULTIPLY, SLASH, REMAINDER, MULTIPLY_ASSIGN, QUOTIENT_ASSIGN, REMAINDER_ASSIGN: - return 11 - } - return 0 -} - -type _keyword struct { - token Token - futureKeyword bool - strict bool -} - -// IsKeyword returns the keyword token if literal is a keyword, a KEYWORD token -// if the literal is a future keyword (const, let, class, super, ...), or 0 if the literal is not a keyword. -// -// If the literal is a keyword, IsKeyword returns a second value indicating if the literal -// is considered a future keyword in strict-mode only. -// -// 7.6.1.2 Future Reserved Words: -// -// const -// class -// enum -// export -// extends -// import -// super -// -// 7.6.1.2 Future Reserved Words (strict): -// -// implements -// interface -// let -// package -// private -// protected -// public -// static -// -func IsKeyword(literal string) (Token, bool) { - if keyword, exists := keywordTable[literal]; exists { - if keyword.futureKeyword { - return KEYWORD, keyword.strict - } - return keyword.token, false - } - return 0, false -} diff --git a/Godeps/_workspace/src/github.com/obscuren/otto/token/token_const.go b/Godeps/_workspace/src/github.com/obscuren/otto/token/token_const.go deleted file mode 100644 index 302153349..000000000 --- a/Godeps/_workspace/src/github.com/obscuren/otto/token/token_const.go +++ /dev/null @@ -1,349 +0,0 @@ -package token - -const ( - _ Token = iota - - ILLEGAL - EOF - COMMENT - KEYWORD - - STRING - BOOLEAN - NULL - NUMBER - IDENTIFIER - - PLUS // + - MINUS // - - MULTIPLY // * - SLASH // / - REMAINDER // % - - AND // & - OR // | - EXCLUSIVE_OR // ^ - SHIFT_LEFT // << - SHIFT_RIGHT // >> - UNSIGNED_SHIFT_RIGHT // >>> - AND_NOT // &^ - - ADD_ASSIGN // += - SUBTRACT_ASSIGN // -= - MULTIPLY_ASSIGN // *= - QUOTIENT_ASSIGN // /= - REMAINDER_ASSIGN // %= - - AND_ASSIGN // &= - OR_ASSIGN // |= - EXCLUSIVE_OR_ASSIGN // ^= - SHIFT_LEFT_ASSIGN // <<= - SHIFT_RIGHT_ASSIGN // >>= - UNSIGNED_SHIFT_RIGHT_ASSIGN // >>>= - AND_NOT_ASSIGN // &^= - - LOGICAL_AND // && - LOGICAL_OR // || - INCREMENT // ++ - DECREMENT // -- - - EQUAL // == - STRICT_EQUAL // === - LESS // < - GREATER // > - ASSIGN // = - NOT // ! - - BITWISE_NOT // ~ - - NOT_EQUAL // != - STRICT_NOT_EQUAL // !== - LESS_OR_EQUAL // <= - GREATER_OR_EQUAL // <= - - LEFT_PARENTHESIS // ( - LEFT_BRACKET // [ - LEFT_BRACE // { - COMMA // , - PERIOD // . - - RIGHT_PARENTHESIS // ) - RIGHT_BRACKET // ] - RIGHT_BRACE // } - SEMICOLON // ; - COLON // : - QUESTION_MARK // ? - - firstKeyword - IF - IN - DO - - VAR - FOR - NEW - TRY - - THIS - ELSE - CASE - VOID - WITH - - WHILE - BREAK - CATCH - THROW - - RETURN - TYPEOF - DELETE - SWITCH - - DEFAULT - FINALLY - - FUNCTION - CONTINUE - DEBUGGER - - INSTANCEOF - lastKeyword -) - -var token2string = [...]string{ - ILLEGAL: "ILLEGAL", - EOF: "EOF", - COMMENT: "COMMENT", - KEYWORD: "KEYWORD", - STRING: "STRING", - BOOLEAN: "BOOLEAN", - NULL: "NULL", - NUMBER: "NUMBER", - IDENTIFIER: "IDENTIFIER", - PLUS: "+", - MINUS: "-", - MULTIPLY: "*", - SLASH: "/", - REMAINDER: "%", - AND: "&", - OR: "|", - EXCLUSIVE_OR: "^", - SHIFT_LEFT: "<<", - SHIFT_RIGHT: ">>", - UNSIGNED_SHIFT_RIGHT: ">>>", - AND_NOT: "&^", - ADD_ASSIGN: "+=", - SUBTRACT_ASSIGN: "-=", - MULTIPLY_ASSIGN: "*=", - QUOTIENT_ASSIGN: "/=", - REMAINDER_ASSIGN: "%=", - AND_ASSIGN: "&=", - OR_ASSIGN: "|=", - EXCLUSIVE_OR_ASSIGN: "^=", - SHIFT_LEFT_ASSIGN: "<<=", - SHIFT_RIGHT_ASSIGN: ">>=", - UNSIGNED_SHIFT_RIGHT_ASSIGN: ">>>=", - AND_NOT_ASSIGN: "&^=", - LOGICAL_AND: "&&", - LOGICAL_OR: "||", - INCREMENT: "++", - DECREMENT: "--", - EQUAL: "==", - STRICT_EQUAL: "===", - LESS: "<", - GREATER: ">", - ASSIGN: "=", - NOT: "!", - BITWISE_NOT: "~", - NOT_EQUAL: "!=", - STRICT_NOT_EQUAL: "!==", - LESS_OR_EQUAL: "<=", - GREATER_OR_EQUAL: "<=", - LEFT_PARENTHESIS: "(", - LEFT_BRACKET: "[", - LEFT_BRACE: "{", - COMMA: ",", - PERIOD: ".", - RIGHT_PARENTHESIS: ")", - RIGHT_BRACKET: "]", - RIGHT_BRACE: "}", - SEMICOLON: ";", - COLON: ":", - QUESTION_MARK: "?", - IF: "if", - IN: "in", - DO: "do", - VAR: "var", - FOR: "for", - NEW: "new", - TRY: "try", - THIS: "this", - ELSE: "else", - CASE: "case", - VOID: "void", - WITH: "with", - WHILE: "while", - BREAK: "break", - CATCH: "catch", - THROW: "throw", - RETURN: "return", - TYPEOF: "typeof", - DELETE: "delete", - SWITCH: "switch", - DEFAULT: "default", - FINALLY: "finally", - FUNCTION: "function", - CONTINUE: "continue", - DEBUGGER: "debugger", - INSTANCEOF: "instanceof", -} - -var keywordTable = map[string]_keyword{ - "if": _keyword{ - token: IF, - }, - "in": _keyword{ - token: IN, - }, - "do": _keyword{ - token: DO, - }, - "var": _keyword{ - token: VAR, - }, - "for": _keyword{ - token: FOR, - }, - "new": _keyword{ - token: NEW, - }, - "try": _keyword{ - token: TRY, - }, - "this": _keyword{ - token: THIS, - }, - "else": _keyword{ - token: ELSE, - }, - "case": _keyword{ - token: CASE, - }, - "void": _keyword{ - token: VOID, - }, - "with": _keyword{ - token: WITH, - }, - "while": _keyword{ - token: WHILE, - }, - "break": _keyword{ - token: BREAK, - }, - "catch": _keyword{ - token: CATCH, - }, - "throw": _keyword{ - token: THROW, - }, - "return": _keyword{ - token: RETURN, - }, - "typeof": _keyword{ - token: TYPEOF, - }, - "delete": _keyword{ - token: DELETE, - }, - "switch": _keyword{ - token: SWITCH, - }, - "default": _keyword{ - token: DEFAULT, - }, - "finally": _keyword{ - token: FINALLY, - }, - "function": _keyword{ - token: FUNCTION, - }, - "continue": _keyword{ - token: CONTINUE, - }, - "debugger": _keyword{ - token: DEBUGGER, - }, - "instanceof": _keyword{ - token: INSTANCEOF, - }, - "const": _keyword{ - token: KEYWORD, - futureKeyword: true, - }, - "class": _keyword{ - token: KEYWORD, - futureKeyword: true, - }, - "enum": _keyword{ - token: KEYWORD, - futureKeyword: true, - }, - "export": _keyword{ - token: KEYWORD, - futureKeyword: true, - }, - "extends": _keyword{ - token: KEYWORD, - futureKeyword: true, - }, - "import": _keyword{ - token: KEYWORD, - futureKeyword: true, - }, - "super": _keyword{ - token: KEYWORD, - futureKeyword: true, - }, - "implements": _keyword{ - token: KEYWORD, - futureKeyword: true, - strict: true, - }, - "interface": _keyword{ - token: KEYWORD, - futureKeyword: true, - strict: true, - }, - "let": _keyword{ - token: KEYWORD, - futureKeyword: true, - strict: true, - }, - "package": _keyword{ - token: KEYWORD, - futureKeyword: true, - strict: true, - }, - "private": _keyword{ - token: KEYWORD, - futureKeyword: true, - strict: true, - }, - "protected": _keyword{ - token: KEYWORD, - futureKeyword: true, - strict: true, - }, - "public": _keyword{ - token: KEYWORD, - futureKeyword: true, - strict: true, - }, - "static": _keyword{ - token: KEYWORD, - futureKeyword: true, - strict: true, - }, -} diff --git a/Godeps/_workspace/src/github.com/obscuren/otto/token/tokenfmt b/Godeps/_workspace/src/github.com/obscuren/otto/token/tokenfmt deleted file mode 100644 index 63dd5d9e6..000000000 --- a/Godeps/_workspace/src/github.com/obscuren/otto/token/tokenfmt +++ /dev/null @@ -1,222 +0,0 @@ -#!/usr/bin/env perl - -use strict; -use warnings; - -my (%token, @order, @keywords); - -{ - my $keywords; - my @const; - push @const, <<_END_; -package token - -const( - _ Token = iota -_END_ - - for (split m/\n/, <<_END_) { -ILLEGAL -EOF -COMMENT -KEYWORD - -STRING -BOOLEAN -NULL -NUMBER -IDENTIFIER - -PLUS + -MINUS - -MULTIPLY * -SLASH / -REMAINDER % - -AND & -OR | -EXCLUSIVE_OR ^ -SHIFT_LEFT << -SHIFT_RIGHT >> -UNSIGNED_SHIFT_RIGHT >>> -AND_NOT &^ - -ADD_ASSIGN += -SUBTRACT_ASSIGN -= -MULTIPLY_ASSIGN *= -QUOTIENT_ASSIGN /= -REMAINDER_ASSIGN %= - -AND_ASSIGN &= -OR_ASSIGN |= -EXCLUSIVE_OR_ASSIGN ^= -SHIFT_LEFT_ASSIGN <<= -SHIFT_RIGHT_ASSIGN >>= -UNSIGNED_SHIFT_RIGHT_ASSIGN >>>= -AND_NOT_ASSIGN &^= - -LOGICAL_AND && -LOGICAL_OR || -INCREMENT ++ -DECREMENT -- - -EQUAL == -STRICT_EQUAL === -LESS < -GREATER > -ASSIGN = -NOT ! - -BITWISE_NOT ~ - -NOT_EQUAL != -STRICT_NOT_EQUAL !== -LESS_OR_EQUAL <= -GREATER_OR_EQUAL <= - -LEFT_PARENTHESIS ( -LEFT_BRACKET [ -LEFT_BRACE { -COMMA , -PERIOD . - -RIGHT_PARENTHESIS ) -RIGHT_BRACKET ] -RIGHT_BRACE } -SEMICOLON ; -COLON : -QUESTION_MARK ? - -firstKeyword -IF -IN -DO - -VAR -FOR -NEW -TRY - -THIS -ELSE -CASE -VOID -WITH - -WHILE -BREAK -CATCH -THROW - -RETURN -TYPEOF -DELETE -SWITCH - -DEFAULT -FINALLY - -FUNCTION -CONTINUE -DEBUGGER - -INSTANCEOF -lastKeyword -_END_ - chomp; - - next if m/^\s*#/; - - my ($name, $symbol) = m/(\w+)\s*(\S+)?/; - - if (defined $symbol) { - push @order, $name; - push @const, "$name // $symbol"; - $token{$name} = $symbol; - } elsif (defined $name) { - $keywords ||= $name eq 'firstKeyword'; - - push @const, $name; - #$const[-1] .= " Token = iota" if 2 == @const; - if ($name =~ m/^([A-Z]+)/) { - push @keywords, $name if $keywords; - push @order, $name; - if ($token{SEMICOLON}) { - $token{$name} = lc $1; - } else { - $token{$name} = $name; - } - } - } else { - push @const, ""; - } - - } - push @const, ")"; - print join "\n", @const, ""; -} - -{ - print <<_END_; - -var token2string = [...]string{ -_END_ - for my $name (@order) { - print "$name: \"$token{$name}\",\n"; - } - print <<_END_; -} -_END_ - - print <<_END_; - -var keywordTable = map[string]_keyword{ -_END_ - for my $name (@keywords) { - print <<_END_ - "@{[ lc $name ]}": _keyword{ - token: $name, - }, -_END_ - } - - for my $name (qw/ - const - class - enum - export - extends - import - super - /) { - print <<_END_ - "$name": _keyword{ - token: KEYWORD, - futureKeyword: true, - }, -_END_ - } - - for my $name (qw/ - implements - interface - let - package - private - protected - public - static - /) { - print <<_END_ - "$name": _keyword{ - token: KEYWORD, - futureKeyword: true, - strict: true, - }, -_END_ - } - - print <<_END_; -} -_END_ -} diff --git a/Godeps/_workspace/src/github.com/obscuren/otto/type_error.go b/Godeps/_workspace/src/github.com/obscuren/otto/type_error.go deleted file mode 100644 index 683fcf929..000000000 --- a/Godeps/_workspace/src/github.com/obscuren/otto/type_error.go +++ /dev/null @@ -1,9 +0,0 @@ -package otto - -func (runtime *_runtime) newErrorObject(message Value) *_object { - self := runtime.newClassObject("Error") - if message.IsDefined() { - self.defineProperty("message", toValue_string(toString(message)), 0111, false) - } - return self -} diff --git a/Godeps/_workspace/src/github.com/obscuren/otto/type_function.go b/Godeps/_workspace/src/github.com/obscuren/otto/type_function.go deleted file mode 100644 index 8a6fee9d7..000000000 --- a/Godeps/_workspace/src/github.com/obscuren/otto/type_function.go +++ /dev/null @@ -1,276 +0,0 @@ -package otto - -import ( - "fmt" -) - -type _functionObject struct { - call _callFunction - construct _constructFunction -} - -func (self _functionObject) source(object *_object) string { - return self.call.Source(object) -} - -func (self0 _functionObject) clone(clone *_clone) _functionObject { - return _functionObject{ - clone.callFunction(self0.call), - self0.construct, - } -} - -func (runtime *_runtime) newNativeFunctionObject(name string, native _nativeFunction, length int) *_object { - self := runtime.newClassObject("Function") - self.value = _functionObject{ - call: newNativeCallFunction(native), - construct: defaultConstructFunction, - } - self.defineProperty("length", toValue_int(length), 0000, false) - return self -} - -func (runtime *_runtime) newBoundFunctionObject(target *_object, this Value, argumentList []Value) *_object { - self := runtime.newClassObject("Function") - self.value = _functionObject{ - call: newBoundCallFunction(target, this, argumentList), - construct: newBoundConstructFunction(target), - } - length := int(toInt32(target.get("length"))) - length -= len(argumentList) - if length < 0 { - length = 0 - } - self.defineProperty("length", toValue_int(length), 0000, false) - self.defineProperty("caller", UndefinedValue(), 0000, false) // TODO Should throw a TypeError - self.defineProperty("arguments", UndefinedValue(), 0000, false) // TODO Should throw a TypeError - return self -} - -func (runtime *_runtime) newBoundFunction(target *_object, this Value, argumentList []Value) *_object { - self := runtime.newBoundFunctionObject(target, this, argumentList) - self.prototype = runtime.Global.FunctionPrototype - prototype := runtime.newObject() - self.defineProperty("prototype", toValue_object(prototype), 0100, false) - prototype.defineProperty("constructor", toValue_object(self), 0100, false) - return self -} - -func (self *_object) functionValue() _functionObject { - value, _ := self.value.(_functionObject) - return value -} - -func (self *_object) Call(this Value, argumentList ...interface{}) Value { - if self.functionValue().call == nil { - panic(newTypeError("%v is not a function", toValue_object(self))) - } - return self.runtime.Call(self, this, self.runtime.toValueArray(argumentList...), false) - // ... -> runtime -> self.Function.Call.Dispatch -> ... -} - -func (self *_object) Construct(this Value, argumentList ...interface{}) Value { - function := self.functionValue() - if function.call == nil { - panic(newTypeError("%v is not a function", toValue_object(self))) - } - if function.construct == nil { - panic(newTypeError("%v is not a constructor", toValue_object(self))) - } - return function.construct(self, this, self.runtime.toValueArray(argumentList...)) -} - -func defaultConstructFunction(self *_object, this Value, argumentList []Value) Value { - newObject := self.runtime.newObject() - newObject.class = "Object" - prototypeValue := self.get("prototype") - if !prototypeValue.IsObject() { - prototypeValue = toValue_object(self.runtime.Global.ObjectPrototype) - } - newObject.prototype = prototypeValue._object() - newObjectValue := toValue_object(newObject) - result := self.Call(newObjectValue, argumentList) - if result.IsObject() { - return result - } - return newObjectValue -} - -func (self *_object) callGet(this Value) Value { - return self.runtime.Call(self, this, []Value(nil), false) -} - -func (self *_object) callSet(this Value, value Value) { - self.runtime.Call(self, this, []Value{value}, false) -} - -// 15.3.5.3 -func (self *_object) HasInstance(of Value) bool { - if self.functionValue().call == nil { - // We should not have a HasInstance method - panic(newTypeError()) - } - if !of.IsObject() { - return false - } - prototype := self.get("prototype") - if !prototype.IsObject() { - panic(newTypeError()) - } - prototypeObject := prototype._object() - - value := of._object().prototype - for value != nil { - if value == prototypeObject { - return true - } - value = value.prototype - } - return false -} - -type _nativeFunction func(FunctionCall) Value - -// _constructFunction -type _constructFunction func(*_object, Value, []Value) Value - -// _callFunction -type _callFunction interface { - Dispatch(*_object, *_functionEnvironment, *_runtime, Value, []Value, bool) Value - Source(*_object) string - ScopeEnvironment() _environment - clone(clone *_clone) _callFunction -} - -// _nativeCallFunction -type _nativeCallFunction struct { - name string - function _nativeFunction -} - -func newNativeCallFunction(native _nativeFunction) _nativeCallFunction { - return _nativeCallFunction{"", native} -} - -func (self _nativeCallFunction) Dispatch(_ *_object, _ *_functionEnvironment, runtime *_runtime, this Value, argumentList []Value, evalHint bool) Value { - return self.function(FunctionCall{ - runtime: runtime, - evalHint: evalHint, - - This: this, - ArgumentList: argumentList, - Otto: runtime.Otto, - }) -} - -func (self _nativeCallFunction) ScopeEnvironment() _environment { - return nil -} - -func (self _nativeCallFunction) Source(*_object) string { - return fmt.Sprintf("function %s() { [native code] }", self.name) -} - -func (self0 _nativeCallFunction) clone(clone *_clone) _callFunction { - return self0 -} - -// _boundCallFunction -type _boundCallFunction struct { - target *_object - this Value - argumentList []Value -} - -func newBoundCallFunction(target *_object, this Value, argumentList []Value) *_boundCallFunction { - self := &_boundCallFunction{ - target: target, - this: this, - argumentList: argumentList, - } - return self -} - -func (self _boundCallFunction) Dispatch(_ *_object, _ *_functionEnvironment, runtime *_runtime, this Value, argumentList []Value, _ bool) Value { - argumentList = append(self.argumentList, argumentList...) - return runtime.Call(self.target, self.this, argumentList, false) -} - -func (self _boundCallFunction) ScopeEnvironment() _environment { - return nil -} - -func (self _boundCallFunction) Source(*_object) string { - return "" -} - -func (self0 _boundCallFunction) clone(clone *_clone) _callFunction { - return _boundCallFunction{ - target: clone.object(self0.target), - this: clone.value(self0.this), - argumentList: clone.valueArray(self0.argumentList), - } -} - -func newBoundConstructFunction(target *_object) _constructFunction { - // This is not exactly as described in 15.3.4.5.2, we let [[Call]] supply the - // bound arguments, etc. - return func(self *_object, this Value, argumentList []Value) Value { - switch value := target.value.(type) { - case _functionObject: - return value.construct(self, this, argumentList) - } - panic(newTypeError()) - } -} - -// FunctionCall{} - -// FunctionCall is an encapsulation of a JavaScript function call. -type FunctionCall struct { - runtime *_runtime - _thisObject *_object - evalHint bool - - This Value - ArgumentList []Value - Otto *Otto -} - -// Argument will return the value of the argument at the given index. -// -// If no such argument exists, undefined is returned. -func (self FunctionCall) Argument(index int) Value { - return valueOfArrayIndex(self.ArgumentList, index) -} - -func (self FunctionCall) getArgument(index int) (Value, bool) { - return getValueOfArrayIndex(self.ArgumentList, index) -} - -func (self FunctionCall) slice(index int) []Value { - if index < len(self.ArgumentList) { - return self.ArgumentList[index:] - } - return []Value{} -} - -func (self *FunctionCall) thisObject() *_object { - if self._thisObject == nil { - this := self.runtime.GetValue(self.This) // FIXME Is this right? - self._thisObject = self.runtime.toObject(this) - } - return self._thisObject -} - -func (self *FunctionCall) thisClassObject(class string) *_object { - thisObject := self.thisObject() - if thisObject.class != class { - panic(newTypeError()) - } - return self._thisObject -} - -func (self FunctionCall) toObject(value Value) *_object { - return self.runtime.toObject(value) -} diff --git a/Godeps/_workspace/src/github.com/obscuren/otto/type_reference.go b/Godeps/_workspace/src/github.com/obscuren/otto/type_reference.go deleted file mode 100644 index 6c4f37278..000000000 --- a/Godeps/_workspace/src/github.com/obscuren/otto/type_reference.go +++ /dev/null @@ -1,157 +0,0 @@ -package otto - -import ( - "github.com/robertkrimen/otto/ast" -) - -type _reference interface { - GetBase() interface{} // GetBase - GetName() string // GetReferencedName - IsStrict() bool // IsStrictReference - IsUnresolvable() bool // IsUnresolvableReference - IsPropertyReference() bool // IsPropertyReference - GetValue() Value // GetValue - PutValue(Value) bool // PutValue - Delete() bool -} - -// Reference - -type _referenceDefault struct { - name string - strict bool -} - -func (self _referenceDefault) GetName() string { - return self.name -} - -func (self _referenceDefault) IsStrict() bool { - return self.strict -} - -// PropertyReference - -type _propertyReference struct { - _referenceDefault - Base *_object -} - -func newPropertyReference(base *_object, name string, strict bool) *_propertyReference { - return &_propertyReference{ - Base: base, - _referenceDefault: _referenceDefault{ - name: name, - strict: strict, - }, - } -} - -func (self *_propertyReference) GetBase() interface{} { - return self.Base -} - -func (self *_propertyReference) IsUnresolvable() bool { - return self.Base == nil -} - -func (self *_propertyReference) IsPropertyReference() bool { - return true -} - -func (self *_propertyReference) GetValue() Value { - if self.Base == nil { - panic(newReferenceError("notDefined", self.name)) - } - return self.Base.get(self.name) -} - -func (self *_propertyReference) PutValue(value Value) bool { - if self.Base == nil { - return false - } - self.Base.put(self.name, value, self.IsStrict()) - return true -} - -func (self *_propertyReference) Delete() bool { - if self.Base == nil { - // TODO Throw an error if strict - return true - } - return self.Base.delete(self.name, self.IsStrict()) -} - -// ArgumentReference - -func newArgumentReference(base *_object, name string, strict bool) *_propertyReference { - if base == nil { - panic(hereBeDragons()) - } - return newPropertyReference(base, name, strict) -} - -type _environmentReference struct { - _referenceDefault - Base _environment - node ast.Node -} - -func newEnvironmentReference(base _environment, name string, strict bool, node ast.Node) *_environmentReference { - return &_environmentReference{ - Base: base, - _referenceDefault: _referenceDefault{ - name: name, - strict: strict, - }, - node: node, - } -} - -func (self *_environmentReference) GetBase() interface{} { - return self.Base -} - -func (self *_environmentReference) IsUnresolvable() bool { - return self.Base == nil // The base (an environment) will never be nil -} - -func (self *_environmentReference) IsPropertyReference() bool { - return false -} - -func (self *_environmentReference) GetValue() Value { - if self.Base == nil { - // This should never be reached, but just in case - } - return self.Base.GetValue(self.name, self.IsStrict()) -} - -func (self *_environmentReference) PutValue(value Value) bool { - if self.Base == nil { - // This should never be reached, but just in case - return false - } - self.Base.SetValue(self.name, value, self.IsStrict()) - return true -} - -func (self *_environmentReference) Delete() bool { - if self.Base == nil { - // This should never be reached, but just in case - return false - } - return self.Base.DeleteBinding(self.name) -} - -// getIdentifierReference - -func getIdentifierReference(environment _environment, name string, strict bool) _reference { - if environment == nil { - return newPropertyReference(nil, name, strict) - } - if environment.HasBinding(name) { - return environment.newReference(name, strict) - } - return getIdentifierReference(environment.Outer(), name, strict) -} diff --git a/Godeps/_workspace/src/github.com/obscuren/otto/.gitignore b/Godeps/_workspace/src/github.com/robertkrimen/otto/.gitignore index 8c2a16949..8c2a16949 100644 --- a/Godeps/_workspace/src/github.com/obscuren/otto/.gitignore +++ b/Godeps/_workspace/src/github.com/robertkrimen/otto/.gitignore diff --git a/Godeps/_workspace/src/github.com/obscuren/otto/DESIGN.markdown b/Godeps/_workspace/src/github.com/robertkrimen/otto/DESIGN.markdown index 288752987..288752987 100644 --- a/Godeps/_workspace/src/github.com/obscuren/otto/DESIGN.markdown +++ b/Godeps/_workspace/src/github.com/robertkrimen/otto/DESIGN.markdown diff --git a/Godeps/_workspace/src/github.com/obscuren/otto/LICENSE b/Godeps/_workspace/src/github.com/robertkrimen/otto/LICENSE index b6179fe38..b6179fe38 100644 --- a/Godeps/_workspace/src/github.com/obscuren/otto/LICENSE +++ b/Godeps/_workspace/src/github.com/robertkrimen/otto/LICENSE diff --git a/Godeps/_workspace/src/github.com/obscuren/otto/Makefile b/Godeps/_workspace/src/github.com/robertkrimen/otto/Makefile index 477723bd0..8d74038eb 100644 --- a/Godeps/_workspace/src/github.com/obscuren/otto/Makefile +++ b/Godeps/_workspace/src/github.com/robertkrimen/otto/Makefile @@ -6,8 +6,8 @@ TESTS := \ ~ TEST := -v --run -TEST := -v --run Test\($(subst $(eval) ,\|,$(TESTS))\) TEST := -v +TEST := -v --run Test\($(subst $(eval) ,\|,$(TESTS))\) TEST := . test: parser inline.go diff --git a/Godeps/_workspace/src/github.com/obscuren/otto/README.markdown b/Godeps/_workspace/src/github.com/robertkrimen/otto/README.markdown index 77ad0c4ed..571743bf1 100644 --- a/Godeps/_workspace/src/github.com/obscuren/otto/README.markdown +++ b/Godeps/_workspace/src/github.com/robertkrimen/otto/README.markdown @@ -60,7 +60,7 @@ Set a Go function vm.Set("sayHello", func(call otto.FunctionCall) otto.Value { fmt.Printf("Hello, %s.\n", call.Argument(0).String()) - return otto.UndefinedValue() + return otto.Value{} }) Set a Go function that returns something useful @@ -139,7 +139,6 @@ For more information: http://github.com/robertkrimen/otto/tree/master/underscore The following are some limitations with otto: * "use strict" will parse, but does nothing. - * Error reporting needs to be improved. * The regular expression engine (re2/regexp) is not fully compatible with the ECMA5 specification. @@ -205,16 +204,18 @@ the interrupt channel to do this: } fmt.Fprintf(os.Stderr, "Ran code successfully: %v\n", duration) }() + vm := otto.New() - vm.Interrupt = make(chan func()) + vm.Interrupt = make(chan func(), 1) // The buffer prevents blocking + go func() { time.Sleep(2 * time.Second) // Stop after two seconds vm.Interrupt <- func() { panic(halt) } }() + vm.Run(unsafe) // Here be dragons (risky code) - vm.Interrupt = nil } Where is setTimeout/setInterval? @@ -242,6 +243,36 @@ Here is some more discussion of the issue: var ErrVersion = errors.New("version mismatch") ``` +#### type Error + +```go +type Error struct { +} +``` + +An Error represents a runtime error, e.g. a TypeError, a ReferenceError, etc. + +#### func (Error) Error + +```go +func (err Error) Error() string +``` +Error returns a description of the error + + TypeError: 'def' is not a function + +#### func (Error) String + +```go +func (err Error) String() string +``` +String returns a description of the error and a trace of where the error +occurred. + + TypeError: 'def' is not a function + at xyz (<anonymous>:3:9) + at <anonymous>:7:1/ + #### type FunctionCall ```go @@ -416,16 +447,16 @@ error if there was a problem during compilation. #### func (*Otto) Copy ```go -func (self *Otto) Copy() *Otto +func (in *Otto) Copy() *Otto ``` Copy will create a copy/clone of the runtime. -Copy is useful for saving some processing time when creating many similar -runtimes. +Copy is useful for saving some time when creating many similar runtimes. + +This method works by walking the original runtime and cloning each object, +scope, stash, etc. into a new runtime. -This implementation is alpha-ish, and works by introspecting every part of the -runtime and reallocating and then relinking everything back together. Please -report if you notice any inadvertent sharing of data between copies. +Be on the lookout for memory leaks or inadvertent sharing of resources. #### func (Otto) Get @@ -562,12 +593,10 @@ NullValue will return a Value representing null. func ToValue(value interface{}) (Value, error) ``` ToValue will convert an interface{} value to a value digestible by -otto/JavaScript This function will not work for advanced types (struct, map, -slice/array, etc.) and you probably should not use it. +otto/JavaScript -ToValue may be deprecated and removed in the near future. - -Try Otto.ToValue for a replacement. +This function will not work for advanced types (struct, map, slice/array, etc.) +and you should use Otto.ToValue instead. #### func TrueValue @@ -630,15 +659,13 @@ func (self Value) Export() (interface{}, error) Export will attempt to convert the value to a Go representation and return it via an interface{} kind. -WARNING: The interface function will be changing soon to: - - Export() interface{} +Export returns an error, but it will always be nil. It is present for backwards +compatibility. -If a reasonable conversion is not possible, then the original result is -returned. +If a reasonable conversion is not possible, then the original value is returned. - undefined -> otto.Value (UndefinedValue()) - null -> interface{}(nil) + undefined -> nil (FIXME?: Should be Value{}) + null -> nil boolean -> bool number -> A number type (int, float32, uint64, ...) string -> string diff --git a/Godeps/_workspace/src/github.com/obscuren/otto/array_test.go b/Godeps/_workspace/src/github.com/robertkrimen/otto/array_test.go index 06f481bd4..06f481bd4 100644 --- a/Godeps/_workspace/src/github.com/obscuren/otto/array_test.go +++ b/Godeps/_workspace/src/github.com/robertkrimen/otto/array_test.go diff --git a/Godeps/_workspace/src/github.com/obscuren/otto/bug_test.go b/Godeps/_workspace/src/github.com/robertkrimen/otto/bug_test.go index 0ee484ddd..5e4d90bae 100644 --- a/Godeps/_workspace/src/github.com/obscuren/otto/bug_test.go +++ b/Godeps/_workspace/src/github.com/robertkrimen/otto/bug_test.go @@ -55,7 +55,7 @@ func Test_issue13(t *testing.T) { t.Error(err) t.FailNow() } - is(result.toString(), "Xyzzy,42,def,ghi") + is(result.string(), "Xyzzy,42,def,ghi") anything := struct { Abc interface{} @@ -231,12 +231,12 @@ func Test_issue24(t *testing.T) { } { - vm.Set("abc", testStruct{Abc: true, Ghi: "Nothing happens."}) + vm.Set("abc", _abcStruct{Abc: true, Ghi: "Nothing happens."}) value, err := vm.Get("abc") is(err, nil) export, _ := value.Export() { - value, valid := export.(testStruct) + value, valid := export.(_abcStruct) is(valid, true) is(value.Abc, true) @@ -245,12 +245,12 @@ func Test_issue24(t *testing.T) { } { - vm.Set("abc", &testStruct{Abc: true, Ghi: "Nothing happens."}) + vm.Set("abc", &_abcStruct{Abc: true, Ghi: "Nothing happens."}) value, err := vm.Get("abc") is(err, nil) export, _ := value.Export() { - value, valid := export.(*testStruct) + value, valid := export.(*_abcStruct) is(valid, true) is(value.Abc, true) @@ -313,10 +313,22 @@ func Test_issue64(t *testing.T) { }) } -func Test_7_3_1(t *testing.T) { +func Test_issue73(t *testing.T) { tt(t, func() { + test, vm := test() + + vm.Set("abc", [4]int{3, 2, 1, 0}) + test(` + var def = [ 0, 1, 2, 3 ]; + JSON.stringify(def) + JSON.stringify(abc); + `, "[0,1,2,3][3,2,1,0]") + }) +} +func Test_7_3_1(t *testing.T) { + tt(t, func() { + test(` eval("var test7_3_1\u2028abc = 66;"); [ abc, typeof test7_3_1 ]; `, "66,undefined") @@ -430,13 +442,13 @@ def" test(` var abc = 0; do { - if(typeof(def) === "function"){ - abc = -1; - break; - } else { - abc = 1; - break; - } + if(typeof(def) === "function"){ + abc = -1; + break; + } else { + abc = 1; + break; + } } while(function def(){}); abc; `, 1) @@ -502,3 +514,104 @@ def" `, "1,0,\t abc def,\t abc ") }) } + +func Test_issue79(t *testing.T) { + tt(t, func() { + test, vm := test() + + vm.Set("abc", []_abcStruct{ + { + Ghi: "一", + Def: 1, + }, + { + Def: 3, + Ghi: "三", + }, + { + Def: 2, + Ghi: "二", + }, + { + Def: 4, + Ghi: "四", + }, + }) + + test(` + abc.sort(function(a,b){ return b.Def-a.Def }); + def = []; + for (i = 0; i < abc.length; i++) { + def.push(abc[i].String()) + } + def; + `, "四,三,二,一") + }) +} + +func Test_issue80(t *testing.T) { + tt(t, func() { + test, _ := test() + + test(` + JSON.stringify([ + 1401868959, + 14018689591, + 140186895901, + 1401868959001, + 14018689590001, + 140186895900001, + 1401868959000001, + 1401868959000001.5, + 14018689590000001, + 140186895900000001, + 1401868959000000001, + 14018689590000000001, + 140186895900000000001, + 140186895900000000001.5 + ]); + `, "[1401868959,14018689591,140186895901,1401868959001,14018689590001,140186895900001,1401868959000001,1.4018689590000015e+15,14018689590000001,140186895900000001,1401868959000000001,1.401868959e+19,1.401868959e+20,1.401868959e+20]") + }) +} + +func Test_issue87(t *testing.T) { + tt(t, func() { + test, vm := test() + + test(` + var def = 0; + abc: { + for (;;) { + def = !1; + break abc; + } + def = !0; + } + def; + `, false) + + _, err := vm.Run(` +/* +CryptoJS v3.1.2 +code.google.com/p/crypto-js +(c) 2009-2013 by Jeff Mott. All rights reserved. +code.google.com/p/crypto-js/wiki/License +*/ +var CryptoJS=CryptoJS||function(h,s){var f={},g=f.lib={},q=function(){},m=g.Base={extend:function(a){q.prototype=this;var c=new q;a&&c.mixIn(a);c.hasOwnProperty("init")||(c.init=function(){c.$super.init.apply(this,arguments)});c.init.prototype=c;c.$super=this;return c},create:function(){var a=this.extend();a.init.apply(a,arguments);return a},init:function(){},mixIn:function(a){for(var c in a)a.hasOwnProperty(c)&&(this[c]=a[c]);a.hasOwnProperty("toString")&&(this.toString=a.toString)},clone:function(){return this.init.prototype.extend(this)}}, +r=g.WordArray=m.extend({init:function(a,c){a=this.words=a||[];this.sigBytes=c!=s?c:4*a.length},toString:function(a){return(a||k).stringify(this)},concat:function(a){var c=this.words,d=a.words,b=this.sigBytes;a=a.sigBytes;this.clamp();if(b%4)for(var e=0;e<a;e++)c[b+e>>>2]|=(d[e>>>2]>>>24-8*(e%4)&255)<<24-8*((b+e)%4);else if(65535<d.length)for(e=0;e<a;e+=4)c[b+e>>>2]=d[e>>>2];else c.push.apply(c,d);this.sigBytes+=a;return this},clamp:function(){var a=this.words,c=this.sigBytes;a[c>>>2]&=4294967295<< +32-8*(c%4);a.length=h.ceil(c/4)},clone:function(){var a=m.clone.call(this);a.words=this.words.slice(0);return a},random:function(a){for(var c=[],d=0;d<a;d+=4)c.push(4294967296*h.random()|0);return new r.init(c,a)}}),l=f.enc={},k=l.Hex={stringify:function(a){var c=a.words;a=a.sigBytes;for(var d=[],b=0;b<a;b++){var e=c[b>>>2]>>>24-8*(b%4)&255;d.push((e>>>4).toString(16));d.push((e&15).toString(16))}return d.join("")},parse:function(a){for(var c=a.length,d=[],b=0;b<c;b+=2)d[b>>>3]|=parseInt(a.substr(b, +2),16)<<24-4*(b%8);return new r.init(d,c/2)}},n=l.Latin1={stringify:function(a){var c=a.words;a=a.sigBytes;for(var d=[],b=0;b<a;b++)d.push(String.fromCharCode(c[b>>>2]>>>24-8*(b%4)&255));return d.join("")},parse:function(a){for(var c=a.length,d=[],b=0;b<c;b++)d[b>>>2]|=(a.charCodeAt(b)&255)<<24-8*(b%4);return new r.init(d,c)}},j=l.Utf8={stringify:function(a){try{return decodeURIComponent(escape(n.stringify(a)))}catch(c){throw Error("Malformed UTF-8 data");}},parse:function(a){return n.parse(unescape(encodeURIComponent(a)))}}, +u=g.BufferedBlockAlgorithm=m.extend({reset:function(){this._data=new r.init;this._nDataBytes=0},_append:function(a){"string"==typeof a&&(a=j.parse(a));this._data.concat(a);this._nDataBytes+=a.sigBytes},_process:function(a){var c=this._data,d=c.words,b=c.sigBytes,e=this.blockSize,f=b/(4*e),f=a?h.ceil(f):h.max((f|0)-this._minBufferSize,0);a=f*e;b=h.min(4*a,b);if(a){for(var g=0;g<a;g+=e)this._doProcessBlock(d,g);g=d.splice(0,a);c.sigBytes-=b}return new r.init(g,b)},clone:function(){var a=m.clone.call(this); +a._data=this._data.clone();return a},_minBufferSize:0});g.Hasher=u.extend({cfg:m.extend(),init:function(a){this.cfg=this.cfg.extend(a);this.reset()},reset:function(){u.reset.call(this);this._doReset()},update:function(a){this._append(a);this._process();return this},finalize:function(a){a&&this._append(a);return this._doFinalize()},blockSize:16,_createHelper:function(a){return function(c,d){return(new a.init(d)).finalize(c)}},_createHmacHelper:function(a){return function(c,d){return(new t.HMAC.init(a, +d)).finalize(c)}}});var t=f.algo={};return f}(Math); +(function(h){for(var s=CryptoJS,f=s.lib,g=f.WordArray,q=f.Hasher,f=s.algo,m=[],r=[],l=function(a){return 4294967296*(a-(a|0))|0},k=2,n=0;64>n;){var j;a:{j=k;for(var u=h.sqrt(j),t=2;t<=u;t++)if(!(j%t)){j=!1;break a}j=!0}j&&(8>n&&(m[n]=l(h.pow(k,0.5))),r[n]=l(h.pow(k,1/3)),n++);k++}var a=[],f=f.SHA256=q.extend({_doReset:function(){this._hash=new g.init(m.slice(0))},_doProcessBlock:function(c,d){for(var b=this._hash.words,e=b[0],f=b[1],g=b[2],j=b[3],h=b[4],m=b[5],n=b[6],q=b[7],p=0;64>p;p++){if(16>p)a[p]= +c[d+p]|0;else{var k=a[p-15],l=a[p-2];a[p]=((k<<25|k>>>7)^(k<<14|k>>>18)^k>>>3)+a[p-7]+((l<<15|l>>>17)^(l<<13|l>>>19)^l>>>10)+a[p-16]}k=q+((h<<26|h>>>6)^(h<<21|h>>>11)^(h<<7|h>>>25))+(h&m^~h&n)+r[p]+a[p];l=((e<<30|e>>>2)^(e<<19|e>>>13)^(e<<10|e>>>22))+(e&f^e&g^f&g);q=n;n=m;m=h;h=j+k|0;j=g;g=f;f=e;e=k+l|0}b[0]=b[0]+e|0;b[1]=b[1]+f|0;b[2]=b[2]+g|0;b[3]=b[3]+j|0;b[4]=b[4]+h|0;b[5]=b[5]+m|0;b[6]=b[6]+n|0;b[7]=b[7]+q|0},_doFinalize:function(){var a=this._data,d=a.words,b=8*this._nDataBytes,e=8*a.sigBytes; +d[e>>>5]|=128<<24-e%32;d[(e+64>>>9<<4)+14]=h.floor(b/4294967296);d[(e+64>>>9<<4)+15]=b;a.sigBytes=4*d.length;this._process();return this._hash},clone:function(){var a=q.clone.call(this);a._hash=this._hash.clone();return a}});s.SHA256=q._createHelper(f);s.HmacSHA256=q._createHmacHelper(f)})(Math); +(function(){var h=CryptoJS,s=h.enc.Utf8;h.algo.HMAC=h.lib.Base.extend({init:function(f,g){f=this._hasher=new f.init;"string"==typeof g&&(g=s.parse(g));var h=f.blockSize,m=4*h;g.sigBytes>m&&(g=f.finalize(g));g.clamp();for(var r=this._oKey=g.clone(),l=this._iKey=g.clone(),k=r.words,n=l.words,j=0;j<h;j++)k[j]^=1549556828,n[j]^=909522486;r.sigBytes=l.sigBytes=m;this.reset()},reset:function(){var f=this._hasher;f.reset();f.update(this._iKey)},update:function(f){this._hasher.update(f);return this},finalize:function(f){var g= +this._hasher;f=g.finalize(f);g.reset();return g.finalize(this._oKey.clone().concat(f))}})})(); + `) + is(err, nil) + + test(`CryptoJS.HmacSHA256("Message", "secret");`, "aa747c502a898200f9e4fa21bac68136f886a0e27aec70ba06daf2e2a5cb5597") + }) +} diff --git a/Godeps/_workspace/src/github.com/obscuren/otto/builtin.go b/Godeps/_workspace/src/github.com/robertkrimen/otto/builtin.go index b4cdf9d21..c3375a108 100644 --- a/Godeps/_workspace/src/github.com/obscuren/otto/builtin.go +++ b/Godeps/_workspace/src/github.com/robertkrimen/otto/builtin.go @@ -2,7 +2,6 @@ package otto import ( "encoding/hex" - "fmt" "math" "net/url" "regexp" @@ -19,25 +18,26 @@ func builtinGlobal_eval(call FunctionCall) Value { return src } runtime := call.runtime - program := runtime.cmpl_parseOrThrow(toString(src)) - if call.evalHint { - runtime.EnterEvalExecutionContext(call) - defer runtime.LeaveExecutionContext() + program := runtime.cmpl_parseOrThrow(src.string()) + if !call.eval { + // Not a direct call to eval, so we enter the global ExecutionContext + runtime.enterGlobalScope() + defer runtime.leaveScope() } - returnValue := runtime.cmpl_evaluate_nodeProgram(program) + returnValue := runtime.cmpl_evaluate_nodeProgram(program, true) if returnValue.isEmpty() { - return UndefinedValue() + return Value{} } return returnValue } func builtinGlobal_isNaN(call FunctionCall) Value { - value := toFloat(call.Argument(0)) + value := call.Argument(0).float64() return toValue_bool(math.IsNaN(value)) } func builtinGlobal_isFinite(call FunctionCall) Value { - value := toFloat(call.Argument(0)) + value := call.Argument(0).float64() return toValue_bool(!math.IsNaN(value) && !math.IsInf(value, 0)) } @@ -70,7 +70,7 @@ func digitValue(chr rune) int { } func builtinGlobal_parseInt(call FunctionCall) Value { - input := strings.TrimSpace(toString(call.Argument(0))) + input := strings.TrimSpace(call.Argument(0).string()) if len(input) == 0 { return NaNValue() } @@ -153,7 +153,7 @@ var parseFloat_matchValid = regexp.MustCompile(`[0-9eE\+\-\.]|Infinity`) func builtinGlobal_parseFloat(call FunctionCall) Value { // Caveat emptor: This implementation does NOT match the specification - input := strings.TrimSpace(toString(call.Argument(0))) + input := strings.TrimSpace(call.Argument(0).string()) if parseFloat_matchBadSpecial.MatchString(input) { return NaNValue() } @@ -185,7 +185,7 @@ func _builtinGlobal_encodeURI(call FunctionCall, escape *regexp.Regexp) Value { case []uint16: input = vl default: - input = utf16.Encode([]rune(toString(value))) + input = utf16.Encode([]rune(value.string())) } if len(input) == 0 { return toValue_string("") @@ -197,18 +197,17 @@ func _builtinGlobal_encodeURI(call FunctionCall, escape *regexp.Regexp) Value { value := input[index] decode := utf16.Decode(input[index : index+1]) if value >= 0xDC00 && value <= 0xDFFF { - panic(newURIError("URI malformed")) + panic(call.runtime.panicURIError("URI malformed")) } if value >= 0xD800 && value <= 0xDBFF { index += 1 if index >= length { - panic(newURIError("URI malformed")) + panic(call.runtime.panicURIError("URI malformed")) } // input = ..., value, value1, ... - value = value value1 := input[index] if value1 < 0xDC00 || value1 > 0xDFFF { - panic(newURIError("URI malformed")) + panic(call.runtime.panicURIError("URI malformed")) } decode = []rune{((rune(value) - 0xD800) * 0x400) + (rune(value1) - 0xDC00) + 0x10000} } @@ -257,17 +256,17 @@ func _decodeURI(input string, reserve bool) (string, bool) { } func builtinGlobal_decodeURI(call FunctionCall) Value { - output, err := _decodeURI(toString(call.Argument(0)), true) + output, err := _decodeURI(call.Argument(0).string(), true) if err { - panic(newURIError("URI malformed")) + panic(call.runtime.panicURIError("URI malformed")) } return toValue_string(output) } func builtinGlobal_decodeURIComponent(call FunctionCall) Value { - output, err := _decodeURI(toString(call.Argument(0)), false) + output, err := _decodeURI(call.Argument(0).string(), false) if err { - panic(newURIError("URI malformed")) + panic(call.runtime.panicURIError("URI malformed")) } return toValue_string(output) } @@ -346,48 +345,9 @@ func builtin_unescape(input string) string { } func builtinGlobal_escape(call FunctionCall) Value { - return toValue_string(builtin_escape(toString(call.Argument(0)))) + return toValue_string(builtin_escape(call.Argument(0).string())) } func builtinGlobal_unescape(call FunctionCall) Value { - return toValue_string(builtin_unescape(toString(call.Argument(0)))) -} - -// Error - -func builtinError(call FunctionCall) Value { - return toValue_object(call.runtime.newError("", call.Argument(0))) -} - -func builtinNewError(self *_object, _ Value, argumentList []Value) Value { - return toValue_object(self.runtime.newError("", valueOfArrayIndex(argumentList, 0))) -} - -func builtinError_toString(call FunctionCall) Value { - thisObject := call.thisObject() - if thisObject == nil { - panic(newTypeError()) - } - - name := "Error" - nameValue := thisObject.get("name") - if nameValue.IsDefined() { - name = toString(nameValue) - } - - message := "" - messageValue := thisObject.get("message") - if messageValue.IsDefined() { - message = toString(messageValue) - } - - if len(name) == 0 { - return toValue_string(message) - } - - if len(message) == 0 { - return toValue_string(name) - } - - return toValue_string(fmt.Sprintf("%s: %s", name, message)) + return toValue_string(builtin_unescape(call.Argument(0).string())) } diff --git a/Godeps/_workspace/src/github.com/obscuren/otto/builtin_array.go b/Godeps/_workspace/src/github.com/robertkrimen/otto/builtin_array.go index aefae1855..44bf88569 100644 --- a/Godeps/_workspace/src/github.com/obscuren/otto/builtin_array.go +++ b/Godeps/_workspace/src/github.com/robertkrimen/otto/builtin_array.go @@ -11,7 +11,7 @@ func builtinArray(call FunctionCall) Value { return toValue_object(builtinNewArrayNative(call.runtime, call.ArgumentList)) } -func builtinNewArray(self *_object, _ Value, argumentList []Value) Value { +func builtinNewArray(self *_object, argumentList []Value) Value { return toValue_object(builtinNewArrayNative(self.runtime, argumentList)) } @@ -19,7 +19,7 @@ func builtinNewArrayNative(runtime *_runtime, argumentList []Value) *_object { if len(argumentList) == 1 { firstArgument := argumentList[0] if firstArgument.IsNumber() { - return runtime.newArray(arrayUint32(firstArgument)) + return runtime.newArray(arrayUint32(runtime, firstArgument)) } } return runtime.newArrayOf(argumentList) @@ -30,7 +30,7 @@ func builtinArray_toString(call FunctionCall) Value { join := thisObject.get("join") if join.isCallable() { join := join._object() - return join.Call(call.This, call.ArgumentList) + return join.call(call.This, call.ArgumentList, false, nativeFrame) } return builtinObject_toString(call) } @@ -46,15 +46,15 @@ func builtinArray_toLocaleString(call FunctionCall) Value { for index := int64(0); index < length; index += 1 { value := thisObject.get(arrayIndexToString(index)) stringValue := "" - switch value._valueType { + switch value.kind { case valueEmpty, valueUndefined, valueNull: default: object := call.runtime.toObject(value) toLocaleString := object.get("toLocaleString") if !toLocaleString.isCallable() { - panic(newTypeError()) + panic(call.runtime.panicTypeError()) } - stringValue = toLocaleString.call(toValue_object(object)).toString() + stringValue = toLocaleString.call(call.runtime, toValue_object(object)).string() } stringList = append(stringList, stringValue) } @@ -66,11 +66,11 @@ func builtinArray_concat(call FunctionCall) Value { valueArray := []Value{} source := append([]Value{toValue_object(thisObject)}, call.ArgumentList...) for _, item := range source { - switch item._valueType { + switch item.kind { case valueObject: object := item._object() if isArray(object) { - length := toInteger(object.get("length")).value + length := object.get("length").number().int64 for index := int64(0); index < length; index += 1 { name := strconv.FormatInt(index, 10) if object.hasProperty(name) { @@ -94,7 +94,7 @@ func builtinArray_shift(call FunctionCall) Value { length := int64(toUint32(thisObject.get("length"))) if 0 == length { thisObject.put("length", toValue_int64(0), true) - return UndefinedValue() + return Value{} } first := thisObject.get("0") for index := int64(1); index < length; index++ { @@ -130,7 +130,7 @@ func builtinArray_pop(call FunctionCall) Value { length := int64(toUint32(thisObject.get("length"))) if 0 == length { thisObject.put("length", toValue_uint32(0), true) - return UndefinedValue() + return Value{} } last := thisObject.get(arrayIndexToString(length - 1)) thisObject.delete(arrayIndexToString(length-1), true) @@ -143,7 +143,7 @@ func builtinArray_join(call FunctionCall) Value { { argument := call.Argument(0) if argument.IsDefined() { - separator = toString(argument) + separator = argument.string() } } thisObject := call.thisObject() @@ -155,10 +155,10 @@ func builtinArray_join(call FunctionCall) Value { for index := int64(0); index < length; index += 1 { value := thisObject.get(arrayIndexToString(index)) stringValue := "" - switch value._valueType { + switch value.kind { case valueEmpty, valueUndefined, valueNull: default: - stringValue = toString(value) + stringValue = value.string() } stringList = append(stringList, stringValue) } @@ -370,8 +370,8 @@ func sortCompare(thisObject *_object, index0, index1 uint, compare *_object) int } if compare == nil { - j.value = toString(x) - k.value = toString(y) + j.value = x.string() + k.value = y.string() if j.value == k.value { return 0 @@ -382,7 +382,7 @@ func sortCompare(thisObject *_object, index0, index1 uint, compare *_object) int return 1 } - return int(toInt32(compare.Call(UndefinedValue(), []Value{x, y}))) + return int(toInt32(compare.call(Value{}, []Value{x, y}, false, nativeFrame))) } func arraySortSwap(thisObject *_object, index0, index1 uint) { @@ -447,7 +447,7 @@ func builtinArray_sort(call FunctionCall) Value { compare := compareValue._object() if compareValue.IsUndefined() { } else if !compareValue.isCallable() { - panic(newTypeError()) + panic(call.runtime.panicTypeError()) } if length > 1 { arraySortQuickSort(thisObject, 0, length-1, compare) @@ -464,7 +464,7 @@ func builtinArray_indexOf(call FunctionCall) Value { if length := int64(toUint32(thisObject.get("length"))); length > 0 { index := int64(0) if len(call.ArgumentList) > 1 { - index = toInteger(call.Argument(1)).value + index = call.Argument(1).number().int64 } if index < 0 { if index += length; index < 0 { @@ -492,7 +492,7 @@ func builtinArray_lastIndexOf(call FunctionCall) Value { length := int64(toUint32(thisObject.get("length"))) index := length - 1 if len(call.ArgumentList) > 1 { - index = toInteger(call.Argument(1)).value + index = call.Argument(1).number().int64 } if 0 > index { index += length @@ -523,15 +523,15 @@ func builtinArray_every(call FunctionCall) Value { callThis := call.Argument(1) for index := int64(0); index < length; index++ { if key := arrayIndexToString(index); thisObject.hasProperty(key) { - if value := thisObject.get(key); iterator.call(callThis, value, toValue_int64(index), this).isTrue() { + if value := thisObject.get(key); iterator.call(call.runtime, callThis, value, toValue_int64(index), this).bool() { continue } - return FalseValue() + return falseValue } } - return TrueValue() + return trueValue } - panic(newTypeError()) + panic(call.runtime.panicTypeError()) } func builtinArray_some(call FunctionCall) Value { @@ -542,14 +542,14 @@ func builtinArray_some(call FunctionCall) Value { callThis := call.Argument(1) for index := int64(0); index < length; index++ { if key := arrayIndexToString(index); thisObject.hasProperty(key) { - if value := thisObject.get(key); iterator.call(callThis, value, toValue_int64(index), this).isTrue() { - return TrueValue() + if value := thisObject.get(key); iterator.call(call.runtime, callThis, value, toValue_int64(index), this).bool() { + return trueValue } } } - return FalseValue() + return falseValue } - panic(newTypeError()) + panic(call.runtime.panicTypeError()) } func builtinArray_forEach(call FunctionCall) Value { @@ -560,12 +560,12 @@ func builtinArray_forEach(call FunctionCall) Value { callThis := call.Argument(1) for index := int64(0); index < length; index++ { if key := arrayIndexToString(index); thisObject.hasProperty(key) { - iterator.call(callThis, thisObject.get(key), toValue_int64(index), this) + iterator.call(call.runtime, callThis, thisObject.get(key), toValue_int64(index), this) } } - return UndefinedValue() + return Value{} } - panic(newTypeError()) + panic(call.runtime.panicTypeError()) } func builtinArray_map(call FunctionCall) Value { @@ -577,14 +577,14 @@ func builtinArray_map(call FunctionCall) Value { values := make([]Value, length) for index := int64(0); index < length; index++ { if key := arrayIndexToString(index); thisObject.hasProperty(key) { - values[index] = iterator.call(callThis, thisObject.get(key), index, this) + values[index] = iterator.call(call.runtime, callThis, thisObject.get(key), index, this) } else { - values[index] = UndefinedValue() + values[index] = Value{} } } return toValue_object(call.runtime.newArrayOf(values)) } - panic(newTypeError()) + panic(call.runtime.panicTypeError()) } func builtinArray_filter(call FunctionCall) Value { @@ -597,14 +597,14 @@ func builtinArray_filter(call FunctionCall) Value { for index := int64(0); index < length; index++ { if key := arrayIndexToString(index); thisObject.hasProperty(key) { value := thisObject.get(key) - if iterator.call(callThis, value, index, this).isTrue() { + if iterator.call(call.runtime, callThis, value, index, this).bool() { values = append(values, value) } } } return toValue_object(call.runtime.newArrayOf(values)) } - panic(newTypeError()) + panic(call.runtime.panicTypeError()) } func builtinArray_reduce(call FunctionCall) Value { @@ -630,13 +630,13 @@ func builtinArray_reduce(call FunctionCall) Value { } for ; index < length; index++ { if key := arrayIndexToString(index); thisObject.hasProperty(key) { - accumulator = iterator.call(UndefinedValue(), accumulator, thisObject.get(key), key, this) + accumulator = iterator.call(call.runtime, Value{}, accumulator, thisObject.get(key), key, this) } } return accumulator } } - panic(newTypeError()) + panic(call.runtime.panicTypeError()) } func builtinArray_reduceRight(call FunctionCall) Value { @@ -662,11 +662,11 @@ func builtinArray_reduceRight(call FunctionCall) Value { } for ; index >= 0; index-- { if key := arrayIndexToString(index); thisObject.hasProperty(key) { - accumulator = iterator.call(UndefinedValue(), accumulator, thisObject.get(key), key, this) + accumulator = iterator.call(call.runtime, Value{}, accumulator, thisObject.get(key), key, this) } } return accumulator } } - panic(newTypeError()) + panic(call.runtime.panicTypeError()) } diff --git a/Godeps/_workspace/src/github.com/obscuren/otto/builtin_boolean.go b/Godeps/_workspace/src/github.com/robertkrimen/otto/builtin_boolean.go index 1aec693ce..59b8e789b 100644 --- a/Godeps/_workspace/src/github.com/obscuren/otto/builtin_boolean.go +++ b/Godeps/_workspace/src/github.com/robertkrimen/otto/builtin_boolean.go @@ -3,10 +3,10 @@ package otto // Boolean func builtinBoolean(call FunctionCall) Value { - return toValue_bool(toBoolean(call.Argument(0))) + return toValue_bool(call.Argument(0).bool()) } -func builtinNewBoolean(self *_object, _ Value, argumentList []Value) Value { +func builtinNewBoolean(self *_object, argumentList []Value) Value { return toValue_object(self.runtime.newBoolean(valueOfArrayIndex(argumentList, 0))) } @@ -16,7 +16,7 @@ func builtinBoolean_toString(call FunctionCall) Value { // Will throw a TypeError if ThisObject is not a Boolean value = call.thisClassObject("Boolean").primitiveValue() } - return toValue_string(toString(value)) + return toValue_string(value.string()) } func builtinBoolean_valueOf(call FunctionCall) Value { diff --git a/Godeps/_workspace/src/github.com/obscuren/otto/builtin_date.go b/Godeps/_workspace/src/github.com/robertkrimen/otto/builtin_date.go index 439d367bc..f20bf8e3f 100644 --- a/Godeps/_workspace/src/github.com/obscuren/otto/builtin_date.go +++ b/Godeps/_workspace/src/github.com/robertkrimen/otto/builtin_date.go @@ -21,12 +21,12 @@ func builtinDate(call FunctionCall) Value { return toValue_string(date.Time().Format(builtinDate_goDateTimeLayout)) } -func builtinNewDate(self *_object, _ Value, argumentList []Value) Value { +func builtinNewDate(self *_object, argumentList []Value) Value { return toValue_object(self.runtime.newDate(newDateTime(argumentList, Time.Local))) } func builtinDate_toString(call FunctionCall) Value { - date := dateObjectOf(call.thisObject()) + date := dateObjectOf(call.runtime, call.thisObject()) if date.isNaN { return toValue_string("Invalid Date") } @@ -34,7 +34,7 @@ func builtinDate_toString(call FunctionCall) Value { } func builtinDate_toDateString(call FunctionCall) Value { - date := dateObjectOf(call.thisObject()) + date := dateObjectOf(call.runtime, call.thisObject()) if date.isNaN { return toValue_string("Invalid Date") } @@ -42,7 +42,7 @@ func builtinDate_toDateString(call FunctionCall) Value { } func builtinDate_toTimeString(call FunctionCall) Value { - date := dateObjectOf(call.thisObject()) + date := dateObjectOf(call.runtime, call.thisObject()) if date.isNaN { return toValue_string("Invalid Date") } @@ -50,7 +50,7 @@ func builtinDate_toTimeString(call FunctionCall) Value { } func builtinDate_toUTCString(call FunctionCall) Value { - date := dateObjectOf(call.thisObject()) + date := dateObjectOf(call.runtime, call.thisObject()) if date.isNaN { return toValue_string("Invalid Date") } @@ -58,7 +58,7 @@ func builtinDate_toUTCString(call FunctionCall) Value { } func builtinDate_toISOString(call FunctionCall) Value { - date := dateObjectOf(call.thisObject()) + date := dateObjectOf(call.runtime, call.thisObject()) if date.isNaN { return toValue_string("Invalid Date") } @@ -69,20 +69,21 @@ func builtinDate_toJSON(call FunctionCall) Value { object := call.thisObject() value := object.DefaultValue(defaultValueHintNumber) // FIXME object.primitiveNumberValue { // FIXME value.isFinite - value := toFloat(value) + value := value.float64() if math.IsNaN(value) || math.IsInf(value, 0) { - return NullValue() + return nullValue } } toISOString := object.get("toISOString") if !toISOString.isCallable() { - panic(newTypeError()) + // FIXME + panic(call.runtime.panicTypeError()) } - return toISOString.call(toValue_object(object), []Value{}) + return toISOString.call(call.runtime, toValue_object(object), []Value{}) } func builtinDate_toGMTString(call FunctionCall) Value { - date := dateObjectOf(call.thisObject()) + date := dateObjectOf(call.runtime, call.thisObject()) if date.isNaN { return toValue_string("Invalid Date") } @@ -90,7 +91,7 @@ func builtinDate_toGMTString(call FunctionCall) Value { } func builtinDate_getTime(call FunctionCall) Value { - date := dateObjectOf(call.thisObject()) + date := dateObjectOf(call.runtime, call.thisObject()) if date.isNaN { return NaNValue() } @@ -101,15 +102,15 @@ func builtinDate_getTime(call FunctionCall) Value { func builtinDate_setTime(call FunctionCall) Value { object := call.thisObject() - date := dateObjectOf(object) - date.Set(toFloat(call.Argument(0))) + date := dateObjectOf(call.runtime, call.thisObject()) + date.Set(call.Argument(0).float64()) object.value = date return date.Value() } func _builtinDate_beforeSet(call FunctionCall, argumentLimit int, timeLocal bool) (*_object, *_dateObject, *_ecmaTime, []int) { object := call.thisObject() - date := dateObjectOf(object) + date := dateObjectOf(call.runtime, call.thisObject()) if date.isNaN { return nil, nil, nil, nil } @@ -126,16 +127,14 @@ func _builtinDate_beforeSet(call FunctionCall, argumentLimit int, timeLocal bool valueList := make([]int, argumentLimit) for index := 0; index < argumentLimit; index++ { value := call.ArgumentList[index] - if value.IsNaN() { + nm := value.number() + switch nm.kind { + case numberInteger, numberFloat: + default: object.value = invalidDateObject return nil, nil, nil, nil } - integer := toInteger(value) - if !integer.valid() { - object.value = invalidDateObject - return nil, nil, nil, nil - } - valueList[index] = int(integer.value) + valueList[index] = int(nm.int64) } baseTime := date.Time() if timeLocal { @@ -146,7 +145,7 @@ func _builtinDate_beforeSet(call FunctionCall, argumentLimit int, timeLocal bool } func builtinDate_parse(call FunctionCall) Value { - date := toString(call.Argument(0)) + date := call.Argument(0).string() return toValue_float64(dateParse(date)) } @@ -161,7 +160,7 @@ func builtinDate_now(call FunctionCall) Value { // This is a placeholder func builtinDate_toLocaleString(call FunctionCall) Value { - date := dateObjectOf(call.thisObject()) + date := dateObjectOf(call.runtime, call.thisObject()) if date.isNaN { return toValue_string("Invalid Date") } @@ -170,7 +169,7 @@ func builtinDate_toLocaleString(call FunctionCall) Value { // This is a placeholder func builtinDate_toLocaleDateString(call FunctionCall) Value { - date := dateObjectOf(call.thisObject()) + date := dateObjectOf(call.runtime, call.thisObject()) if date.isNaN { return toValue_string("Invalid Date") } @@ -179,7 +178,7 @@ func builtinDate_toLocaleDateString(call FunctionCall) Value { // This is a placeholder func builtinDate_toLocaleTimeString(call FunctionCall) Value { - date := dateObjectOf(call.thisObject()) + date := dateObjectOf(call.runtime, call.thisObject()) if date.isNaN { return toValue_string("Invalid Date") } @@ -187,7 +186,7 @@ func builtinDate_toLocaleTimeString(call FunctionCall) Value { } func builtinDate_valueOf(call FunctionCall) Value { - date := dateObjectOf(call.thisObject()) + date := dateObjectOf(call.runtime, call.thisObject()) if date.isNaN { return NaNValue() } @@ -197,7 +196,7 @@ func builtinDate_valueOf(call FunctionCall) Value { func builtinDate_getYear(call FunctionCall) Value { // Will throw a TypeError is ThisObject is nil or // does not have Class of "Date" - date := dateObjectOf(call.thisObject()) + date := dateObjectOf(call.runtime, call.thisObject()) if date.isNaN { return NaNValue() } @@ -207,7 +206,7 @@ func builtinDate_getYear(call FunctionCall) Value { func builtinDate_getFullYear(call FunctionCall) Value { // Will throw a TypeError is ThisObject is nil or // does not have Class of "Date" - date := dateObjectOf(call.thisObject()) + date := dateObjectOf(call.runtime, call.thisObject()) if date.isNaN { return NaNValue() } @@ -215,7 +214,7 @@ func builtinDate_getFullYear(call FunctionCall) Value { } func builtinDate_getUTCFullYear(call FunctionCall) Value { - date := dateObjectOf(call.thisObject()) + date := dateObjectOf(call.runtime, call.thisObject()) if date.isNaN { return NaNValue() } @@ -223,7 +222,7 @@ func builtinDate_getUTCFullYear(call FunctionCall) Value { } func builtinDate_getMonth(call FunctionCall) Value { - date := dateObjectOf(call.thisObject()) + date := dateObjectOf(call.runtime, call.thisObject()) if date.isNaN { return NaNValue() } @@ -231,7 +230,7 @@ func builtinDate_getMonth(call FunctionCall) Value { } func builtinDate_getUTCMonth(call FunctionCall) Value { - date := dateObjectOf(call.thisObject()) + date := dateObjectOf(call.runtime, call.thisObject()) if date.isNaN { return NaNValue() } @@ -239,7 +238,7 @@ func builtinDate_getUTCMonth(call FunctionCall) Value { } func builtinDate_getDate(call FunctionCall) Value { - date := dateObjectOf(call.thisObject()) + date := dateObjectOf(call.runtime, call.thisObject()) if date.isNaN { return NaNValue() } @@ -247,7 +246,7 @@ func builtinDate_getDate(call FunctionCall) Value { } func builtinDate_getUTCDate(call FunctionCall) Value { - date := dateObjectOf(call.thisObject()) + date := dateObjectOf(call.runtime, call.thisObject()) if date.isNaN { return NaNValue() } @@ -256,7 +255,7 @@ func builtinDate_getUTCDate(call FunctionCall) Value { func builtinDate_getDay(call FunctionCall) Value { // Actually day of the week - date := dateObjectOf(call.thisObject()) + date := dateObjectOf(call.runtime, call.thisObject()) if date.isNaN { return NaNValue() } @@ -264,7 +263,7 @@ func builtinDate_getDay(call FunctionCall) Value { } func builtinDate_getUTCDay(call FunctionCall) Value { - date := dateObjectOf(call.thisObject()) + date := dateObjectOf(call.runtime, call.thisObject()) if date.isNaN { return NaNValue() } @@ -272,7 +271,7 @@ func builtinDate_getUTCDay(call FunctionCall) Value { } func builtinDate_getHours(call FunctionCall) Value { - date := dateObjectOf(call.thisObject()) + date := dateObjectOf(call.runtime, call.thisObject()) if date.isNaN { return NaNValue() } @@ -280,7 +279,7 @@ func builtinDate_getHours(call FunctionCall) Value { } func builtinDate_getUTCHours(call FunctionCall) Value { - date := dateObjectOf(call.thisObject()) + date := dateObjectOf(call.runtime, call.thisObject()) if date.isNaN { return NaNValue() } @@ -288,7 +287,7 @@ func builtinDate_getUTCHours(call FunctionCall) Value { } func builtinDate_getMinutes(call FunctionCall) Value { - date := dateObjectOf(call.thisObject()) + date := dateObjectOf(call.runtime, call.thisObject()) if date.isNaN { return NaNValue() } @@ -296,7 +295,7 @@ func builtinDate_getMinutes(call FunctionCall) Value { } func builtinDate_getUTCMinutes(call FunctionCall) Value { - date := dateObjectOf(call.thisObject()) + date := dateObjectOf(call.runtime, call.thisObject()) if date.isNaN { return NaNValue() } @@ -304,7 +303,7 @@ func builtinDate_getUTCMinutes(call FunctionCall) Value { } func builtinDate_getSeconds(call FunctionCall) Value { - date := dateObjectOf(call.thisObject()) + date := dateObjectOf(call.runtime, call.thisObject()) if date.isNaN { return NaNValue() } @@ -312,7 +311,7 @@ func builtinDate_getSeconds(call FunctionCall) Value { } func builtinDate_getUTCSeconds(call FunctionCall) Value { - date := dateObjectOf(call.thisObject()) + date := dateObjectOf(call.runtime, call.thisObject()) if date.isNaN { return NaNValue() } @@ -320,7 +319,7 @@ func builtinDate_getUTCSeconds(call FunctionCall) Value { } func builtinDate_getMilliseconds(call FunctionCall) Value { - date := dateObjectOf(call.thisObject()) + date := dateObjectOf(call.runtime, call.thisObject()) if date.isNaN { return NaNValue() } @@ -328,7 +327,7 @@ func builtinDate_getMilliseconds(call FunctionCall) Value { } func builtinDate_getUTCMilliseconds(call FunctionCall) Value { - date := dateObjectOf(call.thisObject()) + date := dateObjectOf(call.runtime, call.thisObject()) if date.isNaN { return NaNValue() } @@ -336,7 +335,7 @@ func builtinDate_getUTCMilliseconds(call FunctionCall) Value { } func builtinDate_getTimezoneOffset(call FunctionCall) Value { - date := dateObjectOf(call.thisObject()) + date := dateObjectOf(call.runtime, call.thisObject()) if date.isNaN { return NaNValue() } diff --git a/Godeps/_workspace/src/github.com/robertkrimen/otto/builtin_error.go b/Godeps/_workspace/src/github.com/robertkrimen/otto/builtin_error.go new file mode 100644 index 000000000..4c054fbea --- /dev/null +++ b/Godeps/_workspace/src/github.com/robertkrimen/otto/builtin_error.go @@ -0,0 +1,126 @@ +package otto + +import ( + "fmt" +) + +func builtinError(call FunctionCall) Value { + return toValue_object(call.runtime.newError("", call.Argument(0))) +} + +func builtinNewError(self *_object, argumentList []Value) Value { + return toValue_object(self.runtime.newError("", valueOfArrayIndex(argumentList, 0))) +} + +func builtinError_toString(call FunctionCall) Value { + thisObject := call.thisObject() + if thisObject == nil { + panic(call.runtime.panicTypeError()) + } + + name := "Error" + nameValue := thisObject.get("name") + if nameValue.IsDefined() { + name = nameValue.string() + } + + message := "" + messageValue := thisObject.get("message") + if messageValue.IsDefined() { + message = messageValue.string() + } + + if len(name) == 0 { + return toValue_string(message) + } + + if len(message) == 0 { + return toValue_string(name) + } + + return toValue_string(fmt.Sprintf("%s: %s", name, message)) +} + +func (runtime *_runtime) newEvalError(message Value) *_object { + self := runtime.newErrorObject("EvalError", message) + self.prototype = runtime.global.EvalErrorPrototype + return self +} + +func builtinEvalError(call FunctionCall) Value { + return toValue_object(call.runtime.newEvalError(call.Argument(0))) +} + +func builtinNewEvalError(self *_object, argumentList []Value) Value { + return toValue_object(self.runtime.newEvalError(valueOfArrayIndex(argumentList, 0))) +} + +func (runtime *_runtime) newTypeError(message Value) *_object { + self := runtime.newErrorObject("TypeError", message) + self.prototype = runtime.global.TypeErrorPrototype + return self +} + +func builtinTypeError(call FunctionCall) Value { + return toValue_object(call.runtime.newTypeError(call.Argument(0))) +} + +func builtinNewTypeError(self *_object, argumentList []Value) Value { + return toValue_object(self.runtime.newTypeError(valueOfArrayIndex(argumentList, 0))) +} + +func (runtime *_runtime) newRangeError(message Value) *_object { + self := runtime.newErrorObject("RangeError", message) + self.prototype = runtime.global.RangeErrorPrototype + return self +} + +func builtinRangeError(call FunctionCall) Value { + return toValue_object(call.runtime.newRangeError(call.Argument(0))) +} + +func builtinNewRangeError(self *_object, argumentList []Value) Value { + return toValue_object(self.runtime.newRangeError(valueOfArrayIndex(argumentList, 0))) +} + +func (runtime *_runtime) newURIError(message Value) *_object { + self := runtime.newErrorObject("URIError", message) + self.prototype = runtime.global.URIErrorPrototype + return self +} + +func (runtime *_runtime) newReferenceError(message Value) *_object { + self := runtime.newErrorObject("ReferenceError", message) + self.prototype = runtime.global.ReferenceErrorPrototype + return self +} + +func builtinReferenceError(call FunctionCall) Value { + return toValue_object(call.runtime.newReferenceError(call.Argument(0))) +} + +func builtinNewReferenceError(self *_object, argumentList []Value) Value { + return toValue_object(self.runtime.newReferenceError(valueOfArrayIndex(argumentList, 0))) +} + +func (runtime *_runtime) newSyntaxError(message Value) *_object { + self := runtime.newErrorObject("SyntaxError", message) + self.prototype = runtime.global.SyntaxErrorPrototype + return self +} + +func builtinSyntaxError(call FunctionCall) Value { + return toValue_object(call.runtime.newSyntaxError(call.Argument(0))) +} + +func builtinNewSyntaxError(self *_object, argumentList []Value) Value { + return toValue_object(self.runtime.newSyntaxError(valueOfArrayIndex(argumentList, 0))) +} + +func builtinURIError(call FunctionCall) Value { + return toValue_object(call.runtime.newURIError(call.Argument(0))) +} + +func builtinNewURIError(self *_object, argumentList []Value) Value { + return toValue_object(self.runtime.newURIError(valueOfArrayIndex(argumentList, 0))) +} diff --git a/Godeps/_workspace/src/github.com/obscuren/otto/builtin_function.go b/Godeps/_workspace/src/github.com/robertkrimen/otto/builtin_function.go index 80442104d..3d07566c6 100644 --- a/Godeps/_workspace/src/github.com/obscuren/otto/builtin_function.go +++ b/Godeps/_workspace/src/github.com/robertkrimen/otto/builtin_function.go @@ -1,6 +1,7 @@ package otto import ( + "fmt" "regexp" "strings" "unicode" @@ -14,14 +15,14 @@ func builtinFunction(call FunctionCall) Value { return toValue_object(builtinNewFunctionNative(call.runtime, call.ArgumentList)) } -func builtinNewFunction(self *_object, _ Value, argumentList []Value) Value { +func builtinNewFunction(self *_object, argumentList []Value) Value { return toValue_object(builtinNewFunctionNative(self.runtime, argumentList)) } func argumentList2parameterList(argumentList []Value) []string { parameterList := make([]string, 0, len(argumentList)) for _, value := range argumentList { - tmp := strings.FieldsFunc(toString(value), func(chr rune) bool { + tmp := strings.FieldsFunc(value.string(), func(chr rune) bool { return chr == ',' || unicode.IsSpace(chr) }) parameterList = append(parameterList, tmp...) @@ -37,40 +38,51 @@ func builtinNewFunctionNative(runtime *_runtime, argumentList []Value) *_object if count > 0 { tmp := make([]string, 0, count-1) for _, value := range argumentList[0 : count-1] { - tmp = append(tmp, toString(value)) + tmp = append(tmp, value.string()) } parameterList = strings.Join(tmp, ",") - body = toString(argumentList[count-1]) + body = argumentList[count-1].string() } + // FIXME function, err := parser.ParseFunction(parameterList, body) runtime.parseThrow(err) // Will panic/throw appropriately - cmpl_function := parseExpression(function) + cmpl := _compiler{} + cmpl_function := cmpl.parseExpression(function) - return runtime.newNodeFunction(cmpl_function.(*_nodeFunctionLiteral), runtime.GlobalEnvironment) + return runtime.newNodeFunction(cmpl_function.(*_nodeFunctionLiteral), runtime.globalStash) } func builtinFunction_toString(call FunctionCall) Value { object := call.thisClassObject("Function") // Should throw a TypeError unless Function - return toValue_string(object.value.(_functionObject).source(object)) + switch fn := object.value.(type) { + case _nativeFunctionObject: + return toValue_string(fmt.Sprintf("function %s() { [native code] }", fn.name)) + case _nodeFunctionObject: + return toValue_string(fn.node.source) + case _bindFunctionObject: + return toValue_string("function () { [native code] }") + } + + panic(call.runtime.panicTypeError("Function.toString()")) } func builtinFunction_apply(call FunctionCall) Value { if !call.This.isCallable() { - panic(newTypeError()) + panic(call.runtime.panicTypeError()) } this := call.Argument(0) if this.IsUndefined() { // FIXME Not ECMA5 - this = toValue_object(call.runtime.GlobalObject) + this = toValue_object(call.runtime.globalObject) } argumentList := call.Argument(1) - switch argumentList._valueType { + switch argumentList.kind { case valueUndefined, valueNull: - return call.thisObject().Call(this, []Value{}) + return call.thisObject().call(this, nil, false, nativeFrame) case valueObject: default: - panic(newTypeError()) + panic(call.runtime.panicTypeError()) } arrayObject := argumentList._object() @@ -80,29 +92,29 @@ func builtinFunction_apply(call FunctionCall) Value { for index := int64(0); index < length; index++ { valueArray[index] = arrayObject.get(arrayIndexToString(index)) } - return thisObject.Call(this, valueArray) + return thisObject.call(this, valueArray, false, nativeFrame) } func builtinFunction_call(call FunctionCall) Value { if !call.This.isCallable() { - panic(newTypeError()) + panic(call.runtime.panicTypeError()) } thisObject := call.thisObject() this := call.Argument(0) if this.IsUndefined() { // FIXME Not ECMA5 - this = toValue_object(call.runtime.GlobalObject) + this = toValue_object(call.runtime.globalObject) } if len(call.ArgumentList) >= 1 { - return thisObject.Call(this, call.ArgumentList[1:]) + return thisObject.call(this, call.ArgumentList[1:], false, nativeFrame) } - return thisObject.Call(this, []Value{}) + return thisObject.call(this, nil, false, nativeFrame) } func builtinFunction_bind(call FunctionCall) Value { target := call.This if !target.isCallable() { - panic(newTypeError()) + panic(call.runtime.panicTypeError()) } targetObject := target._object() @@ -110,7 +122,7 @@ func builtinFunction_bind(call FunctionCall) Value { argumentList := call.slice(1) if this.IsUndefined() { // FIXME Do this elsewhere? - this = toValue_object(call.runtime.GlobalObject) + this = toValue_object(call.runtime.globalObject) } return toValue_object(call.runtime.newBoundFunction(targetObject, this, argumentList)) diff --git a/Godeps/_workspace/src/github.com/obscuren/otto/builtin_json.go b/Godeps/_workspace/src/github.com/robertkrimen/otto/builtin_json.go index 2501c242e..aed54bf12 100644 --- a/Godeps/_workspace/src/github.com/obscuren/otto/builtin_json.go +++ b/Godeps/_workspace/src/github.com/robertkrimen/otto/builtin_json.go @@ -3,7 +3,7 @@ package otto import ( "bytes" "encoding/json" - "math" + "fmt" "strings" ) @@ -23,13 +23,13 @@ func builtinJSON_parse(call FunctionCall) Value { } var root interface{} - err := json.Unmarshal([]byte(toString(call.Argument(0))), &root) + err := json.Unmarshal([]byte(call.Argument(0).string()), &root) if err != nil { - panic(newSyntaxError(err.Error())) + panic(call.runtime.panicSyntaxError(err.Error())) } value, exists := builtinJSON_parseWalk(ctx, root) if !exists { - value = UndefinedValue() + value = Value{} } if revive { root := ctx.call.runtime.newObject() @@ -65,13 +65,13 @@ func builtinJSON_reviveWalk(ctx _builtinJSON_parseContext, holder *_object, name }) } } - return ctx.reviver.call(toValue_object(holder), name, value) + return ctx.reviver.call(ctx.call.runtime, toValue_object(holder), name, value) } func builtinJSON_parseWalk(ctx _builtinJSON_parseContext, rawValue interface{}) (Value, bool) { switch value := rawValue.(type) { case nil: - return NullValue(), true + return nullValue, true case bool: return toValue_bool(value), true case string: @@ -120,7 +120,7 @@ func builtinJSON_stringify(call FunctionCall) Value { length = 0 for index, _ := range propertyList { value := replacer.get(arrayIndexToString(int64(index))) - switch value._valueType { + switch value.kind { case valueObject: switch value.value.(*_object).class { case "String": @@ -133,7 +133,7 @@ func builtinJSON_stringify(call FunctionCall) Value { default: continue } - name := toString(value) + name := value.string() if seen[name] { continue } @@ -148,24 +148,24 @@ func builtinJSON_stringify(call FunctionCall) Value { } } if spaceValue, exists := call.getArgument(2); exists { - if spaceValue._valueType == valueObject { + if spaceValue.kind == valueObject { switch spaceValue.value.(*_object).class { case "String": - spaceValue = toValue_string(toString(spaceValue)) + spaceValue = toValue_string(spaceValue.string()) case "Number": - spaceValue = toNumber(spaceValue) + spaceValue = spaceValue.numberValue() } } - switch spaceValue._valueType { + switch spaceValue.kind { case valueString: - value := toString(spaceValue) + value := spaceValue.string() if len(value) > 10 { ctx.gap = value[0:10] } else { ctx.gap = value } case valueNumber: - value := toInteger(spaceValue).value + value := spaceValue.number().int64 if value > 10 { value = 10 } else if value < 0 { @@ -178,11 +178,11 @@ func builtinJSON_stringify(call FunctionCall) Value { holder.put("", call.Argument(0), false) value, exists := builtinJSON_stringifyWalk(ctx, "", holder) if !exists { - return UndefinedValue() + return Value{} } valueJSON, err := json.Marshal(value) if err != nil { - panic(newTypeError(err.Error())) + panic(call.runtime.panicTypeError(err.Error())) } if ctx.gap != "" { valueJSON1 := bytes.Buffer{} @@ -198,7 +198,7 @@ func builtinJSON_stringifyWalk(ctx _builtinJSON_stringifyContext, key string, ho if value.IsObject() { object := value._object() if toJSON := object.get("toJSON"); toJSON.IsFunction() { - value = toJSON.call(value, key) + value = toJSON.call(ctx.call.runtime, value, key) } else { // If the object is a GoStruct or something that implements json.Marshaler if object.objectClass.marshalJSON != nil { @@ -211,31 +211,35 @@ func builtinJSON_stringifyWalk(ctx _builtinJSON_stringifyContext, key string, ho } if ctx.replacerFunction != nil { - value = (*ctx.replacerFunction).call(toValue_object(holder), key, value) + value = (*ctx.replacerFunction).call(ctx.call.runtime, toValue_object(holder), key, value) } - if value._valueType == valueObject { + if value.kind == valueObject { switch value.value.(*_object).class { case "Boolean": value = value._object().value.(Value) case "String": - value = toValue_string(toString(value)) + value = toValue_string(value.string()) case "Number": - value = toNumber(value) + value = value.numberValue() } } - switch value._valueType { + switch value.kind { case valueBoolean: - return toBoolean(value), true + return value.bool(), true case valueString: - return toString(value), true + return value.string(), true case valueNumber: - value := toFloat(value) - if math.IsNaN(value) || math.IsInf(value, 0) { + integer := value.number() + switch integer.kind { + case numberInteger: + return integer.int64, true + case numberFloat: + return integer.float64, true + default: return nil, true } - return value, true case valueNull: return nil, true case valueObject: @@ -243,14 +247,24 @@ func builtinJSON_stringifyWalk(ctx _builtinJSON_stringifyContext, key string, ho if value := value._object(); nil != value { for _, object := range ctx.stack { if holder == object { - panic(newTypeError("Converting circular structure to JSON")) + panic(ctx.call.runtime.panicTypeError("Converting circular structure to JSON")) } } ctx.stack = append(ctx.stack, value) defer func() { ctx.stack = ctx.stack[:len(ctx.stack)-1] }() } if isArray(holder) { - length := holder.get("length").value.(uint32) + var length uint32 + switch value := holder.get("length").value.(type) { + case uint32: + length = value + case int: + if value >= 0 { + length = uint32(value) + } + default: + panic(ctx.call.runtime.panicTypeError(fmt.Sprintf("JSON.stringify: invalid length: %v (%[1]T)", value))) + } array := make([]interface{}, length) for index, _ := range array { name := arrayIndexToString(int64(index)) diff --git a/Godeps/_workspace/src/github.com/obscuren/otto/builtin_math.go b/Godeps/_workspace/src/github.com/robertkrimen/otto/builtin_math.go index 37f7d8c85..a9f4a55c1 100644 --- a/Godeps/_workspace/src/github.com/obscuren/otto/builtin_math.go +++ b/Godeps/_workspace/src/github.com/robertkrimen/otto/builtin_math.go @@ -8,31 +8,31 @@ import ( // Math func builtinMath_abs(call FunctionCall) Value { - number := toFloat(call.Argument(0)) + number := call.Argument(0).float64() return toValue_float64(math.Abs(number)) } func builtinMath_acos(call FunctionCall) Value { - number := toFloat(call.Argument(0)) + number := call.Argument(0).float64() return toValue_float64(math.Acos(number)) } func builtinMath_asin(call FunctionCall) Value { - number := toFloat(call.Argument(0)) + number := call.Argument(0).float64() return toValue_float64(math.Asin(number)) } func builtinMath_atan(call FunctionCall) Value { - number := toFloat(call.Argument(0)) + number := call.Argument(0).float64() return toValue_float64(math.Atan(number)) } func builtinMath_atan2(call FunctionCall) Value { - y := toFloat(call.Argument(0)) + y := call.Argument(0).float64() if math.IsNaN(y) { return NaNValue() } - x := toFloat(call.Argument(1)) + x := call.Argument(1).float64() if math.IsNaN(x) { return NaNValue() } @@ -40,27 +40,27 @@ func builtinMath_atan2(call FunctionCall) Value { } func builtinMath_cos(call FunctionCall) Value { - number := toFloat(call.Argument(0)) + number := call.Argument(0).float64() return toValue_float64(math.Cos(number)) } func builtinMath_ceil(call FunctionCall) Value { - number := toFloat(call.Argument(0)) + number := call.Argument(0).float64() return toValue_float64(math.Ceil(number)) } func builtinMath_exp(call FunctionCall) Value { - number := toFloat(call.Argument(0)) + number := call.Argument(0).float64() return toValue_float64(math.Exp(number)) } func builtinMath_floor(call FunctionCall) Value { - number := toFloat(call.Argument(0)) + number := call.Argument(0).float64() return toValue_float64(math.Floor(number)) } func builtinMath_log(call FunctionCall) Value { - number := toFloat(call.Argument(0)) + number := call.Argument(0).float64() return toValue_float64(math.Log(number)) } @@ -69,14 +69,14 @@ func builtinMath_max(call FunctionCall) Value { case 0: return negativeInfinityValue() case 1: - return toValue_float64(toFloat(call.ArgumentList[0])) + return toValue_float64(call.ArgumentList[0].float64()) } - result := toFloat(call.ArgumentList[0]) + result := call.ArgumentList[0].float64() if math.IsNaN(result) { return NaNValue() } for _, value := range call.ArgumentList[1:] { - value := toFloat(value) + value := value.float64() if math.IsNaN(value) { return NaNValue() } @@ -90,14 +90,14 @@ func builtinMath_min(call FunctionCall) Value { case 0: return positiveInfinityValue() case 1: - return toValue_float64(toFloat(call.ArgumentList[0])) + return toValue_float64(call.ArgumentList[0].float64()) } - result := toFloat(call.ArgumentList[0]) + result := call.ArgumentList[0].float64() if math.IsNaN(result) { return NaNValue() } for _, value := range call.ArgumentList[1:] { - value := toFloat(value) + value := value.float64() if math.IsNaN(value) { return NaNValue() } @@ -108,8 +108,8 @@ func builtinMath_min(call FunctionCall) Value { func builtinMath_pow(call FunctionCall) Value { // TODO Make sure this works according to the specification (15.8.2.13) - x := toFloat(call.Argument(0)) - y := toFloat(call.Argument(1)) + x := call.Argument(0).float64() + y := call.Argument(1).float64() if math.Abs(x) == 1 && math.IsInf(y, 0) { return NaNValue() } @@ -121,7 +121,7 @@ func builtinMath_random(call FunctionCall) Value { } func builtinMath_round(call FunctionCall) Value { - number := toFloat(call.Argument(0)) + number := call.Argument(0).float64() value := math.Floor(number + 0.5) if value == 0 { value = math.Copysign(0, number) @@ -130,16 +130,16 @@ func builtinMath_round(call FunctionCall) Value { } func builtinMath_sin(call FunctionCall) Value { - number := toFloat(call.Argument(0)) + number := call.Argument(0).float64() return toValue_float64(math.Sin(number)) } func builtinMath_sqrt(call FunctionCall) Value { - number := toFloat(call.Argument(0)) + number := call.Argument(0).float64() return toValue_float64(math.Sqrt(number)) } func builtinMath_tan(call FunctionCall) Value { - number := toFloat(call.Argument(0)) + number := call.Argument(0).float64() return toValue_float64(math.Tan(number)) } diff --git a/Godeps/_workspace/src/github.com/obscuren/otto/builtin_number.go b/Godeps/_workspace/src/github.com/robertkrimen/otto/builtin_number.go index 3905f5bb4..26a03e7b6 100644 --- a/Godeps/_workspace/src/github.com/obscuren/otto/builtin_number.go +++ b/Godeps/_workspace/src/github.com/robertkrimen/otto/builtin_number.go @@ -9,7 +9,7 @@ import ( func numberValueFromNumberArgumentList(argumentList []Value) Value { if len(argumentList) > 0 { - return toNumber(argumentList[0]) + return argumentList[0].numberValue() } return toValue_int(0) } @@ -18,7 +18,7 @@ func builtinNumber(call FunctionCall) Value { return numberValueFromNumberArgumentList(call.ArgumentList) } -func builtinNewNumber(self *_object, _ Value, argumentList []Value) Value { +func builtinNewNumber(self *_object, argumentList []Value) Value { return toValue_object(self.runtime.newNumber(numberValueFromNumberArgumentList(argumentList))) } @@ -30,12 +30,12 @@ func builtinNumber_toString(call FunctionCall) Value { if radixArgument.IsDefined() { integer := toIntegerFloat(radixArgument) if integer < 2 || integer > 36 { - panic(newRangeError("RangeError: toString() radix must be between 2 and 36")) + panic(call.runtime.panicRangeError("RangeError: toString() radix must be between 2 and 36")) } radix = int(integer) } if radix == 10 { - return toValue_string(toString(value)) + return toValue_string(value.string()) } return toValue_string(numberToStringRadix(value, radix)) } @@ -47,16 +47,16 @@ func builtinNumber_valueOf(call FunctionCall) Value { func builtinNumber_toFixed(call FunctionCall) Value { precision := toIntegerFloat(call.Argument(0)) if 20 < precision || 0 > precision { - panic(newRangeError("toFixed() precision must be between 0 and 20")) + panic(call.runtime.panicRangeError("toFixed() precision must be between 0 and 20")) } if call.This.IsNaN() { return toValue_string("NaN") } - value := toFloat(call.This) + value := call.This.float64() if math.Abs(value) >= 1e21 { return toValue_string(floatToString(value, 64)) } - return toValue_string(strconv.FormatFloat(toFloat(call.This), 'f', int(precision), 64)) + return toValue_string(strconv.FormatFloat(call.This.float64(), 'f', int(precision), 64)) } func builtinNumber_toExponential(call FunctionCall) Value { @@ -67,10 +67,10 @@ func builtinNumber_toExponential(call FunctionCall) Value { if value := call.Argument(0); value.IsDefined() { precision = toIntegerFloat(value) if 0 > precision { - panic(newRangeError("RangeError: toExponential() precision must be greater than 0")) + panic(call.runtime.panicRangeError("RangeError: toString() radix must be between 2 and 36")) } } - return toValue_string(strconv.FormatFloat(toFloat(call.This), 'e', int(precision), 64)) + return toValue_string(strconv.FormatFloat(call.This.float64(), 'e', int(precision), 64)) } func builtinNumber_toPrecision(call FunctionCall) Value { @@ -79,13 +79,13 @@ func builtinNumber_toPrecision(call FunctionCall) Value { } value := call.Argument(0) if value.IsUndefined() { - return toValue_string(toString(call.This)) + return toValue_string(call.This.string()) } precision := toIntegerFloat(value) if 1 > precision { - panic(newRangeError("RangeError: toPrecision() precision must be greater than 1")) + panic(call.runtime.panicRangeError("RangeError: toPrecision() precision must be greater than 1")) } - return toValue_string(strconv.FormatFloat(toFloat(call.This), 'g', int(precision), 64)) + return toValue_string(strconv.FormatFloat(call.This.float64(), 'g', int(precision), 64)) } func builtinNumber_toLocaleString(call FunctionCall) Value { diff --git a/Godeps/_workspace/src/github.com/obscuren/otto/builtin_object.go b/Godeps/_workspace/src/github.com/robertkrimen/otto/builtin_object.go index 2c3648856..c2433f7be 100644 --- a/Godeps/_workspace/src/github.com/obscuren/otto/builtin_object.go +++ b/Godeps/_workspace/src/github.com/robertkrimen/otto/builtin_object.go @@ -8,7 +8,7 @@ import ( func builtinObject(call FunctionCall) Value { value := call.Argument(0) - switch value._valueType { + switch value.kind { case valueUndefined, valueNull: return toValue_object(call.runtime.newObject()) } @@ -16,9 +16,9 @@ func builtinObject(call FunctionCall) Value { return toValue_object(call.runtime.toObject(value)) } -func builtinNewObject(self *_object, _ Value, argumentList []Value) Value { +func builtinNewObject(self *_object, argumentList []Value) Value { value := valueOfArrayIndex(argumentList, 0) - switch value._valueType { + switch value.kind { case valueNull, valueUndefined: case valueNumber, valueString, valueBoolean: return toValue_object(self.runtime.toObject(value)) @@ -34,7 +34,7 @@ func builtinObject_valueOf(call FunctionCall) Value { } func builtinObject_hasOwnProperty(call FunctionCall) Value { - propertyName := toString(call.Argument(0)) + propertyName := call.Argument(0).string() thisObject := call.thisObject() return toValue_bool(thisObject.hasOwnProperty(propertyName)) } @@ -42,27 +42,27 @@ func builtinObject_hasOwnProperty(call FunctionCall) Value { func builtinObject_isPrototypeOf(call FunctionCall) Value { value := call.Argument(0) if !value.IsObject() { - return FalseValue() + return falseValue } prototype := call.toObject(value).prototype thisObject := call.thisObject() for prototype != nil { if thisObject == prototype { - return TrueValue() + return trueValue } prototype = prototype.prototype } - return FalseValue() + return falseValue } func builtinObject_propertyIsEnumerable(call FunctionCall) Value { - propertyName := toString(call.Argument(0)) + propertyName := call.Argument(0).string() thisObject := call.thisObject() property := thisObject.getOwnProperty(propertyName) if property != nil && property.enumerable() { - return TrueValue() + return trueValue } - return FalseValue() + return falseValue } func builtinObject_toString(call FunctionCall) Value { @@ -80,20 +80,20 @@ func builtinObject_toString(call FunctionCall) Value { func builtinObject_toLocaleString(call FunctionCall) Value { toString := call.thisObject().get("toString") if !toString.isCallable() { - panic(newTypeError()) + panic(call.runtime.panicTypeError()) } - return toString.call(call.This) + return toString.call(call.runtime, call.This) } func builtinObject_getPrototypeOf(call FunctionCall) Value { objectValue := call.Argument(0) object := objectValue._object() if object == nil { - panic(newTypeError()) + panic(call.runtime.panicTypeError()) } if object.prototype == nil { - return NullValue() + return nullValue } return toValue_object(object.prototype) @@ -103,13 +103,13 @@ func builtinObject_getOwnPropertyDescriptor(call FunctionCall) Value { objectValue := call.Argument(0) object := objectValue._object() if object == nil { - panic(newTypeError()) + panic(call.runtime.panicTypeError()) } - name := toString(call.Argument(1)) + name := call.Argument(1).string() descriptor := object.getOwnProperty(name) if descriptor == nil { - return UndefinedValue() + return Value{} } return toValue_object(call.runtime.fromPropertyDescriptor(*descriptor)) } @@ -118,10 +118,10 @@ func builtinObject_defineProperty(call FunctionCall) Value { objectValue := call.Argument(0) object := objectValue._object() if object == nil { - panic(newTypeError()) + panic(call.runtime.panicTypeError()) } - name := toString(call.Argument(1)) - descriptor := toPropertyDescriptor(call.Argument(2)) + name := call.Argument(1).string() + descriptor := toPropertyDescriptor(call.runtime, call.Argument(2)) object.defineOwnProperty(name, descriptor, true) return objectValue } @@ -130,12 +130,12 @@ func builtinObject_defineProperties(call FunctionCall) Value { objectValue := call.Argument(0) object := objectValue._object() if object == nil { - panic(newTypeError()) + panic(call.runtime.panicTypeError()) } properties := call.runtime.toObject(call.Argument(1)) properties.enumerate(false, func(name string) bool { - descriptor := toPropertyDescriptor(properties.get(name)) + descriptor := toPropertyDescriptor(call.runtime, properties.get(name)) object.defineOwnProperty(name, descriptor, true) return true }) @@ -146,7 +146,7 @@ func builtinObject_defineProperties(call FunctionCall) Value { func builtinObject_create(call FunctionCall) Value { prototypeValue := call.Argument(0) if !prototypeValue.IsNull() && !prototypeValue.IsObject() { - panic(newTypeError()) + panic(call.runtime.panicTypeError()) } object := call.runtime.newObject() @@ -156,7 +156,7 @@ func builtinObject_create(call FunctionCall) Value { if propertiesValue.IsDefined() { properties := call.runtime.toObject(propertiesValue) properties.enumerate(false, func(name string) bool { - descriptor := toPropertyDescriptor(properties.get(name)) + descriptor := toPropertyDescriptor(call.runtime, properties.get(name)) object.defineOwnProperty(name, descriptor, true) return true }) @@ -170,7 +170,7 @@ func builtinObject_isExtensible(call FunctionCall) Value { if object := object._object(); object != nil { return toValue_bool(object.extensible) } - panic(newTypeError()) + panic(call.runtime.panicTypeError()) } func builtinObject_preventExtensions(call FunctionCall) Value { @@ -178,7 +178,7 @@ func builtinObject_preventExtensions(call FunctionCall) Value { if object := object._object(); object != nil { object.extensible = false } else { - panic(newTypeError()) + panic(call.runtime.panicTypeError()) } return object } @@ -199,7 +199,7 @@ func builtinObject_isSealed(call FunctionCall) Value { }) return toValue_bool(result) } - panic(newTypeError()) + panic(call.runtime.panicTypeError()) } func builtinObject_seal(call FunctionCall) Value { @@ -214,7 +214,7 @@ func builtinObject_seal(call FunctionCall) Value { }) object.extensible = false } else { - panic(newTypeError()) + panic(call.runtime.panicTypeError()) } return object } @@ -235,7 +235,7 @@ func builtinObject_isFrozen(call FunctionCall) Value { }) return toValue_bool(result) } - panic(newTypeError()) + panic(call.runtime.panicTypeError()) } func builtinObject_freeze(call FunctionCall) Value { @@ -259,7 +259,7 @@ func builtinObject_freeze(call FunctionCall) Value { }) object.extensible = false } else { - panic(newTypeError()) + panic(call.runtime.panicTypeError()) } return object } @@ -272,7 +272,7 @@ func builtinObject_keys(call FunctionCall) Value { }) return toValue_object(call.runtime.newArrayOf(keys)) } - panic(newTypeError()) + panic(call.runtime.panicTypeError()) } func builtinObject_getOwnPropertyNames(call FunctionCall) Value { @@ -285,5 +285,5 @@ func builtinObject_getOwnPropertyNames(call FunctionCall) Value { }) return toValue_object(call.runtime.newArrayOf(propertyNames)) } - panic(newTypeError()) + panic(call.runtime.panicTypeError()) } diff --git a/Godeps/_workspace/src/github.com/obscuren/otto/builtin_regexp.go b/Godeps/_workspace/src/github.com/robertkrimen/otto/builtin_regexp.go index 29d009dc2..99422510d 100644 --- a/Godeps/_workspace/src/github.com/obscuren/otto/builtin_regexp.go +++ b/Godeps/_workspace/src/github.com/robertkrimen/otto/builtin_regexp.go @@ -17,7 +17,7 @@ func builtinRegExp(call FunctionCall) Value { return toValue_object(call.runtime.newRegExp(pattern, flags)) } -func builtinNewRegExp(self *_object, _ Value, argumentList []Value) Value { +func builtinNewRegExp(self *_object, argumentList []Value) Value { return toValue_object(self.runtime.newRegExp( valueOfArrayIndex(argumentList, 0), valueOfArrayIndex(argumentList, 1), @@ -26,15 +26,15 @@ func builtinNewRegExp(self *_object, _ Value, argumentList []Value) Value { func builtinRegExp_toString(call FunctionCall) Value { thisObject := call.thisObject() - source := toString(thisObject.get("source")) + source := thisObject.get("source").string() flags := []byte{} - if toBoolean(thisObject.get("global")) { + if thisObject.get("global").bool() { flags = append(flags, 'g') } - if toBoolean(thisObject.get("ignoreCase")) { + if thisObject.get("ignoreCase").bool() { flags = append(flags, 'i') } - if toBoolean(thisObject.get("multiline")) { + if thisObject.get("multiline").bool() { flags = append(flags, 'm') } return toValue_string(fmt.Sprintf("/%s/%s", source, flags)) @@ -42,17 +42,17 @@ func builtinRegExp_toString(call FunctionCall) Value { func builtinRegExp_exec(call FunctionCall) Value { thisObject := call.thisObject() - target := toString(call.Argument(0)) + target := call.Argument(0).string() match, result := execRegExp(thisObject, target) if !match { - return NullValue() + return nullValue } return toValue_object(execResultToArray(call.runtime, target, result)) } func builtinRegExp_test(call FunctionCall) Value { thisObject := call.thisObject() - target := toString(call.Argument(0)) + target := call.Argument(0).string() match, _ := execRegExp(thisObject, target) return toValue_bool(match) } @@ -61,5 +61,5 @@ func builtinRegExp_compile(call FunctionCall) Value { // This (useless) function is deprecated, but is here to provide some // semblance of compatibility. // Caveat emptor: it may not be around for long. - return UndefinedValue() + return Value{} } diff --git a/Godeps/_workspace/src/github.com/obscuren/otto/builtin_string.go b/Godeps/_workspace/src/github.com/robertkrimen/otto/builtin_string.go index e2c6a620c..6a1718458 100644 --- a/Godeps/_workspace/src/github.com/obscuren/otto/builtin_string.go +++ b/Godeps/_workspace/src/github.com/robertkrimen/otto/builtin_string.go @@ -12,7 +12,7 @@ import ( func stringValueFromStringArgumentList(argumentList []Value) Value { if len(argumentList) > 0 { - return toValue_string(toString(argumentList[0])) + return toValue_string(argumentList[0].string()) } return toValue_string("") } @@ -21,7 +21,7 @@ func builtinString(call FunctionCall) Value { return stringValueFromStringArgumentList(call.ArgumentList) } -func builtinNewString(self *_object, _ Value, argumentList []Value) Value { +func builtinNewString(self *_object, argumentList []Value) Value { return toValue_object(self.runtime.newString(stringValueFromStringArgumentList(argumentList))) } @@ -41,8 +41,8 @@ func builtinString_fromCharCode(call FunctionCall) Value { } func builtinString_charAt(call FunctionCall) Value { - checkObjectCoercible(call.This) - idx := int(toInteger(call.Argument(0)).value) + checkObjectCoercible(call.runtime, call.This) + idx := int(call.Argument(0).number().int64) chr := stringAt(call.This._object().stringValue(), idx) if chr == utf8.RuneError { return toValue_string("") @@ -51,8 +51,8 @@ func builtinString_charAt(call FunctionCall) Value { } func builtinString_charCodeAt(call FunctionCall) Value { - checkObjectCoercible(call.This) - idx := int(toInteger(call.Argument(0)).value) + checkObjectCoercible(call.runtime, call.This) + idx := int(call.Argument(0).number().int64) chr := stringAt(call.This._object().stringValue(), idx) if chr == utf8.RuneError { return NaNValue() @@ -61,19 +61,19 @@ func builtinString_charCodeAt(call FunctionCall) Value { } func builtinString_concat(call FunctionCall) Value { - checkObjectCoercible(call.This) + checkObjectCoercible(call.runtime, call.This) var value bytes.Buffer - value.WriteString(toString(call.This)) + value.WriteString(call.This.string()) for _, item := range call.ArgumentList { - value.WriteString(toString(item)) + value.WriteString(item.string()) } return toValue_string(value.String()) } func builtinString_indexOf(call FunctionCall) Value { - checkObjectCoercible(call.This) - value := toString(call.This) - target := toString(call.Argument(0)) + checkObjectCoercible(call.runtime, call.This) + value := call.This.string() + target := call.Argument(0).string() if 2 > len(call.ArgumentList) { return toValue_int(strings.Index(value, target)) } @@ -94,9 +94,9 @@ func builtinString_indexOf(call FunctionCall) Value { } func builtinString_lastIndexOf(call FunctionCall) Value { - checkObjectCoercible(call.This) - value := toString(call.This) - target := toString(call.Argument(0)) + checkObjectCoercible(call.runtime, call.This) + value := call.This.string() + target := call.Argument(0).string() if 2 > len(call.ArgumentList) || call.ArgumentList[1].IsUndefined() { return toValue_int(strings.LastIndex(value, target)) } @@ -104,15 +104,15 @@ func builtinString_lastIndexOf(call FunctionCall) Value { if length == 0 { return toValue_int(strings.LastIndex(value, target)) } - start := toInteger(call.ArgumentList[1]) - if !start.valid() { + start := call.ArgumentList[1].number() + if start.kind == numberInfinity { // FIXME // startNumber is infinity, so start is the end of string (start = length) return toValue_int(strings.LastIndex(value, target)) } - if 0 > start.value { - start.value = 0 + if 0 > start.int64 { + start.int64 = 0 } - end := int(start.value) + len(target) + end := int(start.int64) + len(target) if end > length { end = length } @@ -120,18 +120,18 @@ func builtinString_lastIndexOf(call FunctionCall) Value { } func builtinString_match(call FunctionCall) Value { - checkObjectCoercible(call.This) - target := toString(call.This) + checkObjectCoercible(call.runtime, call.This) + target := call.This.string() matcherValue := call.Argument(0) matcher := matcherValue._object() if !matcherValue.IsObject() || matcher.class != "RegExp" { - matcher = call.runtime.newRegExp(matcherValue, UndefinedValue()) + matcher = call.runtime.newRegExp(matcherValue, Value{}) } - global := toBoolean(matcher.get("global")) + global := matcher.get("global").bool() if !global { match, result := execRegExp(matcher, target) if !match { - return NullValue() + return nullValue } return toValue_object(execResultToArray(call.runtime, target, result)) } @@ -141,7 +141,7 @@ func builtinString_match(call FunctionCall) Value { matchCount := len(result) if result == nil { matcher.put("lastIndex", toValue_int(0), true) - return UndefinedValue() // !match + return Value{} // !match } matchCount = len(result) valueArray := make([]Value, matchCount) @@ -189,8 +189,8 @@ func builtinString_findAndReplaceString(input []byte, lastIndex int, match []int } func builtinString_replace(call FunctionCall) Value { - checkObjectCoercible(call.This) - target := []byte(toString(call.This)) + checkObjectCoercible(call.runtime, call.This) + target := []byte(call.This.string()) searchValue := call.Argument(0) searchObject := searchValue._object() @@ -205,7 +205,7 @@ func builtinString_replace(call FunctionCall) Value { find = -1 } } else { - search = regexp.MustCompile(regexp.QuoteMeta(toString(searchValue))) + search = regexp.MustCompile(regexp.QuoteMeta(searchValue.string())) } found := search.FindAllSubmatchIndex(target, find) @@ -232,18 +232,18 @@ func builtinString_replace(call FunctionCall) Value { if match[offset] != -1 { argumentList[index] = toValue_string(target[match[offset]:match[offset+1]]) } else { - argumentList[index] = UndefinedValue() + argumentList[index] = Value{} } } argumentList[matchCount+0] = toValue_int(match[0]) argumentList[matchCount+1] = toValue_string(target) - replacement := toString(replace.Call(UndefinedValue(), argumentList)) + replacement := replace.call(Value{}, argumentList, false, nativeFrame).string() result = append(result, []byte(replacement)...) lastIndex = match[1] } } else { - replace := []byte(toString(replaceValue)) + replace := []byte(replaceValue.string()) for _, match := range found { result = builtinString_findAndReplaceString(result, lastIndex, match, target, replace) lastIndex = match[1] @@ -260,17 +260,15 @@ func builtinString_replace(call FunctionCall) Value { return toValue_string(string(result)) } - - return UndefinedValue() } func builtinString_search(call FunctionCall) Value { - checkObjectCoercible(call.This) - target := toString(call.This) + checkObjectCoercible(call.runtime, call.This) + target := call.This.string() searchValue := call.Argument(0) search := searchValue._object() if !searchValue.IsObject() || search.class != "RegExp" { - search = call.runtime.newRegExp(searchValue, UndefinedValue()) + search = call.runtime.newRegExp(searchValue, Value{}) } result := search.regExpValue().regularExpression.FindStringIndex(target) if result == nil { @@ -291,8 +289,8 @@ func stringSplitMatch(target string, targetLength int64, index uint, search stri } func builtinString_split(call FunctionCall) Value { - checkObjectCoercible(call.This) - target := toString(call.This) + checkObjectCoercible(call.runtime, call.This) + target := call.This.string() separatorValue := call.Argument(0) limitValue := call.Argument(1) @@ -343,7 +341,7 @@ func builtinString_split(call FunctionCall) Value { captureCount := len(match) / 2 for index := 1; index < captureCount; index++ { offset := index * 2 - value := UndefinedValue() + value := Value{} if match[offset] != -1 { value = toValue_string(target[match[offset]:match[offset+1]]) } @@ -367,7 +365,7 @@ func builtinString_split(call FunctionCall) Value { return toValue_object(call.runtime.newArrayOf(valueArray)) } else { - separator := toString(separatorValue) + separator := separatorValue.string() splitLimit := limit excess := false @@ -389,13 +387,11 @@ func builtinString_split(call FunctionCall) Value { return toValue_object(call.runtime.newArrayOf(valueArray)) } - - return UndefinedValue() } func builtinString_slice(call FunctionCall) Value { - checkObjectCoercible(call.This) - target := toString(call.This) + checkObjectCoercible(call.runtime, call.This) + target := call.This.string() length := int64(len(target)) start, end := rangeStartEnd(call.ArgumentList, length, false) @@ -406,8 +402,8 @@ func builtinString_slice(call FunctionCall) Value { } func builtinString_substring(call FunctionCall) Value { - checkObjectCoercible(call.This) - target := toString(call.This) + checkObjectCoercible(call.runtime, call.This) + target := call.This.string() length := int64(len(target)) start, end := rangeStartEnd(call.ArgumentList, length, true) @@ -418,7 +414,7 @@ func builtinString_substring(call FunctionCall) Value { } func builtinString_substr(call FunctionCall) Value { - target := toString(call.This) + target := call.This.string() size := int64(len(target)) start, length := rangeStartLength(call.ArgumentList, size) @@ -443,42 +439,42 @@ func builtinString_substr(call FunctionCall) Value { } func builtinString_toLowerCase(call FunctionCall) Value { - checkObjectCoercible(call.This) - return toValue_string(strings.ToLower(toString(call.This))) + checkObjectCoercible(call.runtime, call.This) + return toValue_string(strings.ToLower(call.This.string())) } func builtinString_toUpperCase(call FunctionCall) Value { - checkObjectCoercible(call.This) - return toValue_string(strings.ToUpper(toString(call.This))) + checkObjectCoercible(call.runtime, call.This) + return toValue_string(strings.ToUpper(call.This.string())) } // 7.2 Table 2 — Whitespace Characters & 7.3 Table 3 - Line Terminator Characters const builtinString_trim_whitespace = "\u0009\u000A\u000B\u000C\u000D\u0020\u00A0\u1680\u180E\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u2028\u2029\u202F\u205F\u3000\uFEFF" func builtinString_trim(call FunctionCall) Value { - checkObjectCoercible(call.This) - return toValue(strings.Trim(toString(call.This), + checkObjectCoercible(call.runtime, call.This) + return toValue(strings.Trim(call.This.string(), builtinString_trim_whitespace)) } // Mozilla extension, not ECMAScript 5 func builtinString_trimLeft(call FunctionCall) Value { - checkObjectCoercible(call.This) - return toValue(strings.TrimLeft(toString(call.This), + checkObjectCoercible(call.runtime, call.This) + return toValue(strings.TrimLeft(call.This.string(), builtinString_trim_whitespace)) } // Mozilla extension, not ECMAScript 5 func builtinString_trimRight(call FunctionCall) Value { - checkObjectCoercible(call.This) - return toValue(strings.TrimRight(toString(call.This), + checkObjectCoercible(call.runtime, call.This) + return toValue(strings.TrimRight(call.This.string(), builtinString_trim_whitespace)) } func builtinString_localeCompare(call FunctionCall) Value { - checkObjectCoercible(call.This) - this := toString(call.This) - that := toString(call.Argument(0)) + checkObjectCoercible(call.runtime, call.This) + this := call.This.string() + that := call.Argument(0).string() if this < that { return toValue_int(-1) } else if this == that { @@ -491,7 +487,7 @@ func builtinString_localeCompare(call FunctionCall) Value { An alternate version of String.trim func builtinString_trim(call FunctionCall) Value { checkObjectCoercible(call.This) - return toValue_string(strings.TrimFunc(toString(call.This), isWhiteSpaceOrLineTerminator)) + return toValue_string(strings.TrimFunc(call.string(.This), isWhiteSpaceOrLineTerminator)) } */ diff --git a/Godeps/_workspace/src/github.com/obscuren/otto/builtin_test.go b/Godeps/_workspace/src/github.com/robertkrimen/otto/builtin_test.go index f5be00ab6..f5be00ab6 100644 --- a/Godeps/_workspace/src/github.com/obscuren/otto/builtin_test.go +++ b/Godeps/_workspace/src/github.com/robertkrimen/otto/builtin_test.go diff --git a/Godeps/_workspace/src/github.com/robertkrimen/otto/clone.go b/Godeps/_workspace/src/github.com/robertkrimen/otto/clone.go new file mode 100644 index 000000000..f79901b35 --- /dev/null +++ b/Godeps/_workspace/src/github.com/robertkrimen/otto/clone.go @@ -0,0 +1,155 @@ +package otto + +import ( + "fmt" +) + +type _clone struct { + runtime *_runtime + _object map[*_object]*_object + _objectStash map[*_objectStash]*_objectStash + _dclStash map[*_dclStash]*_dclStash + _fnStash map[*_fnStash]*_fnStash +} + +func (in *_runtime) clone() *_runtime { + + in.lck.Lock() + defer in.lck.Unlock() + + out := &_runtime{} + clone := _clone{ + runtime: out, + _object: make(map[*_object]*_object), + _objectStash: make(map[*_objectStash]*_objectStash), + _dclStash: make(map[*_dclStash]*_dclStash), + _fnStash: make(map[*_fnStash]*_fnStash), + } + + globalObject := clone.object(in.globalObject) + out.globalStash = out.newObjectStash(globalObject, nil) + out.globalObject = globalObject + out.global = _global{ + clone.object(in.global.Object), + clone.object(in.global.Function), + clone.object(in.global.Array), + clone.object(in.global.String), + clone.object(in.global.Boolean), + clone.object(in.global.Number), + clone.object(in.global.Math), + clone.object(in.global.Date), + clone.object(in.global.RegExp), + clone.object(in.global.Error), + clone.object(in.global.EvalError), + clone.object(in.global.TypeError), + clone.object(in.global.RangeError), + clone.object(in.global.ReferenceError), + clone.object(in.global.SyntaxError), + clone.object(in.global.URIError), + clone.object(in.global.JSON), + + clone.object(in.global.ObjectPrototype), + clone.object(in.global.FunctionPrototype), + clone.object(in.global.ArrayPrototype), + clone.object(in.global.StringPrototype), + clone.object(in.global.BooleanPrototype), + clone.object(in.global.NumberPrototype), + clone.object(in.global.DatePrototype), + clone.object(in.global.RegExpPrototype), + clone.object(in.global.ErrorPrototype), + clone.object(in.global.EvalErrorPrototype), + clone.object(in.global.TypeErrorPrototype), + clone.object(in.global.RangeErrorPrototype), + clone.object(in.global.ReferenceErrorPrototype), + clone.object(in.global.SyntaxErrorPrototype), + clone.object(in.global.URIErrorPrototype), + } + + out.eval = out.globalObject.property["eval"].value.(Value).value.(*_object) + out.globalObject.prototype = out.global.ObjectPrototype + + // Not sure if this is necessary, but give some help to the GC + clone.runtime = nil + clone._object = nil + clone._objectStash = nil + clone._dclStash = nil + clone._fnStash = nil + + return out +} + +func (clone *_clone) object(in *_object) *_object { + if out, exists := clone._object[in]; exists { + return out + } + out := &_object{} + clone._object[in] = out + return in.objectClass.clone(in, out, clone) +} + +func (clone *_clone) dclStash(in *_dclStash) (*_dclStash, bool) { + if out, exists := clone._dclStash[in]; exists { + return out, true + } + out := &_dclStash{} + clone._dclStash[in] = out + return out, false +} + +func (clone *_clone) objectStash(in *_objectStash) (*_objectStash, bool) { + if out, exists := clone._objectStash[in]; exists { + return out, true + } + out := &_objectStash{} + clone._objectStash[in] = out + return out, false +} + +func (clone *_clone) fnStash(in *_fnStash) (*_fnStash, bool) { + if out, exists := clone._fnStash[in]; exists { + return out, true + } + out := &_fnStash{} + clone._fnStash[in] = out + return out, false +} + +func (clone *_clone) value(in Value) Value { + out := in + switch value := in.value.(type) { + case *_object: + out.value = clone.object(value) + } + return out +} + +func (clone *_clone) valueArray(in []Value) []Value { + out := make([]Value, len(in)) + for index, value := range in { + out[index] = clone.value(value) + } + return out +} + +func (clone *_clone) stash(in _stash) _stash { + if in == nil { + return nil + } + return in.clone(clone) +} + +func (clone *_clone) property(in _property) _property { + out := in + if value, valid := in.value.(Value); valid { + out.value = clone.value(value) + } else { + panic(fmt.Errorf("in.value.(Value) != true")) + } + return out +} + +func (clone *_clone) dclProperty(in _dclProperty) _dclProperty { + out := in + out.value = clone.value(in.value) + return out +} diff --git a/Godeps/_workspace/src/github.com/robertkrimen/otto/cmpl.go b/Godeps/_workspace/src/github.com/robertkrimen/otto/cmpl.go new file mode 100644 index 000000000..c191b4527 --- /dev/null +++ b/Godeps/_workspace/src/github.com/robertkrimen/otto/cmpl.go @@ -0,0 +1,24 @@ +package otto + +import ( + "github.com/robertkrimen/otto/ast" + "github.com/robertkrimen/otto/file" +) + +type _file struct { + name string + src string + base int // This will always be 1 or greater +} + +type _compiler struct { + file *file.File + program *ast.Program +} + +func (cmpl *_compiler) parse() *_nodeProgram { + if cmpl.program != nil { + cmpl.file = cmpl.program.File + } + return cmpl._parse(cmpl.program) +} diff --git a/Godeps/_workspace/src/github.com/obscuren/otto/cmpl_evaluate.go b/Godeps/_workspace/src/github.com/robertkrimen/otto/cmpl_evaluate.go index a5b30f6c0..6741bf394 100644 --- a/Godeps/_workspace/src/github.com/obscuren/otto/cmpl_evaluate.go +++ b/Godeps/_workspace/src/github.com/robertkrimen/otto/cmpl_evaluate.go @@ -4,13 +4,20 @@ import ( "strconv" ) -func (self *_runtime) cmpl_evaluate_nodeProgram(node *_nodeProgram) Value { +func (self *_runtime) cmpl_evaluate_nodeProgram(node *_nodeProgram, eval bool) Value { + if !eval { + self.enterGlobalScope() + defer func() { + self.leaveScope() + }() + } self.cmpl_functionDeclaration(node.functionList) self.cmpl_variableDeclaration(node.varList) + self.scope.frame.file = node.file return self.cmpl_evaluate_nodeStatementList(node.body) } -func (self *_runtime) cmpl_call_nodeFunction(function *_object, environment *_functionEnvironment, node *_nodeFunctionLiteral, this Value, argumentList []Value) Value { +func (self *_runtime) cmpl_call_nodeFunction(function *_object, stash *_fnStash, node *_nodeFunctionLiteral, this Value, argumentList []Value) Value { indexOfParameterName := make([]string, len(argumentList)) // function(abc, def, ghi) @@ -24,19 +31,21 @@ func (self *_runtime) cmpl_call_nodeFunction(function *_object, environment *_fu if name == "arguments" { argumentsFound = true } - value := UndefinedValue() + value := Value{} if index < len(argumentList) { value = argumentList[index] indexOfParameterName[index] = name } - self.localSet(name, value) + // strict = false + self.scope.lexical.setValue(name, value, false) } if !argumentsFound { - arguments := self.newArgumentsObject(indexOfParameterName, environment, len(argumentList)) + arguments := self.newArgumentsObject(indexOfParameterName, stash, len(argumentList)) arguments.defineProperty("callee", toValue_object(function), 0101, false) - environment.arguments = arguments - self.localSet("arguments", toValue_object(arguments)) + stash.arguments = arguments + // strict = false + self.scope.lexical.setValue("arguments", toValue_object(arguments), false) for index, _ := range argumentList { if index < len(node.parameterList) { continue @@ -50,38 +59,38 @@ func (self *_runtime) cmpl_call_nodeFunction(function *_object, environment *_fu self.cmpl_variableDeclaration(node.varList) result := self.cmpl_evaluate_nodeStatement(node.body) - if result.isResult() { + if result.kind == valueResult { return result } - return UndefinedValue() + return Value{} } func (self *_runtime) cmpl_functionDeclaration(list []*_nodeFunctionLiteral) { - executionContext := self._executionContext(0) + executionContext := self.scope eval := executionContext.eval - environment := executionContext.VariableEnvironment + stash := executionContext.variable for _, function := range list { name := function.name value := self.cmpl_evaluate_nodeExpression(function) - if !environment.HasBinding(name) { - environment.CreateMutableBinding(name, eval == true) + if !stash.hasBinding(name) { + stash.createBinding(name, eval == true, value) + } else { + // TODO 10.5.5.e + stash.setBinding(name, value, false) // TODO strict } - // TODO 10.5.5.e - environment.SetMutableBinding(name, value, false) // TODO strict } } func (self *_runtime) cmpl_variableDeclaration(list []string) { - executionContext := self._executionContext(0) + executionContext := self.scope eval := executionContext.eval - environment := executionContext.VariableEnvironment + stash := executionContext.variable for _, name := range list { - if !environment.HasBinding(name) { - environment.CreateMutableBinding(name, eval == true) - environment.SetMutableBinding(name, UndefinedValue(), false) // TODO strict + if !stash.hasBinding(name) { + stash.createBinding(name, eval == true, Value{}) // TODO strict? } } } diff --git a/Godeps/_workspace/src/github.com/obscuren/otto/cmpl_evaluate_expression.go b/Godeps/_workspace/src/github.com/robertkrimen/otto/cmpl_evaluate_expression.go index 657667b36..34449970e 100644 --- a/Godeps/_workspace/src/github.com/obscuren/otto/cmpl_evaluate_expression.go +++ b/Godeps/_workspace/src/github.com/robertkrimen/otto/cmpl_evaluate_expression.go @@ -13,10 +13,10 @@ func (self *_runtime) cmpl_evaluate_nodeExpression(node _nodeExpression) Value { // If the Interrupt channel is nil, then // we avoid runtime.Gosched() overhead (if any) // FIXME: Test this - if self.Otto.Interrupt != nil { + if self.otto.Interrupt != nil { runtime.Gosched() select { - case value := <-self.Otto.Interrupt: + case value := <-self.otto.Interrupt: value() default: } @@ -50,15 +50,14 @@ func (self *_runtime) cmpl_evaluate_nodeExpression(node _nodeExpression) Value { return self.cmpl_evaluate_nodeDotExpression(node) case *_nodeFunctionLiteral: - var local = self.LexicalEnvironment() + var local = self.scope.lexical if node.name != "" { - local = self.newDeclarativeEnvironment(local) + local = self.newDeclarationStash(local) } value := toValue_object(self.newNodeFunction(node, local)) if node.name != "" { - local.CreateMutableBinding(node.name, false) - local.SetMutableBinding(node.name, value, false) + local.createBinding(node.name, false, value) } return value @@ -67,7 +66,7 @@ func (self *_runtime) cmpl_evaluate_nodeExpression(node _nodeExpression) Value { // TODO Should be true or false (strictness) depending on context // getIdentifierReference should not return nil, but we check anyway and panic // so as not to propagate the nil into something else - reference := getIdentifierReference(self.LexicalEnvironment(), name, false) + reference := getIdentifierReference(self, self.scope.lexical, name, false, _at(node.idx)) if reference == nil { // Should never get here! panic(hereBeDragons("referenceError == nil: " + name)) @@ -90,7 +89,7 @@ func (self *_runtime) cmpl_evaluate_nodeExpression(node _nodeExpression) Value { return self.cmpl_evaluate_nodeSequenceExpression(node) case *_nodeThisExpression: - return toValue_object(self._executionContext(0).this) + return toValue_object(self.scope.this) case *_nodeUnaryExpression: return self.cmpl_evaluate_nodeUnaryExpression(node) @@ -108,9 +107,9 @@ func (self *_runtime) cmpl_evaluate_nodeArrayLiteral(node *_nodeArrayLiteral) Va for _, node := range node.value { if node == nil { - valueArray = append(valueArray, Value{}) + valueArray = append(valueArray, emptyValue) } else { - valueArray = append(valueArray, self.GetValue(self.cmpl_evaluate_nodeExpression(node))) + valueArray = append(valueArray, self.cmpl_evaluate_nodeExpression(node).resolve()) } } @@ -123,14 +122,14 @@ func (self *_runtime) cmpl_evaluate_nodeAssignExpression(node *_nodeAssignExpres left := self.cmpl_evaluate_nodeExpression(node.left) right := self.cmpl_evaluate_nodeExpression(node.right) - rightValue := self.GetValue(right) + rightValue := right.resolve() result := rightValue if node.operator != token.ASSIGN { result = self.calculateBinaryExpression(node.operator, left, rightValue) } - self.PutValue(left.reference(), result) + self.putValue(left.reference(), result) return result } @@ -138,22 +137,22 @@ func (self *_runtime) cmpl_evaluate_nodeAssignExpression(node *_nodeAssignExpres func (self *_runtime) cmpl_evaluate_nodeBinaryExpression(node *_nodeBinaryExpression) Value { left := self.cmpl_evaluate_nodeExpression(node.left) - leftValue := self.GetValue(left) + leftValue := left.resolve() switch node.operator { // Logical case token.LOGICAL_AND: - if !toBoolean(leftValue) { + if !leftValue.bool() { return leftValue } right := self.cmpl_evaluate_nodeExpression(node.right) - return self.GetValue(right) + return right.resolve() case token.LOGICAL_OR: - if toBoolean(leftValue) { + if leftValue.bool() { return leftValue } right := self.cmpl_evaluate_nodeExpression(node.right) - return self.GetValue(right) + return right.resolve() } return self.calculateBinaryExpression(node.operator, leftValue, self.cmpl_evaluate_nodeExpression(node.right)) @@ -161,57 +160,90 @@ func (self *_runtime) cmpl_evaluate_nodeBinaryExpression(node *_nodeBinaryExpres func (self *_runtime) cmpl_evaluate_nodeBinaryExpression_comparison(node *_nodeBinaryExpression) Value { - left := self.GetValue(self.cmpl_evaluate_nodeExpression(node.left)) - right := self.GetValue(self.cmpl_evaluate_nodeExpression(node.right)) + left := self.cmpl_evaluate_nodeExpression(node.left).resolve() + right := self.cmpl_evaluate_nodeExpression(node.right).resolve() return toValue_bool(self.calculateComparison(node.operator, left, right)) } func (self *_runtime) cmpl_evaluate_nodeBracketExpression(node *_nodeBracketExpression) Value { target := self.cmpl_evaluate_nodeExpression(node.left) - targetValue := self.GetValue(target) + targetValue := target.resolve() member := self.cmpl_evaluate_nodeExpression(node.member) - memberValue := self.GetValue(member) + memberValue := member.resolve() // TODO Pass in base value as-is, and defer toObject till later? - return toValue(newPropertyReference(self.toObject(targetValue), toString(memberValue), false)) + return toValue(newPropertyReference(self, self.toObject(targetValue), memberValue.string(), false, _at(node.idx))) } func (self *_runtime) cmpl_evaluate_nodeCallExpression(node *_nodeCallExpression, withArgumentList []interface{}) Value { + rt := self + this := Value{} callee := self.cmpl_evaluate_nodeExpression(node.callee) - calleeValue := self.GetValue(callee) + argumentList := []Value{} if withArgumentList != nil { argumentList = self.toValueArray(withArgumentList...) } else { for _, argumentNode := range node.argumentList { - argumentList = append(argumentList, self.GetValue(self.cmpl_evaluate_nodeExpression(argumentNode))) + argumentList = append(argumentList, self.cmpl_evaluate_nodeExpression(argumentNode).resolve()) } } - this := UndefinedValue() - calleeReference := callee.reference() - evalHint := false - if calleeReference != nil { - if calleeReference.IsPropertyReference() { - calleeObject := calleeReference.GetBase().(*_object) - this = toValue_object(calleeObject) - } else { - // TODO ImplictThisValue - } - if calleeReference.GetName() == "eval" { - evalHint = true // Possible direct eval + + rf := callee.reference() + vl := callee.resolve() + + eval := false // Whether this call is a (candidate for) direct call to eval + name := "" + if rf != nil { + switch rf := rf.(type) { + case *_propertyReference: + name = rf.name + object := rf.base + this = toValue_object(object) + eval = rf.name == "eval" // Possible direct eval + case *_stashReference: + // TODO ImplicitThisValue + name = rf.name + eval = rf.name == "eval" // Possible direct eval + default: + // FIXME? + panic(rt.panicTypeError("Here be dragons")) } } - if !calleeValue.IsFunction() { - panic(newTypeError("%v is not a function", calleeValue)) + + at := _at(-1) + switch callee := node.callee.(type) { + case *_nodeIdentifier: + at = _at(callee.idx) + case *_nodeDotExpression: + at = _at(callee.idx) + case *_nodeBracketExpression: + at = _at(callee.idx) + } + + frame := _frame{ + callee: name, + file: self.scope.frame.file, + } + + if !vl.IsFunction() { + if name == "" { + // FIXME Maybe typeof? + panic(rt.panicTypeError("%v is not a function", vl, at)) + } + panic(rt.panicTypeError("'%s' is not a function", name, at)) } - return self.Call(calleeValue._object(), this, argumentList, evalHint) + + self.scope.frame.offset = int(at) + + return vl._object().call(this, argumentList, eval, frame) } func (self *_runtime) cmpl_evaluate_nodeConditionalExpression(node *_nodeConditionalExpression) Value { test := self.cmpl_evaluate_nodeExpression(node.test) - testValue := self.GetValue(test) - if toBoolean(testValue) { + testValue := test.resolve() + if testValue.bool() { return self.cmpl_evaluate_nodeExpression(node.consequent) } return self.cmpl_evaluate_nodeExpression(node.alternate) @@ -219,27 +251,60 @@ func (self *_runtime) cmpl_evaluate_nodeConditionalExpression(node *_nodeConditi func (self *_runtime) cmpl_evaluate_nodeDotExpression(node *_nodeDotExpression) Value { target := self.cmpl_evaluate_nodeExpression(node.left) - targetValue := self.GetValue(target) + targetValue := target.resolve() // TODO Pass in base value as-is, and defer toObject till later? object, err := self.objectCoerce(targetValue) if err != nil { - panic(newTypeError(fmt.Sprintf("Cannot access member '%s' of %s", node.identifier, err.Error()))) + panic(self.panicTypeError("Cannot access member '%s' of %s", node.identifier, err.Error())) } - return toValue(newPropertyReference(object, node.identifier, false)) + return toValue(newPropertyReference(self, object, node.identifier, false, _at(node.idx))) } func (self *_runtime) cmpl_evaluate_nodeNewExpression(node *_nodeNewExpression) Value { + rt := self callee := self.cmpl_evaluate_nodeExpression(node.callee) - calleeValue := self.GetValue(callee) + argumentList := []Value{} for _, argumentNode := range node.argumentList { - argumentList = append(argumentList, self.GetValue(self.cmpl_evaluate_nodeExpression(argumentNode))) + argumentList = append(argumentList, self.cmpl_evaluate_nodeExpression(argumentNode).resolve()) } - this := UndefinedValue() - if !calleeValue.IsFunction() { - panic(newTypeError("%v is not a function", calleeValue)) + + rf := callee.reference() + vl := callee.resolve() + + name := "" + if rf != nil { + switch rf := rf.(type) { + case *_propertyReference: + name = rf.name + case *_stashReference: + name = rf.name + default: + panic(rt.panicTypeError("Here be dragons")) + } } - return calleeValue._object().Construct(this, argumentList) + + at := _at(-1) + switch callee := node.callee.(type) { + case *_nodeIdentifier: + at = _at(callee.idx) + case *_nodeDotExpression: + at = _at(callee.idx) + case *_nodeBracketExpression: + at = _at(callee.idx) + } + + if !vl.IsFunction() { + if name == "" { + // FIXME Maybe typeof? + panic(rt.panicTypeError("%v is not a function", vl, at)) + } + panic(rt.panicTypeError("'%s' is not a function", name, at)) + } + + self.scope.frame.offset = int(at) + + return vl._object().construct(argumentList) } func (self *_runtime) cmpl_evaluate_nodeObjectLiteral(node *_nodeObjectLiteral) Value { @@ -249,15 +314,15 @@ func (self *_runtime) cmpl_evaluate_nodeObjectLiteral(node *_nodeObjectLiteral) for _, property := range node.value { switch property.kind { case "value": - result.defineProperty(property.key, self.GetValue(self.cmpl_evaluate_nodeExpression(property.value)), 0111, false) + result.defineProperty(property.key, self.cmpl_evaluate_nodeExpression(property.value).resolve(), 0111, false) case "get": - getter := self.newNodeFunction(property.value.(*_nodeFunctionLiteral), self.LexicalEnvironment()) + getter := self.newNodeFunction(property.value.(*_nodeFunctionLiteral), self.scope.lexical) descriptor := _property{} descriptor.mode = 0211 descriptor.value = _propertyGetSet{getter, nil} result.defineOwnProperty(property.key, descriptor, false) case "set": - setter := self.newNodeFunction(property.value.(*_nodeFunctionLiteral), self.LexicalEnvironment()) + setter := self.newNodeFunction(property.value.(*_nodeFunctionLiteral), self.scope.lexical) descriptor := _property{} descriptor.mode = 0211 descriptor.value = _propertyGetSet{nil, setter} @@ -274,7 +339,7 @@ func (self *_runtime) cmpl_evaluate_nodeSequenceExpression(node *_nodeSequenceEx var result Value for _, node := range node.sequence { result = self.cmpl_evaluate_nodeExpression(node) - result = self.GetValue(result) + result = result.resolve() } return result } @@ -284,31 +349,31 @@ func (self *_runtime) cmpl_evaluate_nodeUnaryExpression(node *_nodeUnaryExpressi target := self.cmpl_evaluate_nodeExpression(node.operand) switch node.operator { case token.TYPEOF, token.DELETE: - if target._valueType == valueReference && target.reference().IsUnresolvable() { + if target.kind == valueReference && target.reference().invalid() { if node.operator == token.TYPEOF { return toValue_string("undefined") } - return TrueValue() + return trueValue } } switch node.operator { case token.NOT: - targetValue := self.GetValue(target) - if targetValue.toBoolean() { - return FalseValue() + targetValue := target.resolve() + if targetValue.bool() { + return falseValue } - return TrueValue() + return trueValue case token.BITWISE_NOT: - targetValue := self.GetValue(target) + targetValue := target.resolve() integerValue := toInt32(targetValue) return toValue_int32(^integerValue) case token.PLUS: - targetValue := self.GetValue(target) - return toValue_float64(targetValue.toFloat()) + targetValue := target.resolve() + return toValue_float64(targetValue.float64()) case token.MINUS: - targetValue := self.GetValue(target) - value := targetValue.toFloat() + targetValue := target.resolve() + value := targetValue.float64() // TODO Test this sign := float64(-1) if math.Signbit(value) { @@ -316,45 +381,45 @@ func (self *_runtime) cmpl_evaluate_nodeUnaryExpression(node *_nodeUnaryExpressi } return toValue_float64(math.Copysign(value, sign)) case token.INCREMENT: - targetValue := self.GetValue(target) + targetValue := target.resolve() if node.postfix { // Postfix++ - oldValue := targetValue.toFloat() + oldValue := targetValue.float64() newValue := toValue_float64(+1 + oldValue) - self.PutValue(target.reference(), newValue) + self.putValue(target.reference(), newValue) return toValue_float64(oldValue) } else { // ++Prefix - newValue := toValue_float64(+1 + targetValue.toFloat()) - self.PutValue(target.reference(), newValue) + newValue := toValue_float64(+1 + targetValue.float64()) + self.putValue(target.reference(), newValue) return newValue } case token.DECREMENT: - targetValue := self.GetValue(target) + targetValue := target.resolve() if node.postfix { // Postfix-- - oldValue := targetValue.toFloat() + oldValue := targetValue.float64() newValue := toValue_float64(-1 + oldValue) - self.PutValue(target.reference(), newValue) + self.putValue(target.reference(), newValue) return toValue_float64(oldValue) } else { // --Prefix - newValue := toValue_float64(-1 + targetValue.toFloat()) - self.PutValue(target.reference(), newValue) + newValue := toValue_float64(-1 + targetValue.float64()) + self.putValue(target.reference(), newValue) return newValue } case token.VOID: - self.GetValue(target) // FIXME Side effect? - return UndefinedValue() + target.resolve() // FIXME Side effect? + return Value{} case token.DELETE: reference := target.reference() if reference == nil { - return TrueValue() + return trueValue } - return toValue_bool(target.reference().Delete()) + return toValue_bool(target.reference().delete()) case token.TYPEOF: - targetValue := self.GetValue(target) - switch targetValue._valueType { + targetValue := target.resolve() + switch targetValue.kind { case valueUndefined: return toValue_string("undefined") case valueNull: @@ -366,7 +431,7 @@ func (self *_runtime) cmpl_evaluate_nodeUnaryExpression(node *_nodeUnaryExpressi case valueString: return toValue_string("string") case valueObject: - if targetValue._object().functionValue().call != nil { + if targetValue._object().isCall() { return toValue_string("function") } return toValue_string("object") @@ -381,11 +446,11 @@ func (self *_runtime) cmpl_evaluate_nodeUnaryExpression(node *_nodeUnaryExpressi func (self *_runtime) cmpl_evaluate_nodeVariableExpression(node *_nodeVariableExpression) Value { if node.initializer != nil { // FIXME If reference is nil - left := getIdentifierReference(self.LexicalEnvironment(), node.name, false) + left := getIdentifierReference(self, self.scope.lexical, node.name, false, _at(node.idx)) right := self.cmpl_evaluate_nodeExpression(node.initializer) - rightValue := self.GetValue(right) + rightValue := right.resolve() - self.PutValue(left, rightValue) + self.putValue(left, rightValue) } return toValue_string(node.name) } diff --git a/Godeps/_workspace/src/github.com/obscuren/otto/cmpl_evaluate_statement.go b/Godeps/_workspace/src/github.com/robertkrimen/otto/cmpl_evaluate_statement.go index 6add2baea..7be158487 100644 --- a/Godeps/_workspace/src/github.com/obscuren/otto/cmpl_evaluate_statement.go +++ b/Godeps/_workspace/src/github.com/robertkrimen/otto/cmpl_evaluate_statement.go @@ -12,10 +12,10 @@ func (self *_runtime) cmpl_evaluate_nodeStatement(node _nodeStatement) Value { // If the Interrupt channel is nil, then // we avoid runtime.Gosched() overhead (if any) // FIXME: Test this - if self.Otto.Interrupt != nil { + if self.otto.Interrupt != nil { runtime.Gosched() select { - case value := <-self.Otto.Interrupt: + case value := <-self.otto.Interrupt: value() default: } @@ -24,8 +24,18 @@ func (self *_runtime) cmpl_evaluate_nodeStatement(node _nodeStatement) Value { switch node := node.(type) { case *_nodeBlockStatement: - // FIXME If result is break, then return the empty value? - return self.cmpl_evaluate_nodeStatementList(node.list) + labels := self.labels + self.labels = nil + + value := self.cmpl_evaluate_nodeStatementList(node.list) + switch value.kind { + case valueResult: + switch value.evaluateBreak(labels) { + case resultBreak: + return emptyValue + } + } + return value case *_nodeBranchStatement: target := node.label @@ -37,13 +47,13 @@ func (self *_runtime) cmpl_evaluate_nodeStatement(node _nodeStatement) Value { } case *_nodeDebuggerStatement: - return Value{} // Nothing happens. + return emptyValue // Nothing happens. case *_nodeDoWhileStatement: return self.cmpl_evaluate_nodeDoWhileStatement(node) case *_nodeEmptyStatement: - return Value{} + return emptyValue case *_nodeExpressionStatement: return self.cmpl_evaluate_nodeExpression(node.expression) @@ -70,15 +80,15 @@ func (self *_runtime) cmpl_evaluate_nodeStatement(node _nodeStatement) Value { case *_nodeReturnStatement: if node.argument != nil { - return toValue(newReturnResult(self.GetValue(self.cmpl_evaluate_nodeExpression(node.argument)))) + return toValue(newReturnResult(self.cmpl_evaluate_nodeExpression(node.argument).resolve())) } - return toValue(newReturnResult(UndefinedValue())) + return toValue(newReturnResult(Value{})) case *_nodeSwitchStatement: return self.cmpl_evaluate_nodeSwitchStatement(node) case *_nodeThrowStatement: - value := self.GetValue(self.cmpl_evaluate_nodeExpression(node.argument)) + value := self.cmpl_evaluate_nodeExpression(node.argument).resolve() panic(newException(value)) case *_nodeTryStatement: @@ -89,7 +99,7 @@ func (self *_runtime) cmpl_evaluate_nodeStatement(node _nodeStatement) Value { for _, variable := range node.list { self.cmpl_evaluate_nodeVariableExpression(variable.(*_nodeVariableExpression)) } - return Value{} + return emptyValue case *_nodeWhileStatement: return self.cmpl_evaluate_nodeWhileStatement(node) @@ -106,17 +116,17 @@ func (self *_runtime) cmpl_evaluate_nodeStatementList(list []_nodeStatement) Val var result Value for _, node := range list { value := self.cmpl_evaluate_nodeStatement(node) - switch value._valueType { + switch value.kind { case valueResult: return value case valueEmpty: default: - // We have GetValue here to (for example) trigger a + // We have getValue here to (for example) trigger a // ReferenceError (of the not defined variety) // Not sure if this is the best way to error out early // for such errors or if there is a better way // TODO Do we still need this? - result = self.GetValue(value) + result = value.resolve() } } return result @@ -129,12 +139,12 @@ func (self *_runtime) cmpl_evaluate_nodeDoWhileStatement(node *_nodeDoWhileState test := node.test - result := Value{} + result := emptyValue resultBreak: for { for _, node := range node.body { value := self.cmpl_evaluate_nodeStatement(node) - switch value._valueType { + switch value.kind { case valueResult: switch value.evaluateBreakContinue(labels) { case resultReturn: @@ -150,7 +160,7 @@ resultBreak: } } resultContinue: - if !self.GetValue(self.cmpl_evaluate_nodeExpression(test)).isTrue() { + if !self.cmpl_evaluate_nodeExpression(test).resolve().bool() { // Stahp: do ... while (false) break } @@ -164,11 +174,11 @@ func (self *_runtime) cmpl_evaluate_nodeForInStatement(node *_nodeForInStatement self.labels = nil source := self.cmpl_evaluate_nodeExpression(node.source) - sourceValue := self.GetValue(source) + sourceValue := source.resolve() - switch sourceValue._valueType { + switch sourceValue.kind { case valueUndefined, valueNull: - return emptyValue() + return emptyValue } sourceObject := self.toObject(sourceValue) @@ -176,22 +186,22 @@ func (self *_runtime) cmpl_evaluate_nodeForInStatement(node *_nodeForInStatement into := node.into body := node.body - result := Value{} + result := emptyValue object := sourceObject for object != nil { - enumerateValue := Value{} + enumerateValue := emptyValue object.enumerate(false, func(name string) bool { into := self.cmpl_evaluate_nodeExpression(into) // In the case of: for (var abc in def) ... if into.reference() == nil { - identifier := toString(into) + identifier := into.string() // TODO Should be true or false (strictness) depending on context - into = toValue(getIdentifierReference(self.LexicalEnvironment(), identifier, false)) + into = toValue(getIdentifierReference(self, self.scope.lexical, identifier, false, -1)) } - self.PutValue(into.reference(), toValue_string(name)) + self.putValue(into.reference(), toValue_string(name)) for _, node := range body { value := self.cmpl_evaluate_nodeStatement(node) - switch value._valueType { + switch value.kind { case valueResult: switch value.evaluateBreakContinue(labels) { case resultReturn: @@ -233,22 +243,22 @@ func (self *_runtime) cmpl_evaluate_nodeForStatement(node *_nodeForStatement) Va if initializer != nil { initialResult := self.cmpl_evaluate_nodeExpression(initializer) - self.GetValue(initialResult) // Side-effect trigger + initialResult.resolve() // Side-effect trigger } - result := Value{} + result := emptyValue resultBreak: for { if test != nil { testResult := self.cmpl_evaluate_nodeExpression(test) - testResultValue := self.GetValue(testResult) - if toBoolean(testResultValue) == false { + testResultValue := testResult.resolve() + if testResultValue.bool() == false { break } } for _, node := range body { value := self.cmpl_evaluate_nodeStatement(node) - switch value._valueType { + switch value.kind { case valueResult: switch value.evaluateBreakContinue(labels) { case resultReturn: @@ -266,7 +276,7 @@ resultBreak: resultContinue: if update != nil { updateResult := self.cmpl_evaluate_nodeExpression(update) - self.GetValue(updateResult) // Side-effect trigger + updateResult.resolve() // Side-effect trigger } } return result @@ -274,14 +284,14 @@ resultBreak: func (self *_runtime) cmpl_evaluate_nodeIfStatement(node *_nodeIfStatement) Value { test := self.cmpl_evaluate_nodeExpression(node.test) - testValue := self.GetValue(test) - if toBoolean(testValue) { + testValue := test.resolve() + if testValue.bool() { return self.cmpl_evaluate_nodeStatement(node.consequent) } else if node.alternate != nil { return self.cmpl_evaluate_nodeStatement(node.alternate) } - return Value{} + return emptyValue } func (self *_runtime) cmpl_evaluate_nodeSwitchStatement(node *_nodeSwitchStatement) Value { @@ -302,18 +312,18 @@ func (self *_runtime) cmpl_evaluate_nodeSwitchStatement(node *_nodeSwitchStateme } } - result := Value{} + result := emptyValue if target != -1 { for _, clause := range node.body[target:] { for _, statement := range clause.consequent { value := self.cmpl_evaluate_nodeStatement(statement) - switch value._valueType { + switch value.kind { case valueResult: switch value.evaluateBreak(labels) { case resultReturn: return value case resultBreak: - return Value{} + return emptyValue } case valueEmpty: default: @@ -332,14 +342,15 @@ func (self *_runtime) cmpl_evaluate_nodeTryStatement(node *_nodeTryStatement) Va }) if exception && node.catch != nil { - - lexicalEnvironment := self._executionContext(0).newDeclarativeEnvironment(self) + outer := self.scope.lexical + self.scope.lexical = self.newDeclarationStash(outer) defer func() { - self._executionContext(0).LexicalEnvironment = lexicalEnvironment + self.scope.lexical = outer }() // TODO If necessary, convert TypeError<runtime> => TypeError // That, is, such errors can be thrown despite not being JavaScript "native" - self.localSet(node.catch.parameter, tryCatchValue) + // strict = false + self.scope.lexical.setValue(node.catch.parameter, tryCatchValue, false) // FIXME node.CatchParameter // FIXME node.Catch @@ -350,7 +361,7 @@ func (self *_runtime) cmpl_evaluate_nodeTryStatement(node *_nodeTryStatement) Va if node.finally != nil { finallyValue := self.cmpl_evaluate_nodeStatement(node.finally) - if finallyValue.isResult() { + if finallyValue.kind == valueResult { return finallyValue } } @@ -369,16 +380,16 @@ func (self *_runtime) cmpl_evaluate_nodeWhileStatement(node *_nodeWhileStatement labels := append(self.labels, "") self.labels = nil - result := Value{} + result := emptyValue resultBreakContinue: for { - if !self.GetValue(self.cmpl_evaluate_nodeExpression(test)).isTrue() { + if !self.cmpl_evaluate_nodeExpression(test).resolve().bool() { // Stahp: while (false) ... break } for _, node := range body { value := self.cmpl_evaluate_nodeStatement(node) - switch value._valueType { + switch value.kind { case valueResult: switch value.evaluateBreakContinue(labels) { case resultReturn: @@ -399,11 +410,11 @@ resultBreakContinue: func (self *_runtime) cmpl_evaluate_nodeWithStatement(node *_nodeWithStatement) Value { object := self.cmpl_evaluate_nodeExpression(node.object) - objectValue := self.GetValue(object) - previousLexicalEnvironment, lexicalEnvironment := self._executionContext(0).newLexicalEnvironment(self.toObject(objectValue)) - lexicalEnvironment.ProvideThis = true + outer := self.scope.lexical + lexical := self.newObjectStash(self.toObject(object.resolve()), outer) + self.scope.lexical = lexical defer func() { - self._executionContext(0).LexicalEnvironment = previousLexicalEnvironment + self.scope.lexical = outer }() return self.cmpl_evaluate_nodeStatement(node.body) diff --git a/Godeps/_workspace/src/github.com/obscuren/otto/cmpl_parse.go b/Godeps/_workspace/src/github.com/robertkrimen/otto/cmpl_parse.go index 7ce1af57d..e758a5230 100644 --- a/Godeps/_workspace/src/github.com/obscuren/otto/cmpl_parse.go +++ b/Godeps/_workspace/src/github.com/robertkrimen/otto/cmpl_parse.go @@ -5,165 +5,170 @@ import ( "regexp" "github.com/robertkrimen/otto/ast" + "github.com/robertkrimen/otto/file" "github.com/robertkrimen/otto/token" ) var trueLiteral = &_nodeLiteral{value: toValue_bool(true)} var falseLiteral = &_nodeLiteral{value: toValue_bool(false)} -var nullLiteral = &_nodeLiteral{value: NullValue()} +var nullLiteral = &_nodeLiteral{value: nullValue} var emptyStatement = &_nodeEmptyStatement{} -func parseExpression(x ast.Expression) _nodeExpression { - if x == nil { +func (cmpl *_compiler) parseExpression(in ast.Expression) _nodeExpression { + if in == nil { return nil } - switch x := x.(type) { + switch in := in.(type) { case *ast.ArrayLiteral: - y := &_nodeArrayLiteral{ - value: make([]_nodeExpression, len(x.Value)), + out := &_nodeArrayLiteral{ + value: make([]_nodeExpression, len(in.Value)), } - for i, value := range x.Value { - y.value[i] = parseExpression(value) + for i, value := range in.Value { + out.value[i] = cmpl.parseExpression(value) } - return y + return out case *ast.AssignExpression: return &_nodeAssignExpression{ - operator: x.Operator, - left: parseExpression(x.Left), - right: parseExpression(x.Right), + operator: in.Operator, + left: cmpl.parseExpression(in.Left), + right: cmpl.parseExpression(in.Right), } case *ast.BinaryExpression: return &_nodeBinaryExpression{ - operator: x.Operator, - left: parseExpression(x.Left), - right: parseExpression(x.Right), - comparison: x.Comparison, + operator: in.Operator, + left: cmpl.parseExpression(in.Left), + right: cmpl.parseExpression(in.Right), + comparison: in.Comparison, } case *ast.BooleanLiteral: - if x.Value { + if in.Value { return trueLiteral } return falseLiteral case *ast.BracketExpression: return &_nodeBracketExpression{ - left: parseExpression(x.Left), - member: parseExpression(x.Member), + idx: in.Left.Idx0(), + left: cmpl.parseExpression(in.Left), + member: cmpl.parseExpression(in.Member), } case *ast.CallExpression: - y := &_nodeCallExpression{ - callee: parseExpression(x.Callee), - argumentList: make([]_nodeExpression, len(x.ArgumentList)), + out := &_nodeCallExpression{ + callee: cmpl.parseExpression(in.Callee), + argumentList: make([]_nodeExpression, len(in.ArgumentList)), } - for i, value := range x.ArgumentList { - y.argumentList[i] = parseExpression(value) + for i, value := range in.ArgumentList { + out.argumentList[i] = cmpl.parseExpression(value) } - return y + return out case *ast.ConditionalExpression: return &_nodeConditionalExpression{ - test: parseExpression(x.Test), - consequent: parseExpression(x.Consequent), - alternate: parseExpression(x.Alternate), + test: cmpl.parseExpression(in.Test), + consequent: cmpl.parseExpression(in.Consequent), + alternate: cmpl.parseExpression(in.Alternate), } case *ast.DotExpression: return &_nodeDotExpression{ - left: parseExpression(x.Left), - identifier: x.Identifier.Name, + idx: in.Left.Idx0(), + left: cmpl.parseExpression(in.Left), + identifier: in.Identifier.Name, } case *ast.FunctionLiteral: name := "" - if x.Name != nil { - name = x.Name.Name + if in.Name != nil { + name = in.Name.Name } - y := &_nodeFunctionLiteral{ + out := &_nodeFunctionLiteral{ name: name, - body: parseStatement(x.Body), - source: x.Source, + body: cmpl.parseStatement(in.Body), + source: in.Source, + file: cmpl.file, } - if x.ParameterList != nil { - list := x.ParameterList.List - y.parameterList = make([]string, len(list)) + if in.ParameterList != nil { + list := in.ParameterList.List + out.parameterList = make([]string, len(list)) for i, value := range list { - y.parameterList[i] = value.Name + out.parameterList[i] = value.Name } } - for _, value := range x.DeclarationList { + for _, value := range in.DeclarationList { switch value := value.(type) { case *ast.FunctionDeclaration: - y.functionList = append(y.functionList, parseExpression(value.Function).(*_nodeFunctionLiteral)) + out.functionList = append(out.functionList, cmpl.parseExpression(value.Function).(*_nodeFunctionLiteral)) case *ast.VariableDeclaration: for _, value := range value.List { - y.varList = append(y.varList, value.Name) + out.varList = append(out.varList, value.Name) } default: panic(fmt.Errorf("Here be dragons: parseProgram.declaration(%T)", value)) } } - return y + return out case *ast.Identifier: return &_nodeIdentifier{ - name: x.Name, + idx: in.Idx, + name: in.Name, } case *ast.NewExpression: - y := &_nodeNewExpression{ - callee: parseExpression(x.Callee), - argumentList: make([]_nodeExpression, len(x.ArgumentList)), + out := &_nodeNewExpression{ + callee: cmpl.parseExpression(in.Callee), + argumentList: make([]_nodeExpression, len(in.ArgumentList)), } - for i, value := range x.ArgumentList { - y.argumentList[i] = parseExpression(value) + for i, value := range in.ArgumentList { + out.argumentList[i] = cmpl.parseExpression(value) } - return y + return out case *ast.NullLiteral: return nullLiteral case *ast.NumberLiteral: return &_nodeLiteral{ - value: toValue(x.Value), + value: toValue(in.Value), } case *ast.ObjectLiteral: - y := &_nodeObjectLiteral{ - value: make([]_nodeProperty, len(x.Value)), + out := &_nodeObjectLiteral{ + value: make([]_nodeProperty, len(in.Value)), } - for i, value := range x.Value { - y.value[i] = _nodeProperty{ + for i, value := range in.Value { + out.value[i] = _nodeProperty{ key: value.Key, kind: value.Kind, - value: parseExpression(value.Value), + value: cmpl.parseExpression(value.Value), } } - return y + return out case *ast.RegExpLiteral: return &_nodeRegExpLiteral{ - flags: x.Flags, - pattern: x.Pattern, + flags: in.Flags, + pattern: in.Pattern, } case *ast.SequenceExpression: - y := &_nodeSequenceExpression{ - sequence: make([]_nodeExpression, len(x.Sequence)), + out := &_nodeSequenceExpression{ + sequence: make([]_nodeExpression, len(in.Sequence)), } - for i, value := range x.Sequence { - y.sequence[i] = parseExpression(value) + for i, value := range in.Sequence { + out.sequence[i] = cmpl.parseExpression(value) } - return y + return out case *ast.StringLiteral: return &_nodeLiteral{ - value: toValue_string(x.Value), + value: toValue_string(in.Value), } case *ast.ThisExpression: @@ -171,203 +176,211 @@ func parseExpression(x ast.Expression) _nodeExpression { case *ast.UnaryExpression: return &_nodeUnaryExpression{ - operator: x.Operator, - operand: parseExpression(x.Operand), - postfix: x.Postfix, + operator: in.Operator, + operand: cmpl.parseExpression(in.Operand), + postfix: in.Postfix, } case *ast.VariableExpression: return &_nodeVariableExpression{ - name: x.Name, - initializer: parseExpression(x.Initializer), + idx: in.Idx0(), + name: in.Name, + initializer: cmpl.parseExpression(in.Initializer), } } - panic(fmt.Errorf("Here be dragons: parseExpression(%T)", x)) + panic(fmt.Errorf("Here be dragons: cmpl.parseExpression(%T)", in)) } -func parseStatement(x ast.Statement) _nodeStatement { - if x == nil { +func (cmpl *_compiler) parseStatement(in ast.Statement) _nodeStatement { + if in == nil { return nil } - switch x := x.(type) { + switch in := in.(type) { case *ast.BlockStatement: - y := &_nodeBlockStatement{ - list: make([]_nodeStatement, len(x.List)), + out := &_nodeBlockStatement{ + list: make([]_nodeStatement, len(in.List)), } - for i, value := range x.List { - y.list[i] = parseStatement(value) + for i, value := range in.List { + out.list[i] = cmpl.parseStatement(value) } - return y + return out case *ast.BranchStatement: - y := &_nodeBranchStatement{ - branch: x.Token, + out := &_nodeBranchStatement{ + branch: in.Token, } - if x.Label != nil { - y.label = x.Label.Name + if in.Label != nil { + out.label = in.Label.Name } - return y + return out case *ast.DebuggerStatement: return &_nodeDebuggerStatement{} case *ast.DoWhileStatement: - y := &_nodeDoWhileStatement{ - test: parseExpression(x.Test), + out := &_nodeDoWhileStatement{ + test: cmpl.parseExpression(in.Test), } - body := parseStatement(x.Body) + body := cmpl.parseStatement(in.Body) if block, ok := body.(*_nodeBlockStatement); ok { - y.body = block.list + out.body = block.list } else { - y.body = append(y.body, body) + out.body = append(out.body, body) } - return y + return out case *ast.EmptyStatement: return emptyStatement case *ast.ExpressionStatement: return &_nodeExpressionStatement{ - expression: parseExpression(x.Expression), + expression: cmpl.parseExpression(in.Expression), } case *ast.ForInStatement: - y := &_nodeForInStatement{ - into: parseExpression(x.Into), - source: parseExpression(x.Source), + out := &_nodeForInStatement{ + into: cmpl.parseExpression(in.Into), + source: cmpl.parseExpression(in.Source), } - body := parseStatement(x.Body) + body := cmpl.parseStatement(in.Body) if block, ok := body.(*_nodeBlockStatement); ok { - y.body = block.list + out.body = block.list } else { - y.body = append(y.body, body) + out.body = append(out.body, body) } - return y + return out case *ast.ForStatement: - y := &_nodeForStatement{ - initializer: parseExpression(x.Initializer), - update: parseExpression(x.Update), - test: parseExpression(x.Test), + out := &_nodeForStatement{ + initializer: cmpl.parseExpression(in.Initializer), + update: cmpl.parseExpression(in.Update), + test: cmpl.parseExpression(in.Test), } - body := parseStatement(x.Body) + body := cmpl.parseStatement(in.Body) if block, ok := body.(*_nodeBlockStatement); ok { - y.body = block.list + out.body = block.list } else { - y.body = append(y.body, body) + out.body = append(out.body, body) } - return y + return out case *ast.IfStatement: return &_nodeIfStatement{ - test: parseExpression(x.Test), - consequent: parseStatement(x.Consequent), - alternate: parseStatement(x.Alternate), + test: cmpl.parseExpression(in.Test), + consequent: cmpl.parseStatement(in.Consequent), + alternate: cmpl.parseStatement(in.Alternate), } case *ast.LabelledStatement: return &_nodeLabelledStatement{ - label: x.Label.Name, - statement: parseStatement(x.Statement), + label: in.Label.Name, + statement: cmpl.parseStatement(in.Statement), } case *ast.ReturnStatement: return &_nodeReturnStatement{ - argument: parseExpression(x.Argument), + argument: cmpl.parseExpression(in.Argument), } case *ast.SwitchStatement: - y := &_nodeSwitchStatement{ - discriminant: parseExpression(x.Discriminant), - default_: x.Default, - body: make([]*_nodeCaseStatement, len(x.Body)), - } - for i, p := range x.Body { - q := &_nodeCaseStatement{ - test: parseExpression(p.Test), - consequent: make([]_nodeStatement, len(p.Consequent)), + out := &_nodeSwitchStatement{ + discriminant: cmpl.parseExpression(in.Discriminant), + default_: in.Default, + body: make([]*_nodeCaseStatement, len(in.Body)), + } + for i, clause := range in.Body { + out.body[i] = &_nodeCaseStatement{ + test: cmpl.parseExpression(clause.Test), + consequent: make([]_nodeStatement, len(clause.Consequent)), } - for j, value := range p.Consequent { - q.consequent[j] = parseStatement(value) + for j, value := range clause.Consequent { + out.body[i].consequent[j] = cmpl.parseStatement(value) } - y.body[i] = q } - return y + return out case *ast.ThrowStatement: return &_nodeThrowStatement{ - argument: parseExpression(x.Argument), + argument: cmpl.parseExpression(in.Argument), } case *ast.TryStatement: - y := &_nodeTryStatement{ - body: parseStatement(x.Body), - finally: parseStatement(x.Finally), - } - if x.Catch != nil { - y.catch = &_nodeCatchStatement{ - parameter: x.Catch.Parameter.Name, - body: parseStatement(x.Catch.Body), + out := &_nodeTryStatement{ + body: cmpl.parseStatement(in.Body), + finally: cmpl.parseStatement(in.Finally), + } + if in.Catch != nil { + out.catch = &_nodeCatchStatement{ + parameter: in.Catch.Parameter.Name, + body: cmpl.parseStatement(in.Catch.Body), } } - return y + return out case *ast.VariableStatement: - y := &_nodeVariableStatement{ - list: make([]_nodeExpression, len(x.List)), + out := &_nodeVariableStatement{ + list: make([]_nodeExpression, len(in.List)), } - for i, value := range x.List { - y.list[i] = parseExpression(value) + for i, value := range in.List { + out.list[i] = cmpl.parseExpression(value) } - return y + return out case *ast.WhileStatement: - y := &_nodeWhileStatement{ - test: parseExpression(x.Test), + out := &_nodeWhileStatement{ + test: cmpl.parseExpression(in.Test), } - body := parseStatement(x.Body) + body := cmpl.parseStatement(in.Body) if block, ok := body.(*_nodeBlockStatement); ok { - y.body = block.list + out.body = block.list } else { - y.body = append(y.body, body) + out.body = append(out.body, body) } - return y + return out case *ast.WithStatement: return &_nodeWithStatement{ - object: parseExpression(x.Object), - body: parseStatement(x.Body), + object: cmpl.parseExpression(in.Object), + body: cmpl.parseStatement(in.Body), } } - panic(fmt.Errorf("Here be dragons: parseStatement(%T)", x)) + panic(fmt.Errorf("Here be dragons: cmpl.parseStatement(%T)", in)) } -func cmpl_parse(x *ast.Program) *_nodeProgram { - y := &_nodeProgram{ - body: make([]_nodeStatement, len(x.Body)), +func cmpl_parse(in *ast.Program) *_nodeProgram { + cmpl := _compiler{ + program: in, } - for i, value := range x.Body { - y.body[i] = parseStatement(value) + return cmpl.parse() +} + +func (cmpl *_compiler) _parse(in *ast.Program) *_nodeProgram { + out := &_nodeProgram{ + body: make([]_nodeStatement, len(in.Body)), + file: in.File, } - for _, value := range x.DeclarationList { + for i, value := range in.Body { + out.body[i] = cmpl.parseStatement(value) + } + for _, value := range in.DeclarationList { switch value := value.(type) { case *ast.FunctionDeclaration: - y.functionList = append(y.functionList, parseExpression(value.Function).(*_nodeFunctionLiteral)) + out.functionList = append(out.functionList, cmpl.parseExpression(value.Function).(*_nodeFunctionLiteral)) case *ast.VariableDeclaration: for _, value := range value.List { - y.varList = append(y.varList, value.Name) + out.varList = append(out.varList, value.Name) } default: - panic(fmt.Errorf("Here be dragons: parseProgram.DeclarationList(%T)", value)) + panic(fmt.Errorf("Here be dragons: cmpl.parseProgram.DeclarationList(%T)", value)) } } - return y + return out } type _nodeProgram struct { @@ -377,6 +390,8 @@ type _nodeProgram struct { functionList []*_nodeFunctionLiteral variableList []_nodeDeclaration + + file *file.File } type _nodeDeclaration struct { @@ -411,6 +426,7 @@ type ( } _nodeBracketExpression struct { + idx file.Idx left _nodeExpression member _nodeExpression } @@ -427,6 +443,7 @@ type ( } _nodeDotExpression struct { + idx file.Idx left _nodeExpression identifier string } @@ -438,9 +455,11 @@ type ( parameterList []string varList []string functionList []*_nodeFunctionLiteral + file *file.File } _nodeIdentifier struct { + idx file.Idx name string } @@ -483,6 +502,7 @@ type ( } _nodeVariableExpression struct { + idx file.Idx name string initializer _nodeExpression } diff --git a/Godeps/_workspace/src/github.com/obscuren/otto/cmpl_test.go b/Godeps/_workspace/src/github.com/robertkrimen/otto/cmpl_test.go index 01ee86e17..34b050f00 100644 --- a/Godeps/_workspace/src/github.com/obscuren/otto/cmpl_test.go +++ b/Godeps/_workspace/src/github.com/robertkrimen/otto/cmpl_test.go @@ -15,7 +15,7 @@ func Test_cmpl(t *testing.T) { is(err, nil) { program := cmpl_parse(program) - value := vm.runtime.cmpl_evaluate_nodeProgram(program) + value := vm.runtime.cmpl_evaluate_nodeProgram(program, false) if len(expect) > 0 { is(value, expect[0]) } diff --git a/Godeps/_workspace/src/github.com/obscuren/otto/console.go b/Godeps/_workspace/src/github.com/robertkrimen/otto/console.go index 30333ad08..948face77 100644 --- a/Godeps/_workspace/src/github.com/obscuren/otto/console.go +++ b/Godeps/_workspace/src/github.com/robertkrimen/otto/console.go @@ -16,33 +16,33 @@ func formatForConsole(argumentList []Value) string { func builtinConsole_log(call FunctionCall) Value { fmt.Fprintln(os.Stdout, formatForConsole(call.ArgumentList)) - return UndefinedValue() + return Value{} } func builtinConsole_error(call FunctionCall) Value { fmt.Fprintln(os.Stdout, formatForConsole(call.ArgumentList)) - return UndefinedValue() + return Value{} } // Nothing happens. func builtinConsole_dir(call FunctionCall) Value { - return UndefinedValue() + return Value{} } func builtinConsole_time(call FunctionCall) Value { - return UndefinedValue() + return Value{} } func builtinConsole_timeEnd(call FunctionCall) Value { - return UndefinedValue() + return Value{} } func builtinConsole_trace(call FunctionCall) Value { - return UndefinedValue() + return Value{} } func builtinConsole_assert(call FunctionCall) Value { - return UndefinedValue() + return Value{} } func (runtime *_runtime) newConsole() *_object { diff --git a/Godeps/_workspace/src/github.com/obscuren/otto/date_test.go b/Godeps/_workspace/src/github.com/robertkrimen/otto/date_test.go index 18ab528db..a9c71edde 100644 --- a/Godeps/_workspace/src/github.com/obscuren/otto/date_test.go +++ b/Godeps/_workspace/src/github.com/robertkrimen/otto/date_test.go @@ -246,7 +246,10 @@ func TestDate_new(t *testing.T) { // This is probably incorrect, due to differences in Go date/time handling // versus ECMA date/time handling, but we'll leave this here for // future reference - return + + if true { + return + } tt(t, func() { test, _ := test() diff --git a/Godeps/_workspace/src/github.com/obscuren/otto/dbg.go b/Godeps/_workspace/src/github.com/robertkrimen/otto/dbg.go index 51fbdc206..51fbdc206 100644 --- a/Godeps/_workspace/src/github.com/obscuren/otto/dbg.go +++ b/Godeps/_workspace/src/github.com/robertkrimen/otto/dbg.go diff --git a/Godeps/_workspace/src/github.com/obscuren/otto/documentation_test.go b/Godeps/_workspace/src/github.com/robertkrimen/otto/documentation_test.go index dca5093f7..04646117f 100644 --- a/Godeps/_workspace/src/github.com/obscuren/otto/documentation_test.go +++ b/Godeps/_workspace/src/github.com/robertkrimen/otto/documentation_test.go @@ -64,7 +64,7 @@ func ExampleSynopsis() { // 16 // 16 // undefined - // ReferenceError: abcdefghijlmnopqrstuvwxyz is not defined + // ReferenceError: 'abcdefghijlmnopqrstuvwxyz' is not defined // Hello, Xyzzy. // Hello, undefined. // 4 diff --git a/Godeps/_workspace/src/github.com/robertkrimen/otto/error.go b/Godeps/_workspace/src/github.com/robertkrimen/otto/error.go new file mode 100644 index 000000000..111471044 --- /dev/null +++ b/Godeps/_workspace/src/github.com/robertkrimen/otto/error.go @@ -0,0 +1,245 @@ +package otto + +import ( + "errors" + "fmt" + "strings" + + "github.com/robertkrimen/otto/file" +) + +type _exception struct { + value interface{} +} + +func newException(value interface{}) *_exception { + return &_exception{ + value: value, + } +} + +func (self *_exception) eject() interface{} { + value := self.value + self.value = nil // Prevent Go from holding on to the value, whatever it is + return value +} + +type _error struct { + name string + message string + trace []_frame + + offset int +} + +type _frame struct { + file *file.File + offset int + callee string +} + +var ( + nativeFrame = _frame{} +) + +type _at int + +func (fr _frame) location() string { + if fr.file == nil { + return "<unknown>" + } + path := fr.file.Name() + line, column := _position(fr.file, fr.offset) + + if path == "" { + path = "<anonymous>" + } + + str := fmt.Sprintf("%s:%d:%d", path, line, column) + + if fr.callee != "" { + str = fmt.Sprintf("%s (%s)", fr.callee, str) + } + + return str +} + +func _position(file *file.File, offset int) (line, column int) { + { + offset := offset - file.Base() + if offset < 0 { + return -offset, -1 + } + + src := file.Source() + if offset >= len(src) { + return -offset, -len(src) + } + src = src[:offset] + + line := 1 + strings.Count(src, "\n") + column := 0 + if index := strings.LastIndex(src, "\n"); index >= 0 { + column = offset - index + } else { + column = 1 + len(src) + } + return line, column + } +} + +// An Error represents a runtime error, e.g. a TypeError, a ReferenceError, etc. +type Error struct { + _error +} + +// Error returns a description of the error +// +// TypeError: 'def' is not a function +// +func (err Error) Error() string { + if len(err.name) == 0 { + return err.message + } + if len(err.message) == 0 { + return err.name + } + return fmt.Sprintf("%s: %s", err.name, err.message) +} + +// String returns a description of the error and a trace of where the +// error occurred. +// +// TypeError: 'def' is not a function +// at xyz (<anonymous>:3:9) +// at <anonymous>:7:1/ +// +func (err Error) String() string { + str := err.Error() + "\n" + for _, frame := range err.trace { + str += " at " + frame.location() + "\n" + } + return str +} + +func (err _error) describe(format string, in ...interface{}) string { + return fmt.Sprintf(format, in...) +} + +func (self _error) messageValue() Value { + if self.message == "" { + return Value{} + } + return toValue_string(self.message) +} + +func (rt *_runtime) typeErrorResult(throw bool) bool { + if throw { + panic(rt.panicTypeError()) + } + return false +} + +func newError(rt *_runtime, name string, in ...interface{}) _error { + err := _error{ + name: name, + offset: -1, + } + description := "" + length := len(in) + + if rt != nil { + scope := rt.scope + frame := scope.frame + if length > 0 { + if at, ok := in[length-1].(_at); ok { + in = in[0 : length-1] + if scope != nil { + frame.offset = int(at) + } + length -= 1 + } + if length > 0 { + description, in = in[0].(string), in[1:] + } + } + limit := 10 + err.trace = append(err.trace, frame) + if scope != nil { + for limit > 0 { + scope = scope.outer + if scope == nil { + break + } + if scope.frame.offset >= 0 { + err.trace = append(err.trace, scope.frame) + } + limit-- + } + } + } else { + if length > 0 { + description, in = in[0].(string), in[1:] + } + } + err.message = err.describe(description, in...) + return err +} + +func (rt *_runtime) panicTypeError(argumentList ...interface{}) *_exception { + return &_exception{ + value: newError(rt, "TypeError", argumentList...), + } +} + +func (rt *_runtime) panicReferenceError(argumentList ...interface{}) *_exception { + return &_exception{ + value: newError(rt, "ReferenceError", argumentList...), + } +} + +func (rt *_runtime) panicURIError(argumentList ...interface{}) *_exception { + return &_exception{ + value: newError(rt, "URIError", argumentList...), + } +} + +func (rt *_runtime) panicSyntaxError(argumentList ...interface{}) *_exception { + return &_exception{ + value: newError(rt, "SyntaxError", argumentList...), + } +} + +func (rt *_runtime) panicRangeError(argumentList ...interface{}) *_exception { + return &_exception{ + value: newError(rt, "RangeError", argumentList...), + } +} + +func catchPanic(function func()) (err error) { + defer func() { + if caught := recover(); caught != nil { + if exception, ok := caught.(*_exception); ok { + caught = exception.eject() + } + switch caught := caught.(type) { + case _error: + err = &Error{caught} + return + case Value: + if vl := caught._object(); vl != nil { + switch vl := vl.value.(type) { + case _error: + err = &Error{vl} + return + } + } + err = errors.New(caught.string()) + return + } + panic(caught) + } + }() + function() + return nil +} diff --git a/Godeps/_workspace/src/github.com/robertkrimen/otto/error_test.go b/Godeps/_workspace/src/github.com/robertkrimen/otto/error_test.go new file mode 100644 index 000000000..7f1b16af7 --- /dev/null +++ b/Godeps/_workspace/src/github.com/robertkrimen/otto/error_test.go @@ -0,0 +1,192 @@ +package otto + +import ( + "testing" +) + +func TestError(t *testing.T) { + tt(t, func() { + test, _ := test() + + test(` + [ Error.prototype.name, Error.prototype.message, Error.prototype.hasOwnProperty("message") ]; + `, "Error,,true") + }) +} + +func TestError_instanceof(t *testing.T) { + tt(t, func() { + test, _ := test() + + test(`(new TypeError()) instanceof Error`, true) + }) +} + +func TestPanicValue(t *testing.T) { + tt(t, func() { + test, vm := test() + + vm.Set("abc", func(call FunctionCall) Value { + value, err := call.Otto.Run(`({ def: 3.14159 })`) + is(err, nil) + panic(value) + }) + + test(` + try { + abc(); + } + catch (err) { + error = err; + } + [ error instanceof Error, error.message, error.def ]; + `, "false,,3.14159") + }) +} + +func Test_catchPanic(t *testing.T) { + tt(t, func() { + vm := New() + + _, err := vm.Run(` + A syntax error that + does not define + var; + abc; + `) + is(err, "!=", nil) + + _, err = vm.Call(`abc.def`, nil) + is(err, "!=", nil) + }) +} + +func TestErrorContext(t *testing.T) { + tt(t, func() { + vm := New() + + _, err := vm.Run(` + undefined(); + `) + { + err := err.(*Error) + is(err.message, "'undefined' is not a function") + is(len(err.trace), 1) + is(err.trace[0].location(), "<anonymous>:2:13") + } + + _, err = vm.Run(` + ({}).abc(); + `) + { + err := err.(*Error) + is(err.message, "'abc' is not a function") + is(len(err.trace), 1) + is(err.trace[0].location(), "<anonymous>:2:14") + } + + _, err = vm.Run(` + ("abc").abc(); + `) + { + err := err.(*Error) + is(err.message, "'abc' is not a function") + is(len(err.trace), 1) + is(err.trace[0].location(), "<anonymous>:2:14") + } + + _, err = vm.Run(` + var ghi = "ghi"; + ghi(); + `) + { + err := err.(*Error) + is(err.message, "'ghi' is not a function") + is(len(err.trace), 1) + is(err.trace[0].location(), "<anonymous>:3:13") + } + + _, err = vm.Run(` + function def() { + undefined(); + } + function abc() { + def(); + } + abc(); + `) + { + err := err.(*Error) + is(err.message, "'undefined' is not a function") + is(len(err.trace), 3) + is(err.trace[0].location(), "def (<anonymous>:3:17)") + is(err.trace[1].location(), "abc (<anonymous>:6:17)") + is(err.trace[2].location(), "<anonymous>:8:13") + } + + _, err = vm.Run(` + function abc() { + xyz(); + } + abc(); + `) + { + err := err.(*Error) + is(err.message, "'xyz' is not defined") + is(len(err.trace), 2) + is(err.trace[0].location(), "abc (<anonymous>:3:17)") + is(err.trace[1].location(), "<anonymous>:5:13") + } + + _, err = vm.Run(` + mno + 1; + `) + { + err := err.(*Error) + is(err.message, "'mno' is not defined") + is(len(err.trace), 1) + is(err.trace[0].location(), "<anonymous>:2:13") + } + + _, err = vm.Run(` + eval("xyz();"); + `) + { + err := err.(*Error) + is(err.message, "'xyz' is not defined") + is(len(err.trace), 1) + is(err.trace[0].location(), "<anonymous>:1:1") + } + + _, err = vm.Run(` + xyzzy = "Nothing happens." + eval("xyzzy();"); + `) + { + err := err.(*Error) + is(err.message, "'xyzzy' is not a function") + is(len(err.trace), 1) + is(err.trace[0].location(), "<anonymous>:1:1") + } + + _, err = vm.Run(` + throw Error("xyzzy"); + `) + { + err := err.(*Error) + is(err.message, "xyzzy") + is(len(err.trace), 1) + is(err.trace[0].location(), "<anonymous>:2:19") + } + + _, err = vm.Run(` + throw new Error("xyzzy"); + `) + { + err := err.(*Error) + is(err.message, "xyzzy") + is(len(err.trace), 1) + is(err.trace[0].location(), "<anonymous>:2:23") + } + }) +} diff --git a/Godeps/_workspace/src/github.com/obscuren/otto/evaluate.go b/Godeps/_workspace/src/github.com/robertkrimen/otto/evaluate.go index d8c74c0f6..093054cc3 100644 --- a/Godeps/_workspace/src/github.com/obscuren/otto/evaluate.go +++ b/Godeps/_workspace/src/github.com/robertkrimen/otto/evaluate.go @@ -10,7 +10,7 @@ import ( func (self *_runtime) evaluateMultiply(left float64, right float64) Value { // TODO 11.5.1 - return UndefinedValue() + return Value{} } func (self *_runtime) evaluateDivide(left float64, right float64) Value { @@ -49,98 +49,98 @@ func (self *_runtime) evaluateDivide(left float64, right float64) Value { func (self *_runtime) evaluateModulo(left float64, right float64) Value { // TODO 11.5.3 - return UndefinedValue() + return Value{} } func (self *_runtime) calculateBinaryExpression(operator token.Token, left Value, right Value) Value { - leftValue := self.GetValue(left) + leftValue := left.resolve() switch operator { // Additive case token.PLUS: leftValue = toPrimitive(leftValue) - rightValue := self.GetValue(right) + rightValue := right.resolve() rightValue = toPrimitive(rightValue) if leftValue.IsString() || rightValue.IsString() { - return toValue_string(strings.Join([]string{leftValue.toString(), rightValue.toString()}, "")) + return toValue_string(strings.Join([]string{leftValue.string(), rightValue.string()}, "")) } else { - return toValue_float64(leftValue.toFloat() + rightValue.toFloat()) + return toValue_float64(leftValue.float64() + rightValue.float64()) } case token.MINUS: - rightValue := self.GetValue(right) - return toValue_float64(leftValue.toFloat() - rightValue.toFloat()) + rightValue := right.resolve() + return toValue_float64(leftValue.float64() - rightValue.float64()) // Multiplicative case token.MULTIPLY: - rightValue := self.GetValue(right) - return toValue_float64(leftValue.toFloat() * rightValue.toFloat()) + rightValue := right.resolve() + return toValue_float64(leftValue.float64() * rightValue.float64()) case token.SLASH: - rightValue := self.GetValue(right) - return self.evaluateDivide(leftValue.toFloat(), rightValue.toFloat()) + rightValue := right.resolve() + return self.evaluateDivide(leftValue.float64(), rightValue.float64()) case token.REMAINDER: - rightValue := self.GetValue(right) - return toValue_float64(math.Mod(leftValue.toFloat(), rightValue.toFloat())) + rightValue := right.resolve() + return toValue_float64(math.Mod(leftValue.float64(), rightValue.float64())) // Logical case token.LOGICAL_AND: - left := toBoolean(leftValue) + left := leftValue.bool() if !left { - return FalseValue() + return falseValue } - return toValue_bool(toBoolean(self.GetValue(right))) + return toValue_bool(right.resolve().bool()) case token.LOGICAL_OR: - left := toBoolean(leftValue) + left := leftValue.bool() if left { - return TrueValue() + return trueValue } - return toValue_bool(toBoolean(self.GetValue(right))) + return toValue_bool(right.resolve().bool()) // Bitwise case token.AND: - rightValue := self.GetValue(right) + rightValue := right.resolve() return toValue_int32(toInt32(leftValue) & toInt32(rightValue)) case token.OR: - rightValue := self.GetValue(right) + rightValue := right.resolve() return toValue_int32(toInt32(leftValue) | toInt32(rightValue)) case token.EXCLUSIVE_OR: - rightValue := self.GetValue(right) + rightValue := right.resolve() return toValue_int32(toInt32(leftValue) ^ toInt32(rightValue)) // Shift // (Masking of 0x1f is to restrict the shift to a maximum of 31 places) case token.SHIFT_LEFT: - rightValue := self.GetValue(right) + rightValue := right.resolve() return toValue_int32(toInt32(leftValue) << (toUint32(rightValue) & 0x1f)) case token.SHIFT_RIGHT: - rightValue := self.GetValue(right) + rightValue := right.resolve() return toValue_int32(toInt32(leftValue) >> (toUint32(rightValue) & 0x1f)) case token.UNSIGNED_SHIFT_RIGHT: - rightValue := self.GetValue(right) + rightValue := right.resolve() // Shifting an unsigned integer is a logical shift return toValue_uint32(toUint32(leftValue) >> (toUint32(rightValue) & 0x1f)) case token.INSTANCEOF: - rightValue := self.GetValue(right) + rightValue := right.resolve() if !rightValue.IsObject() { - panic(newTypeError("Expecting a function in instanceof check, but got: %v", rightValue)) + panic(self.panicTypeError("Expecting a function in instanceof check, but got: %v", rightValue)) } - return toValue_bool(rightValue._object().HasInstance(leftValue)) + return toValue_bool(rightValue._object().hasInstance(leftValue)) case token.IN: - rightValue := self.GetValue(right) + rightValue := right.resolve() if !rightValue.IsObject() { - panic(newTypeError()) + panic(self.panicTypeError()) } - return toValue_bool(rightValue._object().hasProperty(toString(leftValue))) + return toValue_bool(rightValue._object().hasProperty(leftValue.string())) } panic(hereBeDragons(operator)) } -func valueKindDispatchKey(left _valueType, right _valueType) int { +func valueKindDispatchKey(left _valueKind, right _valueKind) int { return (int(left) << 2) + int(right) } @@ -150,10 +150,10 @@ func makeEqualDispatch() map[int](func(Value, Value) bool) { key := valueKindDispatchKey return map[int](func(Value, Value) bool){ - key(valueNumber, valueObject): func(x Value, y Value) bool { return x.toFloat() == y.toFloat() }, - key(valueString, valueObject): func(x Value, y Value) bool { return x.toFloat() == y.toFloat() }, - key(valueObject, valueNumber): func(x Value, y Value) bool { return x.toFloat() == y.toFloat() }, - key(valueObject, valueString): func(x Value, y Value) bool { return x.toFloat() == y.toFloat() }, + key(valueNumber, valueObject): func(x Value, y Value) bool { return x.float64() == y.float64() }, + key(valueString, valueObject): func(x Value, y Value) bool { return x.float64() == y.float64() }, + key(valueObject, valueNumber): func(x Value, y Value) bool { return x.float64() == y.float64() }, + key(valueObject, valueString): func(x Value, y Value) bool { return x.float64() == y.float64() }, } } @@ -167,7 +167,7 @@ const ( func calculateLessThan(left Value, right Value, leftFirst bool) _lessThanResult { - x := UndefinedValue() + x := Value{} y := x if leftFirst { @@ -179,14 +179,14 @@ func calculateLessThan(left Value, right Value, leftFirst bool) _lessThanResult } result := false - if x._valueType != valueString || y._valueType != valueString { - x, y := x.toFloat(), y.toFloat() + if x.kind != valueString || y.kind != valueString { + x, y := x.float64(), y.float64() if math.IsNaN(x) || math.IsNaN(y) { return lessThanUndefined } result = x < y } else { - x, y := x.toString(), y.toString() + x, y := x.string(), y.string() result = x < y } @@ -197,6 +197,7 @@ func calculateLessThan(left Value, right Value, leftFirst bool) _lessThanResult return lessThanFalse } +// FIXME Probably a map is not the most efficient way to do this var lessThanTable [4](map[_lessThanResult]bool) = [4](map[_lessThanResult]bool){ // < map[_lessThanResult]bool{ @@ -231,8 +232,8 @@ func (self *_runtime) calculateComparison(comparator token.Token, left Value, ri // FIXME Use strictEqualityComparison? // TODO This might be redundant now (with regards to evaluateComparison) - x := self.GetValue(left) - y := self.GetValue(right) + x := left.resolve() + y := right.resolve() kindEqualKind := false result := true @@ -251,7 +252,7 @@ func (self *_runtime) calculateComparison(comparator token.Token, left Value, ri negate = true fallthrough case token.STRICT_EQUAL: - if x._valueType != y._valueType { + if x.kind != y.kind { result = false } else { kindEqualKind = true @@ -260,21 +261,21 @@ func (self *_runtime) calculateComparison(comparator token.Token, left Value, ri negate = true fallthrough case token.EQUAL: - if x._valueType == y._valueType { + if x.kind == y.kind { kindEqualKind = true - } else if x._valueType <= valueUndefined && y._valueType <= valueUndefined { + } else if x.kind <= valueNull && y.kind <= valueNull { result = true - } else if x._valueType <= valueUndefined || y._valueType <= valueUndefined { + } else if x.kind <= valueNull || y.kind <= valueNull { result = false - } else if x._valueType <= valueString && y._valueType <= valueString { - result = x.toFloat() == y.toFloat() - } else if x._valueType == valueBoolean { - result = self.calculateComparison(token.EQUAL, toValue_float64(x.toFloat()), y) - } else if y._valueType == valueBoolean { - result = self.calculateComparison(token.EQUAL, x, toValue_float64(y.toFloat())) - } else if x._valueType == valueObject { + } else if x.kind <= valueString && y.kind <= valueString { + result = x.float64() == y.float64() + } else if x.kind == valueBoolean { + result = self.calculateComparison(token.EQUAL, toValue_float64(x.float64()), y) + } else if y.kind == valueBoolean { + result = self.calculateComparison(token.EQUAL, x, toValue_float64(y.float64())) + } else if x.kind == valueObject { result = self.calculateComparison(token.EQUAL, toPrimitive(x), y) - } else if y._valueType == valueObject { + } else if y.kind == valueObject { result = self.calculateComparison(token.EQUAL, x, toPrimitive(y)) } else { panic(hereBeDragons("Unable to test for equality: %v ==? %v", x, y)) @@ -284,21 +285,21 @@ func (self *_runtime) calculateComparison(comparator token.Token, left Value, ri } if kindEqualKind { - switch x._valueType { + switch x.kind { case valueUndefined, valueNull: result = true case valueNumber: - x := x.toFloat() - y := y.toFloat() + x := x.float64() + y := y.float64() if math.IsNaN(x) || math.IsNaN(y) { result = false } else { result = x == y } case valueString: - result = x.toString() == y.toString() + result = x.string() == y.string() case valueBoolean: - result = x.toBoolean() == y.toBoolean() + result = x.bool() == y.bool() case valueObject: result = x._object() == y._object() default: @@ -313,5 +314,5 @@ func (self *_runtime) calculateComparison(comparator token.Token, left Value, ri return result ERROR: - panic(hereBeDragons("%v (%v) %s %v (%v)", x, x._valueType, comparator, y, y._valueType)) + panic(hereBeDragons("%v (%v) %s %v (%v)", x, x.kind, comparator, y, y.kind)) } diff --git a/Godeps/_workspace/src/github.com/obscuren/otto/function_test.go b/Godeps/_workspace/src/github.com/robertkrimen/otto/function_test.go index bd438022d..c10bf8592 100644 --- a/Godeps/_workspace/src/github.com/obscuren/otto/function_test.go +++ b/Godeps/_workspace/src/github.com/robertkrimen/otto/function_test.go @@ -229,7 +229,7 @@ func TestFunction_bind(t *testing.T) { test(`raise: Math.bind(); - `, "TypeError: undefined is not a function") + `, "TypeError: 'bind' is not a function") test(` function construct(fn, arguments) { @@ -251,6 +251,14 @@ func TestFunction_bind(t *testing.T) { var result = new newFn(); [ result.hasOwnProperty("abc"), result.hasOwnProperty("def"), result.abc, result.def ]; `, "true,true,abc,true") + + test(` + abc = function(){ + return "abc"; + }; + def = abc.bind(); + def.toString(); + `, "function () { [native code] }") }) } diff --git a/Godeps/_workspace/src/github.com/obscuren/otto/global.go b/Godeps/_workspace/src/github.com/robertkrimen/otto/global.go index 87030a0e0..4f035314a 100644 --- a/Godeps/_workspace/src/github.com/obscuren/otto/global.go +++ b/Godeps/_workspace/src/github.com/robertkrimen/otto/global.go @@ -7,28 +7,28 @@ import ( var ( prototypeValueObject = interface{}(nil) - prototypeValueFunction = _functionObject{ - call: _nativeCallFunction{"", func(_ FunctionCall) Value { - return UndefinedValue() - }}, + prototypeValueFunction = _nativeFunctionObject{ + call: func(_ FunctionCall) Value { + return Value{} + }, } prototypeValueString = _stringASCII("") // TODO Make this just false? prototypeValueBoolean = Value{ - _valueType: valueBoolean, - value: false, + kind: valueBoolean, + value: false, } prototypeValueNumber = Value{ - _valueType: valueNumber, - value: 0, + kind: valueNumber, + value: 0, } prototypeValueDate = _dateObject{ epoch: 0, isNaN: false, time: time.Unix(0, 0).UTC(), value: Value{ - _valueType: valueNumber, - value: 0, + kind: valueNumber, + value: 0, }, } prototypeValueRegExp = _regExpObject{ @@ -45,16 +45,13 @@ func newContext() *_runtime { self := &_runtime{} - self.GlobalEnvironment = self.newObjectEnvironment(nil, nil) - self.GlobalObject = self.GlobalEnvironment.Object - - self.EnterGlobalExecutionContext() + self.globalStash = self.newObjectStash(nil, nil) + self.globalObject = self.globalStash.object _newContext(self) - self.eval = self.GlobalObject.property["eval"].value.(Value).value.(*_object) - self.GlobalObject.prototype = self.Global.ObjectPrototype - //self.parser = ast.NewParser() + self.eval = self.globalObject.property["eval"].value.(Value).value.(*_object) + self.globalObject.prototype = self.global.ObjectPrototype return self } @@ -94,13 +91,13 @@ func (self *_object) hasPrimitive() bool { func (runtime *_runtime) newObject() *_object { self := runtime.newClassObject("Object") - self.prototype = runtime.Global.ObjectPrototype + self.prototype = runtime.global.ObjectPrototype return self } func (runtime *_runtime) newArray(length uint32) *_object { self := runtime.newArrayObject(length) - self.prototype = runtime.Global.ArrayPrototype + self.prototype = runtime.global.ArrayPrototype return self } @@ -117,19 +114,19 @@ func (runtime *_runtime) newArrayOf(valueArray []Value) *_object { func (runtime *_runtime) newString(value Value) *_object { self := runtime.newStringObject(value) - self.prototype = runtime.Global.StringPrototype + self.prototype = runtime.global.StringPrototype return self } func (runtime *_runtime) newBoolean(value Value) *_object { self := runtime.newBooleanObject(value) - self.prototype = runtime.Global.BooleanPrototype + self.prototype = runtime.global.BooleanPrototype return self } func (runtime *_runtime) newNumber(value Value) *_object { self := runtime.newNumberObject(value) - self.prototype = runtime.Global.NumberPrototype + self.prototype = runtime.global.NumberPrototype return self } @@ -139,17 +136,17 @@ func (runtime *_runtime) newRegExp(patternValue Value, flagsValue Value) *_objec flags := "" if object := patternValue._object(); object != nil && object.class == "RegExp" { if flagsValue.IsDefined() { - panic(newTypeError("Cannot supply flags when constructing one RegExp from another")) + panic(runtime.panicTypeError("Cannot supply flags when constructing one RegExp from another")) } regExp := object.regExpValue() pattern = regExp.source flags = regExp.flags } else { if patternValue.IsDefined() { - pattern = toString(patternValue) + pattern = patternValue.string() } if flagsValue.IsDefined() { - flags = toString(flagsValue) + flags = flagsValue.string() } } @@ -158,14 +155,14 @@ func (runtime *_runtime) newRegExp(patternValue Value, flagsValue Value) *_objec func (runtime *_runtime) _newRegExp(pattern string, flags string) *_object { self := runtime.newRegExpObject(pattern, flags) - self.prototype = runtime.Global.RegExpPrototype + self.prototype = runtime.global.RegExpPrototype return self } // TODO Should (probably) be one argument, right? This is redundant func (runtime *_runtime) newDate(epoch float64) *_object { self := runtime.newDateObject(epoch) - self.prototype = runtime.Global.DatePrototype + self.prototype = runtime.global.DatePrototype return self } @@ -186,8 +183,8 @@ func (runtime *_runtime) newError(name string, message Value) *_object { return runtime.newURIError(message) } - self = runtime.newErrorObject(message) - self.prototype = runtime.Global.ErrorPrototype + self = runtime.newErrorObject(name, message) + self.prototype = runtime.global.ErrorPrototype if name != "" { self.defineProperty("name", toValue_string(name), 0111, false) } @@ -196,19 +193,29 @@ func (runtime *_runtime) newError(name string, message Value) *_object { func (runtime *_runtime) newNativeFunction(name string, _nativeFunction _nativeFunction) *_object { self := runtime.newNativeFunctionObject(name, _nativeFunction, 0) - self.prototype = runtime.Global.FunctionPrototype + self.prototype = runtime.global.FunctionPrototype prototype := runtime.newObject() self.defineProperty("prototype", toValue_object(prototype), 0100, false) prototype.defineProperty("constructor", toValue_object(self), 0100, false) return self } -func (runtime *_runtime) newNodeFunction(node *_nodeFunctionLiteral, scopeEnvironment _environment) *_object { +func (runtime *_runtime) newNodeFunction(node *_nodeFunctionLiteral, scopeEnvironment _stash) *_object { // TODO Implement 13.2 fully self := runtime.newNodeFunctionObject(node, scopeEnvironment) - self.prototype = runtime.Global.FunctionPrototype + self.prototype = runtime.global.FunctionPrototype prototype := runtime.newObject() self.defineProperty("prototype", toValue_object(prototype), 0100, false) prototype.defineProperty("constructor", toValue_object(self), 0101, false) return self } + +// FIXME Only in one place... +func (runtime *_runtime) newBoundFunction(target *_object, this Value, argumentList []Value) *_object { + self := runtime.newBoundFunctionObject(target, this, argumentList) + self.prototype = runtime.global.FunctionPrototype + prototype := runtime.newObject() + self.defineProperty("prototype", toValue_object(prototype), 0100, false) + prototype.defineProperty("constructor", toValue_object(self), 0100, false) + return self +} diff --git a/Godeps/_workspace/src/github.com/obscuren/otto/global_test.go b/Godeps/_workspace/src/github.com/robertkrimen/otto/global_test.go index c5204e54c..9257b58c3 100644 --- a/Godeps/_workspace/src/github.com/obscuren/otto/global_test.go +++ b/Godeps/_workspace/src/github.com/robertkrimen/otto/global_test.go @@ -31,35 +31,38 @@ func TestGlobal(t *testing.T) { return value } - value := runtime.localGet("Object")._object().Call(UndefinedValue(), []Value{toValue(runtime.newObject())}) - is(value.IsObject(), true) - is(value, "[object Object]") - is(value._object().prototype == runtime.Global.ObjectPrototype, true) - is(value._object().prototype == runtime.Global.Object.get("prototype")._object(), true) - is(value._object().get("toString"), "function toString() { [native code] }") - is(call(value.Object(), "hasOwnProperty", "hasOwnProperty"), false) - - is(call(value._object().get("toString")._object().prototype, "toString"), "function () { [native code] }") // TODO Is this right? - is(value._object().get("toString")._object().get("toString"), "function toString() { [native code] }") - is(value._object().get("toString")._object().get("toString")._object(), "function toString() { [native code] }") - - is(call(value._object(), "propertyIsEnumerable", "isPrototypeOf"), false) - value._object().put("xyzzy", toValue_string("Nothing happens."), false) - is(call(value, "propertyIsEnumerable", "isPrototypeOf"), false) - is(call(value, "propertyIsEnumerable", "xyzzy"), true) - is(value._object().get("xyzzy"), "Nothing happens.") - - is(call(runtime.localGet("Object"), "isPrototypeOf", value), false) - is(call(runtime.localGet("Object")._object().get("prototype"), "isPrototypeOf", value), true) - is(call(runtime.localGet("Function"), "isPrototypeOf", value), false) - - is(runtime.newObject().prototype == runtime.Global.Object.get("prototype")._object(), true) - - abc := runtime.newBoolean(toValue_bool(true)) - is(toValue_object(abc), "true") // TODO Call primitive? - - def := runtime.localGet("Boolean")._object().Construct(UndefinedValue(), []Value{}) - is(def, "false") // TODO Call primitive? + // FIXME enterGlobalScope + if false { + value := runtime.scope.lexical.getBinding("Object", false)._object().call(UndefinedValue(), []Value{toValue(runtime.newObject())}, false, nativeFrame) + is(value.IsObject(), true) + is(value, "[object Object]") + is(value._object().prototype == runtime.global.ObjectPrototype, true) + is(value._object().prototype == runtime.global.Object.get("prototype")._object(), true) + is(value._object().get("toString"), "function toString() { [native code] }") + is(call(value.Object(), "hasOwnProperty", "hasOwnProperty"), false) + + is(call(value._object().get("toString")._object().prototype, "toString"), "function () { [native code] }") // TODO Is this right? + is(value._object().get("toString")._object().get("toString"), "function toString() { [native code] }") + is(value._object().get("toString")._object().get("toString")._object(), "function toString() { [native code] }") + + is(call(value._object(), "propertyIsEnumerable", "isPrototypeOf"), false) + value._object().put("xyzzy", toValue_string("Nothing happens."), false) + is(call(value, "propertyIsEnumerable", "isPrototypeOf"), false) + is(call(value, "propertyIsEnumerable", "xyzzy"), true) + is(value._object().get("xyzzy"), "Nothing happens.") + + is(call(runtime.scope.lexical.getBinding("Object", false), "isPrototypeOf", value), false) + is(call(runtime.scope.lexical.getBinding("Object", false)._object().get("prototype"), "isPrototypeOf", value), true) + is(call(runtime.scope.lexical.getBinding("Function", false), "isPrototypeOf", value), false) + + is(runtime.newObject().prototype == runtime.global.Object.get("prototype")._object(), true) + + abc := runtime.newBoolean(toValue_bool(true)) + is(toValue_object(abc), "true") // TODO Call primitive? + + //def := runtime.localGet("Boolean")._object().Construct(UndefinedValue(), []Value{}) + //is(def, "false") // TODO Call primitive? + } } test(`new Number().constructor == Number`, true) diff --git a/Godeps/_workspace/src/github.com/obscuren/otto/inline b/Godeps/_workspace/src/github.com/robertkrimen/otto/inline index a16d87ad7..c3620b4a2 100644 --- a/Godeps/_workspace/src/github.com/obscuren/otto/inline +++ b/Godeps/_workspace/src/github.com/robertkrimen/otto/inline @@ -43,7 +43,7 @@ for (qw/int int8 int16 int32 int64 uint uint8 uint16 uint32 uint64 float32 float func toValue_$_(value $_) Value { return Value{ - _valueType: valueNumber, + kind: valueNumber, value: value, } } @@ -54,28 +54,28 @@ $fmt->print(<<_END_); func toValue_string(value string) Value { return Value{ - _valueType: valueString, + kind: valueString, value: value, } } func toValue_string16(value []uint16) Value { return Value{ - _valueType: valueString, + kind: valueString, value: value, } } func toValue_bool(value bool) Value { return Value{ - _valueType: valueBoolean, + kind: valueBoolean, value: value, } } func toValue_object(value *_object) Value { return Value{ - _valueType: valueObject, + kind: valueObject, value: value, } } @@ -642,9 +642,9 @@ sub newContext { my $propertyOrder = $self->propertyOrder(@propertyMap); $propertyOrder =~ s/^propertyOrder: //; return - "runtime.GlobalObject.property =", + "runtime.globalObject.property =", @propertyMap, - "runtime.GlobalObject.propertyOrder =", + "runtime.globalObject.propertyOrder =", $propertyOrder, ; }), @@ -666,7 +666,7 @@ sub block { while (@input) { local $_ = shift @input; if (m/^\./) { - $_ = "runtime.Global$_"; + $_ = "runtime.global$_"; } if (m/ :?=$/) { $_ .= shift @input; @@ -712,7 +712,7 @@ sub globalDeclare { my @got; while (@_) { my $name = shift; - push @got, $self->property($name, $self->objectValue("runtime.Global.$name"), "0101"), + push @got, $self->property($name, $self->objectValue("runtime.global.$name"), "0101"), } return @got; } @@ -743,7 +743,7 @@ sub globalObject { runtime: runtime, class: "$name", objectClass: _classObject, - prototype: runtime.Global.ObjectPrototype, + prototype: runtime.global.ObjectPrototype, extensible: true, $propertyMap } @@ -757,7 +757,7 @@ sub globalFunction { my $builtin = "builtin${name}"; my $builtinNew = "builtinNew${name}"; - my $prototype = "runtime.Global.${name}Prototype"; + my $prototype = "runtime.global.${name}Prototype"; my $propertyMap = ""; unshift @_, $self->property("length", $self->numberValue($length), "0"), @@ -772,7 +772,7 @@ sub globalFunction { push @postblock, $self->statement( "$prototype.property[\"constructor\"] =", - $self->property(undef, $self->objectValue("runtime.Global.${name}"), "0101"), + $self->property(undef, $self->objectValue("runtime.global.${name}"), "0101"), ); return trim <<_END_; @@ -780,9 +780,9 @@ sub globalFunction { runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, - value: @{[ $self->functionOf($self->nativeCallFunction($name, $builtin), $builtinNew) ]}, + value: @{[ $self->nativeFunctionOf($name, $builtin, $builtinNew) ]}, $propertyMap } _END_ @@ -813,7 +813,7 @@ sub globalPrototype { } if ($prototype =~ m/^\./) { - $prototype = "runtime.Global$prototype"; + $prototype = "runtime.global$prototype"; } my $propertyMap = ""; @@ -869,11 +869,11 @@ sub newFunction { runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: @{[ join "\n", $self->propertyMap(@propertyMap) ]}, $propertyOrder - value: @{[ $self->functionOf($self->nativeCallFunction($name, $func)) ]}, + value: @{[ $self->nativeFunctionOf($name, $func) ]}, } _END_ ); @@ -892,7 +892,7 @@ sub newObject { runtime: runtime, class: "Object", objectClass: _classObject, - prototype: runtime.Global.ObjectPrototype, + prototype: runtime.global.ObjectPrototype, extensible: true, property: $propertyMap, $propertyOrder, @@ -917,7 +917,7 @@ sub newPrototypeObject { runtime: runtime, class: "$class", objectClass: $objectClass, - prototype: runtime.Global.ObjectPrototype, + prototype: runtime.global.ObjectPrototype, extensible: true, property: $propertyMap, $propertyOrder, @@ -959,6 +959,26 @@ _functionObject{ _END_ } +sub nativeFunctionOf { + my $self = shift; + my $name = shift; + my $call = shift; + my $construct = shift; + if ($construct) { + $construct = "construct: $construct,"; + } else { + $construct = ""; + } + + return trim <<_END_ +_nativeFunctionObject{ + name: "$name", + call: $call, + $construct +} +_END_ +} + sub nameProperty { my $self = shift; my $name = shift; @@ -977,7 +997,7 @@ sub numberValue { my $value = shift; return trim <<_END_; Value{ - _valueType: valueNumber, + kind: valueNumber, value: $value, } _END_ @@ -1028,7 +1048,7 @@ sub objectValue { my $value = shift; return trim <<_END_ Value{ - _valueType: valueObject, + kind: valueObject, value: $value, } _END_ @@ -1039,7 +1059,7 @@ sub stringValue { my $value = shift; return trim <<_END_ Value{ - _valueType: valueString, + kind: valueString, value: "$value", } _END_ @@ -1050,7 +1070,7 @@ sub booleanValue { my $value = shift; return trim <<_END_ Value{ - _valueType: valueBoolean, + kind: valueBoolean, value: $value, } _END_ @@ -1060,7 +1080,7 @@ sub undefinedValue { my $self = shift; return trim <<_END_ Value{ - _valueType: valueUndefined, + kind: valueUndefined, } _END_ } diff --git a/Godeps/_workspace/src/github.com/obscuren/otto/inline.go b/Godeps/_workspace/src/github.com/robertkrimen/otto/inline.go index f8c1d6347..6e5df8393 100644 --- a/Godeps/_workspace/src/github.com/obscuren/otto/inline.go +++ b/Godeps/_workspace/src/github.com/robertkrimen/otto/inline.go @@ -6,7 +6,7 @@ import ( func _newContext(runtime *_runtime) { { - runtime.Global.ObjectPrototype = &_object{ + runtime.global.ObjectPrototype = &_object{ runtime: runtime, class: "Object", objectClass: _classObject, @@ -16,11 +16,11 @@ func _newContext(runtime *_runtime) { } } { - runtime.Global.FunctionPrototype = &_object{ + runtime.global.FunctionPrototype = &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.ObjectPrototype, + prototype: runtime.global.ObjectPrototype, extensible: true, value: prototypeValueFunction, } @@ -30,175 +30,181 @@ func _newContext(runtime *_runtime) { runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 0, + kind: valueNumber, + value: 0, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"valueOf", builtinObject_valueOf}, + value: _nativeFunctionObject{ + name: "valueOf", + call: builtinObject_valueOf, }, } toString_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 0, + kind: valueNumber, + value: 0, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"toString", builtinObject_toString}, + value: _nativeFunctionObject{ + name: "toString", + call: builtinObject_toString, }, } toLocaleString_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 0, + kind: valueNumber, + value: 0, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"toLocaleString", builtinObject_toLocaleString}, + value: _nativeFunctionObject{ + name: "toLocaleString", + call: builtinObject_toLocaleString, }, } hasOwnProperty_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 1, + kind: valueNumber, + value: 1, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"hasOwnProperty", builtinObject_hasOwnProperty}, + value: _nativeFunctionObject{ + name: "hasOwnProperty", + call: builtinObject_hasOwnProperty, }, } isPrototypeOf_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 1, + kind: valueNumber, + value: 1, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"isPrototypeOf", builtinObject_isPrototypeOf}, + value: _nativeFunctionObject{ + name: "isPrototypeOf", + call: builtinObject_isPrototypeOf, }, } propertyIsEnumerable_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 1, + kind: valueNumber, + value: 1, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"propertyIsEnumerable", builtinObject_propertyIsEnumerable}, + value: _nativeFunctionObject{ + name: "propertyIsEnumerable", + call: builtinObject_propertyIsEnumerable, }, } - runtime.Global.ObjectPrototype.property = map[string]_property{ + runtime.global.ObjectPrototype.property = map[string]_property{ "valueOf": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: valueOf_function, + kind: valueObject, + value: valueOf_function, }, }, "toString": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: toString_function, + kind: valueObject, + value: toString_function, }, }, "toLocaleString": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: toLocaleString_function, + kind: valueObject, + value: toLocaleString_function, }, }, "hasOwnProperty": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: hasOwnProperty_function, + kind: valueObject, + value: hasOwnProperty_function, }, }, "isPrototypeOf": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: isPrototypeOf_function, + kind: valueObject, + value: isPrototypeOf_function, }, }, "propertyIsEnumerable": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: propertyIsEnumerable_function, + kind: valueObject, + value: propertyIsEnumerable_function, }, }, "constructor": _property{ @@ -206,7 +212,7 @@ func _newContext(runtime *_runtime) { value: Value{}, }, } - runtime.Global.ObjectPrototype.propertyOrder = []string{ + runtime.global.ObjectPrototype.propertyOrder = []string{ "valueOf", "toString", "toLocaleString", @@ -221,117 +227,121 @@ func _newContext(runtime *_runtime) { runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 0, + kind: valueNumber, + value: 0, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"toString", builtinFunction_toString}, + value: _nativeFunctionObject{ + name: "toString", + call: builtinFunction_toString, }, } apply_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 2, + kind: valueNumber, + value: 2, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"apply", builtinFunction_apply}, + value: _nativeFunctionObject{ + name: "apply", + call: builtinFunction_apply, }, } call_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 1, + kind: valueNumber, + value: 1, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"call", builtinFunction_call}, + value: _nativeFunctionObject{ + name: "call", + call: builtinFunction_call, }, } bind_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 1, + kind: valueNumber, + value: 1, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"bind", builtinFunction_bind}, + value: _nativeFunctionObject{ + name: "bind", + call: builtinFunction_bind, }, } - runtime.Global.FunctionPrototype.property = map[string]_property{ + runtime.global.FunctionPrototype.property = map[string]_property{ "toString": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: toString_function, + kind: valueObject, + value: toString_function, }, }, "apply": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: apply_function, + kind: valueObject, + value: apply_function, }, }, "call": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: call_function, + kind: valueObject, + value: call_function, }, }, "bind": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: bind_function, + kind: valueObject, + value: bind_function, }, }, "constructor": _property{ @@ -341,12 +351,12 @@ func _newContext(runtime *_runtime) { "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 0, + kind: valueNumber, + value: 0, }, }, } - runtime.Global.FunctionPrototype.propertyOrder = []string{ + runtime.global.FunctionPrototype.propertyOrder = []string{ "toString", "apply", "call", @@ -360,402 +370,416 @@ func _newContext(runtime *_runtime) { runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 1, + kind: valueNumber, + value: 1, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"getPrototypeOf", builtinObject_getPrototypeOf}, + value: _nativeFunctionObject{ + name: "getPrototypeOf", + call: builtinObject_getPrototypeOf, }, } getOwnPropertyDescriptor_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 2, + kind: valueNumber, + value: 2, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"getOwnPropertyDescriptor", builtinObject_getOwnPropertyDescriptor}, + value: _nativeFunctionObject{ + name: "getOwnPropertyDescriptor", + call: builtinObject_getOwnPropertyDescriptor, }, } defineProperty_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 3, + kind: valueNumber, + value: 3, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"defineProperty", builtinObject_defineProperty}, + value: _nativeFunctionObject{ + name: "defineProperty", + call: builtinObject_defineProperty, }, } defineProperties_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 2, + kind: valueNumber, + value: 2, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"defineProperties", builtinObject_defineProperties}, + value: _nativeFunctionObject{ + name: "defineProperties", + call: builtinObject_defineProperties, }, } create_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 2, + kind: valueNumber, + value: 2, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"create", builtinObject_create}, + value: _nativeFunctionObject{ + name: "create", + call: builtinObject_create, }, } isExtensible_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 1, + kind: valueNumber, + value: 1, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"isExtensible", builtinObject_isExtensible}, + value: _nativeFunctionObject{ + name: "isExtensible", + call: builtinObject_isExtensible, }, } preventExtensions_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 1, + kind: valueNumber, + value: 1, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"preventExtensions", builtinObject_preventExtensions}, + value: _nativeFunctionObject{ + name: "preventExtensions", + call: builtinObject_preventExtensions, }, } isSealed_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 1, + kind: valueNumber, + value: 1, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"isSealed", builtinObject_isSealed}, + value: _nativeFunctionObject{ + name: "isSealed", + call: builtinObject_isSealed, }, } seal_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 1, + kind: valueNumber, + value: 1, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"seal", builtinObject_seal}, + value: _nativeFunctionObject{ + name: "seal", + call: builtinObject_seal, }, } isFrozen_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 1, + kind: valueNumber, + value: 1, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"isFrozen", builtinObject_isFrozen}, + value: _nativeFunctionObject{ + name: "isFrozen", + call: builtinObject_isFrozen, }, } freeze_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 1, + kind: valueNumber, + value: 1, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"freeze", builtinObject_freeze}, + value: _nativeFunctionObject{ + name: "freeze", + call: builtinObject_freeze, }, } keys_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 1, + kind: valueNumber, + value: 1, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"keys", builtinObject_keys}, + value: _nativeFunctionObject{ + name: "keys", + call: builtinObject_keys, }, } getOwnPropertyNames_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 1, + kind: valueNumber, + value: 1, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"getOwnPropertyNames", builtinObject_getOwnPropertyNames}, + value: _nativeFunctionObject{ + name: "getOwnPropertyNames", + call: builtinObject_getOwnPropertyNames, }, } - runtime.Global.Object = &_object{ + runtime.global.Object = &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, - value: _functionObject{ - call: _nativeCallFunction{"Object", builtinObject}, + value: _nativeFunctionObject{ + name: "Object", + call: builtinObject, construct: builtinNewObject, }, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 1, + kind: valueNumber, + value: 1, }, }, "prototype": _property{ mode: 0, value: Value{ - _valueType: valueObject, - value: runtime.Global.ObjectPrototype, + kind: valueObject, + value: runtime.global.ObjectPrototype, }, }, "getPrototypeOf": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: getPrototypeOf_function, + kind: valueObject, + value: getPrototypeOf_function, }, }, "getOwnPropertyDescriptor": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: getOwnPropertyDescriptor_function, + kind: valueObject, + value: getOwnPropertyDescriptor_function, }, }, "defineProperty": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: defineProperty_function, + kind: valueObject, + value: defineProperty_function, }, }, "defineProperties": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: defineProperties_function, + kind: valueObject, + value: defineProperties_function, }, }, "create": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: create_function, + kind: valueObject, + value: create_function, }, }, "isExtensible": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: isExtensible_function, + kind: valueObject, + value: isExtensible_function, }, }, "preventExtensions": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: preventExtensions_function, + kind: valueObject, + value: preventExtensions_function, }, }, "isSealed": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: isSealed_function, + kind: valueObject, + value: isSealed_function, }, }, "seal": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: seal_function, + kind: valueObject, + value: seal_function, }, }, "isFrozen": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: isFrozen_function, + kind: valueObject, + value: isFrozen_function, }, }, "freeze": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: freeze_function, + kind: valueObject, + value: freeze_function, }, }, "keys": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: keys_function, + kind: valueObject, + value: keys_function, }, }, "getOwnPropertyNames": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: getOwnPropertyNames_function, + kind: valueObject, + value: getOwnPropertyNames_function, }, }, }, @@ -777,12 +801,12 @@ func _newContext(runtime *_runtime) { "getOwnPropertyNames", }, } - runtime.Global.ObjectPrototype.property["constructor"] = + runtime.global.ObjectPrototype.property["constructor"] = _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: runtime.Global.Object, + kind: valueObject, + value: runtime.global.Object, }, } } @@ -791,25 +815,26 @@ func _newContext(runtime *_runtime) { runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, - value: _functionObject{ - call: _nativeCallFunction{"Function", builtinFunction}, + value: _nativeFunctionObject{ + name: "Function", + call: builtinFunction, construct: builtinNewFunction, }, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 1, + kind: valueNumber, + value: 1, }, }, "prototype": _property{ mode: 0, value: Value{ - _valueType: valueObject, - value: runtime.Global.FunctionPrototype, + kind: valueObject, + value: runtime.global.FunctionPrototype, }, }, }, @@ -818,13 +843,13 @@ func _newContext(runtime *_runtime) { "prototype", }, } - runtime.Global.Function = Function - runtime.Global.FunctionPrototype.property["constructor"] = + runtime.global.Function = Function + runtime.global.FunctionPrototype.property["constructor"] = _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: runtime.Global.Function, + kind: valueObject, + value: runtime.global.Function, }, } } @@ -833,646 +858,668 @@ func _newContext(runtime *_runtime) { runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 0, + kind: valueNumber, + value: 0, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"toString", builtinArray_toString}, + value: _nativeFunctionObject{ + name: "toString", + call: builtinArray_toString, }, } toLocaleString_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 0, + kind: valueNumber, + value: 0, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"toLocaleString", builtinArray_toLocaleString}, + value: _nativeFunctionObject{ + name: "toLocaleString", + call: builtinArray_toLocaleString, }, } concat_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 1, + kind: valueNumber, + value: 1, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"concat", builtinArray_concat}, + value: _nativeFunctionObject{ + name: "concat", + call: builtinArray_concat, }, } join_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 1, + kind: valueNumber, + value: 1, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"join", builtinArray_join}, + value: _nativeFunctionObject{ + name: "join", + call: builtinArray_join, }, } splice_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 2, + kind: valueNumber, + value: 2, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"splice", builtinArray_splice}, + value: _nativeFunctionObject{ + name: "splice", + call: builtinArray_splice, }, } shift_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 0, + kind: valueNumber, + value: 0, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"shift", builtinArray_shift}, + value: _nativeFunctionObject{ + name: "shift", + call: builtinArray_shift, }, } pop_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 0, + kind: valueNumber, + value: 0, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"pop", builtinArray_pop}, + value: _nativeFunctionObject{ + name: "pop", + call: builtinArray_pop, }, } push_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 1, + kind: valueNumber, + value: 1, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"push", builtinArray_push}, + value: _nativeFunctionObject{ + name: "push", + call: builtinArray_push, }, } slice_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 2, + kind: valueNumber, + value: 2, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"slice", builtinArray_slice}, + value: _nativeFunctionObject{ + name: "slice", + call: builtinArray_slice, }, } unshift_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 1, + kind: valueNumber, + value: 1, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"unshift", builtinArray_unshift}, + value: _nativeFunctionObject{ + name: "unshift", + call: builtinArray_unshift, }, } reverse_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 0, + kind: valueNumber, + value: 0, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"reverse", builtinArray_reverse}, + value: _nativeFunctionObject{ + name: "reverse", + call: builtinArray_reverse, }, } sort_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 1, + kind: valueNumber, + value: 1, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"sort", builtinArray_sort}, + value: _nativeFunctionObject{ + name: "sort", + call: builtinArray_sort, }, } indexOf_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 1, + kind: valueNumber, + value: 1, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"indexOf", builtinArray_indexOf}, + value: _nativeFunctionObject{ + name: "indexOf", + call: builtinArray_indexOf, }, } lastIndexOf_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 1, + kind: valueNumber, + value: 1, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"lastIndexOf", builtinArray_lastIndexOf}, + value: _nativeFunctionObject{ + name: "lastIndexOf", + call: builtinArray_lastIndexOf, }, } every_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 1, + kind: valueNumber, + value: 1, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"every", builtinArray_every}, + value: _nativeFunctionObject{ + name: "every", + call: builtinArray_every, }, } some_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 1, + kind: valueNumber, + value: 1, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"some", builtinArray_some}, + value: _nativeFunctionObject{ + name: "some", + call: builtinArray_some, }, } forEach_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 1, + kind: valueNumber, + value: 1, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"forEach", builtinArray_forEach}, + value: _nativeFunctionObject{ + name: "forEach", + call: builtinArray_forEach, }, } map_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 1, + kind: valueNumber, + value: 1, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"map", builtinArray_map}, + value: _nativeFunctionObject{ + name: "map", + call: builtinArray_map, }, } filter_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 1, + kind: valueNumber, + value: 1, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"filter", builtinArray_filter}, + value: _nativeFunctionObject{ + name: "filter", + call: builtinArray_filter, }, } reduce_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 1, + kind: valueNumber, + value: 1, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"reduce", builtinArray_reduce}, + value: _nativeFunctionObject{ + name: "reduce", + call: builtinArray_reduce, }, } reduceRight_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 1, + kind: valueNumber, + value: 1, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"reduceRight", builtinArray_reduceRight}, + value: _nativeFunctionObject{ + name: "reduceRight", + call: builtinArray_reduceRight, }, } isArray_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 1, + kind: valueNumber, + value: 1, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"isArray", builtinArray_isArray}, + value: _nativeFunctionObject{ + name: "isArray", + call: builtinArray_isArray, }, } - runtime.Global.ArrayPrototype = &_object{ + runtime.global.ArrayPrototype = &_object{ runtime: runtime, class: "Array", objectClass: _classArray, - prototype: runtime.Global.ObjectPrototype, + prototype: runtime.global.ObjectPrototype, extensible: true, value: nil, property: map[string]_property{ "length": _property{ mode: 0100, value: Value{ - _valueType: valueNumber, - value: uint32(0), + kind: valueNumber, + value: uint32(0), }, }, "toString": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: toString_function, + kind: valueObject, + value: toString_function, }, }, "toLocaleString": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: toLocaleString_function, + kind: valueObject, + value: toLocaleString_function, }, }, "concat": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: concat_function, + kind: valueObject, + value: concat_function, }, }, "join": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: join_function, + kind: valueObject, + value: join_function, }, }, "splice": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: splice_function, + kind: valueObject, + value: splice_function, }, }, "shift": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: shift_function, + kind: valueObject, + value: shift_function, }, }, "pop": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: pop_function, + kind: valueObject, + value: pop_function, }, }, "push": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: push_function, + kind: valueObject, + value: push_function, }, }, "slice": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: slice_function, + kind: valueObject, + value: slice_function, }, }, "unshift": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: unshift_function, + kind: valueObject, + value: unshift_function, }, }, "reverse": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: reverse_function, + kind: valueObject, + value: reverse_function, }, }, "sort": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: sort_function, + kind: valueObject, + value: sort_function, }, }, "indexOf": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: indexOf_function, + kind: valueObject, + value: indexOf_function, }, }, "lastIndexOf": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: lastIndexOf_function, + kind: valueObject, + value: lastIndexOf_function, }, }, "every": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: every_function, + kind: valueObject, + value: every_function, }, }, "some": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: some_function, + kind: valueObject, + value: some_function, }, }, "forEach": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: forEach_function, + kind: valueObject, + value: forEach_function, }, }, "map": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: map_function, + kind: valueObject, + value: map_function, }, }, "filter": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: filter_function, + kind: valueObject, + value: filter_function, }, }, "reduce": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: reduce_function, + kind: valueObject, + value: reduce_function, }, }, "reduceRight": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: reduceRight_function, + kind: valueObject, + value: reduceRight_function, }, }, }, @@ -1501,36 +1548,37 @@ func _newContext(runtime *_runtime) { "reduceRight", }, } - runtime.Global.Array = &_object{ + runtime.global.Array = &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, - value: _functionObject{ - call: _nativeCallFunction{"Array", builtinArray}, + value: _nativeFunctionObject{ + name: "Array", + call: builtinArray, construct: builtinNewArray, }, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 1, + kind: valueNumber, + value: 1, }, }, "prototype": _property{ mode: 0, value: Value{ - _valueType: valueObject, - value: runtime.Global.ArrayPrototype, + kind: valueObject, + value: runtime.global.ArrayPrototype, }, }, "isArray": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: isArray_function, + kind: valueObject, + value: isArray_function, }, }, }, @@ -1540,12 +1588,12 @@ func _newContext(runtime *_runtime) { "isArray", }, } - runtime.Global.ArrayPrototype.property["constructor"] = + runtime.global.ArrayPrototype.property["constructor"] = _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: runtime.Global.Array, + kind: valueObject, + value: runtime.global.Array, }, } } @@ -1554,675 +1602,698 @@ func _newContext(runtime *_runtime) { runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 0, + kind: valueNumber, + value: 0, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"toString", builtinString_toString}, + value: _nativeFunctionObject{ + name: "toString", + call: builtinString_toString, }, } valueOf_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 0, + kind: valueNumber, + value: 0, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"valueOf", builtinString_valueOf}, + value: _nativeFunctionObject{ + name: "valueOf", + call: builtinString_valueOf, }, } charAt_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 1, + kind: valueNumber, + value: 1, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"charAt", builtinString_charAt}, + value: _nativeFunctionObject{ + name: "charAt", + call: builtinString_charAt, }, } charCodeAt_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 1, + kind: valueNumber, + value: 1, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"charCodeAt", builtinString_charCodeAt}, + value: _nativeFunctionObject{ + name: "charCodeAt", + call: builtinString_charCodeAt, }, } concat_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 1, + kind: valueNumber, + value: 1, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"concat", builtinString_concat}, + value: _nativeFunctionObject{ + name: "concat", + call: builtinString_concat, }, } indexOf_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 1, + kind: valueNumber, + value: 1, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"indexOf", builtinString_indexOf}, + value: _nativeFunctionObject{ + name: "indexOf", + call: builtinString_indexOf, }, } lastIndexOf_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 1, + kind: valueNumber, + value: 1, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"lastIndexOf", builtinString_lastIndexOf}, + value: _nativeFunctionObject{ + name: "lastIndexOf", + call: builtinString_lastIndexOf, }, } match_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 1, + kind: valueNumber, + value: 1, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"match", builtinString_match}, + value: _nativeFunctionObject{ + name: "match", + call: builtinString_match, }, } replace_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 2, + kind: valueNumber, + value: 2, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"replace", builtinString_replace}, + value: _nativeFunctionObject{ + name: "replace", + call: builtinString_replace, }, } search_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 1, + kind: valueNumber, + value: 1, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"search", builtinString_search}, + value: _nativeFunctionObject{ + name: "search", + call: builtinString_search, }, } split_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 2, + kind: valueNumber, + value: 2, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"split", builtinString_split}, + value: _nativeFunctionObject{ + name: "split", + call: builtinString_split, }, } slice_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 2, + kind: valueNumber, + value: 2, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"slice", builtinString_slice}, + value: _nativeFunctionObject{ + name: "slice", + call: builtinString_slice, }, } substring_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 2, + kind: valueNumber, + value: 2, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"substring", builtinString_substring}, + value: _nativeFunctionObject{ + name: "substring", + call: builtinString_substring, }, } toLowerCase_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 0, + kind: valueNumber, + value: 0, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"toLowerCase", builtinString_toLowerCase}, + value: _nativeFunctionObject{ + name: "toLowerCase", + call: builtinString_toLowerCase, }, } toUpperCase_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 0, + kind: valueNumber, + value: 0, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"toUpperCase", builtinString_toUpperCase}, + value: _nativeFunctionObject{ + name: "toUpperCase", + call: builtinString_toUpperCase, }, } substr_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 2, + kind: valueNumber, + value: 2, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"substr", builtinString_substr}, + value: _nativeFunctionObject{ + name: "substr", + call: builtinString_substr, }, } trim_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 0, + kind: valueNumber, + value: 0, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"trim", builtinString_trim}, + value: _nativeFunctionObject{ + name: "trim", + call: builtinString_trim, }, } trimLeft_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 0, + kind: valueNumber, + value: 0, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"trimLeft", builtinString_trimLeft}, + value: _nativeFunctionObject{ + name: "trimLeft", + call: builtinString_trimLeft, }, } trimRight_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 0, + kind: valueNumber, + value: 0, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"trimRight", builtinString_trimRight}, + value: _nativeFunctionObject{ + name: "trimRight", + call: builtinString_trimRight, }, } localeCompare_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 1, + kind: valueNumber, + value: 1, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"localeCompare", builtinString_localeCompare}, + value: _nativeFunctionObject{ + name: "localeCompare", + call: builtinString_localeCompare, }, } toLocaleLowerCase_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 0, + kind: valueNumber, + value: 0, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"toLocaleLowerCase", builtinString_toLocaleLowerCase}, + value: _nativeFunctionObject{ + name: "toLocaleLowerCase", + call: builtinString_toLocaleLowerCase, }, } toLocaleUpperCase_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 0, + kind: valueNumber, + value: 0, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"toLocaleUpperCase", builtinString_toLocaleUpperCase}, + value: _nativeFunctionObject{ + name: "toLocaleUpperCase", + call: builtinString_toLocaleUpperCase, }, } fromCharCode_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 1, + kind: valueNumber, + value: 1, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"fromCharCode", builtinString_fromCharCode}, + value: _nativeFunctionObject{ + name: "fromCharCode", + call: builtinString_fromCharCode, }, } - runtime.Global.StringPrototype = &_object{ + runtime.global.StringPrototype = &_object{ runtime: runtime, class: "String", objectClass: _classString, - prototype: runtime.Global.ObjectPrototype, + prototype: runtime.global.ObjectPrototype, extensible: true, value: prototypeValueString, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: int(0), + kind: valueNumber, + value: int(0), }, }, "toString": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: toString_function, + kind: valueObject, + value: toString_function, }, }, "valueOf": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: valueOf_function, + kind: valueObject, + value: valueOf_function, }, }, "charAt": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: charAt_function, + kind: valueObject, + value: charAt_function, }, }, "charCodeAt": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: charCodeAt_function, + kind: valueObject, + value: charCodeAt_function, }, }, "concat": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: concat_function, + kind: valueObject, + value: concat_function, }, }, "indexOf": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: indexOf_function, + kind: valueObject, + value: indexOf_function, }, }, "lastIndexOf": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: lastIndexOf_function, + kind: valueObject, + value: lastIndexOf_function, }, }, "match": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: match_function, + kind: valueObject, + value: match_function, }, }, "replace": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: replace_function, + kind: valueObject, + value: replace_function, }, }, "search": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: search_function, + kind: valueObject, + value: search_function, }, }, "split": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: split_function, + kind: valueObject, + value: split_function, }, }, "slice": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: slice_function, + kind: valueObject, + value: slice_function, }, }, "substring": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: substring_function, + kind: valueObject, + value: substring_function, }, }, "toLowerCase": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: toLowerCase_function, + kind: valueObject, + value: toLowerCase_function, }, }, "toUpperCase": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: toUpperCase_function, + kind: valueObject, + value: toUpperCase_function, }, }, "substr": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: substr_function, + kind: valueObject, + value: substr_function, }, }, "trim": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: trim_function, + kind: valueObject, + value: trim_function, }, }, "trimLeft": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: trimLeft_function, + kind: valueObject, + value: trimLeft_function, }, }, "trimRight": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: trimRight_function, + kind: valueObject, + value: trimRight_function, }, }, "localeCompare": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: localeCompare_function, + kind: valueObject, + value: localeCompare_function, }, }, "toLocaleLowerCase": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: toLocaleLowerCase_function, + kind: valueObject, + value: toLocaleLowerCase_function, }, }, "toLocaleUpperCase": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: toLocaleUpperCase_function, + kind: valueObject, + value: toLocaleUpperCase_function, }, }, }, @@ -2252,36 +2323,37 @@ func _newContext(runtime *_runtime) { "toLocaleUpperCase", }, } - runtime.Global.String = &_object{ + runtime.global.String = &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, - value: _functionObject{ - call: _nativeCallFunction{"String", builtinString}, + value: _nativeFunctionObject{ + name: "String", + call: builtinString, construct: builtinNewString, }, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 1, + kind: valueNumber, + value: 1, }, }, "prototype": _property{ mode: 0, value: Value{ - _valueType: valueObject, - value: runtime.Global.StringPrototype, + kind: valueObject, + value: runtime.global.StringPrototype, }, }, "fromCharCode": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: fromCharCode_function, + kind: valueObject, + value: fromCharCode_function, }, }, }, @@ -2291,12 +2363,12 @@ func _newContext(runtime *_runtime) { "fromCharCode", }, } - runtime.Global.StringPrototype.property["constructor"] = + runtime.global.StringPrototype.property["constructor"] = _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: runtime.Global.String, + kind: valueObject, + value: runtime.global.String, }, } } @@ -2305,66 +2377,68 @@ func _newContext(runtime *_runtime) { runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 0, + kind: valueNumber, + value: 0, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"toString", builtinBoolean_toString}, + value: _nativeFunctionObject{ + name: "toString", + call: builtinBoolean_toString, }, } valueOf_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 0, + kind: valueNumber, + value: 0, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"valueOf", builtinBoolean_valueOf}, + value: _nativeFunctionObject{ + name: "valueOf", + call: builtinBoolean_valueOf, }, } - runtime.Global.BooleanPrototype = &_object{ + runtime.global.BooleanPrototype = &_object{ runtime: runtime, class: "Boolean", objectClass: _classObject, - prototype: runtime.Global.ObjectPrototype, + prototype: runtime.global.ObjectPrototype, extensible: true, value: prototypeValueBoolean, property: map[string]_property{ "toString": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: toString_function, + kind: valueObject, + value: toString_function, }, }, "valueOf": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: valueOf_function, + kind: valueObject, + value: valueOf_function, }, }, }, @@ -2373,29 +2447,30 @@ func _newContext(runtime *_runtime) { "valueOf", }, } - runtime.Global.Boolean = &_object{ + runtime.global.Boolean = &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, - value: _functionObject{ - call: _nativeCallFunction{"Boolean", builtinBoolean}, + value: _nativeFunctionObject{ + name: "Boolean", + call: builtinBoolean, construct: builtinNewBoolean, }, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 1, + kind: valueNumber, + value: 1, }, }, "prototype": _property{ mode: 0, value: Value{ - _valueType: valueObject, - value: runtime.Global.BooleanPrototype, + kind: valueObject, + value: runtime.global.BooleanPrototype, }, }, }, @@ -2404,12 +2479,12 @@ func _newContext(runtime *_runtime) { "prototype", }, } - runtime.Global.BooleanPrototype.property["constructor"] = + runtime.global.BooleanPrototype.property["constructor"] = _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: runtime.Global.Boolean, + kind: valueObject, + value: runtime.global.Boolean, }, } } @@ -2418,182 +2493,188 @@ func _newContext(runtime *_runtime) { runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 0, + kind: valueNumber, + value: 0, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"toString", builtinNumber_toString}, + value: _nativeFunctionObject{ + name: "toString", + call: builtinNumber_toString, }, } valueOf_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 0, + kind: valueNumber, + value: 0, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"valueOf", builtinNumber_valueOf}, + value: _nativeFunctionObject{ + name: "valueOf", + call: builtinNumber_valueOf, }, } toFixed_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 1, + kind: valueNumber, + value: 1, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"toFixed", builtinNumber_toFixed}, + value: _nativeFunctionObject{ + name: "toFixed", + call: builtinNumber_toFixed, }, } toExponential_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 1, + kind: valueNumber, + value: 1, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"toExponential", builtinNumber_toExponential}, + value: _nativeFunctionObject{ + name: "toExponential", + call: builtinNumber_toExponential, }, } toPrecision_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 1, + kind: valueNumber, + value: 1, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"toPrecision", builtinNumber_toPrecision}, + value: _nativeFunctionObject{ + name: "toPrecision", + call: builtinNumber_toPrecision, }, } toLocaleString_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 1, + kind: valueNumber, + value: 1, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"toLocaleString", builtinNumber_toLocaleString}, + value: _nativeFunctionObject{ + name: "toLocaleString", + call: builtinNumber_toLocaleString, }, } - runtime.Global.NumberPrototype = &_object{ + runtime.global.NumberPrototype = &_object{ runtime: runtime, class: "Number", objectClass: _classObject, - prototype: runtime.Global.ObjectPrototype, + prototype: runtime.global.ObjectPrototype, extensible: true, value: prototypeValueNumber, property: map[string]_property{ "toString": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: toString_function, + kind: valueObject, + value: toString_function, }, }, "valueOf": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: valueOf_function, + kind: valueObject, + value: valueOf_function, }, }, "toFixed": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: toFixed_function, + kind: valueObject, + value: toFixed_function, }, }, "toExponential": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: toExponential_function, + kind: valueObject, + value: toExponential_function, }, }, "toPrecision": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: toPrecision_function, + kind: valueObject, + value: toPrecision_function, }, }, "toLocaleString": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: toLocaleString_function, + kind: valueObject, + value: toLocaleString_function, }, }, }, @@ -2606,64 +2687,65 @@ func _newContext(runtime *_runtime) { "toLocaleString", }, } - runtime.Global.Number = &_object{ + runtime.global.Number = &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, - value: _functionObject{ - call: _nativeCallFunction{"Number", builtinNumber}, + value: _nativeFunctionObject{ + name: "Number", + call: builtinNumber, construct: builtinNewNumber, }, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 1, + kind: valueNumber, + value: 1, }, }, "prototype": _property{ mode: 0, value: Value{ - _valueType: valueObject, - value: runtime.Global.NumberPrototype, + kind: valueObject, + value: runtime.global.NumberPrototype, }, }, "MAX_VALUE": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: math.MaxFloat64, + kind: valueNumber, + value: math.MaxFloat64, }, }, "MIN_VALUE": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: math.SmallestNonzeroFloat64, + kind: valueNumber, + value: math.SmallestNonzeroFloat64, }, }, "NaN": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: math.NaN(), + kind: valueNumber, + value: math.NaN(), }, }, "NEGATIVE_INFINITY": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: math.Inf(-1), + kind: valueNumber, + value: math.Inf(-1), }, }, "POSITIVE_INFINITY": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: math.Inf(+1), + kind: valueNumber, + value: math.Inf(+1), }, }, }, @@ -2677,12 +2759,12 @@ func _newContext(runtime *_runtime) { "POSITIVE_INFINITY", }, } - runtime.Global.NumberPrototype.property["constructor"] = + runtime.global.NumberPrototype.property["constructor"] = _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: runtime.Global.Number, + kind: valueObject, + value: runtime.global.Number, }, } } @@ -2691,585 +2773,603 @@ func _newContext(runtime *_runtime) { runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 1, + kind: valueNumber, + value: 1, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"abs", builtinMath_abs}, + value: _nativeFunctionObject{ + name: "abs", + call: builtinMath_abs, }, } acos_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 1, + kind: valueNumber, + value: 1, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"acos", builtinMath_acos}, + value: _nativeFunctionObject{ + name: "acos", + call: builtinMath_acos, }, } asin_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 1, + kind: valueNumber, + value: 1, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"asin", builtinMath_asin}, + value: _nativeFunctionObject{ + name: "asin", + call: builtinMath_asin, }, } atan_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 1, + kind: valueNumber, + value: 1, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"atan", builtinMath_atan}, + value: _nativeFunctionObject{ + name: "atan", + call: builtinMath_atan, }, } atan2_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 1, + kind: valueNumber, + value: 1, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"atan2", builtinMath_atan2}, + value: _nativeFunctionObject{ + name: "atan2", + call: builtinMath_atan2, }, } ceil_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 1, + kind: valueNumber, + value: 1, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"ceil", builtinMath_ceil}, + value: _nativeFunctionObject{ + name: "ceil", + call: builtinMath_ceil, }, } cos_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 1, + kind: valueNumber, + value: 1, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"cos", builtinMath_cos}, + value: _nativeFunctionObject{ + name: "cos", + call: builtinMath_cos, }, } exp_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 1, + kind: valueNumber, + value: 1, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"exp", builtinMath_exp}, + value: _nativeFunctionObject{ + name: "exp", + call: builtinMath_exp, }, } floor_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 1, + kind: valueNumber, + value: 1, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"floor", builtinMath_floor}, + value: _nativeFunctionObject{ + name: "floor", + call: builtinMath_floor, }, } log_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 1, + kind: valueNumber, + value: 1, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"log", builtinMath_log}, + value: _nativeFunctionObject{ + name: "log", + call: builtinMath_log, }, } max_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 2, + kind: valueNumber, + value: 2, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"max", builtinMath_max}, + value: _nativeFunctionObject{ + name: "max", + call: builtinMath_max, }, } min_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 2, + kind: valueNumber, + value: 2, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"min", builtinMath_min}, + value: _nativeFunctionObject{ + name: "min", + call: builtinMath_min, }, } pow_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 2, + kind: valueNumber, + value: 2, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"pow", builtinMath_pow}, + value: _nativeFunctionObject{ + name: "pow", + call: builtinMath_pow, }, } random_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 0, + kind: valueNumber, + value: 0, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"random", builtinMath_random}, + value: _nativeFunctionObject{ + name: "random", + call: builtinMath_random, }, } round_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 1, + kind: valueNumber, + value: 1, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"round", builtinMath_round}, + value: _nativeFunctionObject{ + name: "round", + call: builtinMath_round, }, } sin_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 1, + kind: valueNumber, + value: 1, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"sin", builtinMath_sin}, + value: _nativeFunctionObject{ + name: "sin", + call: builtinMath_sin, }, } sqrt_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 1, + kind: valueNumber, + value: 1, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"sqrt", builtinMath_sqrt}, + value: _nativeFunctionObject{ + name: "sqrt", + call: builtinMath_sqrt, }, } tan_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 1, + kind: valueNumber, + value: 1, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"tan", builtinMath_tan}, + value: _nativeFunctionObject{ + name: "tan", + call: builtinMath_tan, }, } - runtime.Global.Math = &_object{ + runtime.global.Math = &_object{ runtime: runtime, class: "Math", objectClass: _classObject, - prototype: runtime.Global.ObjectPrototype, + prototype: runtime.global.ObjectPrototype, extensible: true, property: map[string]_property{ "abs": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: abs_function, + kind: valueObject, + value: abs_function, }, }, "acos": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: acos_function, + kind: valueObject, + value: acos_function, }, }, "asin": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: asin_function, + kind: valueObject, + value: asin_function, }, }, "atan": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: atan_function, + kind: valueObject, + value: atan_function, }, }, "atan2": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: atan2_function, + kind: valueObject, + value: atan2_function, }, }, "ceil": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: ceil_function, + kind: valueObject, + value: ceil_function, }, }, "cos": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: cos_function, + kind: valueObject, + value: cos_function, }, }, "exp": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: exp_function, + kind: valueObject, + value: exp_function, }, }, "floor": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: floor_function, + kind: valueObject, + value: floor_function, }, }, "log": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: log_function, + kind: valueObject, + value: log_function, }, }, "max": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: max_function, + kind: valueObject, + value: max_function, }, }, "min": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: min_function, + kind: valueObject, + value: min_function, }, }, "pow": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: pow_function, + kind: valueObject, + value: pow_function, }, }, "random": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: random_function, + kind: valueObject, + value: random_function, }, }, "round": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: round_function, + kind: valueObject, + value: round_function, }, }, "sin": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: sin_function, + kind: valueObject, + value: sin_function, }, }, "sqrt": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: sqrt_function, + kind: valueObject, + value: sqrt_function, }, }, "tan": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: tan_function, + kind: valueObject, + value: tan_function, }, }, "E": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: math.E, + kind: valueNumber, + value: math.E, }, }, "LN10": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: math.Ln10, + kind: valueNumber, + value: math.Ln10, }, }, "LN2": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: math.Ln2, + kind: valueNumber, + value: math.Ln2, }, }, "LOG2E": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: math.Log2E, + kind: valueNumber, + value: math.Log2E, }, }, "LOG10E": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: math.Log10E, + kind: valueNumber, + value: math.Log10E, }, }, "PI": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: math.Pi, + kind: valueNumber, + value: math.Pi, }, }, "SQRT1_2": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: sqrt1_2, + kind: valueNumber, + value: sqrt1_2, }, }, "SQRT2": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: math.Sqrt2, + kind: valueNumber, + value: math.Sqrt2, }, }, }, @@ -3308,1408 +3408,1457 @@ func _newContext(runtime *_runtime) { runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 0, + kind: valueNumber, + value: 0, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"toString", builtinDate_toString}, + value: _nativeFunctionObject{ + name: "toString", + call: builtinDate_toString, }, } toDateString_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 0, + kind: valueNumber, + value: 0, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"toDateString", builtinDate_toDateString}, + value: _nativeFunctionObject{ + name: "toDateString", + call: builtinDate_toDateString, }, } toTimeString_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 0, + kind: valueNumber, + value: 0, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"toTimeString", builtinDate_toTimeString}, + value: _nativeFunctionObject{ + name: "toTimeString", + call: builtinDate_toTimeString, }, } toUTCString_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 0, + kind: valueNumber, + value: 0, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"toUTCString", builtinDate_toUTCString}, + value: _nativeFunctionObject{ + name: "toUTCString", + call: builtinDate_toUTCString, }, } toISOString_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 0, + kind: valueNumber, + value: 0, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"toISOString", builtinDate_toISOString}, + value: _nativeFunctionObject{ + name: "toISOString", + call: builtinDate_toISOString, }, } toJSON_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 1, + kind: valueNumber, + value: 1, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"toJSON", builtinDate_toJSON}, + value: _nativeFunctionObject{ + name: "toJSON", + call: builtinDate_toJSON, }, } toGMTString_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 0, + kind: valueNumber, + value: 0, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"toGMTString", builtinDate_toGMTString}, + value: _nativeFunctionObject{ + name: "toGMTString", + call: builtinDate_toGMTString, }, } toLocaleString_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 0, + kind: valueNumber, + value: 0, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"toLocaleString", builtinDate_toLocaleString}, + value: _nativeFunctionObject{ + name: "toLocaleString", + call: builtinDate_toLocaleString, }, } toLocaleDateString_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 0, + kind: valueNumber, + value: 0, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"toLocaleDateString", builtinDate_toLocaleDateString}, + value: _nativeFunctionObject{ + name: "toLocaleDateString", + call: builtinDate_toLocaleDateString, }, } toLocaleTimeString_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 0, + kind: valueNumber, + value: 0, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"toLocaleTimeString", builtinDate_toLocaleTimeString}, + value: _nativeFunctionObject{ + name: "toLocaleTimeString", + call: builtinDate_toLocaleTimeString, }, } valueOf_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 0, + kind: valueNumber, + value: 0, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"valueOf", builtinDate_valueOf}, + value: _nativeFunctionObject{ + name: "valueOf", + call: builtinDate_valueOf, }, } getTime_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 0, + kind: valueNumber, + value: 0, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"getTime", builtinDate_getTime}, + value: _nativeFunctionObject{ + name: "getTime", + call: builtinDate_getTime, }, } getYear_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 0, + kind: valueNumber, + value: 0, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"getYear", builtinDate_getYear}, + value: _nativeFunctionObject{ + name: "getYear", + call: builtinDate_getYear, }, } getFullYear_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 0, + kind: valueNumber, + value: 0, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"getFullYear", builtinDate_getFullYear}, + value: _nativeFunctionObject{ + name: "getFullYear", + call: builtinDate_getFullYear, }, } getUTCFullYear_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 0, + kind: valueNumber, + value: 0, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"getUTCFullYear", builtinDate_getUTCFullYear}, + value: _nativeFunctionObject{ + name: "getUTCFullYear", + call: builtinDate_getUTCFullYear, }, } getMonth_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 0, + kind: valueNumber, + value: 0, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"getMonth", builtinDate_getMonth}, + value: _nativeFunctionObject{ + name: "getMonth", + call: builtinDate_getMonth, }, } getUTCMonth_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 0, + kind: valueNumber, + value: 0, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"getUTCMonth", builtinDate_getUTCMonth}, + value: _nativeFunctionObject{ + name: "getUTCMonth", + call: builtinDate_getUTCMonth, }, } getDate_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 0, + kind: valueNumber, + value: 0, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"getDate", builtinDate_getDate}, + value: _nativeFunctionObject{ + name: "getDate", + call: builtinDate_getDate, }, } getUTCDate_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 0, + kind: valueNumber, + value: 0, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"getUTCDate", builtinDate_getUTCDate}, + value: _nativeFunctionObject{ + name: "getUTCDate", + call: builtinDate_getUTCDate, }, } getDay_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 0, + kind: valueNumber, + value: 0, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"getDay", builtinDate_getDay}, + value: _nativeFunctionObject{ + name: "getDay", + call: builtinDate_getDay, }, } getUTCDay_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 0, + kind: valueNumber, + value: 0, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"getUTCDay", builtinDate_getUTCDay}, + value: _nativeFunctionObject{ + name: "getUTCDay", + call: builtinDate_getUTCDay, }, } getHours_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 0, + kind: valueNumber, + value: 0, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"getHours", builtinDate_getHours}, + value: _nativeFunctionObject{ + name: "getHours", + call: builtinDate_getHours, }, } getUTCHours_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 0, + kind: valueNumber, + value: 0, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"getUTCHours", builtinDate_getUTCHours}, + value: _nativeFunctionObject{ + name: "getUTCHours", + call: builtinDate_getUTCHours, }, } getMinutes_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 0, + kind: valueNumber, + value: 0, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"getMinutes", builtinDate_getMinutes}, + value: _nativeFunctionObject{ + name: "getMinutes", + call: builtinDate_getMinutes, }, } getUTCMinutes_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 0, + kind: valueNumber, + value: 0, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"getUTCMinutes", builtinDate_getUTCMinutes}, + value: _nativeFunctionObject{ + name: "getUTCMinutes", + call: builtinDate_getUTCMinutes, }, } getSeconds_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 0, + kind: valueNumber, + value: 0, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"getSeconds", builtinDate_getSeconds}, + value: _nativeFunctionObject{ + name: "getSeconds", + call: builtinDate_getSeconds, }, } getUTCSeconds_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 0, + kind: valueNumber, + value: 0, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"getUTCSeconds", builtinDate_getUTCSeconds}, + value: _nativeFunctionObject{ + name: "getUTCSeconds", + call: builtinDate_getUTCSeconds, }, } getMilliseconds_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 0, + kind: valueNumber, + value: 0, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"getMilliseconds", builtinDate_getMilliseconds}, + value: _nativeFunctionObject{ + name: "getMilliseconds", + call: builtinDate_getMilliseconds, }, } getUTCMilliseconds_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 0, + kind: valueNumber, + value: 0, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"getUTCMilliseconds", builtinDate_getUTCMilliseconds}, + value: _nativeFunctionObject{ + name: "getUTCMilliseconds", + call: builtinDate_getUTCMilliseconds, }, } getTimezoneOffset_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 0, + kind: valueNumber, + value: 0, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"getTimezoneOffset", builtinDate_getTimezoneOffset}, + value: _nativeFunctionObject{ + name: "getTimezoneOffset", + call: builtinDate_getTimezoneOffset, }, } setTime_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 1, + kind: valueNumber, + value: 1, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"setTime", builtinDate_setTime}, + value: _nativeFunctionObject{ + name: "setTime", + call: builtinDate_setTime, }, } setMilliseconds_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 1, + kind: valueNumber, + value: 1, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"setMilliseconds", builtinDate_setMilliseconds}, + value: _nativeFunctionObject{ + name: "setMilliseconds", + call: builtinDate_setMilliseconds, }, } setUTCMilliseconds_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 1, + kind: valueNumber, + value: 1, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"setUTCMilliseconds", builtinDate_setUTCMilliseconds}, + value: _nativeFunctionObject{ + name: "setUTCMilliseconds", + call: builtinDate_setUTCMilliseconds, }, } setSeconds_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 2, + kind: valueNumber, + value: 2, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"setSeconds", builtinDate_setSeconds}, + value: _nativeFunctionObject{ + name: "setSeconds", + call: builtinDate_setSeconds, }, } setUTCSeconds_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 2, + kind: valueNumber, + value: 2, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"setUTCSeconds", builtinDate_setUTCSeconds}, + value: _nativeFunctionObject{ + name: "setUTCSeconds", + call: builtinDate_setUTCSeconds, }, } setMinutes_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 3, + kind: valueNumber, + value: 3, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"setMinutes", builtinDate_setMinutes}, + value: _nativeFunctionObject{ + name: "setMinutes", + call: builtinDate_setMinutes, }, } setUTCMinutes_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 3, + kind: valueNumber, + value: 3, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"setUTCMinutes", builtinDate_setUTCMinutes}, + value: _nativeFunctionObject{ + name: "setUTCMinutes", + call: builtinDate_setUTCMinutes, }, } setHours_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 4, + kind: valueNumber, + value: 4, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"setHours", builtinDate_setHours}, + value: _nativeFunctionObject{ + name: "setHours", + call: builtinDate_setHours, }, } setUTCHours_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 4, + kind: valueNumber, + value: 4, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"setUTCHours", builtinDate_setUTCHours}, + value: _nativeFunctionObject{ + name: "setUTCHours", + call: builtinDate_setUTCHours, }, } setDate_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 1, + kind: valueNumber, + value: 1, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"setDate", builtinDate_setDate}, + value: _nativeFunctionObject{ + name: "setDate", + call: builtinDate_setDate, }, } setUTCDate_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 1, + kind: valueNumber, + value: 1, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"setUTCDate", builtinDate_setUTCDate}, + value: _nativeFunctionObject{ + name: "setUTCDate", + call: builtinDate_setUTCDate, }, } setMonth_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 2, + kind: valueNumber, + value: 2, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"setMonth", builtinDate_setMonth}, + value: _nativeFunctionObject{ + name: "setMonth", + call: builtinDate_setMonth, }, } setUTCMonth_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 2, + kind: valueNumber, + value: 2, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"setUTCMonth", builtinDate_setUTCMonth}, + value: _nativeFunctionObject{ + name: "setUTCMonth", + call: builtinDate_setUTCMonth, }, } setYear_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 1, + kind: valueNumber, + value: 1, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"setYear", builtinDate_setYear}, + value: _nativeFunctionObject{ + name: "setYear", + call: builtinDate_setYear, }, } setFullYear_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 3, + kind: valueNumber, + value: 3, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"setFullYear", builtinDate_setFullYear}, + value: _nativeFunctionObject{ + name: "setFullYear", + call: builtinDate_setFullYear, }, } setUTCFullYear_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 3, + kind: valueNumber, + value: 3, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"setUTCFullYear", builtinDate_setUTCFullYear}, + value: _nativeFunctionObject{ + name: "setUTCFullYear", + call: builtinDate_setUTCFullYear, }, } parse_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 1, + kind: valueNumber, + value: 1, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"parse", builtinDate_parse}, + value: _nativeFunctionObject{ + name: "parse", + call: builtinDate_parse, }, } UTC_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 7, + kind: valueNumber, + value: 7, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"UTC", builtinDate_UTC}, + value: _nativeFunctionObject{ + name: "UTC", + call: builtinDate_UTC, }, } now_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 0, + kind: valueNumber, + value: 0, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"now", builtinDate_now}, + value: _nativeFunctionObject{ + name: "now", + call: builtinDate_now, }, } - runtime.Global.DatePrototype = &_object{ + runtime.global.DatePrototype = &_object{ runtime: runtime, class: "Date", objectClass: _classObject, - prototype: runtime.Global.ObjectPrototype, + prototype: runtime.global.ObjectPrototype, extensible: true, value: prototypeValueDate, property: map[string]_property{ "toString": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: toString_function, + kind: valueObject, + value: toString_function, }, }, "toDateString": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: toDateString_function, + kind: valueObject, + value: toDateString_function, }, }, "toTimeString": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: toTimeString_function, + kind: valueObject, + value: toTimeString_function, }, }, "toUTCString": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: toUTCString_function, + kind: valueObject, + value: toUTCString_function, }, }, "toISOString": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: toISOString_function, + kind: valueObject, + value: toISOString_function, }, }, "toJSON": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: toJSON_function, + kind: valueObject, + value: toJSON_function, }, }, "toGMTString": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: toGMTString_function, + kind: valueObject, + value: toGMTString_function, }, }, "toLocaleString": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: toLocaleString_function, + kind: valueObject, + value: toLocaleString_function, }, }, "toLocaleDateString": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: toLocaleDateString_function, + kind: valueObject, + value: toLocaleDateString_function, }, }, "toLocaleTimeString": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: toLocaleTimeString_function, + kind: valueObject, + value: toLocaleTimeString_function, }, }, "valueOf": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: valueOf_function, + kind: valueObject, + value: valueOf_function, }, }, "getTime": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: getTime_function, + kind: valueObject, + value: getTime_function, }, }, "getYear": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: getYear_function, + kind: valueObject, + value: getYear_function, }, }, "getFullYear": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: getFullYear_function, + kind: valueObject, + value: getFullYear_function, }, }, "getUTCFullYear": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: getUTCFullYear_function, + kind: valueObject, + value: getUTCFullYear_function, }, }, "getMonth": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: getMonth_function, + kind: valueObject, + value: getMonth_function, }, }, "getUTCMonth": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: getUTCMonth_function, + kind: valueObject, + value: getUTCMonth_function, }, }, "getDate": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: getDate_function, + kind: valueObject, + value: getDate_function, }, }, "getUTCDate": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: getUTCDate_function, + kind: valueObject, + value: getUTCDate_function, }, }, "getDay": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: getDay_function, + kind: valueObject, + value: getDay_function, }, }, "getUTCDay": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: getUTCDay_function, + kind: valueObject, + value: getUTCDay_function, }, }, "getHours": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: getHours_function, + kind: valueObject, + value: getHours_function, }, }, "getUTCHours": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: getUTCHours_function, + kind: valueObject, + value: getUTCHours_function, }, }, "getMinutes": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: getMinutes_function, + kind: valueObject, + value: getMinutes_function, }, }, "getUTCMinutes": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: getUTCMinutes_function, + kind: valueObject, + value: getUTCMinutes_function, }, }, "getSeconds": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: getSeconds_function, + kind: valueObject, + value: getSeconds_function, }, }, "getUTCSeconds": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: getUTCSeconds_function, + kind: valueObject, + value: getUTCSeconds_function, }, }, "getMilliseconds": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: getMilliseconds_function, + kind: valueObject, + value: getMilliseconds_function, }, }, "getUTCMilliseconds": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: getUTCMilliseconds_function, + kind: valueObject, + value: getUTCMilliseconds_function, }, }, "getTimezoneOffset": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: getTimezoneOffset_function, + kind: valueObject, + value: getTimezoneOffset_function, }, }, "setTime": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: setTime_function, + kind: valueObject, + value: setTime_function, }, }, "setMilliseconds": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: setMilliseconds_function, + kind: valueObject, + value: setMilliseconds_function, }, }, "setUTCMilliseconds": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: setUTCMilliseconds_function, + kind: valueObject, + value: setUTCMilliseconds_function, }, }, "setSeconds": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: setSeconds_function, + kind: valueObject, + value: setSeconds_function, }, }, "setUTCSeconds": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: setUTCSeconds_function, + kind: valueObject, + value: setUTCSeconds_function, }, }, "setMinutes": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: setMinutes_function, + kind: valueObject, + value: setMinutes_function, }, }, "setUTCMinutes": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: setUTCMinutes_function, + kind: valueObject, + value: setUTCMinutes_function, }, }, "setHours": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: setHours_function, + kind: valueObject, + value: setHours_function, }, }, "setUTCHours": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: setUTCHours_function, + kind: valueObject, + value: setUTCHours_function, }, }, "setDate": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: setDate_function, + kind: valueObject, + value: setDate_function, }, }, "setUTCDate": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: setUTCDate_function, + kind: valueObject, + value: setUTCDate_function, }, }, "setMonth": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: setMonth_function, + kind: valueObject, + value: setMonth_function, }, }, "setUTCMonth": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: setUTCMonth_function, + kind: valueObject, + value: setUTCMonth_function, }, }, "setYear": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: setYear_function, + kind: valueObject, + value: setYear_function, }, }, "setFullYear": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: setFullYear_function, + kind: valueObject, + value: setFullYear_function, }, }, "setUTCFullYear": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: setUTCFullYear_function, + kind: valueObject, + value: setUTCFullYear_function, }, }, }, @@ -4762,50 +4911,51 @@ func _newContext(runtime *_runtime) { "setUTCFullYear", }, } - runtime.Global.Date = &_object{ + runtime.global.Date = &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, - value: _functionObject{ - call: _nativeCallFunction{"Date", builtinDate}, + value: _nativeFunctionObject{ + name: "Date", + call: builtinDate, construct: builtinNewDate, }, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 7, + kind: valueNumber, + value: 7, }, }, "prototype": _property{ mode: 0, value: Value{ - _valueType: valueObject, - value: runtime.Global.DatePrototype, + kind: valueObject, + value: runtime.global.DatePrototype, }, }, "parse": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: parse_function, + kind: valueObject, + value: parse_function, }, }, "UTC": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: UTC_function, + kind: valueObject, + value: UTC_function, }, }, "now": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: now_function, + kind: valueObject, + value: now_function, }, }, }, @@ -4817,12 +4967,12 @@ func _newContext(runtime *_runtime) { "now", }, } - runtime.Global.DatePrototype.property["constructor"] = + runtime.global.DatePrototype.property["constructor"] = _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: runtime.Global.Date, + kind: valueObject, + value: runtime.global.Date, }, } } @@ -4831,124 +4981,128 @@ func _newContext(runtime *_runtime) { runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 0, + kind: valueNumber, + value: 0, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"toString", builtinRegExp_toString}, + value: _nativeFunctionObject{ + name: "toString", + call: builtinRegExp_toString, }, } exec_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 1, + kind: valueNumber, + value: 1, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"exec", builtinRegExp_exec}, + value: _nativeFunctionObject{ + name: "exec", + call: builtinRegExp_exec, }, } test_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 1, + kind: valueNumber, + value: 1, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"test", builtinRegExp_test}, + value: _nativeFunctionObject{ + name: "test", + call: builtinRegExp_test, }, } compile_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 1, + kind: valueNumber, + value: 1, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"compile", builtinRegExp_compile}, + value: _nativeFunctionObject{ + name: "compile", + call: builtinRegExp_compile, }, } - runtime.Global.RegExpPrototype = &_object{ + runtime.global.RegExpPrototype = &_object{ runtime: runtime, class: "RegExp", objectClass: _classObject, - prototype: runtime.Global.ObjectPrototype, + prototype: runtime.global.ObjectPrototype, extensible: true, value: prototypeValueRegExp, property: map[string]_property{ "toString": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: toString_function, + kind: valueObject, + value: toString_function, }, }, "exec": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: exec_function, + kind: valueObject, + value: exec_function, }, }, "test": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: test_function, + kind: valueObject, + value: test_function, }, }, "compile": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: compile_function, + kind: valueObject, + value: compile_function, }, }, }, @@ -4959,29 +5113,30 @@ func _newContext(runtime *_runtime) { "compile", }, } - runtime.Global.RegExp = &_object{ + runtime.global.RegExp = &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, - value: _functionObject{ - call: _nativeCallFunction{"RegExp", builtinRegExp}, + value: _nativeFunctionObject{ + name: "RegExp", + call: builtinRegExp, construct: builtinNewRegExp, }, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 2, + kind: valueNumber, + value: 2, }, }, "prototype": _property{ mode: 0, value: Value{ - _valueType: valueObject, - value: runtime.Global.RegExpPrototype, + kind: valueObject, + value: runtime.global.RegExpPrototype, }, }, }, @@ -4990,12 +5145,12 @@ func _newContext(runtime *_runtime) { "prototype", }, } - runtime.Global.RegExpPrototype.property["constructor"] = + runtime.global.RegExpPrototype.property["constructor"] = _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: runtime.Global.RegExp, + kind: valueObject, + value: runtime.global.RegExp, }, } } @@ -5004,51 +5159,52 @@ func _newContext(runtime *_runtime) { runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 0, + kind: valueNumber, + value: 0, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"toString", builtinError_toString}, + value: _nativeFunctionObject{ + name: "toString", + call: builtinError_toString, }, } - runtime.Global.ErrorPrototype = &_object{ + runtime.global.ErrorPrototype = &_object{ runtime: runtime, class: "Error", objectClass: _classObject, - prototype: runtime.Global.ObjectPrototype, + prototype: runtime.global.ObjectPrototype, extensible: true, value: nil, property: map[string]_property{ "toString": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: toString_function, + kind: valueObject, + value: toString_function, }, }, "name": _property{ mode: 0101, value: Value{ - _valueType: valueString, - value: "Error", + kind: valueString, + value: "Error", }, }, "message": _property{ mode: 0101, value: Value{ - _valueType: valueString, - value: "", + kind: valueString, + value: "", }, }, }, @@ -5058,29 +5214,30 @@ func _newContext(runtime *_runtime) { "message", }, } - runtime.Global.Error = &_object{ + runtime.global.Error = &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, - value: _functionObject{ - call: _nativeCallFunction{"Error", builtinError}, + value: _nativeFunctionObject{ + name: "Error", + call: builtinError, construct: builtinNewError, }, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 1, + kind: valueNumber, + value: 1, }, }, "prototype": _property{ mode: 0, value: Value{ - _valueType: valueObject, - value: runtime.Global.ErrorPrototype, + kind: valueObject, + value: runtime.global.ErrorPrototype, }, }, }, @@ -5089,29 +5246,29 @@ func _newContext(runtime *_runtime) { "prototype", }, } - runtime.Global.ErrorPrototype.property["constructor"] = + runtime.global.ErrorPrototype.property["constructor"] = _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: runtime.Global.Error, + kind: valueObject, + value: runtime.global.Error, }, } } { - runtime.Global.EvalErrorPrototype = &_object{ + runtime.global.EvalErrorPrototype = &_object{ runtime: runtime, class: "EvalError", objectClass: _classObject, - prototype: runtime.Global.ErrorPrototype, + prototype: runtime.global.ErrorPrototype, extensible: true, value: nil, property: map[string]_property{ "name": _property{ mode: 0101, value: Value{ - _valueType: valueString, - value: "EvalError", + kind: valueString, + value: "EvalError", }, }, }, @@ -5119,29 +5276,30 @@ func _newContext(runtime *_runtime) { "name", }, } - runtime.Global.EvalError = &_object{ + runtime.global.EvalError = &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, - value: _functionObject{ - call: _nativeCallFunction{"EvalError", builtinEvalError}, + value: _nativeFunctionObject{ + name: "EvalError", + call: builtinEvalError, construct: builtinNewEvalError, }, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 1, + kind: valueNumber, + value: 1, }, }, "prototype": _property{ mode: 0, value: Value{ - _valueType: valueObject, - value: runtime.Global.EvalErrorPrototype, + kind: valueObject, + value: runtime.global.EvalErrorPrototype, }, }, }, @@ -5150,29 +5308,29 @@ func _newContext(runtime *_runtime) { "prototype", }, } - runtime.Global.EvalErrorPrototype.property["constructor"] = + runtime.global.EvalErrorPrototype.property["constructor"] = _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: runtime.Global.EvalError, + kind: valueObject, + value: runtime.global.EvalError, }, } } { - runtime.Global.TypeErrorPrototype = &_object{ + runtime.global.TypeErrorPrototype = &_object{ runtime: runtime, class: "TypeError", objectClass: _classObject, - prototype: runtime.Global.ErrorPrototype, + prototype: runtime.global.ErrorPrototype, extensible: true, value: nil, property: map[string]_property{ "name": _property{ mode: 0101, value: Value{ - _valueType: valueString, - value: "TypeError", + kind: valueString, + value: "TypeError", }, }, }, @@ -5180,29 +5338,30 @@ func _newContext(runtime *_runtime) { "name", }, } - runtime.Global.TypeError = &_object{ + runtime.global.TypeError = &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, - value: _functionObject{ - call: _nativeCallFunction{"TypeError", builtinTypeError}, + value: _nativeFunctionObject{ + name: "TypeError", + call: builtinTypeError, construct: builtinNewTypeError, }, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 1, + kind: valueNumber, + value: 1, }, }, "prototype": _property{ mode: 0, value: Value{ - _valueType: valueObject, - value: runtime.Global.TypeErrorPrototype, + kind: valueObject, + value: runtime.global.TypeErrorPrototype, }, }, }, @@ -5211,29 +5370,29 @@ func _newContext(runtime *_runtime) { "prototype", }, } - runtime.Global.TypeErrorPrototype.property["constructor"] = + runtime.global.TypeErrorPrototype.property["constructor"] = _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: runtime.Global.TypeError, + kind: valueObject, + value: runtime.global.TypeError, }, } } { - runtime.Global.RangeErrorPrototype = &_object{ + runtime.global.RangeErrorPrototype = &_object{ runtime: runtime, class: "RangeError", objectClass: _classObject, - prototype: runtime.Global.ErrorPrototype, + prototype: runtime.global.ErrorPrototype, extensible: true, value: nil, property: map[string]_property{ "name": _property{ mode: 0101, value: Value{ - _valueType: valueString, - value: "RangeError", + kind: valueString, + value: "RangeError", }, }, }, @@ -5241,29 +5400,30 @@ func _newContext(runtime *_runtime) { "name", }, } - runtime.Global.RangeError = &_object{ + runtime.global.RangeError = &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, - value: _functionObject{ - call: _nativeCallFunction{"RangeError", builtinRangeError}, + value: _nativeFunctionObject{ + name: "RangeError", + call: builtinRangeError, construct: builtinNewRangeError, }, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 1, + kind: valueNumber, + value: 1, }, }, "prototype": _property{ mode: 0, value: Value{ - _valueType: valueObject, - value: runtime.Global.RangeErrorPrototype, + kind: valueObject, + value: runtime.global.RangeErrorPrototype, }, }, }, @@ -5272,29 +5432,29 @@ func _newContext(runtime *_runtime) { "prototype", }, } - runtime.Global.RangeErrorPrototype.property["constructor"] = + runtime.global.RangeErrorPrototype.property["constructor"] = _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: runtime.Global.RangeError, + kind: valueObject, + value: runtime.global.RangeError, }, } } { - runtime.Global.ReferenceErrorPrototype = &_object{ + runtime.global.ReferenceErrorPrototype = &_object{ runtime: runtime, class: "ReferenceError", objectClass: _classObject, - prototype: runtime.Global.ErrorPrototype, + prototype: runtime.global.ErrorPrototype, extensible: true, value: nil, property: map[string]_property{ "name": _property{ mode: 0101, value: Value{ - _valueType: valueString, - value: "ReferenceError", + kind: valueString, + value: "ReferenceError", }, }, }, @@ -5302,29 +5462,30 @@ func _newContext(runtime *_runtime) { "name", }, } - runtime.Global.ReferenceError = &_object{ + runtime.global.ReferenceError = &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, - value: _functionObject{ - call: _nativeCallFunction{"ReferenceError", builtinReferenceError}, + value: _nativeFunctionObject{ + name: "ReferenceError", + call: builtinReferenceError, construct: builtinNewReferenceError, }, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 1, + kind: valueNumber, + value: 1, }, }, "prototype": _property{ mode: 0, value: Value{ - _valueType: valueObject, - value: runtime.Global.ReferenceErrorPrototype, + kind: valueObject, + value: runtime.global.ReferenceErrorPrototype, }, }, }, @@ -5333,29 +5494,29 @@ func _newContext(runtime *_runtime) { "prototype", }, } - runtime.Global.ReferenceErrorPrototype.property["constructor"] = + runtime.global.ReferenceErrorPrototype.property["constructor"] = _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: runtime.Global.ReferenceError, + kind: valueObject, + value: runtime.global.ReferenceError, }, } } { - runtime.Global.SyntaxErrorPrototype = &_object{ + runtime.global.SyntaxErrorPrototype = &_object{ runtime: runtime, class: "SyntaxError", objectClass: _classObject, - prototype: runtime.Global.ErrorPrototype, + prototype: runtime.global.ErrorPrototype, extensible: true, value: nil, property: map[string]_property{ "name": _property{ mode: 0101, value: Value{ - _valueType: valueString, - value: "SyntaxError", + kind: valueString, + value: "SyntaxError", }, }, }, @@ -5363,29 +5524,30 @@ func _newContext(runtime *_runtime) { "name", }, } - runtime.Global.SyntaxError = &_object{ + runtime.global.SyntaxError = &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, - value: _functionObject{ - call: _nativeCallFunction{"SyntaxError", builtinSyntaxError}, + value: _nativeFunctionObject{ + name: "SyntaxError", + call: builtinSyntaxError, construct: builtinNewSyntaxError, }, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 1, + kind: valueNumber, + value: 1, }, }, "prototype": _property{ mode: 0, value: Value{ - _valueType: valueObject, - value: runtime.Global.SyntaxErrorPrototype, + kind: valueObject, + value: runtime.global.SyntaxErrorPrototype, }, }, }, @@ -5394,29 +5556,29 @@ func _newContext(runtime *_runtime) { "prototype", }, } - runtime.Global.SyntaxErrorPrototype.property["constructor"] = + runtime.global.SyntaxErrorPrototype.property["constructor"] = _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: runtime.Global.SyntaxError, + kind: valueObject, + value: runtime.global.SyntaxError, }, } } { - runtime.Global.URIErrorPrototype = &_object{ + runtime.global.URIErrorPrototype = &_object{ runtime: runtime, class: "URIError", objectClass: _classObject, - prototype: runtime.Global.ErrorPrototype, + prototype: runtime.global.ErrorPrototype, extensible: true, value: nil, property: map[string]_property{ "name": _property{ mode: 0101, value: Value{ - _valueType: valueString, - value: "URIError", + kind: valueString, + value: "URIError", }, }, }, @@ -5424,29 +5586,30 @@ func _newContext(runtime *_runtime) { "name", }, } - runtime.Global.URIError = &_object{ + runtime.global.URIError = &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, - value: _functionObject{ - call: _nativeCallFunction{"URIError", builtinURIError}, + value: _nativeFunctionObject{ + name: "URIError", + call: builtinURIError, construct: builtinNewURIError, }, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 1, + kind: valueNumber, + value: 1, }, }, "prototype": _property{ mode: 0, value: Value{ - _valueType: valueObject, - value: runtime.Global.URIErrorPrototype, + kind: valueObject, + value: runtime.global.URIErrorPrototype, }, }, }, @@ -5455,12 +5618,12 @@ func _newContext(runtime *_runtime) { "prototype", }, } - runtime.Global.URIErrorPrototype.property["constructor"] = + runtime.global.URIErrorPrototype.property["constructor"] = _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: runtime.Global.URIError, + kind: valueObject, + value: runtime.global.URIError, }, } } @@ -5469,65 +5632,67 @@ func _newContext(runtime *_runtime) { runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 2, + kind: valueNumber, + value: 2, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"parse", builtinJSON_parse}, + value: _nativeFunctionObject{ + name: "parse", + call: builtinJSON_parse, }, } stringify_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 3, + kind: valueNumber, + value: 3, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"stringify", builtinJSON_stringify}, + value: _nativeFunctionObject{ + name: "stringify", + call: builtinJSON_stringify, }, } - runtime.Global.JSON = &_object{ + runtime.global.JSON = &_object{ runtime: runtime, class: "JSON", objectClass: _classObject, - prototype: runtime.Global.ObjectPrototype, + prototype: runtime.global.ObjectPrototype, extensible: true, property: map[string]_property{ "parse": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: parse_function, + kind: valueObject, + value: parse_function, }, }, "stringify": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: stringify_function, + kind: valueObject, + value: stringify_function, }, }, }, @@ -5542,463 +5707,474 @@ func _newContext(runtime *_runtime) { runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 1, + kind: valueNumber, + value: 1, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"eval", builtinGlobal_eval}, + value: _nativeFunctionObject{ + name: "eval", + call: builtinGlobal_eval, }, } parseInt_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 2, + kind: valueNumber, + value: 2, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"parseInt", builtinGlobal_parseInt}, + value: _nativeFunctionObject{ + name: "parseInt", + call: builtinGlobal_parseInt, }, } parseFloat_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 1, + kind: valueNumber, + value: 1, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"parseFloat", builtinGlobal_parseFloat}, + value: _nativeFunctionObject{ + name: "parseFloat", + call: builtinGlobal_parseFloat, }, } isNaN_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 1, + kind: valueNumber, + value: 1, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"isNaN", builtinGlobal_isNaN}, + value: _nativeFunctionObject{ + name: "isNaN", + call: builtinGlobal_isNaN, }, } isFinite_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 1, + kind: valueNumber, + value: 1, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"isFinite", builtinGlobal_isFinite}, + value: _nativeFunctionObject{ + name: "isFinite", + call: builtinGlobal_isFinite, }, } decodeURI_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 1, + kind: valueNumber, + value: 1, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"decodeURI", builtinGlobal_decodeURI}, + value: _nativeFunctionObject{ + name: "decodeURI", + call: builtinGlobal_decodeURI, }, } decodeURIComponent_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 1, + kind: valueNumber, + value: 1, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"decodeURIComponent", builtinGlobal_decodeURIComponent}, + value: _nativeFunctionObject{ + name: "decodeURIComponent", + call: builtinGlobal_decodeURIComponent, }, } encodeURI_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 1, + kind: valueNumber, + value: 1, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"encodeURI", builtinGlobal_encodeURI}, + value: _nativeFunctionObject{ + name: "encodeURI", + call: builtinGlobal_encodeURI, }, } encodeURIComponent_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 1, + kind: valueNumber, + value: 1, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"encodeURIComponent", builtinGlobal_encodeURIComponent}, + value: _nativeFunctionObject{ + name: "encodeURIComponent", + call: builtinGlobal_encodeURIComponent, }, } escape_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 1, + kind: valueNumber, + value: 1, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"escape", builtinGlobal_escape}, + value: _nativeFunctionObject{ + name: "escape", + call: builtinGlobal_escape, }, } unescape_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 1, + kind: valueNumber, + value: 1, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"unescape", builtinGlobal_unescape}, + value: _nativeFunctionObject{ + name: "unescape", + call: builtinGlobal_unescape, }, } - runtime.GlobalObject.property = map[string]_property{ + runtime.globalObject.property = map[string]_property{ "eval": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: eval_function, + kind: valueObject, + value: eval_function, }, }, "parseInt": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: parseInt_function, + kind: valueObject, + value: parseInt_function, }, }, "parseFloat": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: parseFloat_function, + kind: valueObject, + value: parseFloat_function, }, }, "isNaN": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: isNaN_function, + kind: valueObject, + value: isNaN_function, }, }, "isFinite": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: isFinite_function, + kind: valueObject, + value: isFinite_function, }, }, "decodeURI": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: decodeURI_function, + kind: valueObject, + value: decodeURI_function, }, }, "decodeURIComponent": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: decodeURIComponent_function, + kind: valueObject, + value: decodeURIComponent_function, }, }, "encodeURI": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: encodeURI_function, + kind: valueObject, + value: encodeURI_function, }, }, "encodeURIComponent": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: encodeURIComponent_function, + kind: valueObject, + value: encodeURIComponent_function, }, }, "escape": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: escape_function, + kind: valueObject, + value: escape_function, }, }, "unescape": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: unescape_function, + kind: valueObject, + value: unescape_function, }, }, "Object": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: runtime.Global.Object, + kind: valueObject, + value: runtime.global.Object, }, }, "Function": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: runtime.Global.Function, + kind: valueObject, + value: runtime.global.Function, }, }, "Array": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: runtime.Global.Array, + kind: valueObject, + value: runtime.global.Array, }, }, "String": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: runtime.Global.String, + kind: valueObject, + value: runtime.global.String, }, }, "Boolean": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: runtime.Global.Boolean, + kind: valueObject, + value: runtime.global.Boolean, }, }, "Number": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: runtime.Global.Number, + kind: valueObject, + value: runtime.global.Number, }, }, "Math": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: runtime.Global.Math, + kind: valueObject, + value: runtime.global.Math, }, }, "Date": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: runtime.Global.Date, + kind: valueObject, + value: runtime.global.Date, }, }, "RegExp": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: runtime.Global.RegExp, + kind: valueObject, + value: runtime.global.RegExp, }, }, "Error": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: runtime.Global.Error, + kind: valueObject, + value: runtime.global.Error, }, }, "EvalError": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: runtime.Global.EvalError, + kind: valueObject, + value: runtime.global.EvalError, }, }, "TypeError": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: runtime.Global.TypeError, + kind: valueObject, + value: runtime.global.TypeError, }, }, "RangeError": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: runtime.Global.RangeError, + kind: valueObject, + value: runtime.global.RangeError, }, }, "ReferenceError": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: runtime.Global.ReferenceError, + kind: valueObject, + value: runtime.global.ReferenceError, }, }, "SyntaxError": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: runtime.Global.SyntaxError, + kind: valueObject, + value: runtime.global.SyntaxError, }, }, "URIError": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: runtime.Global.URIError, + kind: valueObject, + value: runtime.global.URIError, }, }, "JSON": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: runtime.Global.JSON, + kind: valueObject, + value: runtime.global.JSON, }, }, "undefined": _property{ mode: 0, value: Value{ - _valueType: valueUndefined, + kind: valueUndefined, }, }, "NaN": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: math.NaN(), + kind: valueNumber, + value: math.NaN(), }, }, "Infinity": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: math.Inf(+1), + kind: valueNumber, + value: math.Inf(+1), }, }, } - runtime.GlobalObject.propertyOrder = []string{ + runtime.globalObject.propertyOrder = []string{ "eval", "parseInt", "parseFloat", @@ -6040,297 +6216,307 @@ func newConsoleObject(runtime *_runtime) *_object { runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 0, + kind: valueNumber, + value: 0, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"log", builtinConsole_log}, + value: _nativeFunctionObject{ + name: "log", + call: builtinConsole_log, }, } debug_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 0, + kind: valueNumber, + value: 0, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"debug", builtinConsole_log}, + value: _nativeFunctionObject{ + name: "debug", + call: builtinConsole_log, }, } info_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 0, + kind: valueNumber, + value: 0, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"info", builtinConsole_log}, + value: _nativeFunctionObject{ + name: "info", + call: builtinConsole_log, }, } error_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 0, + kind: valueNumber, + value: 0, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"error", builtinConsole_error}, + value: _nativeFunctionObject{ + name: "error", + call: builtinConsole_error, }, } warn_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 0, + kind: valueNumber, + value: 0, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"warn", builtinConsole_error}, + value: _nativeFunctionObject{ + name: "warn", + call: builtinConsole_error, }, } dir_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 0, + kind: valueNumber, + value: 0, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"dir", builtinConsole_dir}, + value: _nativeFunctionObject{ + name: "dir", + call: builtinConsole_dir, }, } time_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 0, + kind: valueNumber, + value: 0, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"time", builtinConsole_time}, + value: _nativeFunctionObject{ + name: "time", + call: builtinConsole_time, }, } timeEnd_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 0, + kind: valueNumber, + value: 0, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"timeEnd", builtinConsole_timeEnd}, + value: _nativeFunctionObject{ + name: "timeEnd", + call: builtinConsole_timeEnd, }, } trace_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 0, + kind: valueNumber, + value: 0, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"trace", builtinConsole_trace}, + value: _nativeFunctionObject{ + name: "trace", + call: builtinConsole_trace, }, } assert_function := &_object{ runtime: runtime, class: "Function", objectClass: _classObject, - prototype: runtime.Global.FunctionPrototype, + prototype: runtime.global.FunctionPrototype, extensible: true, property: map[string]_property{ "length": _property{ mode: 0, value: Value{ - _valueType: valueNumber, - value: 0, + kind: valueNumber, + value: 0, }, }, }, propertyOrder: []string{ "length", }, - value: _functionObject{ - call: _nativeCallFunction{"assert", builtinConsole_assert}, + value: _nativeFunctionObject{ + name: "assert", + call: builtinConsole_assert, }, } return &_object{ runtime: runtime, class: "Object", objectClass: _classObject, - prototype: runtime.Global.ObjectPrototype, + prototype: runtime.global.ObjectPrototype, extensible: true, property: map[string]_property{ "log": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: log_function, + kind: valueObject, + value: log_function, }, }, "debug": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: debug_function, + kind: valueObject, + value: debug_function, }, }, "info": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: info_function, + kind: valueObject, + value: info_function, }, }, "error": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: error_function, + kind: valueObject, + value: error_function, }, }, "warn": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: warn_function, + kind: valueObject, + value: warn_function, }, }, "dir": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: dir_function, + kind: valueObject, + value: dir_function, }, }, "time": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: time_function, + kind: valueObject, + value: time_function, }, }, "timeEnd": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: timeEnd_function, + kind: valueObject, + value: timeEnd_function, }, }, "trace": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: trace_function, + kind: valueObject, + value: trace_function, }, }, "assert": _property{ mode: 0101, value: Value{ - _valueType: valueObject, - value: assert_function, + kind: valueObject, + value: assert_function, }, }, }, @@ -6352,112 +6538,112 @@ func newConsoleObject(runtime *_runtime) *_object { func toValue_int(value int) Value { return Value{ - _valueType: valueNumber, - value: value, + kind: valueNumber, + value: value, } } func toValue_int8(value int8) Value { return Value{ - _valueType: valueNumber, - value: value, + kind: valueNumber, + value: value, } } func toValue_int16(value int16) Value { return Value{ - _valueType: valueNumber, - value: value, + kind: valueNumber, + value: value, } } func toValue_int32(value int32) Value { return Value{ - _valueType: valueNumber, - value: value, + kind: valueNumber, + value: value, } } func toValue_int64(value int64) Value { return Value{ - _valueType: valueNumber, - value: value, + kind: valueNumber, + value: value, } } func toValue_uint(value uint) Value { return Value{ - _valueType: valueNumber, - value: value, + kind: valueNumber, + value: value, } } func toValue_uint8(value uint8) Value { return Value{ - _valueType: valueNumber, - value: value, + kind: valueNumber, + value: value, } } func toValue_uint16(value uint16) Value { return Value{ - _valueType: valueNumber, - value: value, + kind: valueNumber, + value: value, } } func toValue_uint32(value uint32) Value { return Value{ - _valueType: valueNumber, - value: value, + kind: valueNumber, + value: value, } } func toValue_uint64(value uint64) Value { return Value{ - _valueType: valueNumber, - value: value, + kind: valueNumber, + value: value, } } func toValue_float32(value float32) Value { return Value{ - _valueType: valueNumber, - value: value, + kind: valueNumber, + value: value, } } func toValue_float64(value float64) Value { return Value{ - _valueType: valueNumber, - value: value, + kind: valueNumber, + value: value, } } func toValue_string(value string) Value { return Value{ - _valueType: valueString, - value: value, + kind: valueString, + value: value, } } func toValue_string16(value []uint16) Value { return Value{ - _valueType: valueString, - value: value, + kind: valueString, + value: value, } } func toValue_bool(value bool) Value { return Value{ - _valueType: valueBoolean, - value: value, + kind: valueBoolean, + value: value, } } func toValue_object(value *_object) Value { return Value{ - _valueType: valueObject, - value: value, + kind: valueObject, + value: value, } } diff --git a/Godeps/_workspace/src/github.com/obscuren/otto/json_test.go b/Godeps/_workspace/src/github.com/robertkrimen/otto/json_test.go index 4dd2ed7bf..4dd2ed7bf 100644 --- a/Godeps/_workspace/src/github.com/obscuren/otto/json_test.go +++ b/Godeps/_workspace/src/github.com/robertkrimen/otto/json_test.go diff --git a/Godeps/_workspace/src/github.com/obscuren/otto/math_test.go b/Godeps/_workspace/src/github.com/robertkrimen/otto/math_test.go index 499998b14..499998b14 100644 --- a/Godeps/_workspace/src/github.com/obscuren/otto/math_test.go +++ b/Godeps/_workspace/src/github.com/robertkrimen/otto/math_test.go diff --git a/Godeps/_workspace/src/github.com/obscuren/otto/number_test.go b/Godeps/_workspace/src/github.com/robertkrimen/otto/number_test.go index f3790e077..8db01cfc7 100644 --- a/Godeps/_workspace/src/github.com/obscuren/otto/number_test.go +++ b/Godeps/_workspace/src/github.com/robertkrimen/otto/number_test.go @@ -144,15 +144,13 @@ func TestNumber_toLocaleString(t *testing.T) { }) } -func Test_toInteger(t *testing.T) { +func TestValue_number(t *testing.T) { tt(t, func() { - integer := toInteger(toValue(0.0)) - is(integer.valid(), true) - is(integer.exact(), true) + nm := toValue(0.0).number() + is(nm.kind, numberInteger) - integer = toInteger(toValue(3.14159)) - is(integer.valid(), true) - is(integer.exact(), false) + nm = toValue(3.14159).number() + is(nm.kind, numberFloat) }) } diff --git a/Godeps/_workspace/src/github.com/obscuren/otto/object.go b/Godeps/_workspace/src/github.com/robertkrimen/otto/object.go index fe6f58729..849812c91 100644 --- a/Godeps/_workspace/src/github.com/obscuren/otto/object.go +++ b/Godeps/_workspace/src/github.com/robertkrimen/otto/object.go @@ -85,20 +85,20 @@ func (self *_object) DefaultValue(hint _defaultValueHint) Value { } for _, methodName := range methodSequence { method := self.get(methodName) + // FIXME This is redundant... if method.isCallable() { - result := method._object().Call(toValue_object(self)) + result := method._object().call(toValue_object(self), nil, false, nativeFrame) if result.IsPrimitive() { return result } } } - panic(newTypeError()) - return UndefinedValue() + panic(self.runtime.panicTypeError()) } func (self *_object) String() string { - return toString(self.DefaultValue(defaultValueHintString)) + return self.DefaultValue(defaultValueHintString).string() } func (self *_object) defineProperty(name string, value Value, mode _propertyMode, throw bool) bool { @@ -130,7 +130,7 @@ func (self *_object) _read(name string) (_property, bool) { func (self *_object) _write(name string, value interface{}, mode _propertyMode) { if value == nil { - value = UndefinedValue() + value = Value{} } _, exists := self.property[name] self.property[name] = _property{value, mode} diff --git a/Godeps/_workspace/src/github.com/obscuren/otto/object_class.go b/Godeps/_workspace/src/github.com/robertkrimen/otto/object_class.go index 0464503b0..d18b9cede 100644 --- a/Godeps/_workspace/src/github.com/obscuren/otto/object_class.go +++ b/Godeps/_workspace/src/github.com/robertkrimen/otto/object_class.go @@ -193,7 +193,7 @@ func objectGet(self *_object, name string) Value { if property != nil { return property.get(self) } - return UndefinedValue() + return Value{} } // 8.12.4 @@ -214,7 +214,7 @@ func _objectCanPut(self *_object, name string) (canPut bool, property *_property canPut = setter != nil return default: - panic(newTypeError()) + panic(self.runtime.panicTypeError()) } } @@ -238,10 +238,8 @@ func _objectCanPut(self *_object, name string) (canPut bool, property *_property canPut = setter != nil return default: - panic(newTypeError()) + panic(self.runtime.panicTypeError()) } - - return false, nil, nil } // 8.12.5 @@ -258,9 +256,9 @@ func objectPut(self *_object, name string, value Value, throw bool) { // incompatible canPut routine canPut, property, setter := _objectCanPut(self, name) if !canPut { - typeErrorResult(throw) + self.runtime.typeErrorResult(throw) } else if setter != nil { - setter.callSet(toValue(self), value) + setter.call(toValue(self), []Value{value}, false, nativeFrame) } else if property != nil { property.value = value self.defineOwnProperty(name, *property, throw) @@ -274,7 +272,7 @@ func objectPut(self *_object, name string, value Value, throw bool) { // // Right now, code should never get here, see above if !self.canPut(name) { - typeErrorResult(throw) + self.runtime.typeErrorResult(throw) return } @@ -283,7 +281,7 @@ func objectPut(self *_object, name string, value Value, throw bool) { property = self.getProperty(name) if property != nil { if getSet, isAccessor := property.value.(_propertyGetSet); isAccessor { - getSet[1].callSet(toValue(self), value) + getSet[1].call(toValue(self), []Value{value}, false, nativeFrame) return } } @@ -295,14 +293,14 @@ func objectPut(self *_object, name string, value Value, throw bool) { self.defineOwnProperty(name, *property, throw) case _propertyGetSet: if propertyValue[1] != nil { - propertyValue[1].callSet(toValue(self), value) + propertyValue[1].call(toValue(self), []Value{value}, false, nativeFrame) return } if throw { - panic(newTypeError()) + panic(self.runtime.panicTypeError()) } default: - panic(newTypeError()) + panic(self.runtime.panicTypeError()) } } } @@ -442,7 +440,7 @@ func objectDefineOwnProperty(self *_object, name string, descriptor _property, t } Reject: if throw { - panic(newTypeError()) + panic(self.runtime.panicTypeError()) } return false } @@ -456,29 +454,40 @@ func objectDelete(self *_object, name string, throw bool) bool { self._delete(name) return true } - return typeErrorResult(throw) + return self.runtime.typeErrorResult(throw) } -func objectClone(self0 *_object, self1 *_object, clone *_clone) *_object { - *self1 = *self0 +func objectClone(in *_object, out *_object, clone *_clone) *_object { + *out = *in - self1.runtime = clone.runtime - if self1.prototype != nil { - self1.prototype = clone.object(self0.prototype) + out.runtime = clone.runtime + if out.prototype != nil { + out.prototype = clone.object(in.prototype) } - self1.property = make(map[string]_property, len(self0.property)) - self1.propertyOrder = make([]string, len(self0.propertyOrder)) - copy(self1.propertyOrder, self0.propertyOrder) - for index, property := range self0.property { - self1.property[index] = clone.property(property) + out.property = make(map[string]_property, len(in.property)) + out.propertyOrder = make([]string, len(in.propertyOrder)) + copy(out.propertyOrder, in.propertyOrder) + for index, property := range in.property { + out.property[index] = clone.property(property) } - switch value := self0.value.(type) { - case _functionObject: - self1.value = value.clone(clone) + switch value := in.value.(type) { + case _nativeFunctionObject: + out.value = value + case _bindFunctionObject: + out.value = _bindFunctionObject{ + target: clone.object(value.target), + this: clone.value(value.this), + argumentList: clone.valueArray(value.argumentList), + } + case _nodeFunctionObject: + out.value = _nodeFunctionObject{ + node: value.node, + stash: clone.stash(value.stash), + } case _argumentsObject: - self1.value = value.clone(clone) + out.value = value.clone(clone) } - return self1 + return out } diff --git a/Godeps/_workspace/src/github.com/obscuren/otto/object_test.go b/Godeps/_workspace/src/github.com/robertkrimen/otto/object_test.go index d1e90680b..d1e90680b 100644 --- a/Godeps/_workspace/src/github.com/obscuren/otto/object_test.go +++ b/Godeps/_workspace/src/github.com/robertkrimen/otto/object_test.go diff --git a/Godeps/_workspace/src/github.com/obscuren/otto/otto.go b/Godeps/_workspace/src/github.com/robertkrimen/otto/otto.go index 1cb79cb0a..9de3e08c5 100644 --- a/Godeps/_workspace/src/github.com/obscuren/otto/otto.go +++ b/Godeps/_workspace/src/github.com/robertkrimen/otto/otto.go @@ -57,7 +57,7 @@ Set a Go function vm.Set("sayHello", func(call otto.FunctionCall) otto.Value { fmt.Printf("Hello, %s.\n", call.Argument(0).String()) - return otto.UndefinedValue() + return otto.Value{} }) Set a Go function that returns something useful @@ -131,7 +131,6 @@ Caveat Emptor The following are some limitations with otto: * "use strict" will parse, but does nothing. - * Error reporting needs to be improved. * The regular expression engine (re2/regexp) is not fully compatible with the ECMA5 specification. Regular Expression Incompatibility @@ -190,16 +189,18 @@ If you want to stop long running executions (like third-party code), you can use } fmt.Fprintf(os.Stderr, "Ran code successfully: %v\n", duration) }() + vm := otto.New() - vm.Interrupt = make(chan func()) + vm.Interrupt = make(chan func(), 1) // The buffer prevents blocking + go func() { time.Sleep(2 * time.Second) // Stop after two seconds vm.Interrupt <- func() { panic(halt) } }() + vm.Run(unsafe) // Here be dragons (risky code) - vm.Interrupt = nil } Where is setTimeout/setInterval? @@ -242,7 +243,7 @@ func New() *Otto { self := &Otto{ runtime: newContext(), } - self.runtime.Otto = self + self.runtime.otto = self self.Set("console", self.runtime.newConsole()) registry.Apply(func(entry registry.Entry) { @@ -256,7 +257,7 @@ func (otto *Otto) clone() *Otto { self := &Otto{ runtime: otto.runtime.clone(), } - self.runtime.Otto = self + self.runtime.otto = self return self } @@ -272,7 +273,7 @@ func (otto *Otto) clone() *Otto { // func Run(src interface{}) (*Otto, Value, error) { otto := New() - value, err := otto.Run(src) + value, err := otto.Run(src) // This already does safety checking return otto, value, err } @@ -288,7 +289,11 @@ func Run(src interface{}) (*Otto, Value, error) { // src may also be a Program, but if the AST has been modified, then runtime behavior is undefined. // func (self Otto) Run(src interface{}) (Value, error) { - return self.runtime.cmpl_run(src) + value, err := self.runtime.cmpl_run(src) + if !value.safe() { + value = Value{} + } + return value, err } // Get the value of the top-level binding of the given name. @@ -296,15 +301,18 @@ func (self Otto) Run(src interface{}) (Value, error) { // If there is an error (like the binding does not exist), then the value // will be undefined. func (self Otto) Get(name string) (Value, error) { - value := UndefinedValue() + value := Value{} err := catchPanic(func() { value = self.getValue(name) }) + if !value.safe() { + value = Value{} + } return value, err } func (self Otto) getValue(name string) Value { - return self.runtime.GlobalEnvironment.GetValue(name, false) + return self.runtime.globalStash.getBinding(name, false) } // Set the top-level binding of the given name to the given value. @@ -330,7 +338,7 @@ func (self Otto) Set(name string, value interface{}) error { } func (self Otto) setValue(name string, value Value) { - self.runtime.GlobalEnvironment.SetValue(name, value, false) + self.runtime.globalStash.setValue(name, value, false) } // Call the given JavaScript with a given this and arguments. @@ -355,7 +363,7 @@ func (self Otto) setValue(name string, value Value) { // func (self Otto) Call(source string, this interface{}, argumentList ...interface{}) (Value, error) { - thisValue := UndefinedValue() + thisValue := Value{} construct := false if strings.HasPrefix(source, "new ") { @@ -363,6 +371,12 @@ func (self Otto) Call(source string, this interface{}, argumentList ...interface construct = true } + // FIXME enterGlobalScope + self.runtime.enterGlobalScope() + defer func() { + self.runtime.leaveScope() + }() + if !construct && this == nil { program, err := self.runtime.cmpl_parse("", source+"()") if err == nil { @@ -373,7 +387,7 @@ func (self Otto) Call(source string, this interface{}, argumentList ...interface value = self.runtime.cmpl_evaluate_nodeCallExpression(node, argumentList) }) if err != nil { - return UndefinedValue(), err + return Value{}, err } return value, nil } @@ -382,7 +396,7 @@ func (self Otto) Call(source string, this interface{}, argumentList ...interface } else { value, err := self.ToValue(this) if err != nil { - return UndefinedValue(), err + return Value{}, err } thisValue = value } @@ -392,20 +406,20 @@ func (self Otto) Call(source string, this interface{}, argumentList ...interface fn, err := self.Run(source) if err != nil { - return UndefinedValue(), err + return Value{}, err } if construct { - result, err := fn.constructSafe(this, argumentList...) + result, err := fn.constructSafe(self.runtime, this, argumentList...) if err != nil { - return UndefinedValue(), err + return Value{}, err } return result, nil } result, err := fn.Call(this, argumentList...) if err != nil { - return UndefinedValue(), err + return Value{}, err } return result, nil } @@ -441,23 +455,23 @@ func (self Otto) Object(source string) (*Object, error) { // ToValue will convert an interface{} value to a value digestible by otto/JavaScript. func (self Otto) ToValue(value interface{}) (Value, error) { - return self.runtime.ToValue(value) + return self.runtime.safeToValue(value) } // Copy will create a copy/clone of the runtime. // -// Copy is useful for saving some processing time when creating many similar -// runtimes. +// Copy is useful for saving some time when creating many similar runtimes. // -// This implementation is alpha-ish, and works by introspecting every part of the runtime -// and reallocating and then relinking everything back together. Please report if you -// notice any inadvertent sharing of data between copies. -func (self *Otto) Copy() *Otto { - otto := &Otto{ - runtime: self.runtime.clone(), +// This method works by walking the original runtime and cloning each object, scope, stash, +// etc. into a new runtime. +// +// Be on the lookout for memory leaks or inadvertent sharing of resources. +func (in *Otto) Copy() *Otto { + out := &Otto{ + runtime: in.runtime.clone(), } - otto.runtime.Otto = otto - return otto + out.runtime.otto = out + return out } // Object{} @@ -495,7 +509,7 @@ func (self Object) Call(name string, argumentList ...interface{}) (Value, error) function, err := self.Get(name) if err != nil { - return UndefinedValue(), err + return Value{}, err } return function.Call(self.Value(), argumentList...) } @@ -507,10 +521,13 @@ func (self Object) Value() Value { // Get the value of the property with the given name. func (self Object) Get(name string) (Value, error) { - value := UndefinedValue() + value := Value{} err := catchPanic(func() { value = self.object.get(name) }) + if !value.safe() { + value = Value{} + } return value, err } @@ -520,7 +537,7 @@ func (self Object) Get(name string) (Value, error) { // or there is an error during conversion of the given value. func (self Object) Set(name string, value interface{}) error { { - value, err := self.object.runtime.ToValue(value) + value, err := self.object.runtime.safeToValue(value) if err != nil { return err } diff --git a/Godeps/_workspace/src/github.com/obscuren/otto/otto/Makefile b/Godeps/_workspace/src/github.com/robertkrimen/otto/otto/Makefile index bac5cd4a5..bac5cd4a5 100644 --- a/Godeps/_workspace/src/github.com/obscuren/otto/otto/Makefile +++ b/Godeps/_workspace/src/github.com/robertkrimen/otto/otto/Makefile diff --git a/Godeps/_workspace/src/github.com/obscuren/otto/otto/main.go b/Godeps/_workspace/src/github.com/robertkrimen/otto/otto/main.go index 0dcc91e51..f379e42a9 100644 --- a/Godeps/_workspace/src/github.com/obscuren/otto/otto/main.go +++ b/Godeps/_workspace/src/github.com/robertkrimen/otto/otto/main.go @@ -37,7 +37,12 @@ func main() { return err }() if err != nil { - fmt.Println(err) + switch err := err.(type) { + case *otto.Error: + fmt.Print(err.String()) + default: + fmt.Println(err) + } os.Exit(64) } } diff --git a/Godeps/_workspace/src/github.com/obscuren/otto/otto_.go b/Godeps/_workspace/src/github.com/robertkrimen/otto/otto_.go index e9ff66606..e053b54e2 100644 --- a/Godeps/_workspace/src/github.com/obscuren/otto/otto_.go +++ b/Godeps/_workspace/src/github.com/robertkrimen/otto/otto_.go @@ -67,13 +67,13 @@ func getValueOfArrayIndex(array []Value, index int) (Value, bool) { return value, true } } - return UndefinedValue(), false + return Value{}, false } // A range index can be anything from 0 up to length. It is NOT safe to use as an index // to an array, but is useful for slicing and in some ECMA algorithms. func valueToRangeIndex(indexValue Value, length int64, negativeIsZero bool) int64 { - index := toInteger(indexValue).value + index := indexValue.number().int64 if negativeIsZero { if index < 0 { index = 0 @@ -129,7 +129,7 @@ func rangeStartLength(source []Value, size int64) (start, length int64) { lengthValue := valueOfArrayIndex(source, 1) if !lengthValue.IsUndefined() { // Which it is not, so get the value as an array index - length = toInteger(lengthValue).value + length = lengthValue.number().int64 } return } diff --git a/Godeps/_workspace/src/github.com/obscuren/otto/otto_error_test.go b/Godeps/_workspace/src/github.com/robertkrimen/otto/otto_error_test.go index 90863ca12..5ce358819 100644 --- a/Godeps/_workspace/src/github.com/obscuren/otto/otto_error_test.go +++ b/Godeps/_workspace/src/github.com/robertkrimen/otto/otto_error_test.go @@ -18,14 +18,14 @@ func TestOttoError(t *testing.T) { is(err, "TypeError: Nothing happens.") _, err = ToValue([]byte{}) - is(err, "TypeError: Invalid value (slice): Missing runtime: [] ([]uint8)") + is(err, "TypeError: invalid value (slice): missing runtime: [] ([]uint8)") _, err = vm.Run(` (function(){ return abcdef.length })() `) - is(err, "ReferenceError: abcdef is not defined") + is(err, "ReferenceError: 'abcdef' is not defined") _, err = vm.Run(` function start() { @@ -35,14 +35,14 @@ func TestOttoError(t *testing.T) { xyzzy() `) - is(err, "ReferenceError: xyzzy is not defined") + is(err, "ReferenceError: 'xyzzy' is not defined") _, err = vm.Run(` // Just a comment xyzzy `) - is(err, "ReferenceError: xyzzy is not defined") + is(err, "ReferenceError: 'xyzzy' is not defined") }) } diff --git a/Godeps/_workspace/src/github.com/obscuren/otto/otto_test.go b/Godeps/_workspace/src/github.com/robertkrimen/otto/otto_test.go index bacdda724..2f1e1c35f 100644 --- a/Godeps/_workspace/src/github.com/obscuren/otto/otto_test.go +++ b/Godeps/_workspace/src/github.com/robertkrimen/otto/otto_test.go @@ -649,7 +649,7 @@ func Test_PrimitiveValueObjectValue(t *testing.T) { test, _ := test() Number11 := test(`new Number(11)`) - is(toFloat(Number11), 11) + is(Number11.float64(), 11) }) } @@ -700,24 +700,22 @@ func Test_evalDirectIndirect(t *testing.T) { tt(t, func() { test, _ := test() + // (function () {return this;}()).abc = "global"; test(` var abc = "global"; (function(){ try { var _eval = eval; var abc = "function"; - if ( - _eval("\'global\' === abc") === true && // eval (Indirect) - eval("\'function\' === abc") === true // eval (Direct) - ) { - return true; - } - return false; + return [ + _eval("\'global\' === abc"), // eval (Indirect) + eval("\'function\' === abc"), // eval (Direct) + ]; } finally { delete this.abc; } - })() - `, true) + })(); + `, "true,true") }) } @@ -766,7 +764,7 @@ func TestShouldError(t *testing.T) { test(`raise: xyzzy throw new TypeError("Nothing happens.") - `, "ReferenceError: xyzzy is not defined") + `, "ReferenceError: 'xyzzy' is not defined") }) } @@ -868,8 +866,8 @@ func TestDotMember(t *testing.T) { func Test_stringToFloat(t *testing.T) { tt(t, func() { - is(stringToFloat("10e10000"), _Infinity) - is(stringToFloat("10e10_."), _NaN) + is(parseNumber("10e10000"), _Infinity) + is(parseNumber("10e10_."), _NaN) }) } @@ -1014,7 +1012,9 @@ func TestOttoCall_throw(t *testing.T) { // Looks like this has been broken for a while... what // behavior do we want here? - return + if true { + return + } tt(t, func() { test, vm := test() @@ -1024,7 +1024,7 @@ func TestOttoCall_throw(t *testing.T) { call.Otto.Call(`throw eval`, nil, "({ def: 3.14159 })") } call.Otto.Call(`throw Error`, nil, "abcdef") - return UndefinedValue() + return Value{} }) // TODO try { abc(); } catch (err) { error = err } // Possible unrelated error case: @@ -1099,6 +1099,54 @@ func TestOttoCopy(t *testing.T) { `) is(err, nil) is(value, "Xyzzy0[object Object]") + + { + vm0 := New() + vm0.Run(` + var global = (function () {return this;}()) + var abc = 0; + var vm = "vm0"; + + var def = (function(){ + var jkl = 0; + var abc = function() { + global.abc += 1; + jkl += 1; + return 1; + }; + + return function() { + return [ vm, global.abc, jkl, abc() ]; + }; + })(); + `) + + value, err := vm0.Run(` + def(); + `) + is(err, nil) + is(value, "vm0,0,0,1") + + vm1 := vm0.Copy() + vm1.Set("vm", "vm1") + value, err = vm1.Run(` + def(); + `) + is(err, nil) + is(value, "vm1,1,1,1") + + value, err = vm0.Run(` + def(); + `) + is(err, nil) + is(value, "vm0,1,1,1") + + value, err = vm1.Run(` + def(); + `) + is(err, nil) + is(value, "vm1,2,2,1") + } }) } @@ -1109,11 +1157,11 @@ func TestOttoCall_clone(t *testing.T) { { // FIXME terst, Check how this comparison is done - is(rt.Global.Array.prototype, rt.Global.FunctionPrototype) - is(rt.Global.ArrayPrototype, "!=", nil) - is(rt.Global.Array.runtime, rt) - is(rt.Global.Array.prototype.runtime, rt) - is(rt.Global.Array.get("prototype")._object().runtime, rt) + is(rt.global.Array.prototype, rt.global.FunctionPrototype) + is(rt.global.ArrayPrototype, "!=", nil) + is(rt.global.Array.runtime, rt) + is(rt.global.Array.prototype.runtime, rt) + is(rt.global.Array.get("prototype")._object().runtime, rt) } { @@ -1128,14 +1176,14 @@ func TestOttoCall_clone(t *testing.T) { is(value, "1,2,3") object := value._object() is(object, "!=", nil) - is(object.prototype, rt.Global.ArrayPrototype) + is(object.prototype, rt.global.ArrayPrototype) value, err = vm.Run(`Array.prototype`) is(err, nil) object = value._object() is(object.runtime, rt) is(object, "!=", nil) - is(object, rt.Global.ArrayPrototype) + is(object, rt.global.ArrayPrototype) } { diff --git a/Godeps/_workspace/src/github.com/obscuren/otto/panic_test.go b/Godeps/_workspace/src/github.com/robertkrimen/otto/panic_test.go index 06f0a64fc..06f0a64fc 100644 --- a/Godeps/_workspace/src/github.com/obscuren/otto/panic_test.go +++ b/Godeps/_workspace/src/github.com/robertkrimen/otto/panic_test.go diff --git a/Godeps/_workspace/src/github.com/obscuren/otto/parser_test.go b/Godeps/_workspace/src/github.com/robertkrimen/otto/parser_test.go index 7db43d239..7db43d239 100644 --- a/Godeps/_workspace/src/github.com/obscuren/otto/parser_test.go +++ b/Godeps/_workspace/src/github.com/robertkrimen/otto/parser_test.go diff --git a/Godeps/_workspace/src/github.com/obscuren/otto/property.go b/Godeps/_workspace/src/github.com/robertkrimen/otto/property.go index 400753820..5445eccde 100644 --- a/Godeps/_workspace/src/github.com/obscuren/otto/property.go +++ b/Godeps/_workspace/src/github.com/robertkrimen/otto/property.go @@ -85,10 +85,10 @@ func (self _property) get(this *_object) Value { return value case _propertyGetSet: if value[0] != nil { - return value[0].callGet(toValue(this)) + return value[0].call(toValue(this), nil, false, nativeFrame) } } - return UndefinedValue() + return Value{} } func (self _property) isAccessorDescriptor() bool { @@ -115,16 +115,16 @@ func (self _property) isEmpty() bool { // _enumerableValue, _enumerableTrue, _enumerableFalse? // .enumerableValue() .enumerableExists() -func toPropertyDescriptor(value Value) (descriptor _property) { +func toPropertyDescriptor(rt *_runtime, value Value) (descriptor _property) { objectDescriptor := value._object() if objectDescriptor == nil { - panic(newTypeError()) + panic(rt.panicTypeError()) } { descriptor.mode = modeSetMask // Initially nothing is set if objectDescriptor.hasProperty("enumerable") { - if objectDescriptor.get("enumerable").toBoolean() { + if objectDescriptor.get("enumerable").bool() { descriptor.enumerateOn() } else { descriptor.enumerateOff() @@ -132,7 +132,7 @@ func toPropertyDescriptor(value Value) (descriptor _property) { } if objectDescriptor.hasProperty("configurable") { - if objectDescriptor.get("configurable").toBoolean() { + if objectDescriptor.get("configurable").bool() { descriptor.configureOn() } else { descriptor.configureOff() @@ -140,7 +140,7 @@ func toPropertyDescriptor(value Value) (descriptor _property) { } if objectDescriptor.hasProperty("writable") { - if objectDescriptor.get("writable").toBoolean() { + if objectDescriptor.get("writable").bool() { descriptor.writeOn() } else { descriptor.writeOff() @@ -155,7 +155,7 @@ func toPropertyDescriptor(value Value) (descriptor _property) { value := objectDescriptor.get("get") if value.IsDefined() { if !value.isCallable() { - panic(newTypeError()) + panic(rt.panicTypeError()) } getter = value._object() getterSetter = true @@ -169,7 +169,7 @@ func toPropertyDescriptor(value Value) (descriptor _property) { value := objectDescriptor.get("set") if value.IsDefined() { if !value.isCallable() { - panic(newTypeError()) + panic(rt.panicTypeError()) } setter = value._object() getterSetter = true @@ -181,14 +181,14 @@ func toPropertyDescriptor(value Value) (descriptor _property) { if getterSetter { if descriptor.writeSet() { - panic(newTypeError()) + panic(rt.panicTypeError()) } descriptor.value = _propertyGetSet{getter, setter} } if objectDescriptor.hasProperty("value") { if getterSetter { - panic(newTypeError()) + panic(rt.panicTypeError()) } descriptor.value = objectDescriptor.get("value") } @@ -203,11 +203,11 @@ func (self *_runtime) fromPropertyDescriptor(descriptor _property) *_object { object.defineProperty("writable", toValue_bool(descriptor.writable()), 0111, false) } else if descriptor.isAccessorDescriptor() { getSet := descriptor.value.(_propertyGetSet) - get := UndefinedValue() + get := Value{} if getSet[0] != nil { get = toValue_object(getSet[0]) } - set := UndefinedValue() + set := Value{} if getSet[1] != nil { set = toValue_object(getSet[1]) } diff --git a/Godeps/_workspace/src/github.com/obscuren/otto/reflect_test.go b/Godeps/_workspace/src/github.com/robertkrimen/otto/reflect_test.go index f91b38c52..e4e83adeb 100644 --- a/Godeps/_workspace/src/github.com/obscuren/otto/reflect_test.go +++ b/Godeps/_workspace/src/github.com/robertkrimen/otto/reflect_test.go @@ -6,43 +6,63 @@ import ( "testing" ) -type testStruct struct { +type _abcStruct struct { Abc bool Def int Ghi string Jkl interface{} + Mno _mnoStruct + Pqr map[string]int8 } -func (t *testStruct) FuncPointerReciever() string { +func (abc _abcStruct) String() string { + return abc.Ghi +} + +func (abc *_abcStruct) FuncPointer() string { return "abc" } -func (t testStruct) FuncNoArgsNoRet() { +func (abc _abcStruct) Func() { return } -func (t testStruct) FuncNoArgs() string { +func (abc _abcStruct) FuncReturn1() string { return "abc" } -func (t testStruct) FuncNoArgsMultRet() (string, error) { +func (abc _abcStruct) FuncReturn2() (string, error) { return "def", nil } -func (t testStruct) FuncOneArgs(a string) string { +func (abc _abcStruct) Func1Return1(a string) string { return a } -func (t testStruct) FuncMultArgs(a, b string) string { - return a + b +func (abc _abcStruct) Func2Return1(x, y string) string { + return x + y +} + +func (abc _abcStruct) FuncEllipsis(xyz ...string) int { + return len(xyz) } -func (t testStruct) FuncVarArgs(as ...string) int { - return len(as) +func (abc _abcStruct) FuncReturnStruct() _mnoStruct { + return _mnoStruct{} +} + +type _mnoStruct struct { + Ghi string +} + +func (mno _mnoStruct) Func() string { + return "mno" } func TestReflect(t *testing.T) { - return + if true { + return + } tt(t, func() { // Testing dbgf // These should panic @@ -55,16 +75,12 @@ func Test_reflectStruct(t *testing.T) { tt(t, func() { test, vm := test() - // testStruct + // _abcStruct { - abc := &testStruct{} + abc := &_abcStruct{} vm.Set("abc", abc) test(` - abc.FuncPointerReciever(); - `, "abc") - - test(` [ abc.Abc, abc.Ghi ]; `, "false,") @@ -75,7 +91,7 @@ func Test_reflectStruct(t *testing.T) { [ abc.Abc, abc.Ghi ]; `, "true,Nothing happens.") - *abc = testStruct{} + *abc = _abcStruct{} test(` [ abc.Abc, abc.Ghi ]; @@ -109,24 +125,40 @@ func Test_reflectStruct(t *testing.T) { is(abc.Def, 451) test(` - abc.FuncNoArgsNoRet(); + abc.FuncPointer(); + `, "abc") + + test(` + abc.Func(); `, "undefined") + test(` - abc.FuncNoArgs(); + abc.FuncReturn1(); `, "abc") + test(` - abc.FuncOneArgs("abc"); + abc.Func1Return1("abc"); `, "abc") + test(` - abc.FuncMultArgs("abc", "def"); + abc.Func2Return1("abc", "def"); `, "abcdef") + test(` - abc.FuncVarArgs("abc", "def", "ghi"); + abc.FuncEllipsis("abc", "def", "ghi"); `, 3) test(`raise: - abc.FuncNoArgsMultRet(); + abc.FuncReturn2(); `, "TypeError") + + test(` + abc.FuncReturnStruct(); + `, "[object Object]") + + test(` + abc.FuncReturnStruct().Func(); + `, "mno") } }) } @@ -387,7 +419,7 @@ func Test_reflectMapInterface(t *testing.T) { "jkl": "jkl", } vm.Set("abc", abc) - vm.Set("mno", &testStruct{}) + vm.Set("mno", &_abcStruct{}) test(` abc.xyz = "pqr"; @@ -402,10 +434,50 @@ func Test_reflectMapInterface(t *testing.T) { is(abc["xyz"], "pqr") is(abc["ghi"], "[object Object]") is(abc["jkl"], float64(3.14159)) - mno, valid := abc["mno"].(*testStruct) + mno, valid := abc["mno"].(*_abcStruct) is(valid, true) is(mno.Abc, true) is(mno.Ghi, "Something happens.") } }) } + +func TestPassthrough(t *testing.T) { + tt(t, func() { + test, vm := test() + + { + abc := &_abcStruct{ + Mno: _mnoStruct{ + Ghi: "<Mno.Ghi>", + }, + } + vm.Set("abc", abc) + + test(` + abc.Mno.Ghi; + `, "<Mno.Ghi>") + + vm.Set("pqr", map[string]int8{ + "xyzzy": 0, + "Nothing happens.": 1, + }) + + test(` + abc.Ghi = "abc"; + abc.Pqr = pqr; + abc.Pqr["Nothing happens."]; + `, 1) + + mno := _mnoStruct{ + Ghi: "<mno.Ghi>", + } + vm.Set("mno", mno) + + test(` + abc.Mno = mno; + abc.Mno.Ghi; + `, "<mno.Ghi>") + } + }) +} diff --git a/Godeps/_workspace/src/github.com/obscuren/otto/regexp_test.go b/Godeps/_workspace/src/github.com/robertkrimen/otto/regexp_test.go index 36183a0d9..8e65ee46a 100644 --- a/Godeps/_workspace/src/github.com/obscuren/otto/regexp_test.go +++ b/Godeps/_workspace/src/github.com/robertkrimen/otto/regexp_test.go @@ -160,7 +160,10 @@ func TestRegExp_toString(t *testing.T) { } func TestRegExp_zaacbbbcac(t *testing.T) { - return + if true { + return + } + tt(t, func() { test, _ := test() diff --git a/Godeps/_workspace/src/github.com/obscuren/otto/result.go b/Godeps/_workspace/src/github.com/robertkrimen/otto/result.go index cf42c423a..63642e7d0 100644 --- a/Godeps/_workspace/src/github.com/obscuren/otto/result.go +++ b/Godeps/_workspace/src/github.com/robertkrimen/otto/result.go @@ -22,9 +22,9 @@ func newReturnResult(value Value) _result { } func newContinueResult(target string) _result { - return _result{resultContinue, emptyValue(), target} + return _result{resultContinue, emptyValue, target} } func newBreakResult(target string) _result { - return _result{resultBreak, emptyValue(), target} + return _result{resultBreak, emptyValue, target} } diff --git a/Godeps/_workspace/src/github.com/obscuren/otto/runtime.go b/Godeps/_workspace/src/github.com/robertkrimen/otto/runtime.go index 76e51d78c..1ac1b435e 100644 --- a/Godeps/_workspace/src/github.com/obscuren/otto/runtime.go +++ b/Godeps/_workspace/src/github.com/robertkrimen/otto/runtime.go @@ -3,6 +3,7 @@ package otto import ( "errors" "reflect" + "sync" "github.com/robertkrimen/otto/ast" "github.com/robertkrimen/otto/parser" @@ -45,100 +46,54 @@ type _global struct { } type _runtime struct { - Stack [](*_executionContext) - - GlobalObject *_object - GlobalEnvironment *_objectEnvironment - - Global _global - - eval *_object // The builtin eval, for determine indirect versus direct invocation - - Otto *Otto + global _global + globalObject *_object + globalStash *_objectStash + scope *_scope + otto *Otto + eval *_object // The builtin eval, for determine indirect versus direct invocation labels []string // FIXME + lck sync.Mutex } -func (self *_runtime) EnterGlobalExecutionContext() { - self.EnterExecutionContext(newExecutionContext(self.GlobalEnvironment, self.GlobalEnvironment, self.GlobalObject)) +func (self *_runtime) enterScope(scope *_scope) { + scope.outer = self.scope + self.scope = scope } -func (self *_runtime) EnterExecutionContext(scope *_executionContext) { - self.Stack = append(self.Stack, scope) +func (self *_runtime) leaveScope() { + self.scope = self.scope.outer } -func (self *_runtime) LeaveExecutionContext() { - self.Stack = self.Stack[:len(self.Stack)-1] -} - -func (self *_runtime) _executionContext(depth int) *_executionContext { - if depth == 0 { - return self.Stack[len(self.Stack)-1] - } - if len(self.Stack)-1+depth >= 0 { - return self.Stack[len(self.Stack)-1+depth] - } - return nil +// FIXME This is used in two places (cloning) +func (self *_runtime) enterGlobalScope() { + self.enterScope(newScope(self.globalStash, self.globalStash, self.globalObject)) } -func (self *_runtime) EnterFunctionExecutionContext(function *_object, this Value) *_functionEnvironment { - scopeEnvironment := function.functionValue().call.ScopeEnvironment() - if scopeEnvironment == nil { - scopeEnvironment = self.GlobalEnvironment +func (self *_runtime) enterFunctionScope(outer _stash, this Value) *_fnStash { + if outer == nil { + outer = self.globalStash } - environment := self.newFunctionEnvironment(scopeEnvironment) + stash := self.newFunctionStash(outer) var thisObject *_object - switch this._valueType { + switch this.kind { case valueUndefined, valueNull: - thisObject = self.GlobalObject + thisObject = self.globalObject default: thisObject = self.toObject(this) } - self.EnterExecutionContext(newExecutionContext(environment, environment, thisObject)) - return environment -} - -func (self *_runtime) EnterEvalExecutionContext(call FunctionCall) { - // Skip the current function lexical/variable environment, which is of the function execution context call - // to eval (the global execution context). Instead, execute in the context of where the eval was called, - // which is essentially dynamic scoping - parent := self._executionContext(-1) - new := newExecutionContext(parent.LexicalEnvironment, parent.VariableEnvironment, parent.this) - // FIXME Make passing through of self.GlobalObject more general? Whenever newExecutionContext is passed a nil object? - new.eval = true - self.EnterExecutionContext(new) -} - -func (self *_runtime) GetValue(value Value) Value { - if value.isReference() { - return value.reference().GetValue() - } - return value -} - -func (self *_runtime) PutValue(reference _reference, value Value) { - if !reference.PutValue(value) { - // Why? -- If reference.Base == nil - strict := false - self.GlobalObject.defineProperty(reference.GetName(), value, 0111, strict) - } + self.enterScope(newScope(stash, stash, thisObject)) + return stash } -func (self *_runtime) Call(function *_object, this Value, argumentList []Value, evalHint bool) Value { - // Pass eval boolean through to EnterFunctionExecutionContext for further testing - _functionEnvironment := self.EnterFunctionExecutionContext(function, this) - defer func() { - self.LeaveExecutionContext() - }() - - if evalHint { - evalHint = function == self.eval // If evalHint is true, then it IS a direct eval +func (self *_runtime) putValue(reference _reference, value Value) { + name := reference.putValue(value) + if name != "" { + // Why? -- If reference.base == nil + // strict = false + self.globalObject.defineProperty(name, value, 0111, false) } - callValue := function.functionValue().call.Dispatch(function, _functionEnvironment, self, this, argumentList, evalHint) - if value, valid := callValue.value.(_result); valid { - return value.value - } - return callValue } func (self *_runtime) tryCatchEvaluate(inner func() Value) (tryValue Value, exception bool) { @@ -155,10 +110,7 @@ func (self *_runtime) tryCatchEvaluate(inner func() Value) (tryValue Value, exce switch caught := caught.(type) { case _error: exception = true - tryValue = toValue_object(self.newError(caught.Name, caught.MessageValue())) - //case *_syntaxError: - // exception = true - // tryValue = toValue_object(self.newError("SyntaxError", toValue_string(caught.Message))) + tryValue = toValue_object(self.newError(caught.name, caught.messageValue())) case Value: exception = true tryValue = caught @@ -172,30 +124,12 @@ func (self *_runtime) tryCatchEvaluate(inner func() Value) (tryValue Value, exce return } -// _executionContext Proxy - -func (self *_runtime) localGet(name string) Value { - return self._executionContext(0).getValue(name) -} - -func (self *_runtime) localSet(name string, value Value) { - self._executionContext(0).setValue(name, value, false) -} - -func (self *_runtime) VariableEnvironment() _environment { - return self._executionContext(0).VariableEnvironment -} - -func (self *_runtime) LexicalEnvironment() _environment { - return self._executionContext(0).LexicalEnvironment -} - // toObject func (self *_runtime) toObject(value Value) *_object { - switch value._valueType { + switch value.kind { case valueEmpty, valueUndefined, valueNull: - panic(newTypeError()) + panic(self.panicTypeError()) case valueBoolean: return self.newBoolean(value) case valueString: @@ -205,11 +139,11 @@ func (self *_runtime) toObject(value Value) *_object { case valueObject: return value._object() } - panic(newTypeError()) + panic(self.panicTypeError()) } func (self *_runtime) objectCoerce(value Value) (*_object, error) { - switch value._valueType { + switch value.kind { case valueUndefined: return nil, errors.New("undefined") case valueNull: @@ -223,20 +157,20 @@ func (self *_runtime) objectCoerce(value Value) (*_object, error) { case valueObject: return value._object(), nil } - panic(newTypeError()) + panic(self.panicTypeError()) } -func checkObjectCoercible(value Value) { +func checkObjectCoercible(rt *_runtime, value Value) { isObject, mustCoerce := testObjectCoercible(value) if !isObject && !mustCoerce { - panic(newTypeError()) + panic(rt.panicTypeError()) } } // testObjectCoercible func testObjectCoercible(value Value) (isObject bool, mustCoerce bool) { - switch value._valueType { + switch value.kind { case valueReference, valueEmpty, valueNull, valueUndefined: return false, false case valueNumber, valueString, valueBoolean: @@ -249,8 +183,8 @@ func testObjectCoercible(value Value) (isObject bool, mustCoerce bool) { return } -func (self *_runtime) ToValue(value interface{}) (Value, error) { - result := UndefinedValue() +func (self *_runtime) safeToValue(value interface{}) (Value, error) { + result := Value{} err := catchPanic(func() { result = self.toValue(value) }) @@ -267,7 +201,8 @@ func (self *_runtime) toValue(value interface{}) Value { return toValue_object(self.newNativeFunction("", value)) case Object, *Object, _object, *_object: // Nothing happens. - // FIXME + // FIXME We should really figure out what can come here. + // This catch-all is ugly. default: { value := reflect.ValueOf(value) @@ -280,19 +215,21 @@ func (self *_runtime) toValue(value interface{}) Value { return toValue_object(self.newGoArray(value)) } case reflect.Func: + // TODO Maybe cache this? return toValue_object(self.newNativeFunction("", func(call FunctionCall) Value { - args := make([]reflect.Value, len(call.ArgumentList)) - for i, a := range call.ArgumentList { - args[i] = reflect.ValueOf(a.export()) + in := make([]reflect.Value, len(call.ArgumentList)) + for i, value := range call.ArgumentList { + in[i] = reflect.ValueOf(value.export()) } - retvals := value.Call(args) - if len(retvals) > 1 { - panic(newTypeError()) - } else if len(retvals) == 1 { - return toValue(retvals[0].Interface()) + out := value.Call(in) + if len(out) == 1 { + return self.toValue(out[0].Interface()) + } else if len(out) == 0 { + return Value{} } - return UndefinedValue() + + panic(call.runtime.panicTypeError()) })) case reflect.Struct: return toValue_object(self.newGoStructObject(value)) @@ -310,13 +247,13 @@ func (self *_runtime) toValue(value interface{}) Value { func (runtime *_runtime) newGoSlice(value reflect.Value) *_object { self := runtime.newGoSliceObject(value) - self.prototype = runtime.Global.ArrayPrototype + self.prototype = runtime.global.ArrayPrototype return self } func (runtime *_runtime) newGoArray(value reflect.Value) *_object { self := runtime.newGoArrayObject(value) - self.prototype = runtime.Global.ArrayPrototype + self.prototype = runtime.global.ArrayPrototype return self } @@ -344,7 +281,7 @@ func (self *_runtime) parseSource(src interface{}) (*_nodeProgram, *ast.Program, } func (self *_runtime) cmpl_run(src interface{}) (Value, error) { - result := UndefinedValue() + result := Value{} cmpl_program, program, err := self.parseSource(src) if err != nil { return result, err @@ -353,13 +290,13 @@ func (self *_runtime) cmpl_run(src interface{}) (Value, error) { cmpl_program = cmpl_parse(program) } err = catchPanic(func() { - result = self.cmpl_evaluate_nodeProgram(cmpl_program) + result = self.cmpl_evaluate_nodeProgram(cmpl_program, false) }) - switch result._valueType { + switch result.kind { case valueEmpty: - result = UndefinedValue() + result = Value{} case valueReference: - result = self.GetValue(result) + result = result.resolve() } return result, err } @@ -373,12 +310,12 @@ func (self *_runtime) parseThrow(err error) { { err := err[0] if err.Message == "Invalid left-hand side in assignment" { - panic(newReferenceError(err.Message)) + panic(self.panicReferenceError(err.Message)) } - panic(newSyntaxError(err.Message)) + panic(self.panicSyntaxError(err.Message)) } } - panic(newSyntaxError(err.Error())) + panic(self.panicSyntaxError(err.Error())) } func (self *_runtime) parseOrThrow(source string) *ast.Program { diff --git a/Godeps/_workspace/src/github.com/obscuren/otto/runtime_test.go b/Godeps/_workspace/src/github.com/robertkrimen/otto/runtime_test.go index 8706d59a6..2510a0b3f 100644 --- a/Godeps/_workspace/src/github.com/obscuren/otto/runtime_test.go +++ b/Godeps/_workspace/src/github.com/robertkrimen/otto/runtime_test.go @@ -359,7 +359,7 @@ func TestComparison(t *testing.T) { test("1 == 'Hello, World.'", false) - is(stringToFloat("-1"), -1) + is(parseNumber("-1"), -1) test("0+Object", "0function Object() { [native code] }") }) diff --git a/Godeps/_workspace/src/github.com/robertkrimen/otto/scope.go b/Godeps/_workspace/src/github.com/robertkrimen/otto/scope.go new file mode 100644 index 000000000..b80808434 --- /dev/null +++ b/Godeps/_workspace/src/github.com/robertkrimen/otto/scope.go @@ -0,0 +1,34 @@ +package otto + +// _scope: +// entryFile +// entryIdx +// top? +// outer => nil + +// _stash: +// lexical +// variable +// +// _thisStash (ObjectEnvironment) +// _fnStash +// _dclStash + +// An ECMA-262 ExecutionContext +type _scope struct { + lexical _stash + variable _stash + this *_object + eval bool // Replace this with kind? + outer *_scope + + frame _frame +} + +func newScope(lexical _stash, variable _stash, this *_object) *_scope { + return &_scope{ + lexical: lexical, + variable: variable, + this: this, + } +} diff --git a/Godeps/_workspace/src/github.com/obscuren/otto/script.go b/Godeps/_workspace/src/github.com/robertkrimen/otto/script.go index ed8aebbf4..ed8aebbf4 100644 --- a/Godeps/_workspace/src/github.com/obscuren/otto/script.go +++ b/Godeps/_workspace/src/github.com/robertkrimen/otto/script.go diff --git a/Godeps/_workspace/src/github.com/obscuren/otto/script_test.go b/Godeps/_workspace/src/github.com/robertkrimen/otto/script_test.go index 1a25b8a95..4c35c646e 100644 --- a/Godeps/_workspace/src/github.com/obscuren/otto/script_test.go +++ b/Godeps/_workspace/src/github.com/robertkrimen/otto/script_test.go @@ -6,8 +6,6 @@ import ( func TestScript(t *testing.T) { tt(t, func() { - return - vm := New() script, err := vm.Compile("xyzzy", `var abc; if (!abc) abc = 0; abc += 2; abc;`) @@ -20,6 +18,10 @@ func TestScript(t *testing.T) { is(err, nil) is(value, 2) + if true { + return + } + tmp, err := script.marshalBinary() is(err, nil) is(len(tmp), 1228) diff --git a/Godeps/_workspace/src/github.com/robertkrimen/otto/stash.go b/Godeps/_workspace/src/github.com/robertkrimen/otto/stash.go new file mode 100644 index 000000000..578708d3f --- /dev/null +++ b/Godeps/_workspace/src/github.com/robertkrimen/otto/stash.go @@ -0,0 +1,275 @@ +package otto + +import ( + "fmt" +) + +// ====== +// _stash +// ====== + +type _stash interface { + hasBinding(string) bool // + createBinding(string, bool, Value) // CreateMutableBinding + setBinding(string, Value, bool) // SetMutableBinding + getBinding(string, bool) Value // GetBindingValue + deleteBinding(string) bool // + setValue(string, Value, bool) // createBinding + setBinding + + outer() _stash + runtime() *_runtime + + newReference(string, bool, _at) _reference + + clone(clone *_clone) _stash +} + +// ========== +// _objectStash +// ========== + +type _objectStash struct { + _runtime *_runtime + _outer _stash + object *_object +} + +func (self *_objectStash) runtime() *_runtime { + return self._runtime +} + +func (runtime *_runtime) newObjectStash(object *_object, outer _stash) *_objectStash { + if object == nil { + object = runtime.newBaseObject() + object.class = "environment" + } + return &_objectStash{ + _runtime: runtime, + _outer: outer, + object: object, + } +} + +func (in *_objectStash) clone(clone *_clone) _stash { + out, exists := clone.objectStash(in) + if exists { + return out + } + *out = _objectStash{ + clone.runtime, + clone.stash(in._outer), + clone.object(in.object), + } + return out +} + +func (self *_objectStash) hasBinding(name string) bool { + return self.object.hasProperty(name) +} + +func (self *_objectStash) createBinding(name string, deletable bool, value Value) { + if self.object.hasProperty(name) { + panic(hereBeDragons()) + } + mode := _propertyMode(0111) + if !deletable { + mode = _propertyMode(0110) + } + // TODO False? + self.object.defineProperty(name, value, mode, false) +} + +func (self *_objectStash) setBinding(name string, value Value, strict bool) { + self.object.put(name, value, strict) +} + +func (self *_objectStash) setValue(name string, value Value, throw bool) { + if !self.hasBinding(name) { + self.createBinding(name, true, value) // Configurable by default + } else { + self.setBinding(name, value, throw) + } +} + +func (self *_objectStash) getBinding(name string, throw bool) Value { + if self.object.hasProperty(name) { + return self.object.get(name) + } + if throw { // strict? + panic(self._runtime.panicReferenceError("Not Defined", name)) + } + return Value{} +} + +func (self *_objectStash) deleteBinding(name string) bool { + return self.object.delete(name, false) +} + +func (self *_objectStash) outer() _stash { + return self._outer +} + +func (self *_objectStash) newReference(name string, strict bool, at _at) _reference { + return newPropertyReference(self._runtime, self.object, name, strict, at) +} + +// ========= +// _dclStash +// ========= + +type _dclStash struct { + _runtime *_runtime + _outer _stash + property map[string]_dclProperty +} + +type _dclProperty struct { + value Value + mutable bool + deletable bool + readable bool +} + +func (runtime *_runtime) newDeclarationStash(outer _stash) *_dclStash { + return &_dclStash{ + _runtime: runtime, + _outer: outer, + property: map[string]_dclProperty{}, + } +} + +func (in *_dclStash) clone(clone *_clone) _stash { + out, exists := clone.dclStash(in) + if exists { + return out + } + property := make(map[string]_dclProperty, len(in.property)) + for index, value := range in.property { + property[index] = clone.dclProperty(value) + } + *out = _dclStash{ + clone.runtime, + clone.stash(in._outer), + property, + } + return out +} + +func (self *_dclStash) hasBinding(name string) bool { + _, exists := self.property[name] + return exists +} + +func (self *_dclStash) runtime() *_runtime { + return self._runtime +} + +func (self *_dclStash) createBinding(name string, deletable bool, value Value) { + _, exists := self.property[name] + if exists { + panic(fmt.Errorf("createBinding: %s: already exists", name)) + } + self.property[name] = _dclProperty{ + value: value, + mutable: true, + deletable: deletable, + readable: false, + } +} + +func (self *_dclStash) setBinding(name string, value Value, strict bool) { + property, exists := self.property[name] + if !exists { + panic(fmt.Errorf("setBinding: %s: missing", name)) + } + if property.mutable { + property.value = value + self.property[name] = property + } else { + self._runtime.typeErrorResult(strict) + } +} + +func (self *_dclStash) setValue(name string, value Value, throw bool) { + if !self.hasBinding(name) { + self.createBinding(name, false, value) // NOT deletable by default + } else { + self.setBinding(name, value, throw) + } +} + +// FIXME This is called a __lot__ +func (self *_dclStash) getBinding(name string, throw bool) Value { + property, exists := self.property[name] + if !exists { + panic(fmt.Errorf("getBinding: %s: missing", name)) + } + if !property.mutable && !property.readable { + if throw { // strict? + panic(self._runtime.panicTypeError()) + } + return Value{} + } + return property.value +} + +func (self *_dclStash) deleteBinding(name string) bool { + property, exists := self.property[name] + if !exists { + return true + } + if !property.deletable { + return false + } + delete(self.property, name) + return true +} + +func (self *_dclStash) outer() _stash { + return self._outer +} + +func (self *_dclStash) newReference(name string, strict bool, _ _at) _reference { + return &_stashReference{ + name: name, + base: self, + } +} + +// ======== +// _fnStash +// ======== + +type _fnStash struct { + _dclStash + arguments *_object + indexOfArgumentName map[string]string +} + +func (runtime *_runtime) newFunctionStash(outer _stash) *_fnStash { + return &_fnStash{ + _dclStash: _dclStash{ + _runtime: runtime, + _outer: outer, + property: map[string]_dclProperty{}, + }, + } +} + +func (in *_fnStash) clone(clone *_clone) _stash { + out, exists := clone.fnStash(in) + if exists { + return out + } + dclStash := in._dclStash.clone(clone).(*_dclStash) + index := make(map[string]string, len(in.indexOfArgumentName)) + for name, value := range in.indexOfArgumentName { + index[name] = value + } + *out = _fnStash{ + _dclStash: *dclStash, + arguments: clone.object(in.arguments), + indexOfArgumentName: index, + } + return out +} diff --git a/Godeps/_workspace/src/github.com/obscuren/otto/string_test.go b/Godeps/_workspace/src/github.com/robertkrimen/otto/string_test.go index b7b06324b..b7b06324b 100644 --- a/Godeps/_workspace/src/github.com/obscuren/otto/string_test.go +++ b/Godeps/_workspace/src/github.com/robertkrimen/otto/string_test.go diff --git a/Godeps/_workspace/src/github.com/obscuren/otto/terst/terst.go b/Godeps/_workspace/src/github.com/robertkrimen/otto/terst/terst.go index a25ca8b9c..a25ca8b9c 100644 --- a/Godeps/_workspace/src/github.com/obscuren/otto/terst/terst.go +++ b/Godeps/_workspace/src/github.com/robertkrimen/otto/terst/terst.go diff --git a/Godeps/_workspace/src/github.com/obscuren/otto/test/Makefile b/Godeps/_workspace/src/github.com/robertkrimen/otto/test/Makefile index ac76fdeac..ac76fdeac 100644 --- a/Godeps/_workspace/src/github.com/obscuren/otto/test/Makefile +++ b/Godeps/_workspace/src/github.com/robertkrimen/otto/test/Makefile diff --git a/Godeps/_workspace/src/github.com/obscuren/otto/test/tester.go b/Godeps/_workspace/src/github.com/robertkrimen/otto/test/tester.go index ea694fd8d..ea694fd8d 100644 --- a/Godeps/_workspace/src/github.com/obscuren/otto/test/tester.go +++ b/Godeps/_workspace/src/github.com/robertkrimen/otto/test/tester.go diff --git a/Godeps/_workspace/src/github.com/obscuren/otto/testing_test.go b/Godeps/_workspace/src/github.com/robertkrimen/otto/testing_test.go index 90d1771b9..bf820bc0c 100644 --- a/Godeps/_workspace/src/github.com/obscuren/otto/testing_test.go +++ b/Godeps/_workspace/src/github.com/robertkrimen/otto/testing_test.go @@ -31,11 +31,18 @@ func is(arguments ...interface{}) bool { got, expect = arguments[0], arguments[2] } - if value, ok := got.(Value); ok { - if _, ok := expect.(Value); !ok { - if value.value != nil { - got = value.value - } + switch value := got.(type) { + case Value: + if value.value != nil { + got = value.value + } + case *Error: + if value != nil { + got = value.Error() + } + if expect == nil { + // FIXME This is weird + expect = "" } } @@ -120,7 +127,7 @@ func (self *_tester) test(name string, expect ...interface{}) Value { panic(err) } } - value = vm.runtime.GetValue(value) + value = value.resolve() if len(expect) > 0 { is(value, expect[0]) } diff --git a/Godeps/_workspace/src/github.com/obscuren/otto/type_arguments.go b/Godeps/_workspace/src/github.com/robertkrimen/otto/type_arguments.go index e23912ace..841d75855 100644 --- a/Godeps/_workspace/src/github.com/obscuren/otto/type_arguments.go +++ b/Godeps/_workspace/src/github.com/robertkrimen/otto/type_arguments.go @@ -4,7 +4,7 @@ import ( "strconv" ) -func (runtime *_runtime) newArgumentsObject(indexOfParameterName []string, environment _environment, length int) *_object { +func (runtime *_runtime) newArgumentsObject(indexOfParameterName []string, stash _stash, length int) *_object { self := runtime.newClassObject("Arguments") for index, _ := range indexOfParameterName { @@ -15,10 +15,10 @@ func (runtime *_runtime) newArgumentsObject(indexOfParameterName []string, envir self.objectClass = _classArguments self.value = _argumentsObject{ indexOfParameterName: indexOfParameterName, - environment: environment, + stash: stash, } - self.prototype = runtime.Global.ObjectPrototype + self.prototype = runtime.global.ObjectPrototype self.defineProperty("length", toValue_int(length), 0101, false) @@ -32,15 +32,15 @@ type _argumentsObject struct { // indexOfParameterName[1] = "def" // indexOfParameterName[2] = "ghi" // ... - environment _environment + stash _stash } -func (self0 _argumentsObject) clone(clone *_clone) _argumentsObject { - indexOfParameterName := make([]string, len(self0.indexOfParameterName)) - copy(indexOfParameterName, self0.indexOfParameterName) +func (in _argumentsObject) clone(clone *_clone) _argumentsObject { + indexOfParameterName := make([]string, len(in.indexOfParameterName)) + copy(indexOfParameterName, in.indexOfParameterName) return _argumentsObject{ indexOfParameterName, - clone.environment(self0.environment), + clone.stash(in.stash), } } @@ -51,7 +51,7 @@ func (self _argumentsObject) get(name string) (Value, bool) { if name == "" { return Value{}, false } - return self.environment.GetBindingValue(name, false), true + return self.stash.getBinding(name, false), true } return Value{}, false } @@ -59,7 +59,7 @@ func (self _argumentsObject) get(name string) (Value, bool) { func (self _argumentsObject) put(name string, value Value) { index := stringToArrayIndex(name) name = self.indexOfParameterName[index] - self.environment.SetMutableBinding(name, value, false) + self.stash.setBinding(name, value, false) } func (self _argumentsObject) delete(name string) { @@ -85,7 +85,7 @@ func argumentsGetOwnProperty(self *_object, name string) *_property { func argumentsDefineOwnProperty(self *_object, name string, descriptor _property, throw bool) bool { if _, exists := self.value.(_argumentsObject).get(name); exists { if !objectDefineOwnProperty(self, name, descriptor, false) { - return typeErrorResult(throw) + return self.runtime.typeErrorResult(throw) } if value, valid := descriptor.value.(Value); valid { self.value.(_argumentsObject).put(name, value) diff --git a/Godeps/_workspace/src/github.com/obscuren/otto/type_array.go b/Godeps/_workspace/src/github.com/robertkrimen/otto/type_array.go index 6c72824ff..236376a8e 100644 --- a/Godeps/_workspace/src/github.com/obscuren/otto/type_array.go +++ b/Godeps/_workspace/src/github.com/robertkrimen/otto/type_array.go @@ -31,12 +31,13 @@ func objectLength(object *_object) uint32 { return 0 } -func arrayUint32(value Value) uint32 { - tmp := toInteger(value) - if !tmp.exact() || !isUint32(tmp.value) { - panic(newRangeError()) +func arrayUint32(rt *_runtime, value Value) uint32 { + nm := value.number() + if nm.kind != numberInteger || !isUint32(nm.int64) { + // FIXME + panic(rt.panicRangeError()) } - return uint32(tmp.value) + return uint32(nm.int64) } func arrayDefineOwnProperty(self *_object, name string, descriptor _property, throw bool) bool { @@ -52,9 +53,9 @@ func arrayDefineOwnProperty(self *_object, name string, descriptor _property, th } newLengthValue, isValue := descriptor.value.(Value) if !isValue { - panic(newTypeError()) + panic(self.runtime.panicTypeError()) } - newLength := arrayUint32(newLengthValue) + newLength := arrayUint32(self.runtime, newLengthValue) descriptor.value = toValue_uint32(newLength) if newLength > length { return objectDefineOwnProperty(self, name, descriptor, throw) @@ -102,7 +103,7 @@ func arrayDefineOwnProperty(self *_object, name string, descriptor _property, th return objectDefineOwnProperty(self, name, descriptor, throw) Reject: if throw { - panic(newTypeError()) + panic(self.runtime.panicTypeError()) } return false } diff --git a/Godeps/_workspace/src/github.com/obscuren/otto/type_boolean.go b/Godeps/_workspace/src/github.com/robertkrimen/otto/type_boolean.go index c24409de1..afc45c69b 100644 --- a/Godeps/_workspace/src/github.com/obscuren/otto/type_boolean.go +++ b/Godeps/_workspace/src/github.com/robertkrimen/otto/type_boolean.go @@ -5,7 +5,7 @@ import ( ) func (runtime *_runtime) newBooleanObject(value Value) *_object { - return runtime.newPrimitiveObject("Boolean", toValue_bool(toBoolean(value))) + return runtime.newPrimitiveObject("Boolean", toValue_bool(value.bool())) } func booleanToString(value bool) string { diff --git a/Godeps/_workspace/src/github.com/obscuren/otto/type_date.go b/Godeps/_workspace/src/github.com/robertkrimen/otto/type_date.go index 65e822f38..7079e649c 100644 --- a/Godeps/_workspace/src/github.com/obscuren/otto/type_date.go +++ b/Godeps/_workspace/src/github.com/robertkrimen/otto/type_date.go @@ -149,9 +149,9 @@ func (self *_object) dateValue() _dateObject { return value } -func dateObjectOf(_dateObject *_object) _dateObject { +func dateObjectOf(rt *_runtime, _dateObject *_object) _dateObject { if _dateObject == nil || _dateObject.class != "Date" { - panic(newTypeError()) + panic(rt.panicTypeError()) } return _dateObject.dateValue() } @@ -180,7 +180,7 @@ func newDateTime(argumentList []Value, location *Time.Location) (epoch float64) if index >= len(argumentList) { return default_, false } - value := toFloat(argumentList[index]) + value := argumentList[index].float64() if math.IsNaN(value) || math.IsInf(value, 0) { return 0, true } @@ -226,10 +226,10 @@ func newDateTime(argumentList []Value, location *Time.Location) (epoch float64) value := valueOfArrayIndex(argumentList, 0) value = toPrimitive(value) if value.IsString() { - return dateParse(toString(value)) + return dateParse(value.string()) } - return toFloat(value) + return value.float64() } INVALID: diff --git a/Godeps/_workspace/src/github.com/robertkrimen/otto/type_error.go b/Godeps/_workspace/src/github.com/robertkrimen/otto/type_error.go new file mode 100644 index 000000000..c469f5fcb --- /dev/null +++ b/Godeps/_workspace/src/github.com/robertkrimen/otto/type_error.go @@ -0,0 +1,13 @@ +package otto + +func (rt *_runtime) newErrorObject(name string, message Value) *_object { + self := rt.newClassObject("Error") + if message.IsDefined() { + msg := message.string() + self.defineProperty("message", toValue_string(msg), 0111, false) + self.value = newError(rt, name, msg) + } else { + self.value = newError(rt, name) + } + return self +} diff --git a/Godeps/_workspace/src/github.com/robertkrimen/otto/type_function.go b/Godeps/_workspace/src/github.com/robertkrimen/otto/type_function.go new file mode 100644 index 000000000..a5eb7554a --- /dev/null +++ b/Godeps/_workspace/src/github.com/robertkrimen/otto/type_function.go @@ -0,0 +1,262 @@ +package otto + +// _constructFunction +type _constructFunction func(*_object, []Value) Value + +// 13.2.2 [[Construct]] +func defaultConstruct(fn *_object, argumentList []Value) Value { + object := fn.runtime.newObject() + object.class = "Object" + + prototype := fn.get("prototype") + if prototype.kind != valueObject { + prototype = toValue_object(fn.runtime.global.ObjectPrototype) + } + object.prototype = prototype._object() + + this := toValue_object(object) + value := fn.call(this, argumentList, false, nativeFrame) + if value.kind == valueObject { + return value + } + return this +} + +// _nativeFunction +type _nativeFunction func(FunctionCall) Value + +// ===================== // +// _nativeFunctionObject // +// ===================== // + +type _nativeFunctionObject struct { + name string + call _nativeFunction // [[Call]] + construct _constructFunction // [[Construct]] +} + +func (runtime *_runtime) newNativeFunctionObject(name string, native _nativeFunction, length int) *_object { + self := runtime.newClassObject("Function") + self.value = _nativeFunctionObject{ + call: native, + construct: defaultConstruct, + } + self.defineProperty("length", toValue_int(length), 0000, false) + return self +} + +// =================== // +// _bindFunctionObject // +// =================== // + +type _bindFunctionObject struct { + target *_object + this Value + argumentList []Value +} + +func (runtime *_runtime) newBoundFunctionObject(target *_object, this Value, argumentList []Value) *_object { + self := runtime.newClassObject("Function") + self.value = _bindFunctionObject{ + target: target, + this: this, + argumentList: argumentList, + } + length := int(toInt32(target.get("length"))) + length -= len(argumentList) + if length < 0 { + length = 0 + } + self.defineProperty("length", toValue_int(length), 0000, false) + self.defineProperty("caller", Value{}, 0000, false) // TODO Should throw a TypeError + self.defineProperty("arguments", Value{}, 0000, false) // TODO Should throw a TypeError + return self +} + +// [[Construct]] +func (fn _bindFunctionObject) construct(argumentList []Value) Value { + object := fn.target + switch value := object.value.(type) { + case _nativeFunctionObject: + return value.construct(object, fn.argumentList) + case _nodeFunctionObject: + argumentList = append(fn.argumentList, argumentList...) + return object.construct(argumentList) + } + panic(fn.target.runtime.panicTypeError()) +} + +// =================== // +// _nodeFunctionObject // +// =================== // + +type _nodeFunctionObject struct { + node *_nodeFunctionLiteral + stash _stash +} + +func (runtime *_runtime) newNodeFunctionObject(node *_nodeFunctionLiteral, stash _stash) *_object { + self := runtime.newClassObject("Function") + self.value = _nodeFunctionObject{ + node: node, + stash: stash, + } + self.defineProperty("length", toValue_int(len(node.parameterList)), 0000, false) + return self +} + +// ======= // +// _object // +// ======= // + +func (self *_object) isCall() bool { + switch fn := self.value.(type) { + case _nativeFunctionObject: + return fn.call != nil + case _bindFunctionObject: + return true + case _nodeFunctionObject: + return true + } + return false +} + +func (self *_object) call(this Value, argumentList []Value, eval bool, frame _frame) Value { + switch fn := self.value.(type) { + + case _nativeFunctionObject: + // TODO Enter a scope, name from the native object... + // Since eval is a native function, we only have to check for it here + if eval { + eval = self == self.runtime.eval // If eval is true, then it IS a direct eval + } + return fn.call(FunctionCall{ + runtime: self.runtime, + eval: eval, + + This: this, + ArgumentList: argumentList, + Otto: self.runtime.otto, + }) + + case _bindFunctionObject: + // TODO Passthrough site, do not enter a scope + argumentList = append(fn.argumentList, argumentList...) + return fn.target.call(fn.this, argumentList, false, frame) + + case _nodeFunctionObject: + rt := self.runtime + stash := rt.enterFunctionScope(fn.stash, this) + defer func() { + rt.leaveScope() + }() + rt.scope.frame = frame + callValue := rt.cmpl_call_nodeFunction(self, stash, fn.node, this, argumentList) + if value, valid := callValue.value.(_result); valid { + return value.value + } + return callValue + } + + panic(self.runtime.panicTypeError("%v is not a function", toValue_object(self))) +} + +func (self *_object) construct(argumentList []Value) Value { + switch fn := self.value.(type) { + + case _nativeFunctionObject: + if fn.call == nil { + panic(self.runtime.panicTypeError("%v is not a function", toValue_object(self))) + } + if fn.construct == nil { + panic(self.runtime.panicTypeError("%v is not a constructor", toValue_object(self))) + } + return fn.construct(self, argumentList) + + case _bindFunctionObject: + return fn.construct(argumentList) + + case _nodeFunctionObject: + return defaultConstruct(self, argumentList) + } + + panic(self.runtime.panicTypeError("%v is not a function", toValue_object(self))) +} + +// 15.3.5.3 +func (self *_object) hasInstance(of Value) bool { + if !self.isCall() { + // We should not have a hasInstance method + panic(self.runtime.panicTypeError()) + } + if !of.IsObject() { + return false + } + prototype := self.get("prototype") + if !prototype.IsObject() { + panic(self.runtime.panicTypeError()) + } + prototypeObject := prototype._object() + + value := of._object().prototype + for value != nil { + if value == prototypeObject { + return true + } + value = value.prototype + } + return false +} + +// ============ // +// FunctionCall // +// ============ // + +// FunctionCall is an encapsulation of a JavaScript function call. +type FunctionCall struct { + runtime *_runtime + _thisObject *_object + eval bool // This call is a direct call to eval + + This Value + ArgumentList []Value + Otto *Otto +} + +// Argument will return the value of the argument at the given index. +// +// If no such argument exists, undefined is returned. +func (self FunctionCall) Argument(index int) Value { + return valueOfArrayIndex(self.ArgumentList, index) +} + +func (self FunctionCall) getArgument(index int) (Value, bool) { + return getValueOfArrayIndex(self.ArgumentList, index) +} + +func (self FunctionCall) slice(index int) []Value { + if index < len(self.ArgumentList) { + return self.ArgumentList[index:] + } + return []Value{} +} + +func (self *FunctionCall) thisObject() *_object { + if self._thisObject == nil { + this := self.This.resolve() // FIXME Is this right? + self._thisObject = self.runtime.toObject(this) + } + return self._thisObject +} + +func (self *FunctionCall) thisClassObject(class string) *_object { + thisObject := self.thisObject() + if thisObject.class != class { + panic(self.runtime.panicTypeError()) + } + return self._thisObject +} + +func (self FunctionCall) toObject(value Value) *_object { + return self.runtime.toObject(value) +} diff --git a/Godeps/_workspace/src/github.com/obscuren/otto/type_go_array.go b/Godeps/_workspace/src/github.com/robertkrimen/otto/type_go_array.go index cf2ddd437..13a0b10f2 100644 --- a/Godeps/_workspace/src/github.com/obscuren/otto/type_go_array.go +++ b/Godeps/_workspace/src/github.com/robertkrimen/otto/type_go_array.go @@ -67,7 +67,7 @@ func goArrayGetOwnProperty(self *_object, name string) *_property { index := stringToArrayIndex(name) if index >= 0 { object := self.value.(*_goArrayObject) - value := UndefinedValue() + value := Value{} reflectValue, exists := object.getValue(index) if exists { value = self.runtime.toValue(reflectValue.Interface()) @@ -97,7 +97,7 @@ func goArrayEnumerate(self *_object, all bool, each func(string) bool) { func goArrayDefineOwnProperty(self *_object, name string, descriptor _property, throw bool) bool { if name == "length" { - return typeErrorResult(throw) + return self.runtime.typeErrorResult(throw) } else if index := stringToArrayIndex(name); index >= 0 { object := self.value.(*_goArrayObject) if object.writable { @@ -105,7 +105,7 @@ func goArrayDefineOwnProperty(self *_object, name string, descriptor _property, return true } } - return typeErrorResult(throw) + return self.runtime.typeErrorResult(throw) } return objectDefineOwnProperty(self, name, descriptor, throw) } @@ -113,7 +113,7 @@ func goArrayDefineOwnProperty(self *_object, name string, descriptor _property, func goArrayDelete(self *_object, name string, throw bool) bool { // length if name == "length" { - return typeErrorResult(throw) + return self.runtime.typeErrorResult(throw) } // .0, .1, .2, ... @@ -127,7 +127,7 @@ func goArrayDelete(self *_object, name string, throw bool) bool { return true } } - return typeErrorResult(throw) + return self.runtime.typeErrorResult(throw) } return self.delete(name, throw) diff --git a/Godeps/_workspace/src/github.com/obscuren/otto/type_go_map.go b/Godeps/_workspace/src/github.com/robertkrimen/otto/type_go_map.go index 4635fb231..542a2c29d 100644 --- a/Godeps/_workspace/src/github.com/obscuren/otto/type_go_map.go +++ b/Godeps/_workspace/src/github.com/robertkrimen/otto/type_go_map.go @@ -70,10 +70,10 @@ func goMapDefineOwnProperty(self *_object, name string, descriptor _property, th object := self.value.(*_goMapObject) // TODO ...or 0222 if descriptor.mode != 0111 { - return typeErrorResult(throw) + return self.runtime.typeErrorResult(throw) } if !descriptor.isDataDescriptor() { - return typeErrorResult(throw) + return self.runtime.typeErrorResult(throw) } object.value.SetMapIndex(object.toKey(name), object.toValue(descriptor.value.(Value))) return true diff --git a/Godeps/_workspace/src/github.com/obscuren/otto/type_go_slice.go b/Godeps/_workspace/src/github.com/robertkrimen/otto/type_go_slice.go index 5821e2ad3..7143531a8 100644 --- a/Godeps/_workspace/src/github.com/obscuren/otto/type_go_slice.go +++ b/Godeps/_workspace/src/github.com/robertkrimen/otto/type_go_slice.go @@ -56,7 +56,7 @@ func goSliceGetOwnProperty(self *_object, name string) *_property { // .0, .1, .2, ... index := stringToArrayIndex(name) if index >= 0 { - value := UndefinedValue() + value := Value{} reflectValue, exists := self.value.(*_goSliceObject).getValue(index) if exists { value = self.runtime.toValue(reflectValue.Interface()) @@ -86,12 +86,12 @@ func goSliceEnumerate(self *_object, all bool, each func(string) bool) { func goSliceDefineOwnProperty(self *_object, name string, descriptor _property, throw bool) bool { if name == "length" { - return typeErrorResult(throw) + return self.runtime.typeErrorResult(throw) } else if index := stringToArrayIndex(name); index >= 0 { if self.value.(*_goSliceObject).setValue(index, descriptor.value.(Value)) { return true } - return typeErrorResult(throw) + return self.runtime.typeErrorResult(throw) } return objectDefineOwnProperty(self, name, descriptor, throw) } @@ -99,7 +99,7 @@ func goSliceDefineOwnProperty(self *_object, name string, descriptor _property, func goSliceDelete(self *_object, name string, throw bool) bool { // length if name == "length" { - return typeErrorResult(throw) + return self.runtime.typeErrorResult(throw) } // .0, .1, .2, ... @@ -111,7 +111,7 @@ func goSliceDelete(self *_object, name string, throw bool) bool { indexValue.Set(reflect.Zero(object.value.Type().Elem())) return true } - return typeErrorResult(throw) + return self.runtime.typeErrorResult(throw) } return self.delete(name, throw) diff --git a/Godeps/_workspace/src/github.com/obscuren/otto/type_go_struct.go b/Godeps/_workspace/src/github.com/robertkrimen/otto/type_go_struct.go index 4abdf8075..608ac6660 100644 --- a/Godeps/_workspace/src/github.com/obscuren/otto/type_go_struct.go +++ b/Godeps/_workspace/src/github.com/robertkrimen/otto/type_go_struct.go @@ -3,14 +3,15 @@ package otto import ( "encoding/json" "reflect" - "unicode" ) -func upCase(str *string) { - a := []rune(*str) - a[0] = unicode.ToUpper(a[0]) - *str = string(a) -} +// FIXME Make a note about not being able to modify a struct unless it was +// passed as a pointer-to: &struct{ ... } +// This seems to be a limitation of the reflect package. +// This goes for the other Go constructs too. +// I guess we could get around it by either: +// 1. Creating a new struct every time +// 2. Creating an addressable? struct in the constructor func (runtime *_runtime) newGoStructObject(value reflect.Value) *_object { self := runtime.newObject() @@ -35,8 +36,6 @@ func _newGoStructObject(value reflect.Value) *_goStructObject { } func (self _goStructObject) getValue(name string) reflect.Value { - upCase(&name) - if validGoStructName(name) { // Do not reveal hidden or unexported fields if field := reflect.Indirect(self.value).FieldByName(name); (field != reflect.Value{}) { @@ -52,14 +51,10 @@ func (self _goStructObject) getValue(name string) reflect.Value { } func (self _goStructObject) field(name string) (reflect.StructField, bool) { - upCase(&name) - return reflect.Indirect(self.value).Type().FieldByName(name) } func (self _goStructObject) method(name string) (reflect.Method, bool) { - upCase(&name) - return reflect.Indirect(self.value).Type().MethodByName(name) } @@ -74,6 +69,7 @@ func (self _goStructObject) setValue(name string, value Value) bool { panic(err) } fieldValue.Set(reflectValue) + return true } diff --git a/Godeps/_workspace/src/github.com/obscuren/otto/type_number.go b/Godeps/_workspace/src/github.com/robertkrimen/otto/type_number.go index ee7adc985..28de4444c 100644 --- a/Godeps/_workspace/src/github.com/obscuren/otto/type_number.go +++ b/Godeps/_workspace/src/github.com/robertkrimen/otto/type_number.go @@ -1,5 +1,5 @@ package otto func (runtime *_runtime) newNumberObject(value Value) *_object { - return runtime.newPrimitiveObject("Number", toNumber(value)) + return runtime.newPrimitiveObject("Number", value.numberValue()) } diff --git a/Godeps/_workspace/src/github.com/robertkrimen/otto/type_reference.go b/Godeps/_workspace/src/github.com/robertkrimen/otto/type_reference.go new file mode 100644 index 000000000..fd770c6f4 --- /dev/null +++ b/Godeps/_workspace/src/github.com/robertkrimen/otto/type_reference.go @@ -0,0 +1,103 @@ +package otto + +type _reference interface { + invalid() bool // IsUnresolvableReference + getValue() Value // getValue + putValue(Value) string // PutValue + delete() bool +} + +// PropertyReference + +type _propertyReference struct { + name string + strict bool + base *_object + runtime *_runtime + at _at +} + +func newPropertyReference(rt *_runtime, base *_object, name string, strict bool, at _at) *_propertyReference { + return &_propertyReference{ + runtime: rt, + name: name, + strict: strict, + base: base, + at: at, + } +} + +func (self *_propertyReference) invalid() bool { + return self.base == nil +} + +func (self *_propertyReference) getValue() Value { + if self.base == nil { + panic(self.runtime.panicReferenceError("'%s' is not defined", self.name, self.at)) + } + return self.base.get(self.name) +} + +func (self *_propertyReference) putValue(value Value) string { + if self.base == nil { + return self.name + } + self.base.put(self.name, value, self.strict) + return "" +} + +func (self *_propertyReference) delete() bool { + if self.base == nil { + // TODO Throw an error if strict + return true + } + return self.base.delete(self.name, self.strict) +} + +// ArgumentReference + +func newArgumentReference(runtime *_runtime, base *_object, name string, strict bool, at _at) *_propertyReference { + if base == nil { + panic(hereBeDragons()) + } + return newPropertyReference(runtime, base, name, strict, at) +} + +type _stashReference struct { + name string + strict bool + base _stash +} + +func (self *_stashReference) invalid() bool { + return false // The base (an environment) will never be nil +} + +func (self *_stashReference) getValue() Value { + return self.base.getBinding(self.name, self.strict) +} + +func (self *_stashReference) putValue(value Value) string { + self.base.setValue(self.name, value, self.strict) + return "" +} + +func (self *_stashReference) delete() bool { + if self.base == nil { + // This should never be reached, but just in case + return false + } + return self.base.deleteBinding(self.name) +} + +// getIdentifierReference + +func getIdentifierReference(runtime *_runtime, stash _stash, name string, strict bool, at _at) _reference { + if stash == nil { + return newPropertyReference(runtime, nil, name, strict, at) + } + if stash.hasBinding(name) { + return stash.newReference(name, strict, at) + } + return getIdentifierReference(runtime, stash.outer(), name, strict, at) +} diff --git a/Godeps/_workspace/src/github.com/obscuren/otto/type_regexp.go b/Godeps/_workspace/src/github.com/robertkrimen/otto/type_regexp.go index 5f17bde69..57fe31640 100644 --- a/Godeps/_workspace/src/github.com/obscuren/otto/type_regexp.go +++ b/Godeps/_workspace/src/github.com/robertkrimen/otto/type_regexp.go @@ -32,18 +32,18 @@ func (runtime *_runtime) newRegExpObject(pattern string, flags string) *_object switch chr { case 'g': if global { - panic(newError("SyntaxError: newRegExpObject: %s %s", pattern, flags)) + panic(runtime.panicSyntaxError("newRegExpObject: %s %s", pattern, flags)) } global = true case 'm': if multiline { - panic(newError("SyntaxError: newRegExpObject: %s %s", pattern, flags)) + panic(runtime.panicSyntaxError("newRegExpObject: %s %s", pattern, flags)) } multiline = true re2flags += "m" case 'i': if ignoreCase { - panic(newError("SyntaxError: newRegExpObject: %s %s", pattern, flags)) + panic(runtime.panicSyntaxError("newRegExpObject: %s %s", pattern, flags)) } ignoreCase = true re2flags += "i" @@ -52,7 +52,7 @@ func (runtime *_runtime) newRegExpObject(pattern string, flags string) *_object re2pattern, err := parser.TransformRegExp(pattern) if err != nil { - panic(newTypeError("Invalid regular expression: %s", err.Error())) + panic(runtime.panicTypeError("Invalid regular expression: %s", err.Error())) } if len(re2flags) > 0 { re2pattern = fmt.Sprintf("(?%s:%s)", re2flags, re2pattern) @@ -60,7 +60,7 @@ func (runtime *_runtime) newRegExpObject(pattern string, flags string) *_object regularExpression, err := regexp.Compile(re2pattern) if err != nil { - panic(newSyntaxError("Invalid regular expression: %s", err.Error()[22:])) + panic(runtime.panicSyntaxError("Invalid regular expression: %s", err.Error()[22:])) } self.value = _regExpObject{ @@ -86,11 +86,11 @@ func (self *_object) regExpValue() _regExpObject { func execRegExp(this *_object, target string) (match bool, result []int) { if this.class != "RegExp" { - panic(newTypeError("Calling RegExp.exec on a non-RegExp object")) + panic(this.runtime.panicTypeError("Calling RegExp.exec on a non-RegExp object")) } - lastIndex := toInteger(this.get("lastIndex")).value + lastIndex := this.get("lastIndex").number().int64 index := lastIndex - global := toBoolean(this.get("global")) + global := this.get("global").bool() if !global { index = 0 } @@ -126,7 +126,7 @@ func execResultToArray(runtime *_runtime, target string, result []int) *_object if result[offset] != -1 { valueArray[index] = toValue_string(target[result[offset]:result[offset+1]]) } else { - valueArray[index] = UndefinedValue() + valueArray[index] = Value{} } } matchIndex := result[0] diff --git a/Godeps/_workspace/src/github.com/obscuren/otto/type_string.go b/Godeps/_workspace/src/github.com/robertkrimen/otto/type_string.go index fd93316d1..ef3afa42b 100644 --- a/Godeps/_workspace/src/github.com/obscuren/otto/type_string.go +++ b/Godeps/_workspace/src/github.com/robertkrimen/otto/type_string.go @@ -70,7 +70,7 @@ func stringAt(str _stringObject, index int) rune { } func (runtime *_runtime) newStringObject(value Value) *_object { - str := _newStringObject(toString(value)) + str := _newStringObject(value.string()) self := runtime.newClassObject("String") self.defineProperty("length", toValue_int(str.Length()), 0, false) diff --git a/Godeps/_workspace/src/github.com/obscuren/otto/underscore/Makefile b/Godeps/_workspace/src/github.com/robertkrimen/otto/underscore/Makefile index fc872917f..fc872917f 100644 --- a/Godeps/_workspace/src/github.com/obscuren/otto/underscore/Makefile +++ b/Godeps/_workspace/src/github.com/robertkrimen/otto/underscore/Makefile diff --git a/Godeps/_workspace/src/github.com/obscuren/otto/underscore/README.markdown b/Godeps/_workspace/src/github.com/robertkrimen/otto/underscore/README.markdown index bce37b695..bce37b695 100644 --- a/Godeps/_workspace/src/github.com/obscuren/otto/underscore/README.markdown +++ b/Godeps/_workspace/src/github.com/robertkrimen/otto/underscore/README.markdown diff --git a/Godeps/_workspace/src/github.com/obscuren/otto/underscore/source.go b/Godeps/_workspace/src/github.com/robertkrimen/otto/underscore/source.go index 65754ab71..65754ab71 100644 --- a/Godeps/_workspace/src/github.com/obscuren/otto/underscore/source.go +++ b/Godeps/_workspace/src/github.com/robertkrimen/otto/underscore/source.go diff --git a/Godeps/_workspace/src/github.com/obscuren/otto/underscore/testify b/Godeps/_workspace/src/github.com/robertkrimen/otto/underscore/testify index 7f6e0f7c1..7f6e0f7c1 100644 --- a/Godeps/_workspace/src/github.com/obscuren/otto/underscore/testify +++ b/Godeps/_workspace/src/github.com/robertkrimen/otto/underscore/testify diff --git a/Godeps/_workspace/src/github.com/obscuren/otto/underscore/underscore.go b/Godeps/_workspace/src/github.com/robertkrimen/otto/underscore/underscore.go index 714b8f3cf..714b8f3cf 100644 --- a/Godeps/_workspace/src/github.com/obscuren/otto/underscore/underscore.go +++ b/Godeps/_workspace/src/github.com/robertkrimen/otto/underscore/underscore.go diff --git a/Godeps/_workspace/src/github.com/obscuren/otto/underscore_arrays_test.go b/Godeps/_workspace/src/github.com/robertkrimen/otto/underscore_arrays_test.go index 9d6297820..9d6297820 100644 --- a/Godeps/_workspace/src/github.com/obscuren/otto/underscore_arrays_test.go +++ b/Godeps/_workspace/src/github.com/robertkrimen/otto/underscore_arrays_test.go diff --git a/Godeps/_workspace/src/github.com/obscuren/otto/underscore_chaining_test.go b/Godeps/_workspace/src/github.com/robertkrimen/otto/underscore_chaining_test.go index accf04fdc..accf04fdc 100644 --- a/Godeps/_workspace/src/github.com/obscuren/otto/underscore_chaining_test.go +++ b/Godeps/_workspace/src/github.com/robertkrimen/otto/underscore_chaining_test.go diff --git a/Godeps/_workspace/src/github.com/obscuren/otto/underscore_collections_test.go b/Godeps/_workspace/src/github.com/robertkrimen/otto/underscore_collections_test.go index 9afc2a2b2..9afc2a2b2 100644 --- a/Godeps/_workspace/src/github.com/obscuren/otto/underscore_collections_test.go +++ b/Godeps/_workspace/src/github.com/robertkrimen/otto/underscore_collections_test.go diff --git a/Godeps/_workspace/src/github.com/obscuren/otto/underscore_functions_test.go b/Godeps/_workspace/src/github.com/robertkrimen/otto/underscore_functions_test.go index be59e16b3..be59e16b3 100644 --- a/Godeps/_workspace/src/github.com/obscuren/otto/underscore_functions_test.go +++ b/Godeps/_workspace/src/github.com/robertkrimen/otto/underscore_functions_test.go diff --git a/Godeps/_workspace/src/github.com/obscuren/otto/underscore_objects_test.go b/Godeps/_workspace/src/github.com/robertkrimen/otto/underscore_objects_test.go index ae9c5d5ff..1973af8dd 100644 --- a/Godeps/_workspace/src/github.com/obscuren/otto/underscore_objects_test.go +++ b/Godeps/_workspace/src/github.com/robertkrimen/otto/underscore_objects_test.go @@ -492,7 +492,9 @@ func Test_underscore_objects_11(t *testing.T) { // isElement func Test_underscore_objects_12(t *testing.T) { // TEST: ReferenceError: $ is not defined - return + if true { + return + } tt(t, func() { test, _ := test_() @@ -575,7 +577,9 @@ func Test_underscore_objects_15(t *testing.T) { // isString func Test_underscore_objects_16(t *testing.T) { // TEST: ReferenceError: document is not defined - return + if true { + return + } tt(t, func() { test, _ := test_() diff --git a/Godeps/_workspace/src/github.com/obscuren/otto/underscore_test.go b/Godeps/_workspace/src/github.com/robertkrimen/otto/underscore_test.go index 96c8f2e93..d8bf2da18 100644 --- a/Godeps/_workspace/src/github.com/obscuren/otto/underscore_test.go +++ b/Godeps/_workspace/src/github.com/robertkrimen/otto/underscore_test.go @@ -36,17 +36,17 @@ func (self *_tester) underscore() { } vm.Set("assert", func(call FunctionCall) Value { - if !toBoolean(call.Argument(0)) { + if !call.Argument(0).bool() { message := "Assertion failed" if len(call.ArgumentList) > 1 { - message = toString(call.ArgumentList[1]) + message = call.ArgumentList[1].string() } t := terst.Caller().T() is(message, nil) t.Fail() - return FalseValue() + return falseValue } - return TrueValue() + return trueValue }) vm.Run(` diff --git a/Godeps/_workspace/src/github.com/obscuren/otto/underscore_utility_test.go b/Godeps/_workspace/src/github.com/robertkrimen/otto/underscore_utility_test.go index ebabb083b..ebabb083b 100644 --- a/Godeps/_workspace/src/github.com/obscuren/otto/underscore_utility_test.go +++ b/Godeps/_workspace/src/github.com/robertkrimen/otto/underscore_utility_test.go diff --git a/Godeps/_workspace/src/github.com/obscuren/otto/value.go b/Godeps/_workspace/src/github.com/robertkrimen/otto/value.go index 5944126fd..05d61dd62 100644 --- a/Godeps/_workspace/src/github.com/obscuren/otto/value.go +++ b/Godeps/_workspace/src/github.com/robertkrimen/otto/value.go @@ -8,76 +8,80 @@ import ( "unicode/utf16" ) -type _valueType int +type _valueKind int const ( - valueEmpty _valueType = iota + valueUndefined _valueKind = iota valueNull - valueUndefined valueNumber valueString valueBoolean valueObject + + // These are invalid outside of the runtime + valueEmpty valueResult valueReference ) // Value is the representation of a JavaScript value. type Value struct { - _valueType + kind _valueKind value interface{} } +func (vl Value) safe() bool { + return vl.kind < valueEmpty +} + +var ( + emptyValue = Value{kind: valueEmpty} + nullValue = Value{kind: valueNull} + falseValue = Value{kind: valueBoolean, value: false} + trueValue = Value{kind: valueBoolean, value: true} +) + // ToValue will convert an interface{} value to a value digestible by otto/JavaScript -// This function will not work for advanced types (struct, map, slice/array, etc.) and -// you probably should not use it. -// -// ToValue may be deprecated and removed in the near future. // -// Try Otto.ToValue for a replacement. +// This function will not work for advanced types (struct, map, slice/array, etc.) and +// you should use Otto.ToValue instead. func ToValue(value interface{}) (Value, error) { - result := UndefinedValue() + result := Value{} err := catchPanic(func() { result = toValue(value) }) return result, err } -// Empty - -func emptyValue() Value { - return Value{_valueType: valueEmpty} -} - func (value Value) isEmpty() bool { - return value._valueType == valueEmpty + return value.kind == valueEmpty } // Undefined // UndefinedValue will return a Value representing undefined. func UndefinedValue() Value { - return Value{_valueType: valueUndefined} + return Value{} } // IsDefined will return false if the value is undefined, and true otherwise. func (value Value) IsDefined() bool { - return value._valueType != valueUndefined + return value.kind != valueUndefined } // IsUndefined will return true if the value is undefined, and false otherwise. func (value Value) IsUndefined() bool { - return value._valueType == valueUndefined + return value.kind == valueUndefined } // NullValue will return a Value representing null. func NullValue() Value { - return Value{_valueType: valueNull} + return Value{kind: valueNull} } // IsNull will return true if the value is null, and false otherwise. func (value Value) IsNull() bool { - return value._valueType == valueNull + return value.kind == valueNull } // --- @@ -85,19 +89,11 @@ func (value Value) IsNull() bool { func (value Value) isCallable() bool { switch value := value.value.(type) { case *_object: - return value.functionValue().call != nil + return value.isCall() } return false } -func (value Value) isResult() bool { - return value._valueType == valueResult -} - -func (value Value) isReference() bool { - return value._valueType == valueReference -} - // Call the value as a function with the given this value and argument list and // return the result of invocation. It is essentially equivalent to: // @@ -110,35 +106,45 @@ func (value Value) isReference() bool { // 3. An (uncaught) exception is thrown // func (value Value) Call(this Value, argumentList ...interface{}) (Value, error) { - result := UndefinedValue() + result := Value{} err := catchPanic(func() { - result = value.call(this, argumentList...) + // FIXME + result = value.call(nil, this, argumentList...) }) + if !value.safe() { + value = Value{} + } return result, err } -func (value Value) call(this Value, argumentList ...interface{}) Value { +func (value Value) call(rt *_runtime, this Value, argumentList ...interface{}) Value { switch function := value.value.(type) { case *_object: - return function.Call(this, argumentList...) + return function.call(this, function.runtime.toValueArray(argumentList...), false, nativeFrame) } - panic(newTypeError()) + if rt == nil { + panic("FIXME TypeError") + } + panic(rt.panicTypeError()) } -func (value Value) constructSafe(this Value, argumentList ...interface{}) (Value, error) { - result := UndefinedValue() +func (value Value) constructSafe(rt *_runtime, this Value, argumentList ...interface{}) (Value, error) { + result := Value{} err := catchPanic(func() { - result = value.construct(this, argumentList...) + result = value.construct(rt, this, argumentList...) }) return result, err } -func (value Value) construct(this Value, argumentList ...interface{}) Value { - switch function := value.value.(type) { +func (value Value) construct(rt *_runtime, this Value, argumentList ...interface{}) Value { + switch fn := value.value.(type) { case *_object: - return function.Construct(this, argumentList...) + return fn.construct(fn.runtime.toValueArray(argumentList...)) } - panic(newTypeError()) + if rt == nil { + panic("FIXME TypeError") + } + panic(rt.panicTypeError()) } // IsPrimitive will return true if value is a primitive (any kind of primitive). @@ -148,12 +154,12 @@ func (value Value) IsPrimitive() bool { // IsBoolean will return true if value is a boolean (primitive). func (value Value) IsBoolean() bool { - return value._valueType == valueBoolean + return value.kind == valueBoolean } // IsNumber will return true if value is a number (primitive). func (value Value) IsNumber() bool { - return value._valueType == valueNumber + return value.kind == valueNumber } // IsNaN will return true if value is NaN (or would convert to NaN). @@ -169,22 +175,22 @@ func (value Value) IsNaN() bool { return false } - return math.IsNaN(toFloat(value)) + return math.IsNaN(value.float64()) } // IsString will return true if value is a string (primitive). func (value Value) IsString() bool { - return value._valueType == valueString + return value.kind == valueString } // IsObject will return true if value is an object. func (value Value) IsObject() bool { - return value._valueType == valueObject + return value.kind == valueObject } // IsFunction will return true if value is a function. func (value Value) IsFunction() bool { - if value._valueType != valueObject { + if value.kind != valueObject { return false } return value.value.(*_object).class == "Function" @@ -204,56 +210,56 @@ func (value Value) IsFunction() bool { // RegExp // func (value Value) Class() string { - if value._valueType != valueObject { + if value.kind != valueObject { return "" } return value.value.(*_object).class } func (value Value) isArray() bool { - if value._valueType != valueObject { + if value.kind != valueObject { return false } return isArray(value.value.(*_object)) } func (value Value) isStringObject() bool { - if value._valueType != valueObject { + if value.kind != valueObject { return false } return value.value.(*_object).class == "String" } func (value Value) isBooleanObject() bool { - if value._valueType != valueObject { + if value.kind != valueObject { return false } return value.value.(*_object).class == "Boolean" } func (value Value) isNumberObject() bool { - if value._valueType != valueObject { + if value.kind != valueObject { return false } return value.value.(*_object).class == "Number" } func (value Value) isDate() bool { - if value._valueType != valueObject { + if value.kind != valueObject { return false } return value.value.(*_object).class == "Date" } func (value Value) isRegExp() bool { - if value._valueType != valueObject { + if value.kind != valueObject { return false } return value.value.(*_object).class == "RegExp" } func (value Value) isError() bool { - if value._valueType != valueObject { + if value.kind != valueObject { return false } return value.value.(*_object).class == "Error" @@ -262,13 +268,14 @@ func (value Value) isError() bool { // --- func toValue_reflectValuePanic(value interface{}, kind reflect.Kind) { + // FIXME? switch kind { case reflect.Struct: - panic(newTypeError("Invalid value (struct): Missing runtime: %v (%T)", value, value)) + panic(newError(nil, "TypeError", "invalid value (struct): missing runtime: %v (%T)", value, value)) case reflect.Map: - panic(newTypeError("Invalid value (map): Missing runtime: %v (%T)", value, value)) + panic(newError(nil, "TypeError", "invalid value (map): missing runtime: %v (%T)", value, value)) case reflect.Slice: - panic(newTypeError("Invalid value (slice): Missing runtime: %v (%T)", value, value)) + panic(newError(nil, "TypeError", "invalid value (slice): missing runtime: %v (%T)", value, value)) } } @@ -319,7 +326,7 @@ func toValue(value interface{}) Value { return Value{valueResult, value} case nil: // TODO Ugh. - return UndefinedValue() + return Value{} case reflect.Value: for value.Kind() == reflect.Ptr { // We were given a pointer, so we'll drill down until we get a non-pointer @@ -328,7 +335,7 @@ func toValue(value interface{}) Value { // (It would be best not to depend on this behavior) // FIXME: UNDEFINED if value.IsNil() { - return UndefinedValue() + return Value{} } value = value.Elem() } @@ -367,7 +374,8 @@ func toValue(value interface{}) Value { default: return toValue(reflect.ValueOf(value)) } - panic(newTypeError("Invalid value: Unsupported: %v (%T)", value, value)) + // FIXME? + panic(newError(nil, "TypeError", "invalid value: %v (%T)", value, value)) } // String will return the value as a string. @@ -376,19 +384,11 @@ func toValue(value interface{}) Value { func (value Value) String() string { result := "" catchPanic(func() { - result = value.toString() + result = value.string() }) return result } -func (value Value) toBoolean() bool { - return toBoolean(value) -} - -func (value Value) isTrue() bool { - return toBoolean(value) -} - // ToBoolean will convert the value to a boolean (bool). // // ToValue(0).ToBoolean() => false @@ -401,17 +401,16 @@ func (value Value) isTrue() bool { func (value Value) ToBoolean() (bool, error) { result := false err := catchPanic(func() { - result = toBoolean(value) + result = value.bool() }) return result, err } -func (value Value) toNumber() Value { - return toNumber(value) -} - -func (value Value) toFloat() float64 { - return toFloat(value) +func (value Value) numberValue() Value { + if value.kind == valueNumber { + return value + } + return Value{valueNumber, value.float64()} } // ToFloat will convert the value to a number (float64). @@ -424,7 +423,7 @@ func (value Value) toFloat() float64 { func (value Value) ToFloat() (float64, error) { result := float64(0) err := catchPanic(func() { - result = toFloat(value) + result = value.float64() }) return result, err } @@ -439,15 +438,11 @@ func (value Value) ToFloat() (float64, error) { func (value Value) ToInteger() (int64, error) { result := int64(0) err := catchPanic(func() { - result = toInteger(value).value + result = value.number().int64 }) return result, err } -func (value Value) toString() string { - return toString(value) -} - // ToString will convert the value to a string (string). // // ToValue(0).ToString() => "0" @@ -460,7 +455,7 @@ func (value Value) toString() string { func (value Value) ToString() (string, error) { result := "" err := catchPanic(func() { - result = toString(value) + result = value.string() }) return result, err } @@ -492,6 +487,14 @@ func (value Value) reference() _reference { return nil } +func (value Value) resolve() Value { + switch value := value.value.(type) { + case _reference: + return value.getValue() + } + return value +} + var ( __NaN__ float64 = math.NaN() __PositiveInfinity__ float64 = math.Inf(+1) @@ -563,16 +566,16 @@ func FalseValue() Value { } func sameValue(x Value, y Value) bool { - if x._valueType != y._valueType { + if x.kind != y.kind { return false } result := false - switch x._valueType { + switch x.kind { case valueUndefined, valueNull: result = true case valueNumber: - x := x.toFloat() - y := y.toFloat() + x := x.float64() + y := y.float64() if math.IsNaN(x) && math.IsNaN(y) { result = true } else { @@ -583,9 +586,9 @@ func sameValue(x Value, y Value) bool { } } case valueString: - result = x.toString() == y.toString() + result = x.string() == y.string() case valueBoolean: - result = x.toBoolean() == y.toBoolean() + result = x.bool() == y.bool() case valueObject: result = x._object() == y._object() default: @@ -596,25 +599,25 @@ func sameValue(x Value, y Value) bool { } func strictEqualityComparison(x Value, y Value) bool { - if x._valueType != y._valueType { + if x.kind != y.kind { return false } result := false - switch x._valueType { + switch x.kind { case valueUndefined, valueNull: result = true case valueNumber: - x := x.toFloat() - y := y.toFloat() + x := x.float64() + y := y.float64() if math.IsNaN(x) && math.IsNaN(y) { result = false } else { result = x == y } case valueString: - result = x.toString() == y.toString() + result = x.string() == y.string() case valueBoolean: - result = x.toBoolean() == y.toBoolean() + result = x.bool() == y.bool() case valueObject: result = x._object() == y._object() default: @@ -627,15 +630,14 @@ func strictEqualityComparison(x Value, y Value) bool { // Export will attempt to convert the value to a Go representation // and return it via an interface{} kind. // -// WARNING: The interface function will be changing soon to: -// -// Export() interface{} +// Export returns an error, but it will always be nil. It is present +// for backwards compatibility. // // If a reasonable conversion is not possible, then the original -// result is returned. +// value is returned. // -// undefined -> otto.Value (UndefinedValue()) -// null -> interface{}(nil) +// undefined -> nil (FIXME?: Should be Value{}) +// null -> nil // boolean -> bool // number -> A number type (int, float32, uint64, ...) // string -> string @@ -648,7 +650,7 @@ func (self Value) Export() (interface{}, error) { func (self Value) export() interface{} { - switch self._valueType { + switch self.kind { case valueUndefined: return nil case valueNull: @@ -701,7 +703,11 @@ func (self Value) export() interface{} { } } - return self + if self.safe() { + return self + } + + return Value{} } func (self Value) evaluateBreakContinue(labels []string) _resultKind { @@ -730,7 +736,7 @@ func (self Value) evaluateBreak(labels []string) _resultKind { func (self Value) exportNative() interface{} { - switch self._valueType { + switch self.kind { case valueUndefined: return self case valueNull: @@ -761,80 +767,82 @@ func (self Value) exportNative() interface{} { return self } +// Make a best effort to return a reflect.Value corresponding to reflect.Kind, but +// fallback to just returning the Go value we have handy. func (value Value) toReflectValue(kind reflect.Kind) (reflect.Value, error) { switch kind { - case reflect.Bool: - return reflect.ValueOf(value.toBoolean()), nil - case reflect.Int: + case reflect.Bool: // Bool + return reflect.ValueOf(value.bool()), nil + case reflect.Int: // Int // We convert to float64 here because converting to int64 will not tell us // if a value is outside the range of int64 tmp := toIntegerFloat(value) if tmp < float_minInt || tmp > float_maxInt { - return reflect.Value{}, fmt.Errorf("RangeError: %d (%v) to int", tmp, value) + return reflect.Value{}, fmt.Errorf("RangeError: %f (%v) to int", tmp, value) } else { return reflect.ValueOf(int(tmp)), nil } - case reflect.Int8: - tmp := toInteger(value).value + case reflect.Int8: // Int8 + tmp := value.number().int64 if tmp < int64_minInt8 || tmp > int64_maxInt8 { return reflect.Value{}, fmt.Errorf("RangeError: %d (%v) to int8", tmp, value) } else { return reflect.ValueOf(int8(tmp)), nil } - case reflect.Int16: - tmp := toInteger(value).value + case reflect.Int16: // Int16 + tmp := value.number().int64 if tmp < int64_minInt16 || tmp > int64_maxInt16 { return reflect.Value{}, fmt.Errorf("RangeError: %d (%v) to int16", tmp, value) } else { return reflect.ValueOf(int16(tmp)), nil } - case reflect.Int32: - tmp := toInteger(value).value + case reflect.Int32: // Int32 + tmp := value.number().int64 if tmp < int64_minInt32 || tmp > int64_maxInt32 { return reflect.Value{}, fmt.Errorf("RangeError: %d (%v) to int32", tmp, value) } else { return reflect.ValueOf(int32(tmp)), nil } - case reflect.Int64: + case reflect.Int64: // Int64 // We convert to float64 here because converting to int64 will not tell us // if a value is outside the range of int64 tmp := toIntegerFloat(value) if tmp < float_minInt64 || tmp > float_maxInt64 { - return reflect.Value{}, fmt.Errorf("RangeError: %d (%v) to int", tmp, value) + return reflect.Value{}, fmt.Errorf("RangeError: %f (%v) to int", tmp, value) } else { return reflect.ValueOf(int64(tmp)), nil } - case reflect.Uint: + case reflect.Uint: // Uint // We convert to float64 here because converting to int64 will not tell us // if a value is outside the range of uint tmp := toIntegerFloat(value) if tmp < 0 || tmp > float_maxUint { - return reflect.Value{}, fmt.Errorf("RangeError: %d (%v) to uint", tmp, value) + return reflect.Value{}, fmt.Errorf("RangeError: %f (%v) to uint", tmp, value) } else { return reflect.ValueOf(uint(tmp)), nil } - case reflect.Uint8: - tmp := toInteger(value).value + case reflect.Uint8: // Uint8 + tmp := value.number().int64 if tmp < 0 || tmp > int64_maxUint8 { return reflect.Value{}, fmt.Errorf("RangeError: %d (%v) to uint8", tmp, value) } else { return reflect.ValueOf(uint8(tmp)), nil } - case reflect.Uint16: - tmp := toInteger(value).value + case reflect.Uint16: // Uint16 + tmp := value.number().int64 if tmp < 0 || tmp > int64_maxUint16 { return reflect.Value{}, fmt.Errorf("RangeError: %d (%v) to uint16", tmp, value) } else { return reflect.ValueOf(uint16(tmp)), nil } - case reflect.Uint32: - tmp := toInteger(value).value + case reflect.Uint32: // Uint32 + tmp := value.number().int64 if tmp < 0 || tmp > int64_maxUint32 { return reflect.Value{}, fmt.Errorf("RangeError: %d (%v) to uint32", tmp, value) } else { return reflect.ValueOf(uint32(tmp)), nil } - case reflect.Uint64: + case reflect.Uint64: // Uint64 // We convert to float64 here because converting to int64 will not tell us // if a value is outside the range of uint64 tmp := toIntegerFloat(value) @@ -843,8 +851,8 @@ func (value Value) toReflectValue(kind reflect.Kind) (reflect.Value, error) { } else { return reflect.ValueOf(uint64(tmp)), nil } - case reflect.Float32: - tmp := toFloat(value) + case reflect.Float32: // Float32 + tmp := value.float64() tmp1 := tmp if 0 > tmp1 { tmp1 = -tmp1 @@ -854,17 +862,42 @@ func (value Value) toReflectValue(kind reflect.Kind) (reflect.Value, error) { } else { return reflect.ValueOf(float32(tmp)), nil } - case reflect.Float64: - value := toFloat(value) + case reflect.Float64: // Float64 + value := value.float64() return reflect.ValueOf(float64(value)), nil - case reflect.String: - return reflect.ValueOf(value.toString()), nil - case reflect.Interface: - return reflect.ValueOf(value.exportNative()), nil + case reflect.String: // String + return reflect.ValueOf(value.string()), nil + case reflect.Invalid: // Invalid + case reflect.Complex64: // FIXME? Complex64 + case reflect.Complex128: // FIXME? Complex128 + case reflect.Chan: // FIXME? Chan + case reflect.Func: // FIXME? Func + case reflect.Ptr: // FIXME? Ptr + case reflect.UnsafePointer: // FIXME? UnsafePointer + default: + switch value.kind { + case valueObject: + object := value._object() + switch vl := object.value.(type) { + case *_goStructObject: // Struct + return reflect.ValueOf(vl.value.Interface()), nil + case *_goMapObject: // Map + return reflect.ValueOf(vl.value.Interface()), nil + case *_goArrayObject: // Array + return reflect.ValueOf(vl.value.Interface()), nil + case *_goSliceObject: // Slice + return reflect.ValueOf(vl.value.Interface()), nil + } + return reflect.ValueOf(value.exportNative()), nil + case valueEmpty, valueResult, valueReference: + // These are invalid, and should panic + default: + return reflect.ValueOf(value.value), nil + } } - dbgf("%/panic//%@: Invalid: (%v) to reflect.Kind: %v", value, kind) - panic("") + // FIXME Should this end up as a TypeError? + panic(fmt.Errorf("invalid conversion of %v (%v) to reflect.Kind: %v", value.kind, value, kind)) } func stringToReflectValue(value string, kind reflect.Kind) (reflect.Value, error) { @@ -951,6 +984,6 @@ func stringToReflectValue(value string, kind reflect.Kind) (reflect.Value, error return reflect.ValueOf(value), nil } - dbgf("%/panic//%@: Invalid: \"%s\" to reflect.Kind: %v", value, kind) - panic("") + // FIXME This should end up as a TypeError? + panic(fmt.Errorf("invalid conversion of %q to reflect.Kind: %v", value, kind)) } diff --git a/Godeps/_workspace/src/github.com/obscuren/otto/value_boolean.go b/Godeps/_workspace/src/github.com/robertkrimen/otto/value_boolean.go index da8e951fe..3040f4163 100644 --- a/Godeps/_workspace/src/github.com/obscuren/otto/value_boolean.go +++ b/Godeps/_workspace/src/github.com/robertkrimen/otto/value_boolean.go @@ -6,8 +6,8 @@ import ( "reflect" ) -func toBoolean(value Value) bool { - if value._valueType == valueBoolean { +func (value Value) bool() bool { + if value.kind == valueBoolean { return value.value.(bool) } if value.IsUndefined() { @@ -38,12 +38,3 @@ func toBoolean(value Value) bool { } panic(fmt.Errorf("toBoolean(%T)", value.value)) } - -func stringToBoolean(value string) bool { - if value == "true" { - return true - } else if value == "false" { - return false - } - panic(fmt.Errorf("stringToBoolean(%s)", value)) -} diff --git a/Godeps/_workspace/src/github.com/obscuren/otto/value_number.go b/Godeps/_workspace/src/github.com/robertkrimen/otto/value_number.go index badb3a542..54996c729 100644 --- a/Godeps/_workspace/src/github.com/obscuren/otto/value_number.go +++ b/Godeps/_workspace/src/github.com/robertkrimen/otto/value_number.go @@ -10,7 +10,7 @@ import ( var stringToNumberParseInteger = regexp.MustCompile(`^(?:0[xX])`) -func stringToFloat(value string) float64 { +func parseNumber(value string) float64 { value = strings.TrimSpace(value) if value == "" { @@ -41,15 +41,8 @@ func stringToFloat(value string) float64 { return float64(number) } -func toNumber(value Value) Value { - if value._valueType == valueNumber { - return value - } - return Value{valueNumber, toFloat(value)} -} - -func toFloat(value Value) float64 { - switch value._valueType { +func (value Value) float64() float64 { + switch value.kind { case valueUndefined: return math.NaN() case valueNull: @@ -84,9 +77,9 @@ func toFloat(value Value) float64 { case float64: return value case string: - return stringToFloat(value) + return parseNumber(value) case *_object: - return toFloat(value.DefaultValue(defaultValueHintNumber)) + return value.DefaultValue(defaultValueHintNumber).float64() } panic(fmt.Errorf("toFloat(%T)", value.value)) } @@ -145,7 +138,7 @@ const ( ) func toIntegerFloat(value Value) float64 { - float := value.toFloat() + float := value.float64() if math.IsInf(float, 0) { } else if math.IsNaN(float) { float = 0 @@ -157,92 +150,88 @@ func toIntegerFloat(value Value) float64 { return float } -type _integerKind int +type _numberKind int const ( - integerValid _integerKind = iota // 3.0 => 3.0 - integerFloat // 3.14159 => 3.0 - integerInfinite // Infinity => 2**63-1 - integerInvalid // NaN => 0 + numberInteger _numberKind = iota // 3.0 => 3.0 + numberFloat // 3.14159 => 3.0, 1+2**63 > 2**63-1 + numberInfinity // Infinity => 2**63-1 + numberNaN // NaN => 0 ) -type _integer struct { - _integerKind - value int64 -} - -func (self _integer) valid() bool { - return self._integerKind == integerValid || self._integerKind == integerFloat -} - -func (self _integer) exact() bool { - return self._integerKind == integerValid -} - -func (self _integer) infinite() bool { - return self._integerKind == integerInfinite +type _number struct { + kind _numberKind + int64 int64 + float64 float64 } -func toInteger(value Value) (integer _integer) { - switch value := value.value.(type) { +// FIXME +// http://www.goinggo.net/2013/08/gustavos-ieee-754-brain-teaser.html +// http://bazaar.launchpad.net/~niemeyer/strepr/trunk/view/6/strepr.go#L160 +func (vl Value) number() (number _number) { + switch vl := vl.value.(type) { case int8: - integer.value = int64(value) + number.int64 = int64(vl) return case int16: - integer.value = int64(value) + number.int64 = int64(vl) return case uint8: - integer.value = int64(value) + number.int64 = int64(vl) return case uint16: - integer.value = int64(value) + number.int64 = int64(vl) return case uint32: - integer.value = int64(value) + number.int64 = int64(vl) return case int: - integer.value = int64(value) + number.int64 = int64(vl) return case int64: - integer.value = value + number.int64 = vl return } - { - value := value.toFloat() - if value == 0 { - return - } - if math.IsNaN(value) { - integer._integerKind = integerInvalid - return - } - if math.IsInf(value, 0) { - integer._integerKind = integerInfinite - } - if value >= float_maxInt64 { - integer.value = math.MaxInt64 - return - } - if value <= float_minInt64 { - integer.value = math.MinInt64 - return - } - { - value0 := value - value1 := float64(0) - if value0 > 0 { - value1 = math.Floor(value0) - } else { - value1 = math.Ceil(value0) - } - if value0 != value1 { - integer._integerKind = integerFloat - } - integer.value = int64(value1) - return - } + float := vl.float64() + if float == 0 { + return + } + + number.kind = numberFloat + number.float64 = float + + if math.IsNaN(float) { + number.kind = numberNaN + return + } + + if math.IsInf(float, 0) { + number.kind = numberInfinity + } + + if float >= float_maxInt64 { + number.int64 = math.MaxInt64 + return + } + + if float <= float_minInt64 { + number.int64 = math.MinInt64 + return + } + + integer := float64(0) + if float > 0 { + integer = math.Floor(float) + } else { + integer = math.Ceil(float) + } + + if float == integer { + number.kind = numberInteger } + number.int64 = int64(float) + return } // ECMA 262: 9.5 @@ -257,7 +246,7 @@ func toInt32(value Value) int32 { return value } } - floatValue := value.toFloat() + floatValue := value.float64() if math.IsNaN(floatValue) || math.IsInf(floatValue, 0) { return 0 } @@ -291,7 +280,7 @@ func toUint32(value Value) uint32 { return value } } - floatValue := value.toFloat() + floatValue := value.float64() if math.IsNaN(floatValue) || math.IsInf(floatValue, 0) { return 0 } @@ -318,7 +307,7 @@ func toUint16(value Value) uint16 { return value } } - floatValue := value.toFloat() + floatValue := value.float64() if math.IsNaN(floatValue) || math.IsInf(floatValue, 0) { return 0 } diff --git a/Godeps/_workspace/src/github.com/obscuren/otto/value_primitive.go b/Godeps/_workspace/src/github.com/robertkrimen/otto/value_primitive.go index 1f85fb06b..11ed329d1 100644 --- a/Godeps/_workspace/src/github.com/obscuren/otto/value_primitive.go +++ b/Godeps/_workspace/src/github.com/robertkrimen/otto/value_primitive.go @@ -13,11 +13,11 @@ func toPrimitive(value Value) Value { } func _toPrimitive(value Value, hint _defaultValueHint) Value { - switch value._valueType { + switch value.kind { case valueNull, valueUndefined, valueNumber, valueString, valueBoolean: return value case valueObject: return value._object().DefaultValue(hint) } - panic(hereBeDragons(value._valueType, value)) + panic(hereBeDragons(value.kind, value)) } diff --git a/Godeps/_workspace/src/github.com/obscuren/otto/value_string.go b/Godeps/_workspace/src/github.com/robertkrimen/otto/value_string.go index 39749cce2..0fbfd6b25 100644 --- a/Godeps/_workspace/src/github.com/obscuren/otto/value_string.go +++ b/Godeps/_workspace/src/github.com/robertkrimen/otto/value_string.go @@ -10,6 +10,8 @@ import ( var matchLeading0Exponent = regexp.MustCompile(`([eE][\+\-])0+([1-9])`) // 1e-07 => 1e-7 +// FIXME +// https://code.google.com/p/v8/source/browse/branches/bleeding_edge/src/conversions.cc?spec=svn18082&r=18082 func floatToString(value float64, bitsize int) string { // TODO Fit to ECMA-262 9.8.1 specification if math.IsNaN(value) { @@ -28,7 +30,7 @@ func floatToString(value float64, bitsize int) string { } func numberToStringRadix(value Value, radix int) string { - float := toFloat(value) + float := value.float64() if math.IsNaN(float) { return "NaN" } else if math.IsInf(float, 1) { @@ -42,8 +44,8 @@ func numberToStringRadix(value Value, radix int) string { return strconv.FormatInt(int64(float), radix) } -func toString(value Value) string { - if value._valueType == valueString { +func (value Value) string() string { + if value.kind == valueString { switch value := value.value.(type) { case string: return value @@ -95,7 +97,7 @@ func toString(value Value) string { case string: return value case *_object: - return toString(value.DefaultValue(defaultValueHintString)) + return value.DefaultValue(defaultValueHintString).string() } - panic(fmt.Errorf("toString(%v %T)", value.value, value.value)) + panic(fmt.Errorf("%v.string( %T)", value.value, value.value)) } diff --git a/Godeps/_workspace/src/github.com/obscuren/otto/value_test.go b/Godeps/_workspace/src/github.com/robertkrimen/otto/value_test.go index 23d9fd410..4a9bd546f 100644 --- a/Godeps/_workspace/src/github.com/obscuren/otto/value_test.go +++ b/Godeps/_workspace/src/github.com/robertkrimen/otto/value_test.go @@ -15,13 +15,13 @@ func TestValue(t *testing.T) { is(toValue(false), false) is(toValue(1), 1) - is(toValue(1).toFloat(), float64(1)) + is(toValue(1).float64(), float64(1)) }) } func TestObject(t *testing.T) { tt(t, func() { - is(Value{}.isEmpty(), true) + is(emptyValue.isEmpty(), true) //is(newObject().Value(), "[object]") //is(newBooleanObject(false).Value(), "false") //is(newFunctionObject(nil).Value(), "[function]") @@ -87,7 +87,7 @@ func TestToValue(t *testing.T) { func TestToBoolean(t *testing.T) { tt(t, func() { is := func(left interface{}, right bool) { - is(toValue(left).toBoolean(), right) + is(toValue(left).bool(), right) } is("", false) @@ -104,7 +104,7 @@ func TestToFloat(t *testing.T) { tt(t, func() { { is := func(left interface{}, right float64) { - is(toValue(left).toFloat(), right) + is(toValue(left).float64(), right) } is("", 0) is("xyzzy", math.NaN()) @@ -114,16 +114,16 @@ func TestToFloat(t *testing.T) { is(NullValue(), 0) //is(newObjectValue(), math.NaN()) } - is(math.IsNaN(UndefinedValue().toFloat()), true) + is(math.IsNaN(UndefinedValue().float64()), true) }) } func TestToString(t *testing.T) { tt(t, func() { - is("undefined", UndefinedValue().toString()) - is("null", NullValue().toString()) - is("true", toValue(true).toString()) - is("false", toValue(false).toString()) + is("undefined", UndefinedValue().string()) + is("null", NullValue().string()) + is("true", toValue(true).string()) + is("false", toValue(false).string()) is(UndefinedValue(), "undefined") is(NullValue(), "null") diff --git a/cmd/ethereum/admin.go b/cmd/ethereum/admin.go index 880a22c22..e71a12392 100644 --- a/cmd/ethereum/admin.go +++ b/cmd/ethereum/admin.go @@ -8,13 +8,13 @@ import ( "time" "github.com/ethereum/go-ethereum/cmd/utils" - "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/rpc" "github.com/ethereum/go-ethereum/state" "github.com/ethereum/go-ethereum/xeth" - "github.com/obscuren/otto" + "github.com/robertkrimen/otto" ) /* diff --git a/cmd/ethereum/js.go b/cmd/ethereum/js.go index b4b54b7e6..88d16d6a8 100644 --- a/cmd/ethereum/js.go +++ b/cmd/ethereum/js.go @@ -91,7 +91,14 @@ func newJSRE(ethereum *eth.Ethereum, libPath string) *jsre { func (js *jsre) apiBindings() { ethApi := rpc.NewEthereumApi(js.xeth, js.ethereum.DataDir) - js.re.Bind("jeth", rpc.NewJeth(ethApi, js.re.ToVal)) + //js.re.Bind("jeth", rpc.NewJeth(ethApi, js.re.ToVal)) + + jeth := rpc.NewJeth(ethApi, js.re.ToVal, js.re) + //js.re.Bind("jeth", jeth) + js.re.Set("jeth", struct{}{}) + t, _ := js.re.Get("jeth") + jethObj := t.Object() + jethObj.Set("send", jeth.Send) _, err := js.re.Eval(re.BigNumber_JS) diff --git a/cmd/ethereum/js_test.go b/cmd/ethereum/js_test.go index 0d3c22553..e3806d24d 100644 --- a/cmd/ethereum/js_test.go +++ b/cmd/ethereum/js_test.go @@ -2,7 +2,7 @@ package main import ( "fmt" - "github.com/obscuren/otto" + "github.com/robertkrimen/otto" "os" "path" "testing" diff --git a/common/natspec/natspec.go b/common/natspec/natspec.go index 793bf59ae..8e6568cef 100644 --- a/common/natspec/natspec.go +++ b/common/natspec/natspec.go @@ -2,7 +2,7 @@ package natspec import ( "fmt" - "github.com/obscuren/otto" + "github.com/robertkrimen/otto" ) type NatSpec struct { diff --git a/jsre/jsre.go b/jsre/jsre.go index 31ea955e6..a01fb56d8 100644 --- a/jsre/jsre.go +++ b/jsre/jsre.go @@ -2,7 +2,7 @@ package jsre import ( "fmt" - "github.com/obscuren/otto" + "github.com/robertkrimen/otto" "io/ioutil" "github.com/ethereum/go-ethereum/common" diff --git a/jsre/jsre_test.go b/jsre/jsre_test.go index f01854b51..0327b6586 100644 --- a/jsre/jsre_test.go +++ b/jsre/jsre_test.go @@ -1,7 +1,7 @@ package jsre import ( - "github.com/obscuren/otto" + "github.com/robertkrimen/otto" "testing" "github.com/ethereum/go-ethereum/common" diff --git a/rpc/jeth.go b/rpc/jeth.go index 11d4599c9..4e83be8a6 100644 --- a/rpc/jeth.go +++ b/rpc/jeth.go @@ -3,22 +3,29 @@ package rpc import ( "encoding/json" // "fmt" - "github.com/obscuren/otto" + "github.com/ethereum/go-ethereum/jsre" + "github.com/robertkrimen/otto" ) type Jeth struct { ethApi *EthereumApi toVal func(interface{}) otto.Value + re *jsre.JSRE } -func NewJeth(ethApi *EthereumApi, toVal func(interface{}) otto.Value) *Jeth { - return &Jeth{ethApi, toVal} +func NewJeth(ethApi *EthereumApi, toVal func(interface{}) otto.Value, re *jsre.JSRE) *Jeth { + return &Jeth{ethApi, toVal, re} } -func (self *Jeth) err(code int, msg string, id interface{}) otto.Value { +func (self *Jeth) err(code int, msg string, id interface{}) (response otto.Value) { rpcerr := &RpcErrorObject{code, msg} - rpcresponse := &RpcErrorResponse{Jsonrpc: jsonrpcver, Id: id, Error: rpcerr} - return self.toVal(rpcresponse) + self.re.Set("ret_jsonrpc", jsonrpcver) + self.re.Set("ret_id", id) + self.re.Set("ret_error", rpcerr) + response, _ = self.re.Run(` + ret_response = { jsonrpc: ret_jsonrpc, id: ret_id, error: ret_error }; + `) + return } func (self *Jeth) Send(call otto.FunctionCall) (response otto.Value) { @@ -37,7 +44,11 @@ func (self *Jeth) Send(call otto.FunctionCall) (response otto.Value) { if err != nil { return self.err(-32603, err.Error(), req.Id) } - rpcresponse := &RpcSuccessResponse{Jsonrpc: jsonrpcver, Id: req.Id, Result: respif} - response = self.toVal(rpcresponse) + self.re.Set("ret_jsonrpc", jsonrpcver) + self.re.Set("ret_id", req.Id) + self.re.Set("ret_result", respif) + response, err = self.re.Run(` + ret_response = { jsonrpc: ret_jsonrpc, id: ret_id, result: ret_result }; + `) return } |