diff --git a/.gitignore b/.gitignore index 01ff9608..0dfceb5a 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,4 @@ /test/tester .idea dist/ +.vscode/ diff --git a/.golangci.yml b/.golangci.yml index db29a5a9..733922ab 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -4,6 +4,7 @@ run: - terst skip-files: - dbg/dbg.go + - token/token_const.go linters-settings: govet: @@ -11,25 +12,17 @@ linters-settings: goconst: min-len: 2 min-occurrences: 4 + revive: + enable-all-rules: false + rules: + - name: var-naming + disabled: true linters: enable-all: true disable: - dupl - - gas - - errcheck - - gofmt - - gosimple - - interfacer - - megacheck - - maligned - - structcheck - - staticcheck - - unconvert - - unparam - - varcheck - lll - - prealloc - gochecknoglobals - gochecknoinits - scopelint @@ -39,35 +32,23 @@ linters: - goerr113 - wsl - nlreturn - - tagliatelle - gomnd - paralleltest - wrapcheck - testpackage - - golint - - gofumpt - - forbidigo - gocognit - - gocritic - - godot - - nakedret - nestif - - revive - - errorlint - exhaustive - forcetypeassert - - ifshort - - stylecheck - gocyclo - - misspell - cyclop - varnamelen - - nonamedreturns - maintidx - ireturn - exhaustruct - nosnakecase - - deadcode - dupword - - gci +issues: + exclude-use-default: false + max-same-issues: 0 diff --git a/ast/comments.go b/ast/comments.go index 5c948552..425aa217 100644 --- a/ast/comments.go +++ b/ast/comments.go @@ -6,32 +6,44 @@ import ( "github.com/robertkrimen/otto/file" ) -// CommentPosition determines where the comment is in a given context +// CommentPosition determines where the comment is in a given context. type CommentPosition int +// Available comment positions. const ( - _ CommentPosition = iota - LEADING // Before the pertinent expression - TRAILING // After the pertinent expression - KEY // Before a key in an object - COLON // After a colon in a field declaration - FINAL // Final comments in a block, not belonging to a specific expression or the comment after a trailing , in an array or object literal - IF // After an if keyword - WHILE // After a while keyword - DO // After do keyword - FOR // After a for keyword - WITH // After a with keyword + _ CommentPosition = iota + // LEADING is before the pertinent expression. + LEADING + // TRAILING is after the pertinent expression. + TRAILING + // KEY is before a key in an object. + KEY + // COLON is after a colon in a field declaration. + COLON + // FINAL is the final comments in a block, not belonging to a specific expression or the comment after a trailing , in an array or object literal. + FINAL + // IF is after an if keyword. + IF + // WHILE is after a while keyword. + WHILE + // DO is after do keyword. + DO + // FOR is after a for keyword. + FOR + // WITH is after a with keyword. + WITH + // TBD is unknown. TBD ) -// Comment contains the data of the comment +// Comment contains the data of the comment. type Comment struct { Begin file.Idx Text string Position CommentPosition } -// NewComment creates a new comment +// NewComment creates a new comment. func NewComment(text string, idx file.Idx) *Comment { comment := &Comment{ Begin: idx, @@ -42,7 +54,7 @@ func NewComment(text string, idx file.Idx) *Comment { return comment } -// String returns a stringified version of the position +// String returns a stringified version of the position. func (cp CommentPosition) String() string { switch cp { case LEADING: @@ -70,23 +82,23 @@ func (cp CommentPosition) String() string { } } -// String returns a stringified version of the comment +// String returns a stringified version of the comment. func (c Comment) String() string { return fmt.Sprintf("Comment: %v", c.Text) } -// Comments defines the current view of comments from the parser +// Comments defines the current view of comments from the parser. type Comments struct { // CommentMap is a reference to the parser comment map CommentMap CommentMap // Comments lists the comments scanned, not linked to a node yet Comments []*Comment - // future lists the comments after a line break during a sequence of comments - future []*Comment // Current is node for which comments are linked to Current Expression - // wasLineBreak determines if a line break occured while scanning for comments + // future lists the comments after a line break during a sequence of comments + future []*Comment + // wasLineBreak determines if a line break occurred while scanning for comments wasLineBreak bool // primary determines whether or not processing a primary expression primary bool @@ -94,6 +106,7 @@ type Comments struct { afterBlock bool } +// NewComments returns a new Comments. func NewComments() *Comments { comments := &Comments{ CommentMap: CommentMap{}, @@ -107,7 +120,7 @@ func (c *Comments) String() string { } // FetchAll returns all the currently scanned comments, -// including those from the next line +// including those from the next line. func (c *Comments) FetchAll() []*Comment { defer func() { c.Comments = nil @@ -117,7 +130,7 @@ func (c *Comments) FetchAll() []*Comment { return append(c.Comments, c.future...) } -// Fetch returns all the currently scanned comments +// Fetch returns all the currently scanned comments. func (c *Comments) Fetch() []*Comment { defer func() { c.Comments = nil @@ -126,12 +139,12 @@ func (c *Comments) Fetch() []*Comment { return c.Comments } -// ResetLineBreak marks the beginning of a new statement +// ResetLineBreak marks the beginning of a new statement. func (c *Comments) ResetLineBreak() { c.wasLineBreak = false } -// MarkPrimary will mark the context as processing a primary expression +// MarkPrimary will mark the context as processing a primary expression. func (c *Comments) MarkPrimary() { c.primary = true c.wasLineBreak = false @@ -205,7 +218,7 @@ func (c *Comments) SetExpression(node Expression) { c.applyComments(node, previous, TRAILING) } -// PostProcessNode applies all found comments to the given node +// PostProcessNode applies all found comments to the given node. func (c *Comments) PostProcessNode(node Node) { c.applyComments(node, nil, TRAILING) } @@ -228,15 +241,15 @@ func (c *Comments) applyComments(node, previous Node, position CommentPosition) } } -// AtLineBreak will mark a line break +// AtLineBreak will mark a line break. func (c *Comments) AtLineBreak() { c.wasLineBreak = true } -// CommentMap is the data structure where all found comments are stored +// CommentMap is the data structure where all found comments are stored. type CommentMap map[Node][]*Comment -// AddComment adds a single comment to the map +// AddComment adds a single comment to the map. func (cm CommentMap) AddComment(node Node, comment *Comment) { list := cm[node] list = append(list, comment) @@ -244,7 +257,7 @@ func (cm CommentMap) AddComment(node Node, comment *Comment) { cm[node] = list } -// AddComments adds a slice of comments, given a node and an updated position +// AddComments adds a slice of comments, given a node and an updated position. func (cm CommentMap) AddComments(node Node, comments []*Comment, position CommentPosition) { for _, comment := range comments { if comment.Position == TBD { @@ -254,7 +267,7 @@ func (cm CommentMap) AddComments(node Node, comments []*Comment, position Commen } } -// Size returns the size of the map +// Size returns the size of the map. func (cm CommentMap) Size() int { size := 0 for _, comments := range cm { @@ -264,7 +277,7 @@ func (cm CommentMap) Size() int { return size } -// MoveComments moves comments with a given position from a node to another +// MoveComments moves comments with a given position from a node to another. func (cm CommentMap) MoveComments(from, to Node, position CommentPosition) { for i, c := range cm[from] { if c.Position == position { diff --git a/ast/node.go b/ast/node.go index ad98198e..7cc23443 100644 --- a/ast/node.go +++ b/ast/node.go @@ -1,11 +1,8 @@ -/* -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 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 ( @@ -13,381 +10,929 @@ import ( "github.com/robertkrimen/otto/token" ) -// All nodes implement the Node interface. +// Node is implemented by types that represent a node. 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 // -// ========== // +// Expression is implemented by types that represent an Expression. +type Expression interface { + Node + expression() +} -type ( - // All expression nodes implement the Expression interface. - Expression interface { - Node - _expressionNode() - } +// ArrayLiteral represents an array literal. +type ArrayLiteral struct { + LeftBracket file.Idx + RightBracket file.Idx + Value []Expression +} - ArrayLiteral struct { - LeftBracket file.Idx - RightBracket file.Idx - Value []Expression - } +// Idx0 implements Node. +func (al *ArrayLiteral) Idx0() file.Idx { + return al.LeftBracket +} - AssignExpression struct { - Operator token.Token - Left Expression - Right Expression - } +// Idx1 implements Node. +func (al *ArrayLiteral) Idx1() file.Idx { + return al.RightBracket +} - BadExpression struct { - From file.Idx - To file.Idx - } +// expression implements Expression. +func (*ArrayLiteral) expression() {} - BinaryExpression struct { - Operator token.Token - Left Expression - Right Expression - Comparison bool - } +// AssignExpression represents an assignment expression. +type AssignExpression struct { + Operator token.Token + Left Expression + Right Expression +} - BooleanLiteral struct { - Idx file.Idx - Literal string - Value bool - } +// Idx0 implements Node. +func (ae *AssignExpression) Idx0() file.Idx { + return ae.Left.Idx0() +} - BracketExpression struct { - Left Expression - Member Expression - LeftBracket file.Idx - RightBracket file.Idx - } +// Idx1 implements Node. +func (ae *AssignExpression) Idx1() file.Idx { + return ae.Right.Idx1() +} - CallExpression struct { - Callee Expression - LeftParenthesis file.Idx - ArgumentList []Expression - RightParenthesis file.Idx - } +// expression implements Expression. +func (*AssignExpression) expression() {} - ConditionalExpression struct { - Test Expression - Consequent Expression - Alternate Expression - } +// BadExpression represents a bad expression. +type BadExpression struct { + From file.Idx + To file.Idx +} - DotExpression struct { - Left Expression - Identifier *Identifier - } +// Idx0 implements Node. +func (be *BadExpression) Idx0() file.Idx { + return be.From +} - EmptyExpression struct { - Begin file.Idx - End file.Idx - } +// Idx1 implements Node. +func (be *BadExpression) Idx1() file.Idx { + return be.To +} - FunctionLiteral struct { - Function file.Idx - Name *Identifier - ParameterList *ParameterList - Body Statement - Source string +// expression implements Expression. +func (*BadExpression) expression() {} - DeclarationList []Declaration - } +// BinaryExpression represents a binary expression. +type BinaryExpression struct { + Operator token.Token + Left Expression + Right Expression + Comparison bool +} - Identifier struct { - Name string - Idx file.Idx - } +// Idx0 implements Node. +func (be *BinaryExpression) Idx0() file.Idx { + return be.Left.Idx0() +} - NewExpression struct { - New file.Idx - Callee Expression - LeftParenthesis file.Idx - ArgumentList []Expression - RightParenthesis file.Idx - } +// Idx1 implements Node. +func (be *BinaryExpression) Idx1() file.Idx { + return be.Right.Idx1() +} - NullLiteral struct { - Idx file.Idx - Literal string - } +// expression implements Expression. +func (*BinaryExpression) expression() {} - NumberLiteral struct { - Idx file.Idx - Literal string - Value interface{} - } +// BooleanLiteral represents a boolean expression. +type BooleanLiteral struct { + Idx file.Idx + Literal string + Value bool +} - ObjectLiteral struct { - LeftBrace file.Idx - RightBrace file.Idx - Value []Property - } +// Idx0 implements Node. +func (bl *BooleanLiteral) Idx0() file.Idx { + return bl.Idx +} - ParameterList struct { - Opening file.Idx - List []*Identifier - Closing file.Idx - } +// Idx1 implements Node. +func (bl *BooleanLiteral) Idx1() file.Idx { + return file.Idx(int(bl.Idx) + len(bl.Literal)) +} - Property struct { - Key string - Kind string - Value Expression - } +// expression implements Expression. +func (*BooleanLiteral) expression() {} - RegExpLiteral struct { - Idx file.Idx - Literal string - Pattern string - Flags string - Value string - } +// BracketExpression represents a bracketed expression. +type BracketExpression struct { + Left Expression + Member Expression + LeftBracket file.Idx + RightBracket file.Idx +} - SequenceExpression struct { - Sequence []Expression - } +// Idx0 implements Node. +func (be *BracketExpression) Idx0() file.Idx { + return be.Left.Idx0() +} - StringLiteral struct { - Idx file.Idx - Literal string - Value string - } +// Idx1 implements Node. +func (be *BracketExpression) Idx1() file.Idx { + return be.RightBracket + 1 +} - ThisExpression struct { - Idx file.Idx - } +// expression implements Expression. +func (*BracketExpression) expression() {} - UnaryExpression struct { - Operator token.Token - Idx file.Idx // If a prefix operation - Operand Expression - Postfix bool - } +// CallExpression represents a call expression. +type CallExpression struct { + Callee Expression + LeftParenthesis file.Idx + ArgumentList []Expression + RightParenthesis file.Idx +} - VariableExpression struct { - Name string - Idx file.Idx - Initializer Expression - } -) +// Idx0 implements Node. +func (ce *CallExpression) Idx0() file.Idx { + return ce.Callee.Idx0() +} -// _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 (*EmptyExpression) _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() - } +// Idx1 implements Node. +func (ce *CallExpression) Idx1() file.Idx { + return ce.RightParenthesis + 1 +} - BadStatement struct { - From file.Idx - To file.Idx - } +// expression implements Expression. +func (*CallExpression) expression() {} - BlockStatement struct { - LeftBrace file.Idx - List []Statement - RightBrace file.Idx - } +// ConditionalExpression represents a conditional expression. +type ConditionalExpression struct { + Test Expression + Consequent Expression + Alternate Expression +} - BranchStatement struct { - Idx file.Idx - Token token.Token - Label *Identifier - } +// Idx0 implements Node. +func (ce *ConditionalExpression) Idx0() file.Idx { + return ce.Test.Idx0() +} - CaseStatement struct { - Case file.Idx - Test Expression - Consequent []Statement - } +// Idx1 implements Node. +func (ce *ConditionalExpression) Idx1() file.Idx { + return ce.Test.Idx1() +} - CatchStatement struct { - Catch file.Idx - Parameter *Identifier - Body Statement - } +// expression implements Expression. +func (*ConditionalExpression) expression() {} - DebuggerStatement struct { - Debugger file.Idx - } +// DotExpression represents a dot expression. +type DotExpression struct { + Left Expression + Identifier *Identifier +} - DoWhileStatement struct { - Do file.Idx - Test Expression - Body Statement - } +// Idx0 implements Node. +func (de *DotExpression) Idx0() file.Idx { + return de.Left.Idx0() +} - EmptyStatement struct { - Semicolon file.Idx - } +// Idx1 implements Node. +func (de *DotExpression) Idx1() file.Idx { + return de.Identifier.Idx1() +} - ExpressionStatement struct { - Expression Expression - } +// expression implements Expression. +func (*DotExpression) expression() {} - ForInStatement struct { - For file.Idx - Into Expression - Source Expression - Body Statement - } +// EmptyExpression represents an empty expression. +type EmptyExpression struct { + Begin file.Idx + End file.Idx +} - ForStatement struct { - For file.Idx - Initializer Expression - Update Expression - Test Expression - Body Statement - } +// Idx0 implements Node. +func (ee *EmptyExpression) Idx0() file.Idx { + return ee.Begin +} - FunctionStatement struct { - Function *FunctionLiteral - } +// Idx1 implements Node. +func (ee *EmptyExpression) Idx1() file.Idx { + return ee.End +} - IfStatement struct { - If file.Idx - Test Expression - Consequent Statement - Alternate Statement - } +// expression implements Expression. +func (*EmptyExpression) expression() {} - LabelledStatement struct { - Label *Identifier - Colon file.Idx - Statement Statement - } +// FunctionLiteral represents a function literal. +type FunctionLiteral struct { + Function file.Idx + Name *Identifier + ParameterList *ParameterList + Body Statement + Source string - ReturnStatement struct { - Return file.Idx - Argument Expression - } + DeclarationList []Declaration +} - SwitchStatement struct { - Switch file.Idx - Discriminant Expression - Default int - Body []*CaseStatement - } +// Idx0 implements Node. +func (fl *FunctionLiteral) Idx0() file.Idx { + return fl.Function +} - ThrowStatement struct { - Throw file.Idx - Argument Expression - } +// Idx1 implements Node. +func (fl *FunctionLiteral) Idx1() file.Idx { + return fl.Body.Idx1() +} - TryStatement struct { - Try file.Idx - Body Statement - Catch *CatchStatement - Finally Statement - } +// expression implements Expression. +func (*FunctionLiteral) expression() {} - VariableStatement struct { - Var file.Idx - List []Expression - } +// Identifier represents an identifier. +type Identifier struct { + Name string + Idx file.Idx +} - WhileStatement struct { - While file.Idx - Test Expression - Body Statement - } +// Idx0 implements Node. +func (i *Identifier) Idx0() file.Idx { + return i.Idx +} + +// Idx1 implements Node. +func (i *Identifier) Idx1() file.Idx { + return file.Idx(int(i.Idx) + len(i.Name)) +} + +// expression implements Expression. +func (*Identifier) expression() {} + +// NewExpression represents a new expression. +type NewExpression struct { + New file.Idx + Callee Expression + LeftParenthesis file.Idx + ArgumentList []Expression + RightParenthesis file.Idx +} - WithStatement struct { - With file.Idx - Object Expression - Body Statement +// Idx0 implements Node. +func (ne *NewExpression) Idx0() file.Idx { + return ne.New +} + +// Idx1 implements Node. +func (ne *NewExpression) Idx1() file.Idx { + if ne.RightParenthesis > 0 { + return ne.RightParenthesis + 1 } -) + return ne.Callee.Idx1() +} + +// expression implements Expression. +func (*NewExpression) expression() {} + +// NullLiteral represents a null literal. +type NullLiteral struct { + Idx file.Idx + Literal string +} + +// Idx0 implements Node. +func (nl *NullLiteral) Idx0() file.Idx { + return nl.Idx +} + +// Idx1 implements Node. +func (nl *NullLiteral) Idx1() file.Idx { + return file.Idx(int(nl.Idx) + 4) +} + +// expression implements Expression. +func (*NullLiteral) expression() {} + +// NumberLiteral represents a number literal. +type NumberLiteral struct { + Idx file.Idx + Literal string + Value interface{} +} + +// Idx0 implements Node. +func (nl *NumberLiteral) Idx0() file.Idx { + return nl.Idx +} + +// Idx1 implements Node. +func (nl *NumberLiteral) Idx1() file.Idx { + return file.Idx(int(nl.Idx) + len(nl.Literal)) +} + +// expression implements Expression. +func (*NumberLiteral) expression() {} + +// ObjectLiteral represents an object literal. +type ObjectLiteral struct { + LeftBrace file.Idx + RightBrace file.Idx + Value []Property +} + +// Idx0 implements Node. +func (ol *ObjectLiteral) Idx0() file.Idx { + return ol.LeftBrace +} + +// Idx1 implements Node. +func (ol *ObjectLiteral) Idx1() file.Idx { + return ol.RightBrace +} + +// expression implements Expression. +func (*ObjectLiteral) expression() {} + +// ParameterList represents a parameter list. +type ParameterList struct { + Opening file.Idx + List []*Identifier + Closing file.Idx +} + +// Property represents a property. +type Property struct { + Key string + Kind string + Value Expression +} -// _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 (*FunctionStatement) _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() +// RegExpLiteral represents a regular expression literal. +type RegExpLiteral struct { + Idx file.Idx + Literal string + Pattern string + Flags string + Value string +} + +// Idx0 implements Node. +func (rl *RegExpLiteral) Idx0() file.Idx { + return rl.Idx +} + +// Idx1 implements Node. +func (rl *RegExpLiteral) Idx1() file.Idx { + return file.Idx(int(rl.Idx) + len(rl.Literal)) +} + +// expression implements Expression. +func (*RegExpLiteral) expression() {} + +// SequenceExpression represents a sequence literal. +type SequenceExpression struct { + Sequence []Expression +} + +// Idx0 implements Node. +func (se *SequenceExpression) Idx0() file.Idx { + return se.Sequence[0].Idx0() +} + +// Idx1 implements Node. +func (se *SequenceExpression) Idx1() file.Idx { + return se.Sequence[0].Idx1() +} + +// expression implements Expression. +func (*SequenceExpression) expression() {} + +// StringLiteral represents a string literal. +type StringLiteral struct { + Idx file.Idx + Literal string + Value string +} + +// Idx0 implements Node. +func (sl *StringLiteral) Idx0() file.Idx { + return sl.Idx +} + +// Idx1 implements Node. +func (sl *StringLiteral) Idx1() file.Idx { + return file.Idx(int(sl.Idx) + len(sl.Literal)) +} + +// expression implements Expression. +func (*StringLiteral) expression() {} + +// ThisExpression represents a this expression. +type ThisExpression struct { + Idx file.Idx +} + +// Idx0 implements Node. +func (te *ThisExpression) Idx0() file.Idx { + return te.Idx +} + +// Idx1 implements Node. +func (te *ThisExpression) Idx1() file.Idx { + return te.Idx + 4 +} + +// expression implements Expression. +func (*ThisExpression) expression() {} + +// UnaryExpression represents a unary expression. +type UnaryExpression struct { + Operator token.Token + Idx file.Idx // If a prefix operation + Operand Expression + Postfix bool +} + +// Idx0 implements Node. +func (ue *UnaryExpression) Idx0() file.Idx { + return ue.Idx +} + +// Idx1 implements Node. +func (ue *UnaryExpression) Idx1() file.Idx { + if ue.Postfix { + return ue.Operand.Idx1() + 2 // ++ -- } + return ue.Operand.Idx1() +} + +// expression implements Expression. +func (*UnaryExpression) expression() {} + +// VariableExpression represents a variable expression. +type VariableExpression struct { + Name string + Idx file.Idx + Initializer Expression +} + +// Idx0 implements Node. +func (ve *VariableExpression) Idx0() file.Idx { + return ve.Idx +} - FunctionDeclaration struct { - Function *FunctionLiteral +// Idx1 implements Node. +func (ve *VariableExpression) Idx1() file.Idx { + if ve.Initializer == nil { + return file.Idx(int(ve.Idx) + len(ve.Name) + 1) } + return ve.Initializer.Idx1() +} + +// expression implements Expression. +func (*VariableExpression) expression() {} - VariableDeclaration struct { - Var file.Idx - List []*VariableExpression +// Statement is implemented by types which represent a statement. +type Statement interface { + Node + statement() +} + +// BadStatement represents a bad statement. +type BadStatement struct { + From file.Idx + To file.Idx +} + +// Idx0 implements Node. +func (bs *BadStatement) Idx0() file.Idx { + return bs.From +} + +// Idx1 implements Node. +func (bs *BadStatement) Idx1() file.Idx { + return bs.To +} + +// expression implements Statement. +func (*BadStatement) statement() {} + +// BlockStatement represents a block statement. +type BlockStatement struct { + LeftBrace file.Idx + List []Statement + RightBrace file.Idx +} + +// Idx0 implements Node. +func (bs *BlockStatement) Idx0() file.Idx { + return bs.LeftBrace +} + +// Idx1 implements Node. +func (bs *BlockStatement) Idx1() file.Idx { + return bs.RightBrace + 1 +} + +// expression implements Statement. +func (*BlockStatement) statement() {} + +// BranchStatement represents a branch statement. +type BranchStatement struct { + Idx file.Idx + Token token.Token + Label *Identifier +} + +// Idx1 implements Node. +func (bs *BranchStatement) Idx1() file.Idx { + return bs.Idx +} + +// Idx0 implements Node. +func (bs *BranchStatement) Idx0() file.Idx { + return bs.Idx +} + +// expression implements Statement. +func (*BranchStatement) statement() {} + +// CaseStatement represents a case statement. +type CaseStatement struct { + Case file.Idx + Test Expression + Consequent []Statement +} + +// Idx0 implements Node. +func (cs *CaseStatement) Idx0() file.Idx { + return cs.Case +} + +// Idx1 implements Node. +func (cs *CaseStatement) Idx1() file.Idx { + return cs.Consequent[len(cs.Consequent)-1].Idx1() +} + +// expression implements Statement. +func (*CaseStatement) statement() {} + +// CatchStatement represents a catch statement. +type CatchStatement struct { + Catch file.Idx + Parameter *Identifier + Body Statement +} + +// Idx0 implements Node. +func (cs *CatchStatement) Idx0() file.Idx { + return cs.Catch +} + +// Idx1 implements Node. +func (cs *CatchStatement) Idx1() file.Idx { + return cs.Body.Idx1() +} + +// expression implements Statement. +func (*CatchStatement) statement() {} + +// DebuggerStatement represents a debugger statement. +type DebuggerStatement struct { + Debugger file.Idx +} + +// Idx0 implements Node. +func (ds *DebuggerStatement) Idx0() file.Idx { + return ds.Debugger +} + +// Idx1 implements Node. +func (ds *DebuggerStatement) Idx1() file.Idx { + return ds.Debugger + 8 +} + +// expression implements Statement. +func (*DebuggerStatement) statement() {} + +// DoWhileStatement represents a do while statement. +type DoWhileStatement struct { + Do file.Idx + Test Expression + Body Statement +} + +// Idx0 implements Node. +func (dws *DoWhileStatement) Idx0() file.Idx { + return dws.Do +} + +// Idx1 implements Node. +func (dws *DoWhileStatement) Idx1() file.Idx { + return dws.Test.Idx1() +} + +// expression implements Statement. +func (*DoWhileStatement) statement() {} + +// EmptyStatement represents a empty statement. +type EmptyStatement struct { + Semicolon file.Idx +} + +// Idx0 implements Node. +func (es *EmptyStatement) Idx0() file.Idx { + return es.Semicolon +} + +// Idx1 implements Node. +func (es *EmptyStatement) Idx1() file.Idx { + return es.Semicolon + 1 +} + +// expression implements Statement. +func (*EmptyStatement) statement() {} + +// ExpressionStatement represents a expression statement. +type ExpressionStatement struct { + Expression Expression +} + +// Idx0 implements Node. +func (es *ExpressionStatement) Idx0() file.Idx { + return es.Expression.Idx0() +} + +// Idx1 implements Node. +func (es *ExpressionStatement) Idx1() file.Idx { + return es.Expression.Idx1() +} + +// expression implements Statement. +func (*ExpressionStatement) statement() {} + +// ForInStatement represents a for in statement. +type ForInStatement struct { + For file.Idx + Into Expression + Source Expression + Body Statement +} + +// Idx0 implements Node. +func (fis *ForInStatement) Idx0() file.Idx { + return fis.For +} + +// Idx1 implements Node. +func (fis *ForInStatement) Idx1() file.Idx { + return fis.Body.Idx1() +} + +// expression implements Statement. +func (*ForInStatement) statement() {} + +// ForStatement represents a for statement. +type ForStatement struct { + For file.Idx + Initializer Expression + Update Expression + Test Expression + Body Statement +} + +// Idx0 implements Node. +func (fs *ForStatement) Idx0() file.Idx { + return fs.For +} + +// Idx1 implements Node. +func (fs *ForStatement) Idx1() file.Idx { + return fs.Body.Idx1() +} + +// expression implements Statement. +func (*ForStatement) statement() {} + +// FunctionStatement represents a function statement. +type FunctionStatement struct { + Function *FunctionLiteral +} + +// Idx0 implements Node. +func (fs *FunctionStatement) Idx0() file.Idx { + return fs.Function.Idx0() +} + +// Idx1 implements Node. +func (fs *FunctionStatement) Idx1() file.Idx { + return fs.Function.Idx1() +} + +// expression implements Statement. +func (*FunctionStatement) statement() {} + +// IfStatement represents a if statement. +type IfStatement struct { + If file.Idx + Test Expression + Consequent Statement + Alternate Statement +} + +// Idx0 implements Node. +func (is *IfStatement) Idx0() file.Idx { + return is.If +} + +// Idx1 implements Node. +func (is *IfStatement) Idx1() file.Idx { + if is.Alternate != nil { + return is.Alternate.Idx1() } -) + return is.Consequent.Idx1() +} + +// expression implements Statement. +func (*IfStatement) statement() {} + +// LabelledStatement represents a labelled statement. +type LabelledStatement struct { + Label *Identifier + Colon file.Idx + Statement Statement +} + +// Idx0 implements Node. +func (ls *LabelledStatement) Idx0() file.Idx { + return ls.Label.Idx0() +} + +// Idx1 implements Node. +func (ls *LabelledStatement) Idx1() file.Idx { + return ls.Colon + 1 +} + +// expression implements Statement. +func (*LabelledStatement) statement() {} + +// ReturnStatement represents a return statement. +type ReturnStatement struct { + Return file.Idx + Argument Expression +} + +// Idx0 implements Node. +func (rs *ReturnStatement) Idx0() file.Idx { + return rs.Return +} + +// Idx1 implements Node. +func (rs *ReturnStatement) Idx1() file.Idx { + return rs.Return +} + +// expression implements Statement. +func (*ReturnStatement) statement() {} + +// SwitchStatement represents a switch statement. +type SwitchStatement struct { + Switch file.Idx + Discriminant Expression + Default int + Body []*CaseStatement +} + +// Idx0 implements Node. +func (ss *SwitchStatement) Idx0() file.Idx { + return ss.Switch +} + +// Idx1 implements Node. +func (ss *SwitchStatement) Idx1() file.Idx { + return ss.Body[len(ss.Body)-1].Idx1() +} + +// expression implements Statement. +func (*SwitchStatement) statement() {} + +// ThrowStatement represents a throw statement. +type ThrowStatement struct { + Throw file.Idx + Argument Expression +} + +// Idx0 implements Node. +func (ts *ThrowStatement) Idx0() file.Idx { + return ts.Throw +} + +// Idx1 implements Node. +func (ts *ThrowStatement) Idx1() file.Idx { + return ts.Throw +} -// _declarationNode +// expression implements Statement. +func (*ThrowStatement) statement() {} -func (*FunctionDeclaration) _declarationNode() {} -func (*VariableDeclaration) _declarationNode() {} +// TryStatement represents a try statement. +type TryStatement struct { + Try file.Idx + Body Statement + Catch *CatchStatement + Finally Statement +} + +// Idx0 implements Node. +func (ts *TryStatement) Idx0() file.Idx { + return ts.Try +} + +// Idx1 implements Node. +func (ts *TryStatement) Idx1() file.Idx { + return ts.Try +} + +// expression implements Statement. +func (*TryStatement) statement() {} + +// VariableStatement represents a variable statement. +type VariableStatement struct { + Var file.Idx + List []Expression +} + +// Idx0 implements Node. +func (vs *VariableStatement) Idx0() file.Idx { + return vs.Var +} + +// Idx1 implements Node. +func (vs *VariableStatement) Idx1() file.Idx { + return vs.List[len(vs.List)-1].Idx1() +} + +// expression implements Statement. +func (*VariableStatement) statement() {} + +// WhileStatement represents a while statement. +type WhileStatement struct { + While file.Idx + Test Expression + Body Statement +} + +// Idx0 implements Node. +func (ws *WhileStatement) Idx0() file.Idx { + return ws.While +} + +// Idx1 implements Node. +func (ws *WhileStatement) Idx1() file.Idx { + return ws.Body.Idx1() +} + +// expression implements Statement. +func (*WhileStatement) statement() {} -// ==== // -// Node // -// ==== // +// WithStatement represents a with statement. +type WithStatement struct { + With file.Idx + Object Expression + Body Statement +} + +// Idx0 implements Node. +func (ws *WithStatement) Idx0() file.Idx { + return ws.With +} + +// Idx1 implements Node. +func (ws *WithStatement) Idx1() file.Idx { + return ws.Body.Idx1() +} + +// expression implements Statement. +func (*WithStatement) statement() {} + +// Declaration is implemented by type which represent declarations. +type Declaration interface { + declaration() +} + +// FunctionDeclaration represents a function declaration. +type FunctionDeclaration struct { + Function *FunctionLiteral +} +func (*FunctionDeclaration) declaration() {} + +// VariableDeclaration represents a variable declaration. +type VariableDeclaration struct { + Var file.Idx + List []*VariableExpression +} + +// declaration implements Declaration. +func (*VariableDeclaration) declaration() {} + +// Program represents a full program. type Program struct { Body []Statement @@ -398,122 +943,12 @@ type Program struct { Comments CommentMap } -// ==== // -// 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 *EmptyExpression) Idx0() file.Idx { return self.Begin } -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 *FunctionStatement) Idx0() file.Idx { return self.Function.Idx0() } -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 *EmptyExpression) Idx1() file.Idx { return self.End } -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 { - if self.RightParenthesis > 0 { - return self.RightParenthesis + 1 - } - return self.Callee.Idx1() -} -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 + 4 } -func (self *UnaryExpression) Idx1() file.Idx { - if self.Postfix { - return self.Operand.Idx1() + 2 // ++ -- - } - return self.Operand.Idx1() +// Idx0 implements Node. +func (p *Program) Idx0() file.Idx { + return p.Body[0].Idx0() +} + +// Idx1 implements Node. +func (p *Program) Idx1() file.Idx { + return p.Body[len(p.Body)-1].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 *FunctionStatement) Idx1() file.Idx { return self.Function.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/ast/walk_test.go b/ast/walk_test.go index f063a181..1748c67d 100644 --- a/ast/walk_test.go +++ b/ast/walk_test.go @@ -30,8 +30,7 @@ func (w *walker) pop(n ast.Node) { panic("pop of empty stack") } - toPop := w.stack[size-1] - if toPop != n { + if toPop := w.stack[size-1]; toPop != n { panic("pop: nodes do not equal") } diff --git a/builtin.go b/builtin.go index b178d505..3e63dca6 100644 --- a/builtin.go +++ b/builtin.go @@ -2,6 +2,7 @@ package otto import ( "encoding/hex" + "errors" "math" "net/url" "regexp" @@ -11,34 +12,34 @@ import ( "unicode/utf8" ) -// Global -func builtinGlobal_eval(call FunctionCall) Value { +// Global. +func builtinGlobalEval(call FunctionCall) Value { src := call.Argument(0) if !src.IsString() { return src } - runtime := call.runtime - program := runtime.cmpl_parseOrThrow(src.string(), nil) + rt := call.runtime + program := rt.cmplParseOrThrow(src.string(), nil) if !call.eval { // Not a direct call to eval, so we enter the global ExecutionContext - runtime.enterGlobalScope() - defer runtime.leaveScope() + rt.enterGlobalScope() + defer rt.leaveScope() } - returnValue := runtime.cmpl_evaluate_nodeProgram(program, true) + returnValue := rt.cmplEvaluateNodeProgram(program, true) if returnValue.isEmpty() { return Value{} } return returnValue } -func builtinGlobal_isNaN(call FunctionCall) Value { +func builtinGlobalIsNaN(call FunctionCall) Value { value := call.Argument(0).float64() - return toValue_bool(math.IsNaN(value)) + return boolValue(math.IsNaN(value)) } -func builtinGlobal_isFinite(call FunctionCall) Value { +func builtinGlobalIsFinite(call FunctionCall) Value { value := call.Argument(0).float64() - return toValue_bool(!math.IsNaN(value) && !math.IsInf(value, 0)) + return boolValue(!math.IsNaN(value) && !math.IsInf(value, 0)) } func digitValue(chr rune) int { @@ -53,8 +54,8 @@ func digitValue(chr rune) int { return 36 // Larger than any legal digit value } -func builtinGlobal_parseInt(call FunctionCall) Value { - input := strings.Trim(call.Argument(0).string(), builtinString_trim_whitespace) +func builtinGlobalParseInt(call FunctionCall) Value { + input := strings.Trim(call.Argument(0).string(), builtinStringTrimWhitespace) if len(input) == 0 { return NaNValue() } @@ -106,7 +107,7 @@ func builtinGlobal_parseInt(call FunctionCall) Value { value, err := strconv.ParseInt(input, radix, 64) if err != nil { - if err.(*strconv.NumError).Err == strconv.ErrRange { + if errors.Is(err, strconv.ErrRange) { base := float64(base) // Could just be a very large number (e.g. 0x8000000000000000) var value float64 @@ -120,7 +121,7 @@ func builtinGlobal_parseInt(call FunctionCall) Value { if negative { value *= -1 } - return toValue_float64(value) + return float64Value(value) } return NaNValue() } @@ -128,24 +129,26 @@ func builtinGlobal_parseInt(call FunctionCall) Value { value *= -1 } - return toValue_int64(value) + return int64Value(value) } -var parseFloat_matchBadSpecial = regexp.MustCompile(`[\+\-]?(?:[Ii]nf$|infinity)`) -var parseFloat_matchValid = regexp.MustCompile(`[0-9eE\+\-\.]|Infinity`) +var ( + parseFloatMatchBadSpecial = regexp.MustCompile(`[\+\-]?(?:[Ii]nf$|infinity)`) + parseFloatMatchValid = regexp.MustCompile(`[0-9eE\+\-\.]|Infinity`) +) -func builtinGlobal_parseFloat(call FunctionCall) Value { +func builtinGlobalParseFloat(call FunctionCall) Value { // Caveat emptor: This implementation does NOT match the specification - input := strings.Trim(call.Argument(0).string(), builtinString_trim_whitespace) + input := strings.Trim(call.Argument(0).string(), builtinStringTrimWhitespace) - if parseFloat_matchBadSpecial.MatchString(input) { + if parseFloatMatchBadSpecial.MatchString(input) { return NaNValue() } value, err := strconv.ParseFloat(input, 64) if err != nil { for end := len(input); end > 0; end-- { input := input[0:end] - if !parseFloat_matchValid.MatchString(input) { + if !parseFloatMatchValid.MatchString(input) { return NaNValue() } value, err = strconv.ParseFloat(input, 64) @@ -157,12 +160,12 @@ func builtinGlobal_parseFloat(call FunctionCall) Value { return NaNValue() } } - return toValue_float64(value) + return float64Value(value) } // encodeURI/decodeURI -func _builtinGlobal_encodeURI(call FunctionCall, escape *regexp.Regexp) Value { +func encodeDecodeURI(call FunctionCall, escape *regexp.Regexp) Value { value := call.Argument(0) var input []uint16 switch vl := value.value.(type) { @@ -172,7 +175,7 @@ func _builtinGlobal_encodeURI(call FunctionCall, escape *regexp.Regexp) Value { input = utf16.Encode([]rune(value.string())) } if len(input) == 0 { - return toValue_string("") + return stringValue("") } output := []byte{} length := len(input) @@ -184,7 +187,7 @@ func _builtinGlobal_encodeURI(call FunctionCall, escape *regexp.Regexp) Value { panic(call.runtime.panicURIError("URI malformed")) } if value >= 0xD800 && value <= 0xDBFF { - index += 1 + index++ if index >= length { panic(call.runtime.panicURIError("URI malformed")) } @@ -195,43 +198,42 @@ func _builtinGlobal_encodeURI(call FunctionCall, escape *regexp.Regexp) Value { } decode = []rune{((rune(value) - 0xD800) * 0x400) + (rune(value1) - 0xDC00) + 0x10000} } - index += 1 + index++ size := utf8.EncodeRune(encode, decode[0]) encode := encode[0:size] output = append(output, encode...) } - { - value := escape.ReplaceAllFunc(output, func(target []byte) []byte { - // Probably a better way of doing this - if target[0] == ' ' { - return []byte("%20") - } - return []byte(url.QueryEscape(string(target))) - }) - return toValue_string(string(value)) - } + + bytes := escape.ReplaceAllFunc(output, func(target []byte) []byte { + // Probably a better way of doing this + if target[0] == ' ' { + return []byte("%20") + } + return []byte(url.QueryEscape(string(target))) + }) + return stringValue(string(bytes)) } -var encodeURI_Regexp = regexp.MustCompile(`([^~!@#$&*()=:/,;?+'])`) +var encodeURIRegexp = regexp.MustCompile(`([^~!@#$&*()=:/,;?+'])`) -func builtinGlobal_encodeURI(call FunctionCall) Value { - return _builtinGlobal_encodeURI(call, encodeURI_Regexp) +func builtinGlobalEncodeURI(call FunctionCall) Value { + return encodeDecodeURI(call, encodeURIRegexp) } -var encodeURIComponent_Regexp = regexp.MustCompile(`([^~!*()'])`) +var encodeURIComponentRegexp = regexp.MustCompile(`([^~!*()'])`) -func builtinGlobal_encodeURIComponent(call FunctionCall) Value { - return _builtinGlobal_encodeURI(call, encodeURIComponent_Regexp) +func builtinGlobalEncodeURIComponent(call FunctionCall) Value { + return encodeDecodeURI(call, encodeURIComponentRegexp) } -// 3B/2F/3F/3A/40/26/3D/2B/24/2C/23 -var decodeURI_guard = regexp.MustCompile(`(?i)(?:%)(3B|2F|3F|3A|40|26|3D|2B|24|2C|23)`) +// 3B/2F/3F/3A/40/26/3D/2B/24/2C/23. +var decodeURIGuard = regexp.MustCompile(`(?i)(?:%)(3B|2F|3F|3A|40|26|3D|2B|24|2C|23)`) -func _decodeURI(input string, reserve bool) (string, bool) { +func decodeURI(input string, reserve bool) (string, bool) { if reserve { - input = decodeURI_guard.ReplaceAllString(input, "%25$1") + input = decodeURIGuard.ReplaceAllString(input, "%25$1") } - input = strings.Replace(input, "+", "%2B", -1) // Ugly hack to make QueryUnescape work with our use case + input = strings.ReplaceAll(input, "+", "%2B") // Ugly hack to make QueryUnescape work with our use case output, err := url.QueryUnescape(input) if err != nil || !utf8.ValidString(output) { return "", true @@ -239,25 +241,25 @@ func _decodeURI(input string, reserve bool) (string, bool) { return output, false } -func builtinGlobal_decodeURI(call FunctionCall) Value { - output, err := _decodeURI(call.Argument(0).string(), true) +func builtinGlobalDecodeURI(call FunctionCall) Value { + output, err := decodeURI(call.Argument(0).string(), true) if err { panic(call.runtime.panicURIError("URI malformed")) } - return toValue_string(output) + return stringValue(output) } -func builtinGlobal_decodeURIComponent(call FunctionCall) Value { - output, err := _decodeURI(call.Argument(0).string(), false) +func builtinGlobalDecodeURIComponent(call FunctionCall) Value { + output, err := decodeURI(call.Argument(0).string(), false) if err { panic(call.runtime.panicURIError("URI malformed")) } - return toValue_string(output) + return stringValue(output) } // escape/unescape -func builtin_shouldEscape(chr byte) bool { +func builtinShouldEscape(chr byte) bool { if 'A' <= chr && chr <= 'Z' || 'a' <= chr && chr <= 'z' || '0' <= chr && chr <= '9' { return false } @@ -266,11 +268,11 @@ func builtin_shouldEscape(chr byte) bool { const escapeBase16 = "0123456789ABCDEF" -func builtin_escape(input string) string { +func builtinEscape(input string) string { output := make([]byte, 0, len(input)) length := len(input) for index := 0; index < length; { - if builtin_shouldEscape(input[index]) { + if builtinShouldEscape(input[index]) { chr, width := utf8.DecodeRuneInString(input[index:]) chr16 := utf16.Encode([]rune{chr})[0] if 256 > chr16 { @@ -289,13 +291,13 @@ func builtin_escape(input string) string { index += width } else { output = append(output, input[index]) - index += 1 + index++ } } return string(output) } -func builtin_unescape(input string) string { +func builtinUnescape(input string) string { output := make([]rune, 0, len(input)) length := len(input) for index := 0; index < length; { @@ -322,15 +324,15 @@ func builtin_unescape(input string) string { } } output = append(output, rune(input[index])) - index += 1 + index++ } return string(output) } -func builtinGlobal_escape(call FunctionCall) Value { - return toValue_string(builtin_escape(call.Argument(0).string())) +func builtinGlobalEscape(call FunctionCall) Value { + return stringValue(builtinEscape(call.Argument(0).string())) } -func builtinGlobal_unescape(call FunctionCall) Value { - return toValue_string(builtin_unescape(call.Argument(0).string())) +func builtinGlobalUnescape(call FunctionCall) Value { + return stringValue(builtinUnescape(call.Argument(0).string())) } diff --git a/builtin_array.go b/builtin_array.go index 20e89ee5..2744bca0 100644 --- a/builtin_array.go +++ b/builtin_array.go @@ -8,92 +8,93 @@ import ( // Array func builtinArray(call FunctionCall) Value { - return toValue_object(builtinNewArrayNative(call.runtime, call.ArgumentList)) + return objectValue(builtinNewArrayNative(call.runtime, call.ArgumentList)) } -func builtinNewArray(self *_object, argumentList []Value) Value { - return toValue_object(builtinNewArrayNative(self.runtime, argumentList)) +func builtinNewArray(obj *object, argumentList []Value) Value { + return objectValue(builtinNewArrayNative(obj.runtime, argumentList)) } -func builtinNewArrayNative(runtime *_runtime, argumentList []Value) *_object { +func builtinNewArrayNative(rt *runtime, argumentList []Value) *object { if len(argumentList) == 1 { firstArgument := argumentList[0] if firstArgument.IsNumber() { - return runtime.newArray(arrayUint32(runtime, firstArgument)) + return rt.newArray(arrayUint32(rt, firstArgument)) } } - return runtime.newArrayOf(argumentList) + return rt.newArrayOf(argumentList) } -func builtinArray_toString(call FunctionCall) Value { +func builtinArrayToString(call FunctionCall) Value { thisObject := call.thisObject() join := thisObject.get("join") if join.isCallable() { - join := join._object() + join := join.object() return join.call(call.This, call.ArgumentList, false, nativeFrame) } - return builtinObject_toString(call) + return builtinObjectToString(call) } -func builtinArray_toLocaleString(call FunctionCall) Value { +func builtinArrayToLocaleString(call FunctionCall) Value { separator := "," thisObject := call.thisObject() length := int64(toUint32(thisObject.get(propertyLength))) if length == 0 { - return toValue_string("") + return stringValue("") } stringList := make([]string, 0, length) - for index := int64(0); index < length; index += 1 { + for index := int64(0); index < length; index++ { value := thisObject.get(arrayIndexToString(index)) stringValue := "" switch value.kind { case valueEmpty, valueUndefined, valueNull: default: - object := call.runtime.toObject(value) - toLocaleString := object.get("toLocaleString") + obj := call.runtime.toObject(value) + toLocaleString := obj.get("toLocaleString") if !toLocaleString.isCallable() { panic(call.runtime.panicTypeError()) } - stringValue = toLocaleString.call(call.runtime, toValue_object(object)).string() + stringValue = toLocaleString.call(call.runtime, objectValue(obj)).string() } stringList = append(stringList, stringValue) } - return toValue_string(strings.Join(stringList, separator)) + return stringValue(strings.Join(stringList, separator)) } -func builtinArray_concat(call FunctionCall) Value { +func builtinArrayConcat(call FunctionCall) Value { thisObject := call.thisObject() valueArray := []Value{} - source := append([]Value{toValue_object(thisObject)}, call.ArgumentList...) + source := append([]Value{objectValue(thisObject)}, call.ArgumentList...) for _, item := range source { switch item.kind { case valueObject: - object := item._object() - if isArray(object) { - length := object.get(propertyLength).number().int64 - for index := int64(0); index < length; index += 1 { + obj := item.object() + if isArray(obj) { + length := obj.get(propertyLength).number().int64 + for index := int64(0); index < length; index++ { name := strconv.FormatInt(index, 10) - if object.hasProperty(name) { - valueArray = append(valueArray, object.get(name)) + if obj.hasProperty(name) { + valueArray = append(valueArray, obj.get(name)) } else { valueArray = append(valueArray, Value{}) } } continue } + fallthrough default: valueArray = append(valueArray, item) } } - return toValue_object(call.runtime.newArrayOf(valueArray)) + return objectValue(call.runtime.newArrayOf(valueArray)) } -func builtinArray_shift(call FunctionCall) Value { +func builtinArrayShift(call FunctionCall) Value { thisObject := call.thisObject() length := int64(toUint32(thisObject.get(propertyLength))) - if 0 == length { - thisObject.put(propertyLength, toValue_int64(0), true) + if length == 0 { + thisObject.put(propertyLength, int64Value(0), true) return Value{} } first := thisObject.get("0") @@ -107,52 +108,50 @@ func builtinArray_shift(call FunctionCall) Value { } } thisObject.delete(arrayIndexToString(length-1), true) - thisObject.put(propertyLength, toValue_int64(length-1), true) + thisObject.put(propertyLength, int64Value(length-1), true) return first } -func builtinArray_push(call FunctionCall) Value { +func builtinArrayPush(call FunctionCall) Value { thisObject := call.thisObject() itemList := call.ArgumentList index := int64(toUint32(thisObject.get(propertyLength))) for len(itemList) > 0 { thisObject.put(arrayIndexToString(index), itemList[0], true) itemList = itemList[1:] - index += 1 + index++ } - length := toValue_int64(index) + length := int64Value(index) thisObject.put(propertyLength, length, true) return length } -func builtinArray_pop(call FunctionCall) Value { +func builtinArrayPop(call FunctionCall) Value { thisObject := call.thisObject() length := int64(toUint32(thisObject.get(propertyLength))) - if 0 == length { - thisObject.put(propertyLength, toValue_uint32(0), true) + if length == 0 { + thisObject.put(propertyLength, uint32Value(0), true) return Value{} } last := thisObject.get(arrayIndexToString(length - 1)) thisObject.delete(arrayIndexToString(length-1), true) - thisObject.put(propertyLength, toValue_int64(length-1), true) + thisObject.put(propertyLength, int64Value(length-1), true) return last } -func builtinArray_join(call FunctionCall) Value { +func builtinArrayJoin(call FunctionCall) Value { separator := "," - { - argument := call.Argument(0) - if argument.IsDefined() { - separator = argument.string() - } + argument := call.Argument(0) + if argument.IsDefined() { + separator = argument.string() } thisObject := call.thisObject() length := int64(toUint32(thisObject.get(propertyLength))) if length == 0 { - return toValue_string("") + return stringValue("") } stringList := make([]string, 0, length) - for index := int64(0); index < length; index += 1 { + for index := int64(0); index < length; index++ { value := thisObject.get(arrayIndexToString(index)) stringValue := "" switch value.kind { @@ -162,10 +161,10 @@ func builtinArray_join(call FunctionCall) Value { } stringList = append(stringList, stringValue) } - return toValue_string(strings.Join(stringList, separator)) + return stringValue(strings.Join(stringList, separator)) } -func builtinArray_splice(call FunctionCall) Value { +func builtinArraySplice(call FunctionCall) Value { thisObject := call.thisObject() length := int64(toUint32(thisObject.get(propertyLength))) @@ -177,7 +176,7 @@ func builtinArray_splice(call FunctionCall) Value { valueArray := make([]Value, deleteCount) for index := int64(0); index < deleteCount; index++ { - indexString := arrayIndexToString(int64(start + index)) + indexString := arrayIndexToString(start + index) if thisObject.hasProperty(indexString) { valueArray[index] = thisObject.get(indexString) } @@ -197,7 +196,7 @@ func builtinArray_splice(call FunctionCall) Value { } if itemCount < deleteCount { // The Object/Array is shrinking - stop := int64(length) - deleteCount + stop := length - deleteCount // The new length of the Object/Array before // appending the itemList remainder // Stopping at the lower bound of the insertion: @@ -215,7 +214,7 @@ func builtinArray_splice(call FunctionCall) Value { // Delete off the end // We don't bother to delete below (if any) since those // will be overwritten anyway - for index := int64(length); index > (stop + itemCount); index-- { + for index := length; index > (stop + itemCount); index-- { thisObject.delete(arrayIndexToString(index-1), true) } } else if itemCount > deleteCount { @@ -226,7 +225,7 @@ func builtinArray_splice(call FunctionCall) Value { // Starting from the upper bound of the deletion: // Move an item from the after the deleted portion // to a position after the inserted portion - for index := int64(length) - deleteCount; index > start; index-- { + for index := length - deleteCount; index > start; index-- { from := arrayIndexToString(index + deleteCount - 1) to := arrayIndexToString(index + itemCount - 1) if thisObject.hasProperty(from) { @@ -240,12 +239,12 @@ func builtinArray_splice(call FunctionCall) Value { for index := int64(0); index < itemCount; index++ { thisObject.put(arrayIndexToString(index+start), itemList[index], true) } - thisObject.put(propertyLength, toValue_int64(int64(length)+itemCount-deleteCount), true) + thisObject.put(propertyLength, int64Value(length+itemCount-deleteCount), true) - return toValue_object(call.runtime.newArrayOf(valueArray)) + return objectValue(call.runtime.newArrayOf(valueArray)) } -func builtinArray_slice(call FunctionCall) Value { +func builtinArraySlice(call FunctionCall) Value { thisObject := call.thisObject() length := int64(toUint32(thisObject.get(propertyLength))) @@ -253,7 +252,7 @@ func builtinArray_slice(call FunctionCall) Value { if start >= end { // Always an empty array - return toValue_object(call.runtime.newArray(0)) + return objectValue(call.runtime.newArray(0)) } sliceLength := end - start sliceValueArray := make([]Value, sliceLength) @@ -265,10 +264,10 @@ func builtinArray_slice(call FunctionCall) Value { } } - return toValue_object(call.runtime.newArrayOf(sliceValueArray)) + return objectValue(call.runtime.newArrayOf(sliceValueArray)) } -func builtinArray_unshift(call FunctionCall) Value { +func builtinArrayUnshift(call FunctionCall) Value { thisObject := call.thisObject() length := int64(toUint32(thisObject.get(propertyLength))) itemList := call.ArgumentList @@ -288,12 +287,12 @@ func builtinArray_unshift(call FunctionCall) Value { thisObject.put(arrayIndexToString(index), itemList[index], true) } - newLength := toValue_int64(length + itemCount) + newLength := int64Value(length + itemCount) thisObject.put(propertyLength, newLength, true) return newLength } -func builtinArray_reverse(call FunctionCall) Value { +func builtinArrayReverse(call FunctionCall) Value { thisObject := call.thisObject() length := int64(toUint32(thisObject.get(propertyLength))) @@ -315,30 +314,29 @@ func builtinArray_reverse(call FunctionCall) Value { lower.exists = thisObject.hasProperty(lower.name) upper.exists = thisObject.hasProperty(upper.name) - if lower.exists && upper.exists { + switch { + case lower.exists && upper.exists: lowerValue := thisObject.get(lower.name) upperValue := thisObject.get(upper.name) thisObject.put(lower.name, upperValue, true) thisObject.put(upper.name, lowerValue, true) - } else if !lower.exists && upper.exists { + case !lower.exists && upper.exists: value := thisObject.get(upper.name) thisObject.delete(upper.name, true) thisObject.put(lower.name, value, true) - } else if lower.exists && !upper.exists { + case lower.exists && !upper.exists: value := thisObject.get(lower.name) thisObject.delete(lower.name, true) thisObject.put(upper.name, value, true) - } else { - // Nothing happens. } - lower.index += 1 + lower.index++ } return call.This } -func sortCompare(thisObject *_object, index0, index1 uint, compare *_object) int { +func sortCompare(thisObject *object, index0, index1 uint, compare *object) int { j := struct { name string exists bool @@ -351,11 +349,12 @@ func sortCompare(thisObject *_object, index0, index1 uint, compare *_object) int k.name = arrayIndexToString(int64(index1)) k.exists = thisObject.hasProperty(k.name) - if !j.exists && !k.exists { + switch { + case !j.exists && !k.exists: return 0 - } else if !j.exists { + case !j.exists: return 1 - } else if !k.exists { + case !k.exists: return -1 } @@ -364,11 +363,12 @@ func sortCompare(thisObject *_object, index0, index1 uint, compare *_object) int j.defined = x.IsDefined() k.defined = y.IsDefined() - if !j.defined && !k.defined { + switch { + case !j.defined && !k.defined: return 0 - } else if !j.defined { + case !j.defined: return 1 - } else if !k.defined { + case !k.defined: return -1 } @@ -388,7 +388,7 @@ func sortCompare(thisObject *_object, index0, index1 uint, compare *_object) int return toIntSign(compare.call(Value{}, []Value{x, y}, false, nativeFrame)) } -func arraySortSwap(thisObject *_object, index0, index1 uint) { +func arraySortSwap(thisObject *object, index0, index1 uint) { j := struct { name string exists bool @@ -400,25 +400,24 @@ func arraySortSwap(thisObject *_object, index0, index1 uint) { k.name = arrayIndexToString(int64(index1)) k.exists = thisObject.hasProperty(k.name) - if j.exists && k.exists { - jValue := thisObject.get(j.name) - kValue := thisObject.get(k.name) - thisObject.put(j.name, kValue, true) - thisObject.put(k.name, jValue, true) - } else if !j.exists && k.exists { + switch { + case j.exists && k.exists: + jv := thisObject.get(j.name) + kv := thisObject.get(k.name) + thisObject.put(j.name, kv, true) + thisObject.put(k.name, jv, true) + case !j.exists && k.exists: value := thisObject.get(k.name) thisObject.delete(k.name, true) thisObject.put(j.name, value, true) - } else if j.exists && !k.exists { + case j.exists && !k.exists: value := thisObject.get(j.name) thisObject.delete(j.name, true) thisObject.put(k.name, value, true) - } else { - // Nothing happens. } } -func arraySortQuickPartition(thisObject *_object, left, right, pivot uint, compare *_object) (uint, uint) { +func arraySortQuickPartition(thisObject *object, left, right, pivot uint, compare *object) (uint, uint) { arraySortSwap(thisObject, pivot, right) // Right is now the pivot value cursor := left cursor2 := left @@ -429,18 +428,18 @@ func arraySortQuickPartition(thisObject *_object, left, right, pivot uint, compa if cursor < cursor2 { arraySortSwap(thisObject, index, cursor2) } - cursor += 1 - cursor2 += 1 + cursor++ + cursor2++ } else if comparison == 0 { arraySortSwap(thisObject, index, cursor2) - cursor2 += 1 + cursor2++ } } arraySortSwap(thisObject, cursor2, right) return cursor, cursor2 } -func arraySortQuickSort(thisObject *_object, left, right uint, compare *_object) { +func arraySortQuickSort(thisObject *object, left, right uint, compare *object) { if left < right { middle := left + (right-left)/2 pivot, pivot2 := arraySortQuickPartition(thisObject, left, right, middle, compare) @@ -451,11 +450,11 @@ func arraySortQuickSort(thisObject *_object, left, right uint, compare *_object) } } -func builtinArray_sort(call FunctionCall) Value { +func builtinArraySort(call FunctionCall) Value { thisObject := call.thisObject() length := uint(toUint32(thisObject.get(propertyLength))) compareValue := call.Argument(0) - compare := compareValue._object() + compare := compareValue.object() if compareValue.IsUndefined() { } else if !compareValue.isCallable() { panic(call.runtime.panicTypeError()) @@ -466,11 +465,11 @@ func builtinArray_sort(call FunctionCall) Value { return call.This } -func builtinArray_isArray(call FunctionCall) Value { - return toValue_bool(isArray(call.Argument(0)._object())) +func builtinArrayIsArray(call FunctionCall) Value { + return boolValue(isArray(call.Argument(0).object())) } -func builtinArray_indexOf(call FunctionCall) Value { +func builtinArrayIndexOf(call FunctionCall) Value { thisObject, matchValue := call.thisObject(), call.Argument(0) if length := int64(toUint32(thisObject.get(propertyLength))); length > 0 { index := int64(0) @@ -485,20 +484,20 @@ func builtinArray_indexOf(call FunctionCall) Value { index = -1 } for ; index >= 0 && index < length; index++ { - name := arrayIndexToString(int64(index)) + name := arrayIndexToString(index) if !thisObject.hasProperty(name) { continue } value := thisObject.get(name) if strictEqualityComparison(matchValue, value) { - return toValue_uint32(uint32(index)) + return uint32Value(uint32(index)) } } } - return toValue_int(-1) + return intValue(-1) } -func builtinArray_lastIndexOf(call FunctionCall) Value { +func builtinArrayLastIndexOf(call FunctionCall) Value { thisObject, matchValue := call.thisObject(), call.Argument(0) length := int64(toUint32(thisObject.get(propertyLength))) index := length - 1 @@ -511,30 +510,30 @@ func builtinArray_lastIndexOf(call FunctionCall) Value { if index > length { index = length - 1 } else if 0 > index { - return toValue_int(-1) + return intValue(-1) } for ; index >= 0; index-- { - name := arrayIndexToString(int64(index)) + name := arrayIndexToString(index) if !thisObject.hasProperty(name) { continue } value := thisObject.get(name) if strictEqualityComparison(matchValue, value) { - return toValue_uint32(uint32(index)) + return uint32Value(uint32(index)) } } - return toValue_int(-1) + return intValue(-1) } -func builtinArray_every(call FunctionCall) Value { +func builtinArrayEvery(call FunctionCall) Value { thisObject := call.thisObject() - this := toValue_object(thisObject) + this := objectValue(thisObject) if iterator := call.Argument(0); iterator.isCallable() { length := int64(toUint32(thisObject.get(propertyLength))) 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(call.runtime, callThis, value, toValue_int64(index), this).bool() { + if value := thisObject.get(key); iterator.call(call.runtime, callThis, value, int64Value(index), this).bool() { continue } return falseValue @@ -545,15 +544,15 @@ func builtinArray_every(call FunctionCall) Value { panic(call.runtime.panicTypeError()) } -func builtinArray_some(call FunctionCall) Value { +func builtinArraySome(call FunctionCall) Value { thisObject := call.thisObject() - this := toValue_object(thisObject) + this := objectValue(thisObject) if iterator := call.Argument(0); iterator.isCallable() { length := int64(toUint32(thisObject.get(propertyLength))) 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(call.runtime, callThis, value, toValue_int64(index), this).bool() { + if value := thisObject.get(key); iterator.call(call.runtime, callThis, value, int64Value(index), this).bool() { return trueValue } } @@ -563,15 +562,15 @@ func builtinArray_some(call FunctionCall) Value { panic(call.runtime.panicTypeError()) } -func builtinArray_forEach(call FunctionCall) Value { +func builtinArrayForEach(call FunctionCall) Value { thisObject := call.thisObject() - this := toValue_object(thisObject) + this := objectValue(thisObject) if iterator := call.Argument(0); iterator.isCallable() { length := int64(toUint32(thisObject.get(propertyLength))) callThis := call.Argument(1) for index := int64(0); index < length; index++ { if key := arrayIndexToString(index); thisObject.hasProperty(key) { - iterator.call(call.runtime, callThis, thisObject.get(key), toValue_int64(index), this) + iterator.call(call.runtime, callThis, thisObject.get(key), int64Value(index), this) } } return Value{} @@ -579,9 +578,9 @@ func builtinArray_forEach(call FunctionCall) Value { panic(call.runtime.panicTypeError()) } -func builtinArray_map(call FunctionCall) Value { +func builtinArrayMap(call FunctionCall) Value { thisObject := call.thisObject() - this := toValue_object(thisObject) + this := objectValue(thisObject) if iterator := call.Argument(0); iterator.isCallable() { length := int64(toUint32(thisObject.get(propertyLength))) callThis := call.Argument(1) @@ -593,14 +592,14 @@ func builtinArray_map(call FunctionCall) Value { values[index] = Value{} } } - return toValue_object(call.runtime.newArrayOf(values)) + return objectValue(call.runtime.newArrayOf(values)) } panic(call.runtime.panicTypeError()) } -func builtinArray_filter(call FunctionCall) Value { +func builtinArrayFilter(call FunctionCall) Value { thisObject := call.thisObject() - this := toValue_object(thisObject) + this := objectValue(thisObject) if iterator := call.Argument(0); iterator.isCallable() { length := int64(toUint32(thisObject.get(propertyLength))) callThis := call.Argument(1) @@ -613,14 +612,14 @@ func builtinArray_filter(call FunctionCall) Value { } } } - return toValue_object(call.runtime.newArrayOf(values)) + return objectValue(call.runtime.newArrayOf(values)) } panic(call.runtime.panicTypeError()) } -func builtinArray_reduce(call FunctionCall) Value { +func builtinArrayReduce(call FunctionCall) Value { thisObject := call.thisObject() - this := toValue_object(thisObject) + this := objectValue(thisObject) if iterator := call.Argument(0); iterator.isCallable() { initial := len(call.ArgumentList) > 1 start := call.Argument(1) @@ -633,6 +632,7 @@ func builtinArray_reduce(call FunctionCall) Value { if key := arrayIndexToString(index); thisObject.hasProperty(key) { accumulator = thisObject.get(key) index++ + break } } @@ -650,9 +650,9 @@ func builtinArray_reduce(call FunctionCall) Value { panic(call.runtime.panicTypeError()) } -func builtinArray_reduceRight(call FunctionCall) Value { +func builtinArrayReduceRight(call FunctionCall) Value { thisObject := call.thisObject() - this := toValue_object(thisObject) + this := objectValue(thisObject) if iterator := call.Argument(0); iterator.isCallable() { initial := len(call.ArgumentList) > 1 start := call.Argument(1) diff --git a/builtin_boolean.go b/builtin_boolean.go index 25a596e2..54f02028 100644 --- a/builtin_boolean.go +++ b/builtin_boolean.go @@ -3,26 +3,26 @@ package otto // Boolean func builtinBoolean(call FunctionCall) Value { - return toValue_bool(call.Argument(0).bool()) + return boolValue(call.Argument(0).bool()) } -func builtinNewBoolean(self *_object, argumentList []Value) Value { - return toValue_object(self.runtime.newBoolean(valueOfArrayIndex(argumentList, 0))) +func builtinNewBoolean(obj *object, argumentList []Value) Value { + return objectValue(obj.runtime.newBoolean(valueOfArrayIndex(argumentList, 0))) } -func builtinBoolean_toString(call FunctionCall) Value { +func builtinBooleanToString(call FunctionCall) Value { value := call.This if !value.IsBoolean() { // Will throw a TypeError if ThisObject is not a Boolean - value = call.thisClassObject(classBoolean).primitiveValue() + value = call.thisClassObject(classBooleanName).primitiveValue() } - return toValue_string(value.string()) + return stringValue(value.string()) } -func builtinBoolean_valueOf(call FunctionCall) Value { +func builtinBooleanValueOf(call FunctionCall) Value { value := call.This if !value.IsBoolean() { - value = call.thisClassObject(classBoolean).primitiveValue() + value = call.thisClassObject(classBooleanName).primitiveValue() } return value } diff --git a/builtin_date.go b/builtin_date.go index ff6dbb73..3ee81b0b 100644 --- a/builtin_date.go +++ b/builtin_date.go @@ -9,114 +9,111 @@ import ( const ( // TODO Be like V8? - // builtinDate_goDateTimeLayout = "Mon Jan 2 2006 15:04:05 GMT-0700 (MST)" - builtinDate_goDateTimeLayout = Time.RFC1123 // "Mon, 02 Jan 2006 15:04:05 MST" - builtinDate_goDateLayout = "Mon, 02 Jan 2006" - builtinDate_goTimeLayout = "15:04:05 MST" + // builtinDateDateTimeLayout = "Mon Jan 2 2006 15:04:05 GMT-0700 (MST)". + builtinDateDateTimeLayout = Time.RFC1123 // "Mon, 02 Jan 2006 15:04:05 MST" + builtinDateDateLayout = "Mon, 02 Jan 2006" + builtinDateTimeLayout = "15:04:05 MST" ) -var ( - // utcTimeZone is the time zone used for UTC calculations. - // It is GMT not UTC as that's what Javascript does because toUTCString is - // actually an alias to toGMTString. - utcTimeZone = Time.FixedZone("GMT", 0) -) +// utcTimeZone is the time zone used for UTC calculations. +// It is GMT not UTC as that's what Javascript does because toUTCString is +// actually an alias to toGMTString. +var utcTimeZone = Time.FixedZone("GMT", 0) func builtinDate(call FunctionCall) Value { - date := &_dateObject{} + date := &dateObject{} date.Set(newDateTime([]Value{}, Time.Local)) - return toValue_string(date.Time().Format(builtinDate_goDateTimeLayout)) + return stringValue(date.Time().Format(builtinDateDateTimeLayout)) } -func builtinNewDate(self *_object, argumentList []Value) Value { - return toValue_object(self.runtime.newDate(newDateTime(argumentList, Time.Local))) +func builtinNewDate(obj *object, argumentList []Value) Value { + return objectValue(obj.runtime.newDate(newDateTime(argumentList, Time.Local))) } -func builtinDate_toString(call FunctionCall) Value { +func builtinDateToString(call FunctionCall) Value { date := dateObjectOf(call.runtime, call.thisObject()) if date.isNaN { - return toValue_string("Invalid Date") + return stringValue("Invalid Date") } - return toValue_string(date.Time().Local().Format(builtinDate_goDateTimeLayout)) + return stringValue(date.Time().Local().Format(builtinDateDateTimeLayout)) } -func builtinDate_toDateString(call FunctionCall) Value { +func builtinDateToDateString(call FunctionCall) Value { date := dateObjectOf(call.runtime, call.thisObject()) if date.isNaN { - return toValue_string("Invalid Date") + return stringValue("Invalid Date") } - return toValue_string(date.Time().Local().Format(builtinDate_goDateLayout)) + return stringValue(date.Time().Local().Format(builtinDateDateLayout)) } -func builtinDate_toTimeString(call FunctionCall) Value { +func builtinDateToTimeString(call FunctionCall) Value { date := dateObjectOf(call.runtime, call.thisObject()) if date.isNaN { - return toValue_string("Invalid Date") + return stringValue("Invalid Date") } - return toValue_string(date.Time().Local().Format(builtinDate_goTimeLayout)) + return stringValue(date.Time().Local().Format(builtinDateTimeLayout)) } -func builtinDate_toUTCString(call FunctionCall) Value { +func builtinDateToUTCString(call FunctionCall) Value { date := dateObjectOf(call.runtime, call.thisObject()) if date.isNaN { - return toValue_string("Invalid Date") + return stringValue("Invalid Date") } - return toValue_string(date.Time().In(utcTimeZone).Format(builtinDate_goDateTimeLayout)) + return stringValue(date.Time().In(utcTimeZone).Format(builtinDateDateTimeLayout)) } -func builtinDate_toISOString(call FunctionCall) Value { +func builtinDateToISOString(call FunctionCall) Value { date := dateObjectOf(call.runtime, call.thisObject()) if date.isNaN { - return toValue_string("Invalid Date") + return stringValue("Invalid Date") } - return toValue_string(date.Time().Format("2006-01-02T15:04:05.000Z")) + return stringValue(date.Time().Format("2006-01-02T15:04:05.000Z")) } -func builtinDate_toJSON(call FunctionCall) Value { - object := call.thisObject() - value := object.DefaultValue(defaultValueHintNumber) // FIXME object.primitiveNumberValue - { // FIXME value.isFinite - value := value.float64() - if math.IsNaN(value) || math.IsInf(value, 0) { - return nullValue - } +func builtinDateToJSON(call FunctionCall) Value { + obj := call.thisObject() + value := obj.DefaultValue(defaultValueHintNumber) // FIXME object.primitiveNumberValue + // FIXME fv.isFinite + if fv := value.float64(); math.IsNaN(fv) || math.IsInf(fv, 0) { + return nullValue } - toISOString := object.get("toISOString") + + toISOString := obj.get("toISOString") if !toISOString.isCallable() { // FIXME panic(call.runtime.panicTypeError()) } - return toISOString.call(call.runtime, toValue_object(object), []Value{}) + return toISOString.call(call.runtime, objectValue(obj), []Value{}) } -func builtinDate_toGMTString(call FunctionCall) Value { +func builtinDateToGMTString(call FunctionCall) Value { date := dateObjectOf(call.runtime, call.thisObject()) if date.isNaN { - return toValue_string("Invalid Date") + return stringValue("Invalid Date") } - return toValue_string(date.Time().Format("Mon, 02 Jan 2006 15:04:05 GMT")) + return stringValue(date.Time().Format("Mon, 02 Jan 2006 15:04:05 GMT")) } -func builtinDate_getTime(call FunctionCall) Value { +func builtinDateGetTime(call FunctionCall) Value { date := dateObjectOf(call.runtime, call.thisObject()) if date.isNaN { return NaNValue() } // We do this (convert away from a float) so the user // does not get something back in exponential notation - return toValue_int64(int64(date.Epoch())) + return int64Value(date.Epoch()) } -func builtinDate_setTime(call FunctionCall) Value { - object := call.thisObject() +func builtinDateSetTime(call FunctionCall) Value { + obj := call.thisObject() date := dateObjectOf(call.runtime, call.thisObject()) date.Set(call.Argument(0).float64()) - object.value = date + obj.value = date return date.Value() } -func _builtinDate_beforeSet(call FunctionCall, argumentLimit int, timeLocal bool) (*_object, *_dateObject, *_ecmaTime, []int) { - object := call.thisObject() +func builtinDateBeforeSet(call FunctionCall, argumentLimit int, timeLocal bool) (*object, *dateObject, *ecmaTime, []int) { + obj := call.thisObject() date := dateObjectOf(call.runtime, call.thisObject()) if date.isNaN { return nil, nil, nil, nil @@ -127,7 +124,7 @@ func _builtinDate_beforeSet(call FunctionCall, argumentLimit int, timeLocal bool } if argumentLimit == 0 { - object.value = invalidDateObject + obj.value = invalidDateObject return nil, nil, nil, nil } @@ -138,7 +135,7 @@ func _builtinDate_beforeSet(call FunctionCall, argumentLimit int, timeLocal bool switch nm.kind { case numberInteger, numberFloat: default: - object.value = invalidDateObject + obj.value = invalidDateObject return nil, nil, nil, nil } valueList[index] = int(nm.int64) @@ -147,52 +144,52 @@ func _builtinDate_beforeSet(call FunctionCall, argumentLimit int, timeLocal bool if timeLocal { baseTime = baseTime.Local() } - ecmaTime := ecmaTime(baseTime) - return object, &date, &ecmaTime, valueList + ecmaTime := newEcmaTime(baseTime) + return obj, &date, &ecmaTime, valueList } -func builtinDate_parse(call FunctionCall) Value { +func builtinDateParse(call FunctionCall) Value { date := call.Argument(0).string() - return toValue_float64(dateParse(date)) + return float64Value(dateParse(date)) } -func builtinDate_UTC(call FunctionCall) Value { - return toValue_float64(newDateTime(call.ArgumentList, Time.UTC)) +func builtinDateUTC(call FunctionCall) Value { + return float64Value(newDateTime(call.ArgumentList, Time.UTC)) } -func builtinDate_now(call FunctionCall) Value { +func builtinDateNow(call FunctionCall) Value { call.ArgumentList = []Value(nil) - return builtinDate_UTC(call) + return builtinDateUTC(call) } -// This is a placeholder -func builtinDate_toLocaleString(call FunctionCall) Value { +// This is a placeholder. +func builtinDateToLocaleString(call FunctionCall) Value { date := dateObjectOf(call.runtime, call.thisObject()) if date.isNaN { - return toValue_string("Invalid Date") + return stringValue("Invalid Date") } - return toValue_string(date.Time().Local().Format("2006-01-02 15:04:05")) + return stringValue(date.Time().Local().Format("2006-01-02 15:04:05")) } -// This is a placeholder -func builtinDate_toLocaleDateString(call FunctionCall) Value { +// This is a placeholder. +func builtinDateToLocaleDateString(call FunctionCall) Value { date := dateObjectOf(call.runtime, call.thisObject()) if date.isNaN { - return toValue_string("Invalid Date") + return stringValue("Invalid Date") } - return toValue_string(date.Time().Local().Format("2006-01-02")) + return stringValue(date.Time().Local().Format("2006-01-02")) } -// This is a placeholder -func builtinDate_toLocaleTimeString(call FunctionCall) Value { +// This is a placeholder. +func builtinDateToLocaleTimeString(call FunctionCall) Value { date := dateObjectOf(call.runtime, call.thisObject()) if date.isNaN { - return toValue_string("Invalid Date") + return stringValue("Invalid Date") } - return toValue_string(date.Time().Local().Format("15:04:05")) + return stringValue(date.Time().Local().Format("15:04:05")) } -func builtinDate_valueOf(call FunctionCall) Value { +func builtinDateValueOf(call FunctionCall) Value { date := dateObjectOf(call.runtime, call.thisObject()) if date.isNaN { return NaNValue() @@ -200,148 +197,148 @@ func builtinDate_valueOf(call FunctionCall) Value { return date.Value() } -func builtinDate_getYear(call FunctionCall) Value { +func builtinDateGetYear(call FunctionCall) Value { // Will throw a TypeError is ThisObject is nil or // does not have Class of "Date" date := dateObjectOf(call.runtime, call.thisObject()) if date.isNaN { return NaNValue() } - return toValue_int(date.Time().Local().Year() - 1900) + return intValue(date.Time().Local().Year() - 1900) } -func builtinDate_getFullYear(call FunctionCall) Value { +func builtinDateGetFullYear(call FunctionCall) Value { // Will throw a TypeError is ThisObject is nil or // does not have Class of "Date" date := dateObjectOf(call.runtime, call.thisObject()) if date.isNaN { return NaNValue() } - return toValue_int(date.Time().Local().Year()) + return intValue(date.Time().Local().Year()) } -func builtinDate_getUTCFullYear(call FunctionCall) Value { +func builtinDateGetUTCFullYear(call FunctionCall) Value { date := dateObjectOf(call.runtime, call.thisObject()) if date.isNaN { return NaNValue() } - return toValue_int(date.Time().Year()) + return intValue(date.Time().Year()) } -func builtinDate_getMonth(call FunctionCall) Value { +func builtinDateGetMonth(call FunctionCall) Value { date := dateObjectOf(call.runtime, call.thisObject()) if date.isNaN { return NaNValue() } - return toValue_int(dateFromGoMonth(date.Time().Local().Month())) + return intValue(dateFromGoMonth(date.Time().Local().Month())) } -func builtinDate_getUTCMonth(call FunctionCall) Value { +func builtinDateGetUTCMonth(call FunctionCall) Value { date := dateObjectOf(call.runtime, call.thisObject()) if date.isNaN { return NaNValue() } - return toValue_int(dateFromGoMonth(date.Time().Month())) + return intValue(dateFromGoMonth(date.Time().Month())) } -func builtinDate_getDate(call FunctionCall) Value { +func builtinDateGetDate(call FunctionCall) Value { date := dateObjectOf(call.runtime, call.thisObject()) if date.isNaN { return NaNValue() } - return toValue_int(date.Time().Local().Day()) + return intValue(date.Time().Local().Day()) } -func builtinDate_getUTCDate(call FunctionCall) Value { +func builtinDateGetUTCDate(call FunctionCall) Value { date := dateObjectOf(call.runtime, call.thisObject()) if date.isNaN { return NaNValue() } - return toValue_int(date.Time().Day()) + return intValue(date.Time().Day()) } -func builtinDate_getDay(call FunctionCall) Value { +func builtinDateGetDay(call FunctionCall) Value { // Actually day of the week date := dateObjectOf(call.runtime, call.thisObject()) if date.isNaN { return NaNValue() } - return toValue_int(dateFromGoDay(date.Time().Local().Weekday())) + return intValue(dateFromGoDay(date.Time().Local().Weekday())) } -func builtinDate_getUTCDay(call FunctionCall) Value { +func builtinDateGetUTCDay(call FunctionCall) Value { date := dateObjectOf(call.runtime, call.thisObject()) if date.isNaN { return NaNValue() } - return toValue_int(dateFromGoDay(date.Time().Weekday())) + return intValue(dateFromGoDay(date.Time().Weekday())) } -func builtinDate_getHours(call FunctionCall) Value { +func builtinDateGetHours(call FunctionCall) Value { date := dateObjectOf(call.runtime, call.thisObject()) if date.isNaN { return NaNValue() } - return toValue_int(date.Time().Local().Hour()) + return intValue(date.Time().Local().Hour()) } -func builtinDate_getUTCHours(call FunctionCall) Value { +func builtinDateGetUTCHours(call FunctionCall) Value { date := dateObjectOf(call.runtime, call.thisObject()) if date.isNaN { return NaNValue() } - return toValue_int(date.Time().Hour()) + return intValue(date.Time().Hour()) } -func builtinDate_getMinutes(call FunctionCall) Value { +func builtinDateGetMinutes(call FunctionCall) Value { date := dateObjectOf(call.runtime, call.thisObject()) if date.isNaN { return NaNValue() } - return toValue_int(date.Time().Local().Minute()) + return intValue(date.Time().Local().Minute()) } -func builtinDate_getUTCMinutes(call FunctionCall) Value { +func builtinDateGetUTCMinutes(call FunctionCall) Value { date := dateObjectOf(call.runtime, call.thisObject()) if date.isNaN { return NaNValue() } - return toValue_int(date.Time().Minute()) + return intValue(date.Time().Minute()) } -func builtinDate_getSeconds(call FunctionCall) Value { +func builtinDateGetSeconds(call FunctionCall) Value { date := dateObjectOf(call.runtime, call.thisObject()) if date.isNaN { return NaNValue() } - return toValue_int(date.Time().Local().Second()) + return intValue(date.Time().Local().Second()) } -func builtinDate_getUTCSeconds(call FunctionCall) Value { +func builtinDateGetUTCSeconds(call FunctionCall) Value { date := dateObjectOf(call.runtime, call.thisObject()) if date.isNaN { return NaNValue() } - return toValue_int(date.Time().Second()) + return intValue(date.Time().Second()) } -func builtinDate_getMilliseconds(call FunctionCall) Value { +func builtinDateGetMilliseconds(call FunctionCall) Value { date := dateObjectOf(call.runtime, call.thisObject()) if date.isNaN { return NaNValue() } - return toValue_int(date.Time().Local().Nanosecond() / (100 * 100 * 100)) + return intValue(date.Time().Local().Nanosecond() / (100 * 100 * 100)) } -func builtinDate_getUTCMilliseconds(call FunctionCall) Value { +func builtinDateGetUTCMilliseconds(call FunctionCall) Value { date := dateObjectOf(call.runtime, call.thisObject()) if date.isNaN { return NaNValue() } - return toValue_int(date.Time().Nanosecond() / (100 * 100 * 100)) + return intValue(date.Time().Nanosecond() / (100 * 100 * 100)) } -func builtinDate_getTimezoneOffset(call FunctionCall) Value { +func builtinDateGetTimezoneOffset(call FunctionCall) Value { date := dateObjectOf(call.runtime, call.thisObject()) if date.isNaN { return NaNValue() @@ -358,11 +355,11 @@ func builtinDate_getTimezoneOffset(call FunctionCall) Value { timeLocal.Nanosecond(), Time.UTC, ) - return toValue_float64(date.Time().Sub(timeLocalAsUTC).Seconds() / 60) + return float64Value(date.Time().Sub(timeLocalAsUTC).Seconds() / 60) } -func builtinDate_setMilliseconds(call FunctionCall) Value { - object, date, ecmaTime, value := _builtinDate_beforeSet(call, 1, true) +func builtinDateSetMilliseconds(call FunctionCall) Value { + obj, date, ecmaTime, value := builtinDateBeforeSet(call, 1, true) if ecmaTime == nil { return NaNValue() } @@ -370,12 +367,12 @@ func builtinDate_setMilliseconds(call FunctionCall) Value { ecmaTime.millisecond = value[0] date.SetTime(ecmaTime.goTime()) - object.value = *date + obj.value = *date return date.Value() } -func builtinDate_setUTCMilliseconds(call FunctionCall) Value { - object, date, ecmaTime, value := _builtinDate_beforeSet(call, 1, false) +func builtinDateSetUTCMilliseconds(call FunctionCall) Value { + obj, date, ecmaTime, value := builtinDateBeforeSet(call, 1, false) if ecmaTime == nil { return NaNValue() } @@ -383,12 +380,12 @@ func builtinDate_setUTCMilliseconds(call FunctionCall) Value { ecmaTime.millisecond = value[0] date.SetTime(ecmaTime.goTime()) - object.value = *date + obj.value = *date return date.Value() } -func builtinDate_setSeconds(call FunctionCall) Value { - object, date, ecmaTime, value := _builtinDate_beforeSet(call, 2, true) +func builtinDateSetSeconds(call FunctionCall) Value { + obj, date, ecmaTime, value := builtinDateBeforeSet(call, 2, true) if ecmaTime == nil { return NaNValue() } @@ -399,12 +396,12 @@ func builtinDate_setSeconds(call FunctionCall) Value { ecmaTime.second = value[0] date.SetTime(ecmaTime.goTime()) - object.value = *date + obj.value = *date return date.Value() } -func builtinDate_setUTCSeconds(call FunctionCall) Value { - object, date, ecmaTime, value := _builtinDate_beforeSet(call, 2, false) +func builtinDateSetUTCSeconds(call FunctionCall) Value { + obj, date, ecmaTime, value := builtinDateBeforeSet(call, 2, false) if ecmaTime == nil { return NaNValue() } @@ -415,12 +412,12 @@ func builtinDate_setUTCSeconds(call FunctionCall) Value { ecmaTime.second = value[0] date.SetTime(ecmaTime.goTime()) - object.value = *date + obj.value = *date return date.Value() } -func builtinDate_setMinutes(call FunctionCall) Value { - object, date, ecmaTime, value := _builtinDate_beforeSet(call, 3, true) +func builtinDateSetMinutes(call FunctionCall) Value { + obj, date, ecmaTime, value := builtinDateBeforeSet(call, 3, true) if ecmaTime == nil { return NaNValue() } @@ -434,12 +431,12 @@ func builtinDate_setMinutes(call FunctionCall) Value { ecmaTime.minute = value[0] date.SetTime(ecmaTime.goTime()) - object.value = *date + obj.value = *date return date.Value() } -func builtinDate_setUTCMinutes(call FunctionCall) Value { - object, date, ecmaTime, value := _builtinDate_beforeSet(call, 3, false) +func builtinDateSetUTCMinutes(call FunctionCall) Value { + obj, date, ecmaTime, value := builtinDateBeforeSet(call, 3, false) if ecmaTime == nil { return NaNValue() } @@ -453,58 +450,58 @@ func builtinDate_setUTCMinutes(call FunctionCall) Value { ecmaTime.minute = value[0] date.SetTime(ecmaTime.goTime()) - object.value = *date + obj.value = *date return date.Value() } -func builtinDate_setHours(call FunctionCall) Value { - object, date, ecmaTime, value := _builtinDate_beforeSet(call, 4, true) +func builtinDateSetHours(call FunctionCall) Value { + obj, date, ecmaTime, value := builtinDateBeforeSet(call, 4, true) if ecmaTime == nil { return NaNValue() } - if len(value) > 3 { + switch { + case len(value) > 3: ecmaTime.millisecond = value[3] + fallthrough + case len(value) > 2: ecmaTime.second = value[2] - ecmaTime.minute = value[1] - } else if len(value) > 2 { - ecmaTime.second = value[2] - ecmaTime.minute = value[1] - } else if len(value) > 1 { + fallthrough + case len(value) > 1: ecmaTime.minute = value[1] } ecmaTime.hour = value[0] date.SetTime(ecmaTime.goTime()) - object.value = *date + obj.value = *date return date.Value() } -func builtinDate_setUTCHours(call FunctionCall) Value { - object, date, ecmaTime, value := _builtinDate_beforeSet(call, 4, false) +func builtinDateSetUTCHours(call FunctionCall) Value { + obj, date, ecmaTime, value := builtinDateBeforeSet(call, 4, false) if ecmaTime == nil { return NaNValue() } - if len(value) > 3 { + switch { + case len(value) > 3: ecmaTime.millisecond = value[3] + fallthrough + case len(value) > 2: ecmaTime.second = value[2] - ecmaTime.minute = value[1] - } else if len(value) > 2 { - ecmaTime.second = value[2] - ecmaTime.minute = value[1] - } else if len(value) > 1 { + fallthrough + case len(value) > 1: ecmaTime.minute = value[1] } ecmaTime.hour = value[0] date.SetTime(ecmaTime.goTime()) - object.value = *date + obj.value = *date return date.Value() } -func builtinDate_setDate(call FunctionCall) Value { - object, date, ecmaTime, value := _builtinDate_beforeSet(call, 1, true) +func builtinDateSetDate(call FunctionCall) Value { + obj, date, ecmaTime, value := builtinDateBeforeSet(call, 1, true) if ecmaTime == nil { return NaNValue() } @@ -512,12 +509,12 @@ func builtinDate_setDate(call FunctionCall) Value { ecmaTime.day = value[0] date.SetTime(ecmaTime.goTime()) - object.value = *date + obj.value = *date return date.Value() } -func builtinDate_setUTCDate(call FunctionCall) Value { - object, date, ecmaTime, value := _builtinDate_beforeSet(call, 1, false) +func builtinDateSetUTCDate(call FunctionCall) Value { + obj, date, ecmaTime, value := builtinDateBeforeSet(call, 1, false) if ecmaTime == nil { return NaNValue() } @@ -525,12 +522,12 @@ func builtinDate_setUTCDate(call FunctionCall) Value { ecmaTime.day = value[0] date.SetTime(ecmaTime.goTime()) - object.value = *date + obj.value = *date return date.Value() } -func builtinDate_setMonth(call FunctionCall) Value { - object, date, ecmaTime, value := _builtinDate_beforeSet(call, 2, true) +func builtinDateSetMonth(call FunctionCall) Value { + obj, date, ecmaTime, value := builtinDateBeforeSet(call, 2, true) if ecmaTime == nil { return NaNValue() } @@ -541,12 +538,12 @@ func builtinDate_setMonth(call FunctionCall) Value { ecmaTime.month = value[0] date.SetTime(ecmaTime.goTime()) - object.value = *date + obj.value = *date return date.Value() } -func builtinDate_setUTCMonth(call FunctionCall) Value { - object, date, ecmaTime, value := _builtinDate_beforeSet(call, 2, false) +func builtinDateSetUTCMonth(call FunctionCall) Value { + obj, date, ecmaTime, value := builtinDateBeforeSet(call, 2, false) if ecmaTime == nil { return NaNValue() } @@ -557,12 +554,12 @@ func builtinDate_setUTCMonth(call FunctionCall) Value { ecmaTime.month = value[0] date.SetTime(ecmaTime.goTime()) - object.value = *date + obj.value = *date return date.Value() } -func builtinDate_setYear(call FunctionCall) Value { - object, date, ecmaTime, value := _builtinDate_beforeSet(call, 1, true) +func builtinDateSetYear(call FunctionCall) Value { + obj, date, ecmaTime, value := builtinDateBeforeSet(call, 1, true) if ecmaTime == nil { return NaNValue() } @@ -574,12 +571,12 @@ func builtinDate_setYear(call FunctionCall) Value { ecmaTime.year = year date.SetTime(ecmaTime.goTime()) - object.value = *date + obj.value = *date return date.Value() } -func builtinDate_setFullYear(call FunctionCall) Value { - object, date, ecmaTime, value := _builtinDate_beforeSet(call, 3, true) +func builtinDateSetFullYear(call FunctionCall) Value { + obj, date, ecmaTime, value := builtinDateBeforeSet(call, 3, true) if ecmaTime == nil { return NaNValue() } @@ -593,12 +590,12 @@ func builtinDate_setFullYear(call FunctionCall) Value { ecmaTime.year = value[0] date.SetTime(ecmaTime.goTime()) - object.value = *date + obj.value = *date return date.Value() } -func builtinDate_setUTCFullYear(call FunctionCall) Value { - object, date, ecmaTime, value := _builtinDate_beforeSet(call, 3, false) +func builtinDateSetUTCFullYear(call FunctionCall) Value { + obj, date, ecmaTime, value := builtinDateBeforeSet(call, 3, false) if ecmaTime == nil { return NaNValue() } @@ -612,7 +609,7 @@ func builtinDate_setUTCFullYear(call FunctionCall) Value { ecmaTime.year = value[0] date.SetTime(ecmaTime.goTime()) - object.value = *date + obj.value = *date return date.Value() } diff --git a/builtin_error.go b/builtin_error.go index 95f9cd99..7e043d7c 100644 --- a/builtin_error.go +++ b/builtin_error.go @@ -5,20 +5,20 @@ import ( ) func builtinError(call FunctionCall) Value { - return toValue_object(call.runtime.newError(classError, call.Argument(0), 1)) + return objectValue(call.runtime.newError(classErrorName, call.Argument(0), 1)) } -func builtinNewError(self *_object, argumentList []Value) Value { - return toValue_object(self.runtime.newError(classError, valueOfArrayIndex(argumentList, 0), 0)) +func builtinNewError(obj *object, argumentList []Value) Value { + return objectValue(obj.runtime.newError(classErrorName, valueOfArrayIndex(argumentList, 0), 0)) } -func builtinError_toString(call FunctionCall) Value { +func builtinErrorToString(call FunctionCall) Value { thisObject := call.thisObject() if thisObject == nil { panic(call.runtime.panicTypeError()) } - name := classError + name := classErrorName nameValue := thisObject.get("name") if nameValue.IsDefined() { name = nameValue.string() @@ -31,96 +31,96 @@ func builtinError_toString(call FunctionCall) Value { } if len(name) == 0 { - return toValue_string(message) + return stringValue(message) } if len(message) == 0 { - return toValue_string(name) + return stringValue(name) } - return toValue_string(fmt.Sprintf("%s: %s", name, message)) + return stringValue(fmt.Sprintf("%s: %s", name, message)) } -func (runtime *_runtime) newEvalError(message Value) *_object { - self := runtime.newErrorObject("EvalError", message, 0) - self.prototype = runtime.global.EvalErrorPrototype - return self +func (rt *runtime) newEvalError(message Value) *object { + o := rt.newErrorObject("EvalError", message, 0) + o.prototype = rt.global.EvalErrorPrototype + return o } func builtinEvalError(call FunctionCall) Value { - return toValue_object(call.runtime.newEvalError(call.Argument(0))) + return objectValue(call.runtime.newEvalError(call.Argument(0))) } -func builtinNewEvalError(self *_object, argumentList []Value) Value { - return toValue_object(self.runtime.newEvalError(valueOfArrayIndex(argumentList, 0))) +func builtinNewEvalError(obj *object, argumentList []Value) Value { + return objectValue(obj.runtime.newEvalError(valueOfArrayIndex(argumentList, 0))) } -func (runtime *_runtime) newTypeError(message Value) *_object { - self := runtime.newErrorObject("TypeError", message, 0) - self.prototype = runtime.global.TypeErrorPrototype - return self +func (rt *runtime) newTypeError(message Value) *object { + o := rt.newErrorObject("TypeError", message, 0) + o.prototype = rt.global.TypeErrorPrototype + return o } func builtinTypeError(call FunctionCall) Value { - return toValue_object(call.runtime.newTypeError(call.Argument(0))) + return objectValue(call.runtime.newTypeError(call.Argument(0))) } -func builtinNewTypeError(self *_object, argumentList []Value) Value { - return toValue_object(self.runtime.newTypeError(valueOfArrayIndex(argumentList, 0))) +func builtinNewTypeError(obj *object, argumentList []Value) Value { + return objectValue(obj.runtime.newTypeError(valueOfArrayIndex(argumentList, 0))) } -func (runtime *_runtime) newRangeError(message Value) *_object { - self := runtime.newErrorObject("RangeError", message, 0) - self.prototype = runtime.global.RangeErrorPrototype - return self +func (rt *runtime) newRangeError(message Value) *object { + o := rt.newErrorObject("RangeError", message, 0) + o.prototype = rt.global.RangeErrorPrototype + return o } func builtinRangeError(call FunctionCall) Value { - return toValue_object(call.runtime.newRangeError(call.Argument(0))) + return objectValue(call.runtime.newRangeError(call.Argument(0))) } -func builtinNewRangeError(self *_object, argumentList []Value) Value { - return toValue_object(self.runtime.newRangeError(valueOfArrayIndex(argumentList, 0))) +func builtinNewRangeError(obj *object, argumentList []Value) Value { + return objectValue(obj.runtime.newRangeError(valueOfArrayIndex(argumentList, 0))) } -func (runtime *_runtime) newURIError(message Value) *_object { - self := runtime.newErrorObject("URIError", message, 0) - self.prototype = runtime.global.URIErrorPrototype - return self +func (rt *runtime) newURIError(message Value) *object { + o := rt.newErrorObject("URIError", message, 0) + o.prototype = rt.global.URIErrorPrototype + return o } -func (runtime *_runtime) newReferenceError(message Value) *_object { - self := runtime.newErrorObject("ReferenceError", message, 0) - self.prototype = runtime.global.ReferenceErrorPrototype - return self +func (rt *runtime) newReferenceError(message Value) *object { + o := rt.newErrorObject("ReferenceError", message, 0) + o.prototype = rt.global.ReferenceErrorPrototype + return o } func builtinReferenceError(call FunctionCall) Value { - return toValue_object(call.runtime.newReferenceError(call.Argument(0))) + return objectValue(call.runtime.newReferenceError(call.Argument(0))) } -func builtinNewReferenceError(self *_object, argumentList []Value) Value { - return toValue_object(self.runtime.newReferenceError(valueOfArrayIndex(argumentList, 0))) +func builtinNewReferenceError(obj *object, argumentList []Value) Value { + return objectValue(obj.runtime.newReferenceError(valueOfArrayIndex(argumentList, 0))) } -func (runtime *_runtime) newSyntaxError(message Value) *_object { - self := runtime.newErrorObject("SyntaxError", message, 0) - self.prototype = runtime.global.SyntaxErrorPrototype - return self +func (rt *runtime) newSyntaxError(message Value) *object { + o := rt.newErrorObject("SyntaxError", message, 0) + o.prototype = rt.global.SyntaxErrorPrototype + return o } func builtinSyntaxError(call FunctionCall) Value { - return toValue_object(call.runtime.newSyntaxError(call.Argument(0))) + return objectValue(call.runtime.newSyntaxError(call.Argument(0))) } -func builtinNewSyntaxError(self *_object, argumentList []Value) Value { - return toValue_object(self.runtime.newSyntaxError(valueOfArrayIndex(argumentList, 0))) +func builtinNewSyntaxError(obj *object, argumentList []Value) Value { + return objectValue(obj.runtime.newSyntaxError(valueOfArrayIndex(argumentList, 0))) } func builtinURIError(call FunctionCall) Value { - return toValue_object(call.runtime.newURIError(call.Argument(0))) + return objectValue(call.runtime.newURIError(call.Argument(0))) } -func builtinNewURIError(self *_object, argumentList []Value) Value { - return toValue_object(self.runtime.newURIError(valueOfArrayIndex(argumentList, 0))) +func builtinNewURIError(obj *object, argumentList []Value) Value { + return objectValue(obj.runtime.newURIError(valueOfArrayIndex(argumentList, 0))) } diff --git a/builtin_function.go b/builtin_function.go index f988c835..6ae1ae1b 100644 --- a/builtin_function.go +++ b/builtin_function.go @@ -11,11 +11,11 @@ import ( // Function func builtinFunction(call FunctionCall) Value { - return toValue_object(builtinNewFunctionNative(call.runtime, call.ArgumentList)) + return objectValue(builtinNewFunctionNative(call.runtime, call.ArgumentList)) } -func builtinNewFunction(self *_object, argumentList []Value) Value { - return toValue_object(builtinNewFunctionNative(self.runtime, argumentList)) +func builtinNewFunction(obj *object, argumentList []Value) Value { + return objectValue(builtinNewFunctionNative(obj.runtime, argumentList)) } func argumentList2parameterList(argumentList []Value) []string { @@ -29,10 +29,9 @@ func argumentList2parameterList(argumentList []Value) []string { return parameterList } -func builtinNewFunctionNative(runtime *_runtime, argumentList []Value) *_object { +func builtinNewFunctionNative(rt *runtime, argumentList []Value) *object { var parameterList, body string - count := len(argumentList) - if count > 0 { + if count := len(argumentList); count > 0 { tmp := make([]string, 0, count-1) for _, value := range argumentList[0 : count-1] { tmp = append(tmp, value.string()) @@ -43,35 +42,35 @@ func builtinNewFunctionNative(runtime *_runtime, argumentList []Value) *_object // FIXME function, err := parser.ParseFunction(parameterList, body) - runtime.parseThrow(err) // Will panic/throw appropriately - cmpl := _compiler{} - cmpl_function := cmpl.parseExpression(function) + rt.parseThrow(err) // Will panic/throw appropriately + cmpl := compiler{} + cmplFunction := cmpl.parseExpression(function) - return runtime.newNodeFunction(cmpl_function.(*_nodeFunctionLiteral), runtime.globalStash) + return rt.newNodeFunction(cmplFunction.(*nodeFunctionLiteral), rt.globalStash) } -func builtinFunction_toString(call FunctionCall) Value { - object := call.thisClassObject(classFunction) // Should throw a TypeError unless Function - 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] }") +func builtinFunctionToString(call FunctionCall) Value { + obj := call.thisClassObject(classFunctionName) // Should throw a TypeError unless Function + switch fn := obj.value.(type) { + case nativeFunctionObject: + return stringValue(fmt.Sprintf("function %s() { [native code] }", fn.name)) + case nodeFunctionObject: + return stringValue(fn.node.source) + case bindFunctionObject: + return stringValue("function () { [native code] }") } panic(call.runtime.panicTypeError("Function.toString()")) } -func builtinFunction_apply(call FunctionCall) Value { +func builtinFunctionApply(call FunctionCall) Value { if !call.This.isCallable() { panic(call.runtime.panicTypeError()) } this := call.Argument(0) if this.IsUndefined() { // FIXME Not ECMA5 - this = toValue_object(call.runtime.globalObject) + this = objectValue(call.runtime.globalObject) } argumentList := call.Argument(1) switch argumentList.kind { @@ -82,7 +81,7 @@ func builtinFunction_apply(call FunctionCall) Value { panic(call.runtime.panicTypeError()) } - arrayObject := argumentList._object() + arrayObject := argumentList.object() thisObject := call.thisObject() length := int64(toUint32(arrayObject.get(propertyLength))) valueArray := make([]Value, length) @@ -92,7 +91,7 @@ func builtinFunction_apply(call FunctionCall) Value { return thisObject.call(this, valueArray, false, nativeFrame) } -func builtinFunction_call(call FunctionCall) Value { +func builtinFunctionCall(call FunctionCall) Value { if !call.This.isCallable() { panic(call.runtime.panicTypeError()) } @@ -100,7 +99,7 @@ func builtinFunction_call(call FunctionCall) Value { this := call.Argument(0) if this.IsUndefined() { // FIXME Not ECMA5 - this = toValue_object(call.runtime.globalObject) + this = objectValue(call.runtime.globalObject) } if len(call.ArgumentList) >= 1 { return thisObject.call(this, call.ArgumentList[1:], false, nativeFrame) @@ -108,19 +107,19 @@ func builtinFunction_call(call FunctionCall) Value { return thisObject.call(this, nil, false, nativeFrame) } -func builtinFunction_bind(call FunctionCall) Value { +func builtinFunctionBind(call FunctionCall) Value { target := call.This if !target.isCallable() { panic(call.runtime.panicTypeError()) } - targetObject := target._object() + targetObject := target.object() this := call.Argument(0) argumentList := call.slice(1) if this.IsUndefined() { // FIXME Do this elsewhere? - this = toValue_object(call.runtime.globalObject) + this = objectValue(call.runtime.globalObject) } - return toValue_object(call.runtime.newBoundFunction(targetObject, this, argumentList)) + return objectValue(call.runtime.newBoundFunction(targetObject, this, argumentList)) } diff --git a/builtin_json.go b/builtin_json.go index adfc76f2..9d59c445 100644 --- a/builtin_json.go +++ b/builtin_json.go @@ -7,13 +7,13 @@ import ( "strings" ) -type _builtinJSON_parseContext struct { +type builtinJSONParseContext struct { call FunctionCall reviver Value } -func builtinJSON_parse(call FunctionCall) Value { - ctx := _builtinJSON_parseContext{ +func builtinJSONParse(call FunctionCall) Value { + ctx := builtinJSONParseContext{ call: call, } revive := false @@ -27,109 +27,107 @@ func builtinJSON_parse(call FunctionCall) Value { if err != nil { panic(call.runtime.panicSyntaxError(err.Error())) } - value, exists := builtinJSON_parseWalk(ctx, root) + value, exists := builtinJSONParseWalk(ctx, root) if !exists { value = Value{} } if revive { root := ctx.call.runtime.newObject() root.put("", value, false) - return builtinJSON_reviveWalk(ctx, root, "") + return builtinJSONReviveWalk(ctx, root, "") } return value } -func builtinJSON_reviveWalk(ctx _builtinJSON_parseContext, holder *_object, name string) Value { +func builtinJSONReviveWalk(ctx builtinJSONParseContext, holder *object, name string) Value { value := holder.get(name) - if object := value._object(); object != nil { - if isArray(object) { - length := int64(objectLength(object)) - for index := int64(0); index < length; index += 1 { + if obj := value.object(); obj != nil { + if isArray(obj) { + length := int64(objectLength(obj)) + for index := int64(0); index < length; index++ { name := arrayIndexToString(index) - value := builtinJSON_reviveWalk(ctx, object, name) + value := builtinJSONReviveWalk(ctx, obj, name) if value.IsUndefined() { - object.delete(name, false) + obj.delete(name, false) } else { - object.defineProperty(name, value, 0111, false) + obj.defineProperty(name, value, 0o111, false) } } } else { - object.enumerate(false, func(name string) bool { - value := builtinJSON_reviveWalk(ctx, object, name) + obj.enumerate(false, func(name string) bool { + value := builtinJSONReviveWalk(ctx, obj, name) if value.IsUndefined() { - object.delete(name, false) + obj.delete(name, false) } else { - object.defineProperty(name, value, 0111, false) + obj.defineProperty(name, value, 0o111, false) } return true }) } } - return ctx.reviver.call(ctx.call.runtime, toValue_object(holder), name, value) + return ctx.reviver.call(ctx.call.runtime, objectValue(holder), name, value) } -func builtinJSON_parseWalk(ctx _builtinJSON_parseContext, rawValue interface{}) (Value, bool) { +func builtinJSONParseWalk(ctx builtinJSONParseContext, rawValue interface{}) (Value, bool) { switch value := rawValue.(type) { case nil: return nullValue, true case bool: - return toValue_bool(value), true + return boolValue(value), true case string: - return toValue_string(value), true + return stringValue(value), true case float64: - return toValue_float64(value), true + return float64Value(value), true case []interface{}: arrayValue := make([]Value, len(value)) for index, rawValue := range value { - if value, exists := builtinJSON_parseWalk(ctx, rawValue); exists { + if value, exists := builtinJSONParseWalk(ctx, rawValue); exists { arrayValue[index] = value } } - return toValue_object(ctx.call.runtime.newArrayOf(arrayValue)), true + return objectValue(ctx.call.runtime.newArrayOf(arrayValue)), true case map[string]interface{}: - object := ctx.call.runtime.newObject() + obj := ctx.call.runtime.newObject() for name, rawValue := range value { - if value, exists := builtinJSON_parseWalk(ctx, rawValue); exists { - object.put(name, value, false) + if value, exists := builtinJSONParseWalk(ctx, rawValue); exists { + obj.put(name, value, false) } } - return toValue_object(object), true + return objectValue(obj), true } return Value{}, false } -type _builtinJSON_stringifyContext struct { +type builtinJSONStringifyContext struct { call FunctionCall - stack []*_object + stack []*object propertyList []string replacerFunction *Value gap string } -func builtinJSON_stringify(call FunctionCall) Value { - ctx := _builtinJSON_stringifyContext{ +func builtinJSONStringify(call FunctionCall) Value { + ctx := builtinJSONStringifyContext{ call: call, - stack: []*_object{nil}, + stack: []*object{nil}, } - replacer := call.Argument(1)._object() + replacer := call.Argument(1).object() if replacer != nil { if isArray(replacer) { length := objectLength(replacer) seen := map[string]bool{} propertyList := make([]string, length) length = 0 - for index, _ := range propertyList { + for index := range propertyList { value := replacer.get(arrayIndexToString(int64(index))) switch value.kind { case valueObject: - switch value.value.(*_object).class { - case classString: - case classNumber: + switch value.value.(*object).class { + case classStringName, classNumberName: default: continue } - case valueString: - case valueNumber: + case valueString, valueNumber: default: continue } @@ -138,21 +136,21 @@ func builtinJSON_stringify(call FunctionCall) Value { continue } seen[name] = true - length += 1 + length++ propertyList[index] = name } ctx.propertyList = propertyList[0:length] - } else if replacer.class == classFunction { - value := toValue_object(replacer) + } else if replacer.class == classFunctionName { + value := objectValue(replacer) ctx.replacerFunction = &value } } if spaceValue, exists := call.getArgument(2); exists { if spaceValue.kind == valueObject { - switch spaceValue.value.(*_object).class { - case classString: - spaceValue = toValue_string(spaceValue.string()) - case classNumber: + switch spaceValue.value.(*object).class { + case classStringName: + spaceValue = stringValue(spaceValue.string()) + case classNumberName: spaceValue = spaceValue.numberValue() } } @@ -176,7 +174,7 @@ func builtinJSON_stringify(call FunctionCall) Value { } holder := call.runtime.newObject() holder.put("", call.Argument(0), false) - value, exists := builtinJSON_stringifyWalk(ctx, "", holder) + value, exists := builtinJSONStringifyWalk(ctx, "", holder) if !exists { return Value{} } @@ -186,41 +184,41 @@ func builtinJSON_stringify(call FunctionCall) Value { } if ctx.gap != "" { valueJSON1 := bytes.Buffer{} - json.Indent(&valueJSON1, valueJSON, "", ctx.gap) + if err = json.Indent(&valueJSON1, valueJSON, "", ctx.gap); err != nil { + panic(call.runtime.panicTypeError(err.Error())) + } valueJSON = valueJSON1.Bytes() } - return toValue_string(string(valueJSON)) + return stringValue(string(valueJSON)) } -func builtinJSON_stringifyWalk(ctx _builtinJSON_stringifyContext, key string, holder *_object) (interface{}, bool) { +func builtinJSONStringifyWalk(ctx builtinJSONStringifyContext, key string, holder *object) (interface{}, bool) { value := holder.get(key) if value.IsObject() { - object := value._object() - if toJSON := object.get("toJSON"); toJSON.IsFunction() { + obj := value.object() + if toJSON := obj.get("toJSON"); toJSON.IsFunction() { value = toJSON.call(ctx.call.runtime, value, key) - } else { + } else if obj.objectClass.marshalJSON != nil { // If the object is a GoStruct or something that implements json.Marshaler - if object.objectClass.marshalJSON != nil { - marshaler := object.objectClass.marshalJSON(object) - if marshaler != nil { - return marshaler, true - } + marshaler := obj.objectClass.marshalJSON(obj) + if marshaler != nil { + return marshaler, true } } } if ctx.replacerFunction != nil { - value = ctx.replacerFunction.call(ctx.call.runtime, toValue_object(holder), key, value) + value = ctx.replacerFunction.call(ctx.call.runtime, objectValue(holder), key, value) } if value.kind == valueObject { - switch value.value.(*_object).class { - case classBoolean: - value = value._object().value.(Value) - case classString: - value = toValue_string(value.string()) - case classNumber: + switch value.value.(*object).class { + case classBooleanName: + value = value.object().value.(Value) + case classStringName: + value = stringValue(value.string()) + case classNumberName: value = value.numberValue() } } @@ -243,10 +241,10 @@ func builtinJSON_stringifyWalk(ctx _builtinJSON_stringifyContext, key string, ho case valueNull: return nil, true case valueObject: - holder := value._object() - if value := value._object(); nil != value { - for _, object := range ctx.stack { - if holder == object { + holder := value.object() + if value := value.object(); nil != value { + for _, obj := range ctx.stack { + if holder == obj { panic(ctx.call.runtime.panicTypeError("Converting circular structure to JSON")) } } @@ -266,33 +264,33 @@ func builtinJSON_stringifyWalk(ctx _builtinJSON_stringifyContext, key string, ho panic(ctx.call.runtime.panicTypeError(fmt.Sprintf("JSON.stringify: invalid length: %v (%[1]T)", value))) } array := make([]interface{}, length) - for index, _ := range array { + for index := range array { name := arrayIndexToString(int64(index)) - value, _ := builtinJSON_stringifyWalk(ctx, name, holder) + value, _ := builtinJSONStringifyWalk(ctx, name, holder) array[index] = value } return array, true - } else if holder.class != classFunction { - object := map[string]interface{}{} + } else if holder.class != classFunctionName { + obj := map[string]interface{}{} if ctx.propertyList != nil { for _, name := range ctx.propertyList { - value, exists := builtinJSON_stringifyWalk(ctx, name, holder) + value, exists := builtinJSONStringifyWalk(ctx, name, holder) if exists { - object[name] = value + obj[name] = value } } } else { // Go maps are without order, so this doesn't conform to the ECMA ordering // standard, but oh well... holder.enumerate(false, func(name string) bool { - value, exists := builtinJSON_stringifyWalk(ctx, name, holder) + value, exists := builtinJSONStringifyWalk(ctx, name, holder) if exists { - object[name] = value + obj[name] = value } return true }) } - return object, true + return obj, true } } return nil, false diff --git a/builtin_math.go b/builtin_math.go index 7ce90c33..1774fd8d 100644 --- a/builtin_math.go +++ b/builtin_math.go @@ -7,27 +7,27 @@ import ( // Math -func builtinMath_abs(call FunctionCall) Value { +func builtinMathAbs(call FunctionCall) Value { number := call.Argument(0).float64() - return toValue_float64(math.Abs(number)) + return float64Value(math.Abs(number)) } -func builtinMath_acos(call FunctionCall) Value { +func builtinMathAcos(call FunctionCall) Value { number := call.Argument(0).float64() - return toValue_float64(math.Acos(number)) + return float64Value(math.Acos(number)) } -func builtinMath_asin(call FunctionCall) Value { +func builtinMathAsin(call FunctionCall) Value { number := call.Argument(0).float64() - return toValue_float64(math.Asin(number)) + return float64Value(math.Asin(number)) } -func builtinMath_atan(call FunctionCall) Value { +func builtinMathAtan(call FunctionCall) Value { number := call.Argument(0).float64() - return toValue_float64(math.Atan(number)) + return float64Value(math.Atan(number)) } -func builtinMath_atan2(call FunctionCall) Value { +func builtinMathAtan2(call FunctionCall) Value { y := call.Argument(0).float64() if math.IsNaN(y) { return NaNValue() @@ -36,40 +36,40 @@ func builtinMath_atan2(call FunctionCall) Value { if math.IsNaN(x) { return NaNValue() } - return toValue_float64(math.Atan2(y, x)) + return float64Value(math.Atan2(y, x)) } -func builtinMath_cos(call FunctionCall) Value { +func builtinMathCos(call FunctionCall) Value { number := call.Argument(0).float64() - return toValue_float64(math.Cos(number)) + return float64Value(math.Cos(number)) } -func builtinMath_ceil(call FunctionCall) Value { +func builtinMathCeil(call FunctionCall) Value { number := call.Argument(0).float64() - return toValue_float64(math.Ceil(number)) + return float64Value(math.Ceil(number)) } -func builtinMath_exp(call FunctionCall) Value { +func builtinMathExp(call FunctionCall) Value { number := call.Argument(0).float64() - return toValue_float64(math.Exp(number)) + return float64Value(math.Exp(number)) } -func builtinMath_floor(call FunctionCall) Value { +func builtinMathFloor(call FunctionCall) Value { number := call.Argument(0).float64() - return toValue_float64(math.Floor(number)) + return float64Value(math.Floor(number)) } -func builtinMath_log(call FunctionCall) Value { +func builtinMathLog(call FunctionCall) Value { number := call.Argument(0).float64() - return toValue_float64(math.Log(number)) + return float64Value(math.Log(number)) } -func builtinMath_max(call FunctionCall) Value { +func builtinMathMax(call FunctionCall) Value { switch len(call.ArgumentList) { case 0: return negativeInfinityValue() case 1: - return toValue_float64(call.ArgumentList[0].float64()) + return float64Value(call.ArgumentList[0].float64()) } result := call.ArgumentList[0].float64() if math.IsNaN(result) { @@ -82,15 +82,15 @@ func builtinMath_max(call FunctionCall) Value { } result = math.Max(result, value) } - return toValue_float64(result) + return float64Value(result) } -func builtinMath_min(call FunctionCall) Value { +func builtinMathMin(call FunctionCall) Value { switch len(call.ArgumentList) { case 0: return positiveInfinityValue() case 1: - return toValue_float64(call.ArgumentList[0].float64()) + return float64Value(call.ArgumentList[0].float64()) } result := call.ArgumentList[0].float64() if math.IsNaN(result) { @@ -103,49 +103,49 @@ func builtinMath_min(call FunctionCall) Value { } result = math.Min(result, value) } - return toValue_float64(result) + return float64Value(result) } -func builtinMath_pow(call FunctionCall) Value { +func builtinMathPow(call FunctionCall) Value { // TODO Make sure this works according to the specification (15.8.2.13) x := call.Argument(0).float64() y := call.Argument(1).float64() if math.Abs(x) == 1 && math.IsInf(y, 0) { return NaNValue() } - return toValue_float64(math.Pow(x, y)) + return float64Value(math.Pow(x, y)) } -func builtinMath_random(call FunctionCall) Value { +func builtinMathRandom(call FunctionCall) Value { var v float64 if call.runtime.random != nil { v = call.runtime.random() } else { - v = rand.Float64() + v = rand.Float64() //nolint: gosec } - return toValue_float64(v) + return float64Value(v) } -func builtinMath_round(call FunctionCall) Value { +func builtinMathRound(call FunctionCall) Value { number := call.Argument(0).float64() value := math.Floor(number + 0.5) if value == 0 { value = math.Copysign(0, number) } - return toValue_float64(value) + return float64Value(value) } -func builtinMath_sin(call FunctionCall) Value { +func builtinMathSin(call FunctionCall) Value { number := call.Argument(0).float64() - return toValue_float64(math.Sin(number)) + return float64Value(math.Sin(number)) } -func builtinMath_sqrt(call FunctionCall) Value { +func builtinMathSqrt(call FunctionCall) Value { number := call.Argument(0).float64() - return toValue_float64(math.Sqrt(number)) + return float64Value(math.Sqrt(number)) } -func builtinMath_tan(call FunctionCall) Value { +func builtinMathTan(call FunctionCall) Value { number := call.Argument(0).float64() - return toValue_float64(math.Tan(number)) + return float64Value(math.Tan(number)) } diff --git a/builtin_number.go b/builtin_number.go index 202a81cb..acdeb501 100644 --- a/builtin_number.go +++ b/builtin_number.go @@ -15,20 +15,20 @@ func numberValueFromNumberArgumentList(argumentList []Value) Value { if len(argumentList) > 0 { return argumentList[0].numberValue() } - return toValue_int(0) + return intValue(0) } func builtinNumber(call FunctionCall) Value { return numberValueFromNumberArgumentList(call.ArgumentList) } -func builtinNewNumber(self *_object, argumentList []Value) Value { - return toValue_object(self.runtime.newNumber(numberValueFromNumberArgumentList(argumentList))) +func builtinNewNumber(obj *object, argumentList []Value) Value { + return objectValue(obj.runtime.newNumber(numberValueFromNumberArgumentList(argumentList))) } -func builtinNumber_toString(call FunctionCall) Value { +func builtinNumberToString(call FunctionCall) Value { // Will throw a TypeError if ThisObject is not a Number - value := call.thisClassObject(classNumber).primitiveValue() + value := call.thisClassObject(classNumberName).primitiveValue() radix := 10 radixArgument := call.Argument(0) if radixArgument.IsDefined() { @@ -39,33 +39,32 @@ func builtinNumber_toString(call FunctionCall) Value { radix = int(integer) } if radix == 10 { - return toValue_string(value.string()) + return stringValue(value.string()) } - return toValue_string(numberToStringRadix(value, radix)) + return stringValue(numberToStringRadix(value, radix)) } -func builtinNumber_valueOf(call FunctionCall) Value { - return call.thisClassObject(classNumber).primitiveValue() +func builtinNumberValueOf(call FunctionCall) Value { + return call.thisClassObject(classNumberName).primitiveValue() } -func builtinNumber_toFixed(call FunctionCall) Value { +func builtinNumberToFixed(call FunctionCall) Value { precision := toIntegerFloat(call.Argument(0)) if 20 < precision || 0 > precision { panic(call.runtime.panicRangeError("toFixed() precision must be between 0 and 20")) } if call.This.IsNaN() { - return toValue_string("NaN") + return stringValue("NaN") } - value := call.This.float64() - if math.Abs(value) >= 1e21 { - return toValue_string(floatToString(value, 64)) + if value := call.This.float64(); math.Abs(value) >= 1e21 { + return stringValue(floatToString(value, 64)) } - return toValue_string(strconv.FormatFloat(call.This.float64(), 'f', int(precision), 64)) + return stringValue(strconv.FormatFloat(call.This.float64(), 'f', int(precision), 64)) } -func builtinNumber_toExponential(call FunctionCall) Value { +func builtinNumberToExponential(call FunctionCall) Value { if call.This.IsNaN() { - return toValue_string("NaN") + return stringValue("NaN") } precision := float64(-1) if value := call.Argument(0); value.IsDefined() { @@ -74,33 +73,33 @@ func builtinNumber_toExponential(call FunctionCall) Value { panic(call.runtime.panicRangeError("toString() radix must be between 2 and 36")) } } - return toValue_string(strconv.FormatFloat(call.This.float64(), 'e', int(precision), 64)) + return stringValue(strconv.FormatFloat(call.This.float64(), 'e', int(precision), 64)) } -func builtinNumber_toPrecision(call FunctionCall) Value { +func builtinNumberToPrecision(call FunctionCall) Value { if call.This.IsNaN() { - return toValue_string("NaN") + return stringValue("NaN") } value := call.Argument(0) if value.IsUndefined() { - return toValue_string(call.This.string()) + return stringValue(call.This.string()) } precision := toIntegerFloat(value) if 1 > precision { panic(call.runtime.panicRangeError("toPrecision() precision must be greater than 1")) } - return toValue_string(strconv.FormatFloat(call.This.float64(), 'g', int(precision), 64)) + return stringValue(strconv.FormatFloat(call.This.float64(), 'g', int(precision), 64)) } -func builtinNumber_isNaN(call FunctionCall) Value { +func builtinNumberIsNaN(call FunctionCall) Value { if len(call.ArgumentList) < 1 { - return toValue_bool(false) + return boolValue(false) } - return toValue_bool(call.Argument(0).IsNaN()) + return boolValue(call.Argument(0).IsNaN()) } -func builtinNumber_toLocaleString(call FunctionCall) Value { - value := call.thisClassObject(classNumber).primitiveValue() +func builtinNumberToLocaleString(call FunctionCall) Value { + value := call.thisClassObject(classNumberName).primitiveValue() locale := call.Argument(0) lang := defaultLanguage if locale.IsDefined() { @@ -108,5 +107,5 @@ func builtinNumber_toLocaleString(call FunctionCall) Value { } p := message.NewPrinter(lang) - return toValue_string(p.Sprintf("%v", number.Decimal(value.value))) + return stringValue(p.Sprintf("%v", number.Decimal(value.value))) } diff --git a/builtin_object.go b/builtin_object.go index f9a39d3f..0592c487 100644 --- a/builtin_object.go +++ b/builtin_object.go @@ -10,36 +10,36 @@ func builtinObject(call FunctionCall) Value { value := call.Argument(0) switch value.kind { case valueUndefined, valueNull: - return toValue_object(call.runtime.newObject()) + return objectValue(call.runtime.newObject()) } - return toValue_object(call.runtime.toObject(value)) + return objectValue(call.runtime.toObject(value)) } -func builtinNewObject(self *_object, argumentList []Value) Value { +func builtinNewObject(obj *object, argumentList []Value) Value { value := valueOfArrayIndex(argumentList, 0) switch value.kind { case valueNull, valueUndefined: case valueNumber, valueString, valueBoolean: - return toValue_object(self.runtime.toObject(value)) + return objectValue(obj.runtime.toObject(value)) case valueObject: return value default: } - return toValue_object(self.runtime.newObject()) + return objectValue(obj.runtime.newObject()) } -func builtinObject_valueOf(call FunctionCall) Value { - return toValue_object(call.thisObject()) +func builtinObjectValueOf(call FunctionCall) Value { + return objectValue(call.thisObject()) } -func builtinObject_hasOwnProperty(call FunctionCall) Value { +func builtinObjectHasOwnProperty(call FunctionCall) Value { propertyName := call.Argument(0).string() thisObject := call.thisObject() - return toValue_bool(thisObject.hasOwnProperty(propertyName)) + return boolValue(thisObject.hasOwnProperty(propertyName)) } -func builtinObject_isPrototypeOf(call FunctionCall) Value { +func builtinObjectIsPrototypeOf(call FunctionCall) Value { value := call.Argument(0) if !value.IsObject() { return falseValue @@ -55,29 +55,30 @@ func builtinObject_isPrototypeOf(call FunctionCall) Value { return falseValue } -func builtinObject_propertyIsEnumerable(call FunctionCall) Value { +func builtinObjectPropertyIsEnumerable(call FunctionCall) Value { propertyName := call.Argument(0).string() thisObject := call.thisObject() - property := thisObject.getOwnProperty(propertyName) - if property != nil && property.enumerable() { + prop := thisObject.getOwnProperty(propertyName) + if prop != nil && prop.enumerable() { return trueValue } return falseValue } -func builtinObject_toString(call FunctionCall) Value { +func builtinObjectToString(call FunctionCall) Value { var result string - if call.This.IsUndefined() { + switch { + case call.This.IsUndefined(): result = "[object Undefined]" - } else if call.This.IsNull() { + case call.This.IsNull(): result = "[object Null]" - } else { + default: result = fmt.Sprintf("[object %s]", call.thisObject().class) } - return toValue_string(result) + return stringValue(result) } -func builtinObject_toLocaleString(call FunctionCall) Value { +func builtinObjectToLocaleString(call FunctionCall) Value { toString := call.thisObject().get("toString") if !toString.isCallable() { panic(call.runtime.panicTypeError()) @@ -85,205 +86,205 @@ func builtinObject_toLocaleString(call FunctionCall) Value { return toString.call(call.runtime, call.This) } -func builtinObject_getPrototypeOf(call FunctionCall) Value { - objectValue := call.Argument(0) - object := objectValue._object() - if object == nil { +func builtinObjectGetPrototypeOf(call FunctionCall) Value { + val := call.Argument(0) + obj := val.object() + if obj == nil { panic(call.runtime.panicTypeError()) } - if object.prototype == nil { + if obj.prototype == nil { return nullValue } - return toValue_object(object.prototype) + return objectValue(obj.prototype) } -func builtinObject_getOwnPropertyDescriptor(call FunctionCall) Value { - objectValue := call.Argument(0) - object := objectValue._object() - if object == nil { +func builtinObjectGetOwnPropertyDescriptor(call FunctionCall) Value { + val := call.Argument(0) + obj := val.object() + if obj == nil { panic(call.runtime.panicTypeError()) } name := call.Argument(1).string() - descriptor := object.getOwnProperty(name) + descriptor := obj.getOwnProperty(name) if descriptor == nil { return Value{} } - return toValue_object(call.runtime.fromPropertyDescriptor(*descriptor)) + return objectValue(call.runtime.fromPropertyDescriptor(*descriptor)) } -func builtinObject_defineProperty(call FunctionCall) Value { - objectValue := call.Argument(0) - object := objectValue._object() - if object == nil { +func builtinObjectDefineProperty(call FunctionCall) Value { + val := call.Argument(0) + obj := val.object() + if obj == nil { panic(call.runtime.panicTypeError()) } name := call.Argument(1).string() descriptor := toPropertyDescriptor(call.runtime, call.Argument(2)) - object.defineOwnProperty(name, descriptor, true) - return objectValue + obj.defineOwnProperty(name, descriptor, true) + return val } -func builtinObject_defineProperties(call FunctionCall) Value { - objectValue := call.Argument(0) - object := objectValue._object() - if object == nil { +func builtinObjectDefineProperties(call FunctionCall) Value { + val := call.Argument(0) + obj := val.object() + if obj == nil { panic(call.runtime.panicTypeError()) } properties := call.runtime.toObject(call.Argument(1)) properties.enumerate(false, func(name string) bool { descriptor := toPropertyDescriptor(call.runtime, properties.get(name)) - object.defineOwnProperty(name, descriptor, true) + obj.defineOwnProperty(name, descriptor, true) return true }) - return objectValue + return val } -func builtinObject_create(call FunctionCall) Value { +func builtinObjectCreate(call FunctionCall) Value { prototypeValue := call.Argument(0) if !prototypeValue.IsNull() && !prototypeValue.IsObject() { panic(call.runtime.panicTypeError()) } - object := call.runtime.newObject() - object.prototype = prototypeValue._object() + obj := call.runtime.newObject() + obj.prototype = prototypeValue.object() propertiesValue := call.Argument(1) if propertiesValue.IsDefined() { properties := call.runtime.toObject(propertiesValue) properties.enumerate(false, func(name string) bool { descriptor := toPropertyDescriptor(call.runtime, properties.get(name)) - object.defineOwnProperty(name, descriptor, true) + obj.defineOwnProperty(name, descriptor, true) return true }) } - return toValue_object(object) + return objectValue(obj) } -func builtinObject_isExtensible(call FunctionCall) Value { - object := call.Argument(0) - if object := object._object(); object != nil { - return toValue_bool(object.extensible) +func builtinObjectIsExtensible(call FunctionCall) Value { + val := call.Argument(0) + if obj := val.object(); obj != nil { + return boolValue(obj.extensible) } panic(call.runtime.panicTypeError()) } -func builtinObject_preventExtensions(call FunctionCall) Value { - object := call.Argument(0) - if object := object._object(); object != nil { - object.extensible = false +func builtinObjectPreventExtensions(call FunctionCall) Value { + val := call.Argument(0) + if obj := val.object(); obj != nil { + obj.extensible = false } else { panic(call.runtime.panicTypeError()) } - return object + return val } -func builtinObject_isSealed(call FunctionCall) Value { - object := call.Argument(0) - if object := object._object(); object != nil { - if object.extensible { - return toValue_bool(false) +func builtinObjectIsSealed(call FunctionCall) Value { + val := call.Argument(0) + if obj := val.object(); obj != nil { + if obj.extensible { + return boolValue(false) } result := true - object.enumerate(true, func(name string) bool { - property := object.getProperty(name) - if property.configurable() { + obj.enumerate(true, func(name string) bool { + prop := obj.getProperty(name) + if prop.configurable() { result = false } return true }) - return toValue_bool(result) + return boolValue(result) } panic(call.runtime.panicTypeError()) } -func builtinObject_seal(call FunctionCall) Value { - object := call.Argument(0) - if object := object._object(); object != nil { - object.enumerate(true, func(name string) bool { - if property := object.getOwnProperty(name); nil != property && property.configurable() { - property.configureOff() - object.defineOwnProperty(name, *property, true) +func builtinObjectSeal(call FunctionCall) Value { + val := call.Argument(0) + if obj := val.object(); obj != nil { + obj.enumerate(true, func(name string) bool { + if prop := obj.getOwnProperty(name); nil != prop && prop.configurable() { + prop.configureOff() + obj.defineOwnProperty(name, *prop, true) } return true }) - object.extensible = false + obj.extensible = false } else { panic(call.runtime.panicTypeError()) } - return object + return val } -func builtinObject_isFrozen(call FunctionCall) Value { - object := call.Argument(0) - if object := object._object(); object != nil { - if object.extensible { - return toValue_bool(false) +func builtinObjectIsFrozen(call FunctionCall) Value { + val := call.Argument(0) + if obj := val.object(); obj != nil { + if obj.extensible { + return boolValue(false) } result := true - object.enumerate(true, func(name string) bool { - property := object.getProperty(name) - if property.configurable() || property.writable() { + obj.enumerate(true, func(name string) bool { + prop := obj.getProperty(name) + if prop.configurable() || prop.writable() { result = false } return true }) - return toValue_bool(result) + return boolValue(result) } panic(call.runtime.panicTypeError()) } -func builtinObject_freeze(call FunctionCall) Value { - object := call.Argument(0) - if object := object._object(); object != nil { - object.enumerate(true, func(name string) bool { - if property, update := object.getOwnProperty(name), false; nil != property { - if property.isDataDescriptor() && property.writable() { - property.writeOff() +func builtinObjectFreeze(call FunctionCall) Value { + val := call.Argument(0) + if obj := val.object(); obj != nil { + obj.enumerate(true, func(name string) bool { + if prop, update := obj.getOwnProperty(name), false; nil != prop { + if prop.isDataDescriptor() && prop.writable() { + prop.writeOff() update = true } - if property.configurable() { - property.configureOff() + if prop.configurable() { + prop.configureOff() update = true } if update { - object.defineOwnProperty(name, *property, true) + obj.defineOwnProperty(name, *prop, true) } } return true }) - object.extensible = false + obj.extensible = false } else { panic(call.runtime.panicTypeError()) } - return object + return val } -func builtinObject_keys(call FunctionCall) Value { - if object, keys := call.Argument(0)._object(), []Value(nil); nil != object { - object.enumerate(false, func(name string) bool { - keys = append(keys, toValue_string(name)) +func builtinObjectKeys(call FunctionCall) Value { + if obj, keys := call.Argument(0).object(), []Value(nil); nil != obj { + obj.enumerate(false, func(name string) bool { + keys = append(keys, stringValue(name)) return true }) - return toValue_object(call.runtime.newArrayOf(keys)) + return objectValue(call.runtime.newArrayOf(keys)) } panic(call.runtime.panicTypeError()) } -func builtinObject_getOwnPropertyNames(call FunctionCall) Value { - if object, propertyNames := call.Argument(0)._object(), []Value(nil); nil != object { - object.enumerate(true, func(name string) bool { - if object.hasOwnProperty(name) { - propertyNames = append(propertyNames, toValue_string(name)) +func builtinObjectGetOwnPropertyNames(call FunctionCall) Value { + if obj, propertyNames := call.Argument(0).object(), []Value(nil); nil != obj { + obj.enumerate(true, func(name string) bool { + if obj.hasOwnProperty(name) { + propertyNames = append(propertyNames, stringValue(name)) } return true }) - return toValue_object(call.runtime.newArrayOf(propertyNames)) + return objectValue(call.runtime.newArrayOf(propertyNames)) } panic(call.runtime.panicTypeError()) } diff --git a/builtin_regexp.go b/builtin_regexp.go index b577bcc2..f96078d0 100644 --- a/builtin_regexp.go +++ b/builtin_regexp.go @@ -9,22 +9,22 @@ import ( func builtinRegExp(call FunctionCall) Value { pattern := call.Argument(0) flags := call.Argument(1) - if object := pattern._object(); object != nil { - if object.class == classRegExp && flags.IsUndefined() { + if obj := pattern.object(); obj != nil { + if obj.class == classRegExpName && flags.IsUndefined() { return pattern } } - return toValue_object(call.runtime.newRegExp(pattern, flags)) + return objectValue(call.runtime.newRegExp(pattern, flags)) } -func builtinNewRegExp(self *_object, argumentList []Value) Value { - return toValue_object(self.runtime.newRegExp( +func builtinNewRegExp(obj *object, argumentList []Value) Value { + return objectValue(obj.runtime.newRegExp( valueOfArrayIndex(argumentList, 0), valueOfArrayIndex(argumentList, 1), )) } -func builtinRegExp_toString(call FunctionCall) Value { +func builtinRegExpToString(call FunctionCall) Value { thisObject := call.thisObject() source := thisObject.get("source").string() flags := []byte{} @@ -37,32 +37,32 @@ func builtinRegExp_toString(call FunctionCall) Value { if thisObject.get("multiline").bool() { flags = append(flags, 'm') } - return toValue_string(fmt.Sprintf("/%s/%s", source, flags)) + return stringValue(fmt.Sprintf("/%s/%s", source, flags)) } -func builtinRegExp_exec(call FunctionCall) Value { +func builtinRegExpExec(call FunctionCall) Value { thisObject := call.thisObject() target := call.Argument(0).string() match, result := execRegExp(thisObject, target) if !match { return nullValue } - return toValue_object(execResultToArray(call.runtime, target, result)) + return objectValue(execResultToArray(call.runtime, target, result)) } -func builtinRegExp_test(call FunctionCall) Value { +func builtinRegExpTest(call FunctionCall) Value { thisObject := call.thisObject() target := call.Argument(0).string() match, result := execRegExp(thisObject, target) if !match { - return toValue_bool(match) + return boolValue(match) } // Match extract and assign input, $_ and $1 -> $9 on global RegExp. - input := toValue_string(target) - call.runtime.global.RegExp.defineProperty("$_", input, 0100, false) - call.runtime.global.RegExp.defineProperty("input", input, 0100, false) + input := stringValue(target) + call.runtime.global.RegExp.defineProperty("$_", input, 0o100, false) + call.runtime.global.RegExp.defineProperty("input", input, 0o100, false) var start int n := 1 @@ -71,7 +71,7 @@ func builtinRegExp_test(call FunctionCall) Value { if i%2 == 0 { start = v } else { - re.defineProperty(fmt.Sprintf("$%d", n), toValue_string(target[start:v]), 0100, false) + re.defineProperty(fmt.Sprintf("$%d", n), stringValue(target[start:v]), 0o100, false) n++ if n == 10 { break @@ -81,16 +81,16 @@ func builtinRegExp_test(call FunctionCall) Value { if n <= 9 { // Erase remaining. - empty := toValue_string("") + empty := stringValue("") for i := n; i <= 9; i++ { - re.defineProperty(fmt.Sprintf("$%d", i), empty, 0100, false) + re.defineProperty(fmt.Sprintf("$%d", i), empty, 0o100, false) } } - return toValue_bool(match) + return boolValue(match) } -func builtinRegExp_compile(call FunctionCall) Value { +func builtinRegExpCompile(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. diff --git a/builtin_string.go b/builtin_string.go index 3ac24ea6..e32b71f2 100644 --- a/builtin_string.go +++ b/builtin_string.go @@ -13,62 +13,63 @@ import ( func stringValueFromStringArgumentList(argumentList []Value) Value { if len(argumentList) > 0 { - return toValue_string(argumentList[0].string()) + return stringValue(argumentList[0].string()) } - return toValue_string("") + return stringValue("") } func builtinString(call FunctionCall) Value { return stringValueFromStringArgumentList(call.ArgumentList) } -func builtinNewString(self *_object, argumentList []Value) Value { - return toValue_object(self.runtime.newString(stringValueFromStringArgumentList(argumentList))) +func builtinNewString(obj *object, argumentList []Value) Value { + return objectValue(obj.runtime.newString(stringValueFromStringArgumentList(argumentList))) } -func builtinString_toString(call FunctionCall) Value { - return call.thisClassObject(classString).primitiveValue() +func builtinStringToString(call FunctionCall) Value { + return call.thisClassObject(classStringName).primitiveValue() } -func builtinString_valueOf(call FunctionCall) Value { - return call.thisClassObject(classString).primitiveValue() + +func builtinStringValueOf(call FunctionCall) Value { + return call.thisClassObject(classStringName).primitiveValue() } -func builtinString_fromCharCode(call FunctionCall) Value { +func builtinStringFromCharCode(call FunctionCall) Value { chrList := make([]uint16, len(call.ArgumentList)) for index, value := range call.ArgumentList { chrList[index] = toUint16(value) } - return toValue_string16(chrList) + return string16Value(chrList) } -func builtinString_charAt(call FunctionCall) Value { +func builtinStringCharAt(call FunctionCall) Value { checkObjectCoercible(call.runtime, call.This) idx := int(call.Argument(0).number().int64) - chr := stringAt(call.This._object().stringValue(), idx) + chr := stringAt(call.This.object().stringValue(), idx) if chr == utf8.RuneError { - return toValue_string("") + return stringValue("") } - return toValue_string(string(chr)) + return stringValue(string(chr)) } -func builtinString_charCodeAt(call FunctionCall) Value { +func builtinStringCharCodeAt(call FunctionCall) Value { checkObjectCoercible(call.runtime, call.This) idx := int(call.Argument(0).number().int64) - chr := stringAt(call.This._object().stringValue(), idx) + chr := stringAt(call.This.object().stringValue(), idx) if chr == utf8.RuneError { return NaNValue() } - return toValue_uint16(uint16(chr)) + return uint16Value(uint16(chr)) } -func builtinString_concat(call FunctionCall) Value { +func builtinStringConcat(call FunctionCall) Value { checkObjectCoercible(call.runtime, call.This) var value bytes.Buffer value.WriteString(call.This.string()) for _, item := range call.ArgumentList { value.WriteString(item.string()) } - return toValue_string(value.String()) + return stringValue(value.String()) } func lastIndexRune(s, substr string) int { @@ -89,44 +90,44 @@ func utf16Length(s string) int { return len(utf16.Encode([]rune(s))) } -func builtinString_indexOf(call FunctionCall) Value { +func builtinStringIndexOf(call FunctionCall) Value { checkObjectCoercible(call.runtime, call.This) value := call.This.string() target := call.Argument(0).string() if 2 > len(call.ArgumentList) { - return toValue_int(indexRune(value, target)) + return intValue(indexRune(value, target)) } start := toIntegerFloat(call.Argument(1)) if 0 > start { start = 0 } else if start >= float64(len(value)) { if target == "" { - return toValue_int(len(value)) + return intValue(len(value)) } - return toValue_int(-1) + return intValue(-1) } index := indexRune(value[int(start):], target) if index >= 0 { index += int(start) } - return toValue_int(index) + return intValue(index) } -func builtinString_lastIndexOf(call FunctionCall) Value { +func builtinStringLastIndexOf(call FunctionCall) Value { 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(lastIndexRune(value, target)) + return intValue(lastIndexRune(value, target)) } length := len(value) if length == 0 { - return toValue_int(lastIndexRune(value, target)) + return intValue(lastIndexRune(value, target)) } 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(lastIndexRune(value, target)) + return intValue(lastIndexRune(value, target)) } if 0 > start.int64 { start.int64 = 0 @@ -135,15 +136,15 @@ func builtinString_lastIndexOf(call FunctionCall) Value { if end > length { end = length } - return toValue_int(lastIndexRune(value[:end], target)) + return intValue(lastIndexRune(value[:end], target)) } -func builtinString_match(call FunctionCall) Value { +func builtinStringMatch(call FunctionCall) Value { checkObjectCoercible(call.runtime, call.This) target := call.This.string() matcherValue := call.Argument(0) - matcher := matcherValue._object() - if !matcherValue.IsObject() || matcher.class != classRegExp { + matcher := matcherValue.object() + if !matcherValue.IsObject() || matcher.class != classRegExpName { matcher = call.runtime.newRegExp(matcherValue, Value{}) } global := matcher.get("global").bool() @@ -152,34 +153,32 @@ func builtinString_match(call FunctionCall) Value { if !match { return nullValue } - return toValue_object(execResultToArray(call.runtime, target, result)) + return objectValue(execResultToArray(call.runtime, target, result)) } - { - result := matcher.regExpValue().regularExpression.FindAllStringIndex(target, -1) - if result == nil { - matcher.put("lastIndex", toValue_int(0), true) - return Value{} // !match - } - matchCount := len(result) - valueArray := make([]Value, matchCount) - for index := 0; index < matchCount; index++ { - valueArray[index] = toValue_string(target[result[index][0]:result[index][1]]) - } - matcher.put("lastIndex", toValue_int(result[matchCount-1][1]), true) - return toValue_object(call.runtime.newArrayOf(valueArray)) + result := matcher.regExpValue().regularExpression.FindAllStringIndex(target, -1) + if result == nil { + matcher.put("lastIndex", intValue(0), true) + return Value{} // !match + } + matchCount := len(result) + valueArray := make([]Value, matchCount) + for index := 0; index < matchCount; index++ { + valueArray[index] = stringValue(target[result[index][0]:result[index][1]]) } + matcher.put("lastIndex", intValue(result[matchCount-1][1]), true) + return objectValue(call.runtime.newArrayOf(valueArray)) } -var builtinString_replace_Regexp = regexp.MustCompile("\\$(?:[\\$\\&\\'\\`1-9]|0[1-9]|[1-9][0-9])") +var builtinStringReplaceRegexp = regexp.MustCompile("\\$(?:[\\$\\&\\'\\`1-9]|0[1-9]|[1-9][0-9])") -func builtinString_findAndReplaceString(input []byte, lastIndex int, match []int, target []byte, replaceValue []byte) (output []byte) { +func builtinStringFindAndReplaceString(input []byte, lastIndex int, match []int, target []byte, replaceValue []byte) []byte { matchCount := len(match) / 2 - output = input + output := input if match[0] != lastIndex { output = append(output, target[lastIndex:match[0]]...) } - replacement := builtinString_replace_Regexp.ReplaceAllFunc(replaceValue, func(part []byte) []byte { + replacement := builtinStringReplaceRegexp.ReplaceAllFunc(replaceValue, func(part []byte) []byte { // TODO Check if match[0] or match[1] can be -1 in this scenario switch part[1] { case '$': @@ -193,37 +192,38 @@ func builtinString_findAndReplaceString(input []byte, lastIndex int, match []int } matchNumberParse, err := strconv.ParseInt(string(part[1:]), 10, 64) if err != nil { - return []byte{} + return nil } matchNumber := int(matchNumberParse) if matchNumber >= matchCount { - return []byte{} + return nil } offset := 2 * matchNumber if match[offset] != -1 { return target[match[offset]:match[offset+1]] } - return []byte{} // The empty string + return nil // The empty string }) - output = append(output, replacement...) - return output + + return append(output, replacement...) } -func builtinString_replace(call FunctionCall) Value { +func builtinStringReplace(call FunctionCall) Value { checkObjectCoercible(call.runtime, call.This) target := []byte(call.This.string()) searchValue := call.Argument(0) - searchObject := searchValue._object() + searchObject := searchValue.object() // TODO If a capture is -1? var search *regexp.Regexp global := false find := 1 - if searchValue.IsObject() && searchObject.class == classRegExp { + if searchValue.IsObject() && searchObject.class == classRegExpName { regExp := searchObject.regExpValue() search = regExp.regularExpression if regExp.global { find = -1 + global = true } } else { search = regexp.MustCompile(regexp.QuoteMeta(searchValue.string())) @@ -231,73 +231,70 @@ func builtinString_replace(call FunctionCall) Value { found := search.FindAllSubmatchIndex(target, find) if found == nil { - return toValue_string(string(target)) // !match - } - - { - lastIndex := 0 - result := []byte{} - - replaceValue := call.Argument(1) - if replaceValue.isCallable() { - target := string(target) - replace := replaceValue._object() - for _, match := range found { - if match[0] != lastIndex { - result = append(result, target[lastIndex:match[0]]...) - } - matchCount := len(match) / 2 - argumentList := make([]Value, matchCount+2) - for index := 0; index < matchCount; index++ { - offset := 2 * index - if match[offset] != -1 { - argumentList[index] = toValue_string(target[match[offset]:match[offset+1]]) - } else { - argumentList[index] = Value{} - } - } - argumentList[matchCount+0] = toValue_int(match[0]) - argumentList[matchCount+1] = toValue_string(target) - replacement := replace.call(Value{}, argumentList, false, nativeFrame).string() - result = append(result, []byte(replacement)...) - lastIndex = match[1] + return stringValue(string(target)) // !match + } + + lastIndex := 0 + result := []byte{} + replaceValue := call.Argument(1) + if replaceValue.isCallable() { + target := string(target) + replace := replaceValue.object() + for _, match := range found { + if match[0] != lastIndex { + result = append(result, target[lastIndex:match[0]]...) } - } else { - replace := []byte(replaceValue.string()) - for _, match := range found { - result = builtinString_findAndReplaceString(result, lastIndex, match, target, replace) - lastIndex = match[1] + matchCount := len(match) / 2 + argumentList := make([]Value, matchCount+2) + for index := 0; index < matchCount; index++ { + offset := 2 * index + if match[offset] != -1 { + argumentList[index] = stringValue(target[match[offset]:match[offset+1]]) + } else { + argumentList[index] = Value{} + } } + argumentList[matchCount+0] = intValue(match[0]) + argumentList[matchCount+1] = stringValue(target) + replacement := replace.call(Value{}, argumentList, false, nativeFrame).string() + result = append(result, []byte(replacement)...) + lastIndex = match[1] } - - if lastIndex != len(target) { - result = append(result, target[lastIndex:]...) + } else { + replace := []byte(replaceValue.string()) + for _, match := range found { + result = builtinStringFindAndReplaceString(result, lastIndex, match, target, replace) + lastIndex = match[1] } + } - if global && searchObject != nil { - searchObject.put("lastIndex", toValue_int(lastIndex), true) - } + if lastIndex != len(target) { + result = append(result, target[lastIndex:]...) + } - return toValue_string(string(result)) + if global && searchObject != nil { + searchObject.put("lastIndex", intValue(lastIndex), true) } + + return stringValue(string(result)) } -func builtinString_search(call FunctionCall) Value { +func builtinStringSearch(call FunctionCall) Value { checkObjectCoercible(call.runtime, call.This) target := call.This.string() searchValue := call.Argument(0) - search := searchValue._object() - if !searchValue.IsObject() || search.class != classRegExp { + search := searchValue.object() + if !searchValue.IsObject() || search.class != classRegExpName { search = call.runtime.newRegExp(searchValue, Value{}) } result := search.regExpValue().regularExpression.FindStringIndex(target) if result == nil { - return toValue_int(-1) + return intValue(-1) } - return toValue_int(result[0]) + return intValue(result[0]) } -func builtinString_split(call FunctionCall) Value { +func builtinStringSplit(call FunctionCall) Value { checkObjectCoercible(call.runtime, call.This) target := call.This.string() @@ -309,16 +306,16 @@ func builtinString_split(call FunctionCall) Value { } if limit == 0 { - return toValue_object(call.runtime.newArray(0)) + return objectValue(call.runtime.newArray(0)) } if separatorValue.IsUndefined() { - return toValue_object(call.runtime.newArrayOf([]Value{toValue_string(target)})) + return objectValue(call.runtime.newArrayOf([]Value{stringValue(target)})) } if separatorValue.isRegExp() { targetLength := len(target) - search := separatorValue._object().regExpValue().regularExpression + search := separatorValue.object().regExpValue().regularExpression valueArray := []Value{} result := search.FindAllStringSubmatchIndex(target, -1) lastIndex := 0 @@ -333,11 +330,11 @@ func builtinString_split(call FunctionCall) Value { } if lastIndex != match[0] { - valueArray = append(valueArray, toValue_string(target[lastIndex:match[0]])) + valueArray = append(valueArray, stringValue(target[lastIndex:match[0]])) found++ } else if lastIndex == match[0] { if lastIndex != -1 { - valueArray = append(valueArray, toValue_string("")) + valueArray = append(valueArray, stringValue("")) found++ } } @@ -352,7 +349,7 @@ func builtinString_split(call FunctionCall) Value { offset := index * 2 value := Value{} if match[offset] != -1 { - value = toValue_string(target[match[offset]:match[offset+1]]) + value = stringValue(target[match[offset]:match[offset+1]]) } valueArray = append(valueArray, value) found++ @@ -364,14 +361,14 @@ func builtinString_split(call FunctionCall) Value { if found != limit { if lastIndex != targetLength { - valueArray = append(valueArray, toValue_string(target[lastIndex:targetLength])) + valueArray = append(valueArray, stringValue(target[lastIndex:targetLength])) } else { - valueArray = append(valueArray, toValue_string("")) + valueArray = append(valueArray, stringValue("")) } } RETURN: - return toValue_object(call.runtime.newArrayOf(valueArray)) + return objectValue(call.runtime.newArrayOf(valueArray)) } else { separator := separatorValue.string() @@ -390,26 +387,26 @@ func builtinString_split(call FunctionCall) Value { valueArray := make([]Value, len(split)) for index, value := range split { - valueArray[index] = toValue_string(value) + valueArray[index] = stringValue(value) } - return toValue_object(call.runtime.newArrayOf(valueArray)) + return objectValue(call.runtime.newArrayOf(valueArray)) } } -func builtinString_slice(call FunctionCall) Value { +func builtinStringSlice(call FunctionCall) Value { checkObjectCoercible(call.runtime, call.This) target := call.This.string() length := int64(len(target)) start, end := rangeStartEnd(call.ArgumentList, length, false) if end-start <= 0 { - return toValue_string("") + return stringValue("") } - return toValue_string(string(target[start:end])) + return stringValue(target[start:end]) } -func builtinString_substring(call FunctionCall) Value { +func builtinStringSubstring(call FunctionCall) Value { checkObjectCoercible(call.runtime, call.This) target := []rune(call.This.string()) @@ -418,21 +415,21 @@ func builtinString_substring(call FunctionCall) Value { if start > end { start, end = end, start } - return toValue_string(string(target[start:end])) + return stringValue(string(target[start:end])) } -func builtinString_substr(call FunctionCall) Value { +func builtinStringSubstr(call FunctionCall) Value { target := []rune(call.This.string()) size := int64(len(target)) start, length := rangeStartLength(call.ArgumentList, size) if start >= size { - return toValue_string("") + return stringValue("") } if length <= 0 { - return toValue_string("") + return stringValue("") } if start+length >= size { @@ -443,66 +440,58 @@ func builtinString_substr(call FunctionCall) Value { length = size - start } - return toValue_string(string(target[start : start+length])) + return stringValue(string(target[start : start+length])) } -func builtinString_toLowerCase(call FunctionCall) Value { +func builtinStringToLowerCase(call FunctionCall) Value { checkObjectCoercible(call.runtime, call.This) - return toValue_string(strings.ToLower(call.This.string())) + return stringValue(strings.ToLower(call.This.string())) } -func builtinString_toUpperCase(call FunctionCall) Value { +func builtinStringToUpperCase(call FunctionCall) Value { checkObjectCoercible(call.runtime, call.This) - return toValue_string(strings.ToUpper(call.This.string())) + return stringValue(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" +// 7.2 Table 2 — Whitespace Characters & 7.3 Table 3 - Line Terminator Characters. +const builtinStringTrimWhitespace = "\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 { +func builtinStringTrim(call FunctionCall) Value { checkObjectCoercible(call.runtime, call.This) return toValue(strings.Trim(call.This.string(), - builtinString_trim_whitespace)) + builtinStringTrimWhitespace)) } -// Mozilla extension, not ECMAScript 5 -func builtinString_trimLeft(call FunctionCall) Value { +// Mozilla extension, not ECMAScript 5. +func builtinStringTrimLeft(call FunctionCall) Value { checkObjectCoercible(call.runtime, call.This) return toValue(strings.TrimLeft(call.This.string(), - builtinString_trim_whitespace)) + builtinStringTrimWhitespace)) } -// Mozilla extension, not ECMAScript 5 -func builtinString_trimRight(call FunctionCall) Value { +// Mozilla extension, not ECMAScript 5. +func builtinStringTrimRight(call FunctionCall) Value { checkObjectCoercible(call.runtime, call.This) return toValue(strings.TrimRight(call.This.string(), - builtinString_trim_whitespace)) + builtinStringTrimWhitespace)) } -func builtinString_localeCompare(call FunctionCall) Value { +func builtinStringLocaleCompare(call FunctionCall) Value { checkObjectCoercible(call.runtime, call.This) - this := call.This.string() + this := call.This.string() //nolint: ifshort that := call.Argument(0).string() if this < that { - return toValue_int(-1) + return intValue(-1) } else if this == that { - return toValue_int(0) + return intValue(0) } - return toValue_int(1) -} - -/* -An alternate version of String.trim -func builtinString_trim(call FunctionCall) Value { - checkObjectCoercible(call.This) - return toValue_string(strings.TrimFunc(call.string(.This), isWhiteSpaceOrLineTerminator)) + return intValue(1) } -*/ -func builtinString_toLocaleLowerCase(call FunctionCall) Value { - return builtinString_toLowerCase(call) +func builtinStringToLocaleLowerCase(call FunctionCall) Value { + return builtinStringToLowerCase(call) } -func builtinString_toLocaleUpperCase(call FunctionCall) Value { - return builtinString_toUpperCase(call) +func builtinStringToLocaleUpperCase(call FunctionCall) Value { + return builtinStringToUpperCase(call) } diff --git a/builtin_test.go b/builtin_test.go index c43b5798..f6adc304 100644 --- a/builtin_test.go +++ b/builtin_test.go @@ -93,25 +93,25 @@ func TestString_substr(t *testing.T) { func Test_builtin_escape(t *testing.T) { tt(t, func() { - is(builtin_escape("abc"), "abc") + is(builtinEscape("abc"), "abc") - is(builtin_escape("="), "%3D") + is(builtinEscape("="), "%3D") - is(builtin_escape("abc=%+32"), "abc%3D%25+32") + is(builtinEscape("abc=%+32"), "abc%3D%25+32") - is(builtin_escape("世界"), "%u4E16%u754C") + is(builtinEscape("世界"), "%u4E16%u754C") }) } func Test_builtin_unescape(t *testing.T) { tt(t, func() { - is(builtin_unescape("abc"), "abc") + is(builtinUnescape("abc"), "abc") - is(builtin_unescape("=%3D"), "==") + is(builtinUnescape("=%3D"), "==") - is(builtin_unescape("abc%3D%25+32"), "abc=%+32") + is(builtinUnescape("abc%3D%25+32"), "abc=%+32") - is(builtin_unescape("%u4E16%u754C"), "世界") + is(builtinUnescape("%u4E16%u754C"), "世界") }) } diff --git a/call_test.go b/call_test.go index 349696a2..52fb6983 100644 --- a/call_test.go +++ b/call_test.go @@ -3,6 +3,8 @@ package otto import ( "reflect" "testing" + + "github.com/stretchr/testify/require" ) const ( @@ -11,361 +13,561 @@ const ( func BenchmarkNativeCallWithString(b *testing.B) { vm := New() - vm.Set("x", func(a1 string) {}) - s, _ := vm.Compile("test.js", `x("zzz")`) + err := vm.Set("x", func(a1 string) {}) + require.NoError(b, err) + + s, err := vm.Compile("test.js", `x("zzz")`) + require.NoError(b, err) + for i := 0; i < b.N; i++ { - vm.Run(s) + _, err := vm.Run(s) + require.NoError(b, err) } } func BenchmarkNativeCallWithFloat32(b *testing.B) { vm := New() - vm.Set("x", func(a1 float32) {}) - s, _ := vm.Compile("test.js", `x(1.1)`) + err := vm.Set("x", func(a1 float32) {}) + require.NoError(b, err) + + s, err := vm.Compile("test.js", `x(1.1)`) + require.NoError(b, err) + for i := 0; i < b.N; i++ { - vm.Run(s) + _, err := vm.Run(s) + require.NoError(b, err) } } func BenchmarkNativeCallWithFloat64(b *testing.B) { vm := New() - vm.Set("x", func(a1 float64) {}) - s, _ := vm.Compile("test.js", `x(1.1)`) + err := vm.Set("x", func(a1 float64) {}) + require.NoError(b, err) + + s, err := vm.Compile("test.js", `x(1.1)`) + require.NoError(b, err) + for i := 0; i < b.N; i++ { - vm.Run(s) + _, err := vm.Run(s) + require.NoError(b, err) } } func BenchmarkNativeCallWithInt(b *testing.B) { vm := New() - vm.Set("x", func(a1 int) {}) - s, _ := vm.Compile("test.js", `x(1)`) + err := vm.Set("x", func(a1 int) {}) + require.NoError(b, err) + + s, err := vm.Compile("test.js", `x(1)`) + require.NoError(b, err) + for i := 0; i < b.N; i++ { - vm.Run(s) + _, err := vm.Run(s) + require.NoError(b, err) } } func BenchmarkNativeCallWithUint(b *testing.B) { vm := New() - vm.Set("x", func(a1 uint) {}) - s, _ := vm.Compile("test.js", `x(1)`) + err := vm.Set("x", func(a1 uint) {}) + require.NoError(b, err) + + s, err := vm.Compile("test.js", `x(1)`) + require.NoError(b, err) + for i := 0; i < b.N; i++ { - vm.Run(s) + _, err := vm.Run(s) + require.NoError(b, err) } } func BenchmarkNativeCallWithInt8(b *testing.B) { vm := New() - vm.Set("x", func(a1 int8) {}) - s, _ := vm.Compile("test.js", `x(1)`) + err := vm.Set("x", func(a1 int8) {}) + require.NoError(b, err) + + s, err := vm.Compile("test.js", `x(1)`) + require.NoError(b, err) + for i := 0; i < b.N; i++ { - vm.Run(s) + _, err := vm.Run(s) + require.NoError(b, err) } } func BenchmarkNativeCallWithUint8(b *testing.B) { vm := New() - vm.Set("x", func(a1 uint8) {}) - s, _ := vm.Compile("test.js", `x(1)`) + err := vm.Set("x", func(a1 uint8) {}) + require.NoError(b, err) + + s, err := vm.Compile("test.js", `x(1)`) + require.NoError(b, err) + for i := 0; i < b.N; i++ { - vm.Run(s) + _, err := vm.Run(s) + require.NoError(b, err) } } func BenchmarkNativeCallWithInt16(b *testing.B) { vm := New() - vm.Set("x", func(a1 int16) {}) - s, _ := vm.Compile("test.js", `x(1)`) + err := vm.Set("x", func(a1 int16) {}) + require.NoError(b, err) + + s, err := vm.Compile("test.js", `x(1)`) + require.NoError(b, err) + for i := 0; i < b.N; i++ { - vm.Run(s) + _, err := vm.Run(s) + require.NoError(b, err) } } func BenchmarkNativeCallWithUint16(b *testing.B) { vm := New() - vm.Set("x", func(a1 uint16) {}) - s, _ := vm.Compile("test.js", `x(1)`) + err := vm.Set("x", func(a1 uint16) {}) + require.NoError(b, err) + + s, err := vm.Compile("test.js", `x(1)`) + require.NoError(b, err) + for i := 0; i < b.N; i++ { - vm.Run(s) + _, err := vm.Run(s) + require.NoError(b, err) } } func BenchmarkNativeCallWithInt32(b *testing.B) { vm := New() - vm.Set("x", func(a1 int32) {}) - s, _ := vm.Compile("test.js", `x(1)`) + err := vm.Set("x", func(a1 int32) {}) + require.NoError(b, err) + + s, err := vm.Compile("test.js", `x(1)`) + require.NoError(b, err) + for i := 0; i < b.N; i++ { - vm.Run(s) + _, err := vm.Run(s) + require.NoError(b, err) } } func BenchmarkNativeCallWithUint32(b *testing.B) { vm := New() - vm.Set("x", func(a1 uint32) {}) - s, _ := vm.Compile("test.js", `x(1)`) + err := vm.Set("x", func(a1 uint32) {}) + require.NoError(b, err) + + s, err := vm.Compile("test.js", `x(1)`) + require.NoError(b, err) + for i := 0; i < b.N; i++ { - vm.Run(s) + _, err := vm.Run(s) + require.NoError(b, err) } } func BenchmarkNativeCallWithInt64(b *testing.B) { vm := New() - vm.Set("x", func(a1 int64) {}) - s, _ := vm.Compile("test.js", `x(1)`) + err := vm.Set("x", func(a1 int64) {}) + require.NoError(b, err) + + s, err := vm.Compile("test.js", `x(1)`) + require.NoError(b, err) + for i := 0; i < b.N; i++ { - vm.Run(s) + _, err := vm.Run(s) + require.NoError(b, err) } } func BenchmarkNativeCallWithUint64(b *testing.B) { vm := New() - vm.Set("x", func(a1 uint64) {}) - s, _ := vm.Compile("test.js", `x(1)`) + err := vm.Set("x", func(a1 uint64) {}) + require.NoError(b, err) + + s, err := vm.Compile("test.js", `x(1)`) + require.NoError(b, err) + for i := 0; i < b.N; i++ { - vm.Run(s) + _, err := vm.Run(s) + require.NoError(b, err) } } func BenchmarkNativeCallWithStringInt(b *testing.B) { vm := New() - vm.Set("x", func(a1 string, a2 int) {}) - s, _ := vm.Compile("test.js", `x("zzz", 1)`) + err := vm.Set("x", func(a1 string, a2 int) {}) + require.NoError(b, err) + + s, err := vm.Compile("test.js", `x("zzz", 1)`) + require.NoError(b, err) + for i := 0; i < b.N; i++ { - vm.Run(s) + _, err := vm.Run(s) + require.NoError(b, err) } } func BenchmarkNativeCallWithIntVariadic0(b *testing.B) { vm := New() - vm.Set("x", func(a ...int) {}) - s, _ := vm.Compile("test.js", `x()`) + err := vm.Set("x", func(a ...int) {}) + require.NoError(b, err) + + s, err := vm.Compile("test.js", `x()`) + require.NoError(b, err) + for i := 0; i < b.N; i++ { - vm.Run(s) + _, err := vm.Run(s) + require.NoError(b, err) } } func BenchmarkNativeCallWithIntVariadic1(b *testing.B) { vm := New() - vm.Set("x", func(a ...int) {}) - s, _ := vm.Compile("test.js", `x(1)`) + err := vm.Set("x", func(a ...int) {}) + require.NoError(b, err) + + s, err := vm.Compile("test.js", `x(1)`) + require.NoError(b, err) + for i := 0; i < b.N; i++ { - vm.Run(s) + _, err := vm.Run(s) + require.NoError(b, err) } } func BenchmarkNativeCallWithIntVariadic3(b *testing.B) { vm := New() - vm.Set("x", func(a ...int) {}) - s, _ := vm.Compile("test.js", `x(1, 2, 3)`) + err := vm.Set("x", func(a ...int) {}) + require.NoError(b, err) + + s, err := vm.Compile("test.js", `x(1, 2, 3)`) + require.NoError(b, err) + for i := 0; i < b.N; i++ { - vm.Run(s) + _, err := vm.Run(s) + require.NoError(b, err) } } func BenchmarkNativeCallWithIntVariadic10(b *testing.B) { vm := New() - vm.Set("x", func(a ...int) {}) - s, _ := vm.Compile("test.js", `x(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)`) + err := vm.Set("x", func(a ...int) {}) + require.NoError(b, err) + + s, err := vm.Compile("test.js", `x(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)`) + require.NoError(b, err) + for i := 0; i < b.N; i++ { - vm.Run(s) + _, err := vm.Run(s) + require.NoError(b, err) } } func BenchmarkNativeCallWithIntArray0(b *testing.B) { vm := New() - vm.Set("x", func(a []int) {}) - s, _ := vm.Compile("test.js", `x([])`) + err := vm.Set("x", func(a []int) {}) + require.NoError(b, err) + + s, err := vm.Compile("test.js", `x([])`) + require.NoError(b, err) + for i := 0; i < b.N; i++ { - vm.Run(s) + _, err := vm.Run(s) + require.NoError(b, err) } } func BenchmarkNativeCallWithIntArray1(b *testing.B) { vm := New() - vm.Set("x", func(a []int) {}) - s, _ := vm.Compile("test.js", `x([1])`) + err := vm.Set("x", func(a []int) {}) + require.NoError(b, err) + + s, err := vm.Compile("test.js", `x([1])`) + require.NoError(b, err) + for i := 0; i < b.N; i++ { - vm.Run(s) + _, err := vm.Run(s) + require.NoError(b, err) } } func BenchmarkNativeCallWithIntArray3(b *testing.B) { vm := New() - vm.Set("x", func(a []int) {}) - s, _ := vm.Compile("test.js", `x([1, 2, 3])`) + err := vm.Set("x", func(a []int) {}) + require.NoError(b, err) + + s, err := vm.Compile("test.js", `x([1, 2, 3])`) + require.NoError(b, err) + for i := 0; i < b.N; i++ { - vm.Run(s) + _, err := vm.Run(s) + require.NoError(b, err) } } func BenchmarkNativeCallWithIntArray10(b *testing.B) { vm := New() - vm.Set("x", func(a []int) {}) - s, _ := vm.Compile("test.js", `x([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])`) + err := vm.Set("x", func(a []int) {}) + require.NoError(b, err) + + s, err := vm.Compile("test.js", `x([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])`) + require.NoError(b, err) + for i := 0; i < b.N; i++ { - vm.Run(s) + _, err := vm.Run(s) + require.NoError(b, err) } } func BenchmarkNativeCallWithIntVariadicArray0(b *testing.B) { vm := New() - vm.Set("x", func(a ...int) {}) - s, _ := vm.Compile("test.js", `x([])`) + err := vm.Set("x", func(a ...int) {}) + require.NoError(b, err) + + s, err := vm.Compile("test.js", `x([])`) + require.NoError(b, err) + for i := 0; i < b.N; i++ { - vm.Run(s) + _, err := vm.Run(s) + require.NoError(b, err) } } func BenchmarkNativeCallWithIntVariadicArray1(b *testing.B) { vm := New() - vm.Set("x", func(a ...int) {}) - s, _ := vm.Compile("test.js", `x([1])`) + err := vm.Set("x", func(a ...int) {}) + require.NoError(b, err) + + s, err := vm.Compile("test.js", `x([1])`) + require.NoError(b, err) + for i := 0; i < b.N; i++ { - vm.Run(s) + _, err := vm.Run(s) + require.NoError(b, err) } } func BenchmarkNativeCallWithIntVariadicArray3(b *testing.B) { vm := New() - vm.Set("x", func(a ...int) {}) - s, _ := vm.Compile("test.js", `x([1, 2, 3])`) + err := vm.Set("x", func(a ...int) {}) + require.NoError(b, err) + + s, err := vm.Compile("test.js", `x([1, 2, 3])`) + require.NoError(b, err) + for i := 0; i < b.N; i++ { - vm.Run(s) + _, err := vm.Run(s) + require.NoError(b, err) } } func BenchmarkNativeCallWithIntVariadicArray10(b *testing.B) { vm := New() - vm.Set("x", func(a ...int) {}) - s, _ := vm.Compile("test.js", `x([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])`) + err := vm.Set("x", func(a ...int) {}) + require.NoError(b, err) + + s, err := vm.Compile("test.js", `x([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])`) + require.NoError(b, err) + for i := 0; i < b.N; i++ { - vm.Run(s) + _, err := vm.Run(s) + require.NoError(b, err) } } func BenchmarkNativeCallWithStringIntVariadic0(b *testing.B) { vm := New() - vm.Set("x", func(a1 string, a2 ...int) {}) - s, _ := vm.Compile("test.js", `x("a")`) + err := vm.Set("x", func(a1 string, a2 ...int) {}) + require.NoError(b, err) + + s, err := vm.Compile("test.js", `x("a")`) + require.NoError(b, err) + for i := 0; i < b.N; i++ { - vm.Run(s) + _, err := vm.Run(s) + require.NoError(b, err) } } func BenchmarkNativeCallWithStringIntVariadic1(b *testing.B) { vm := New() - vm.Set("x", func(a1 string, a2 ...int) {}) - s, _ := vm.Compile("test.js", `x("a", 1)`) + err := vm.Set("x", func(a1 string, a2 ...int) {}) + require.NoError(b, err) + + s, err := vm.Compile("test.js", `x("a", 1)`) + require.NoError(b, err) + for i := 0; i < b.N; i++ { - vm.Run(s) + _, err := vm.Run(s) + require.NoError(b, err) } } func BenchmarkNativeCallWithStringIntVariadic3(b *testing.B) { vm := New() - vm.Set("x", func(a1 string, a2 ...int) {}) - s, _ := vm.Compile("test.js", `x("a", 1, 2, 3)`) + err := vm.Set("x", func(a1 string, a2 ...int) {}) + require.NoError(b, err) + + s, err := vm.Compile("test.js", `x("a", 1, 2, 3)`) + require.NoError(b, err) + for i := 0; i < b.N; i++ { - vm.Run(s) + _, err := vm.Run(s) + require.NoError(b, err) } } func BenchmarkNativeCallWithStringIntVariadic10(b *testing.B) { vm := New() - vm.Set("x", func(a1 string, a2 ...int) {}) - s, _ := vm.Compile("test.js", `x("a", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10)`) + err := vm.Set("x", func(a1 string, a2 ...int) {}) + require.NoError(b, err) + + s, err := vm.Compile("test.js", `x("a", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10)`) + require.NoError(b, err) + for i := 0; i < b.N; i++ { - vm.Run(s) + _, err := vm.Run(s) + require.NoError(b, err) } } func BenchmarkNativeCallWithStringIntVariadicArray0(b *testing.B) { vm := New() - vm.Set("x", func(a1 string, a2 ...int) {}) - s, _ := vm.Compile("test.js", `x("a", [])`) + err := vm.Set("x", func(a1 string, a2 ...int) {}) + require.NoError(b, err) + + s, err := vm.Compile("test.js", `x("a", [])`) + require.NoError(b, err) + for i := 0; i < b.N; i++ { - vm.Run(s) + _, err := vm.Run(s) + require.NoError(b, err) } } func BenchmarkNativeCallWithStringIntVariadicArray1(b *testing.B) { vm := New() - vm.Set("x", func(a1 string, a2 ...int) {}) - s, _ := vm.Compile("test.js", `x("a", [1])`) + err := vm.Set("x", func(a1 string, a2 ...int) {}) + require.NoError(b, err) + + s, err := vm.Compile("test.js", `x("a", [1])`) + require.NoError(b, err) + for i := 0; i < b.N; i++ { - vm.Run(s) + _, err := vm.Run(s) + require.NoError(b, err) } } func BenchmarkNativeCallWithStringIntVariadicArray3(b *testing.B) { vm := New() - vm.Set("x", func(a1 string, a2 ...int) {}) - s, _ := vm.Compile("test.js", `x("a", [1, 2, 3])`) + err := vm.Set("x", func(a1 string, a2 ...int) {}) + require.NoError(b, err) + + s, err := vm.Compile("test.js", `x("a", [1, 2, 3])`) + require.NoError(b, err) + for i := 0; i < b.N; i++ { - vm.Run(s) + _, err := vm.Run(s) + require.NoError(b, err) } } func BenchmarkNativeCallWithStringIntVariadicArray10(b *testing.B) { vm := New() - vm.Set("x", func(a1 string, a2 ...int) {}) - s, _ := vm.Compile("test.js", `x("a", [1, 2, 3, 4, 5, 6, 7, 8, 9, 10])`) + err := vm.Set("x", func(a1 string, a2 ...int) {}) + require.NoError(b, err) + + s, err := vm.Compile("test.js", `x("a", [1, 2, 3, 4, 5, 6, 7, 8, 9, 10])`) + require.NoError(b, err) + for i := 0; i < b.N; i++ { - vm.Run(s) + _, err := vm.Run(s) + require.NoError(b, err) } } func BenchmarkNativeCallWithMap(b *testing.B) { vm := New() - vm.Set("x", func(a map[string]string) {}) - s, _ := vm.Compile("test.js", `x({a: "b", c: "d"})`) + err := vm.Set("x", func(a map[string]string) {}) + require.NoError(b, err) + + s, err := vm.Compile("test.js", `x({a: "b", c: "d"})`) + require.NoError(b, err) + for i := 0; i < b.N; i++ { - vm.Run(s) + _, err := vm.Run(s) + require.NoError(b, err) } } func BenchmarkNativeCallWithMapVariadic(b *testing.B) { vm := New() - vm.Set("x", func(a ...map[string]string) {}) - s, _ := vm.Compile("test.js", `x({a: "b", c: "d"}, {w: "x", y: "z"})`) + err := vm.Set("x", func(a ...map[string]string) {}) + require.NoError(b, err) + + s, err := vm.Compile("test.js", `x({a: "b", c: "d"}, {w: "x", y: "z"})`) + require.NoError(b, err) + for i := 0; i < b.N; i++ { - vm.Run(s) + _, err := vm.Run(s) + require.NoError(b, err) } } func BenchmarkNativeCallWithMapVariadicArray(b *testing.B) { vm := New() - vm.Set("x", func(a ...map[string]string) {}) - s, _ := vm.Compile("test.js", `x([{a: "b", c: "d"}, {w: "x", y: "z"}])`) + err := vm.Set("x", func(a ...map[string]string) {}) + require.NoError(b, err) + + s, err := vm.Compile("test.js", `x([{a: "b", c: "d"}, {w: "x", y: "z"}])`) + require.NoError(b, err) + for i := 0; i < b.N; i++ { - vm.Run(s) + _, err := vm.Run(s) + require.NoError(b, err) } } func BenchmarkNativeCallWithFunction(b *testing.B) { vm := New() - vm.Set("x", func(a func()) {}) - s, _ := vm.Compile("test.js", `x(function() {})`) + err := vm.Set("x", func(a func()) {}) + require.NoError(b, err) + + s, err := vm.Compile("test.js", `x(function() {})`) + require.NoError(b, err) + for i := 0; i < b.N; i++ { - vm.Run(s) + _, err := vm.Run(s) + require.NoError(b, err) } } func BenchmarkNativeCallWithFunctionInt(b *testing.B) { vm := New() - vm.Set("x", func(a func(int)) {}) - s, _ := vm.Compile("test.js", `x(function(n) {})`) + err := vm.Set("x", func(a func(int)) {}) + require.NoError(b, err) + + s, err := vm.Compile("test.js", `x(function(n) {})`) + require.NoError(b, err) + for i := 0; i < b.N; i++ { - vm.Run(s) + _, err := vm.Run(s) + require.NoError(b, err) } } func BenchmarkNativeCallWithFunctionString(b *testing.B) { vm := New() - vm.Set("x", func(a func(string)) {}) - s, _ := vm.Compile("test.js", `x(function(n) {})`) + err := vm.Set("x", func(a func(string)) {}) + require.NoError(b, err) + + s, err := vm.Compile("test.js", `x(function(n) {})`) + require.NoError(b, err) + for i := 0; i < b.N; i++ { - vm.Run(s) + _, err := vm.Run(s) + require.NoError(b, err) } } @@ -374,15 +576,17 @@ func TestNativeCallWithString(t *testing.T) { called := false - vm.Set("x", func(a1 string) { + err := vm.Set("x", func(a1 string) { if a1 != "zzz" { t.Fail() } called = true }) + require.NoError(t, err) - s, _ := vm.Compile("test.js", `x("zzz")`) + s, err := vm.Compile("test.js", `x("zzz")`) + require.NoError(t, err) if _, err := vm.Run(s); err != nil { t.Logf("err should have been nil; was %s\n", err.Error()) @@ -399,15 +603,17 @@ func TestNativeCallWithFloat32(t *testing.T) { called := false - vm.Set("x", func(a1 float32) { + err := vm.Set("x", func(a1 float32) { if a1 != 1.1 { t.Fail() } called = true }) + require.NoError(t, err) - s, _ := vm.Compile("test.js", `x(1.1)`) + s, err := vm.Compile("test.js", `x(1.1)`) + require.NoError(t, err) if _, err := vm.Run(s); err != nil { t.Logf("err should have been nil; was %s\n", err.Error()) @@ -424,15 +630,17 @@ func TestNativeCallWithFloat64(t *testing.T) { called := false - vm.Set("x", func(a1 float64) { + err := vm.Set("x", func(a1 float64) { if a1 != 1.1 { t.Fail() } called = true }) + require.NoError(t, err) - s, _ := vm.Compile("test.js", `x(1.1)`) + s, err := vm.Compile("test.js", `x(1.1)`) + require.NoError(t, err) if _, err := vm.Run(s); err != nil { t.Logf("err should have been nil; was %s\n", err.Error()) @@ -449,15 +657,17 @@ func TestNativeCallWithInt(t *testing.T) { called := false - vm.Set("x", func(a1 int) { + err := vm.Set("x", func(a1 int) { if a1 != 1 { t.Fail() } called = true }) + require.NoError(t, err) - s, _ := vm.Compile("test.js", `x(1)`) + s, err := vm.Compile("test.js", `x(1)`) + require.NoError(t, err) if _, err := vm.Run(s); err != nil { t.Logf("err should have been nil; was %s\n", err.Error()) @@ -474,15 +684,17 @@ func TestNativeCallWithUint(t *testing.T) { called := false - vm.Set("x", func(a1 uint) { + err := vm.Set("x", func(a1 uint) { if a1 != 1 { t.Fail() } called = true }) + require.NoError(t, err) - s, _ := vm.Compile("test.js", `x(1)`) + s, err := vm.Compile("test.js", `x(1)`) + require.NoError(t, err) if _, err := vm.Run(s); err != nil { t.Logf("err should have been nil; was %s\n", err.Error()) @@ -499,15 +711,17 @@ func TestNativeCallWithInt8(t *testing.T) { called := false - vm.Set("x", func(a1 int8) { + err := vm.Set("x", func(a1 int8) { if a1 != 1 { t.Fail() } called = true }) + require.NoError(t, err) - s, _ := vm.Compile("test.js", `x(1)`) + s, err := vm.Compile("test.js", `x(1)`) + require.NoError(t, err) if _, err := vm.Run(s); err != nil { t.Logf("err should have been nil; was %s\n", err.Error()) @@ -524,15 +738,17 @@ func TestNativeCallWithUint8(t *testing.T) { called := false - vm.Set("x", func(a1 uint8) { + err := vm.Set("x", func(a1 uint8) { if a1 != 1 { t.Fail() } called = true }) + require.NoError(t, err) - s, _ := vm.Compile("test.js", `x(1)`) + s, err := vm.Compile("test.js", `x(1)`) + require.NoError(t, err) if _, err := vm.Run(s); err != nil { t.Logf("err should have been nil; was %s\n", err.Error()) @@ -549,15 +765,17 @@ func TestNativeCallWithInt16(t *testing.T) { called := false - vm.Set("x", func(a1 int16) { + err := vm.Set("x", func(a1 int16) { if a1 != 1 { t.Fail() } called = true }) + require.NoError(t, err) - s, _ := vm.Compile("test.js", `x(1)`) + s, err := vm.Compile("test.js", `x(1)`) + require.NoError(t, err) if _, err := vm.Run(s); err != nil { t.Logf("err should have been nil; was %s\n", err.Error()) @@ -574,15 +792,17 @@ func TestNativeCallWithUint16(t *testing.T) { called := false - vm.Set("x", func(a1 uint16) { + err := vm.Set("x", func(a1 uint16) { if a1 != 1 { t.Fail() } called = true }) + require.NoError(t, err) - s, _ := vm.Compile("test.js", `x(1)`) + s, err := vm.Compile("test.js", `x(1)`) + require.NoError(t, err) if _, err := vm.Run(s); err != nil { t.Logf("err should have been nil; was %s\n", err.Error()) @@ -599,15 +819,17 @@ func TestNativeCallWithInt32(t *testing.T) { called := false - vm.Set("x", func(a1 int32) { + err := vm.Set("x", func(a1 int32) { if a1 != 1 { t.Fail() } called = true }) + require.NoError(t, err) - s, _ := vm.Compile("test.js", `x(1)`) + s, err := vm.Compile("test.js", `x(1)`) + require.NoError(t, err) if _, err := vm.Run(s); err != nil { t.Logf("err should have been nil; was %s\n", err.Error()) @@ -624,15 +846,17 @@ func TestNativeCallWithUint32(t *testing.T) { called := false - vm.Set("x", func(a1 uint32) { + err := vm.Set("x", func(a1 uint32) { if a1 != 1 { t.Fail() } called = true }) + require.NoError(t, err) - s, _ := vm.Compile("test.js", `x(1)`) + s, err := vm.Compile("test.js", `x(1)`) + require.NoError(t, err) if _, err := vm.Run(s); err != nil { t.Logf("err should have been nil; was %s\n", err.Error()) @@ -649,15 +873,17 @@ func TestNativeCallWithInt64(t *testing.T) { called := false - vm.Set("x", func(a1 int64) { + err := vm.Set("x", func(a1 int64) { if a1 != 1 { t.Fail() } called = true }) + require.NoError(t, err) - s, _ := vm.Compile("test.js", `x(1)`) + s, err := vm.Compile("test.js", `x(1)`) + require.NoError(t, err) if _, err := vm.Run(s); err != nil { t.Logf("err should have been nil; was %s\n", err.Error()) @@ -674,15 +900,17 @@ func TestNativeCallWithUint64(t *testing.T) { called := false - vm.Set("x", func(a1 uint64) { + err := vm.Set("x", func(a1 uint64) { if a1 != 1 { t.Fail() } called = true }) + require.NoError(t, err) - s, _ := vm.Compile("test.js", `x(1)`) + s, err := vm.Compile("test.js", `x(1)`) + require.NoError(t, err) if _, err := vm.Run(s); err != nil { t.Logf("err should have been nil; was %s\n", err.Error()) @@ -699,15 +927,17 @@ func TestNativeCallWithStringInt(t *testing.T) { called := false - vm.Set("x", func(a1 string, a2 int) { + err := vm.Set("x", func(a1 string, a2 int) { if a1 != "zzz" || a2 != 1 { t.Fail() } called = true }) + require.NoError(t, err) - s, _ := vm.Compile("test.js", `x("zzz", 1)`) + s, err := vm.Compile("test.js", `x("zzz", 1)`) + require.NoError(t, err) if _, err := vm.Run(s); err != nil { t.Logf("err should have been nil; was %s\n", err.Error()) @@ -724,15 +954,17 @@ func TestNativeCallWithIntVariadic0(t *testing.T) { called := false - vm.Set("x", func(a ...int) { + err := vm.Set("x", func(a ...int) { if !reflect.DeepEqual(a, []int{}) { t.Fail() } called = true }) + require.NoError(t, err) - s, _ := vm.Compile("test.js", `x()`) + s, err := vm.Compile("test.js", `x()`) + require.NoError(t, err) if _, err := vm.Run(s); err != nil { t.Logf("err should have been nil; was %s\n", err.Error()) @@ -749,15 +981,17 @@ func TestNativeCallWithIntVariadic1(t *testing.T) { called := false - vm.Set("x", func(a ...int) { + err := vm.Set("x", func(a ...int) { if !reflect.DeepEqual(a, []int{1}) { t.Fail() } called = true }) + require.NoError(t, err) - s, _ := vm.Compile("test.js", `x(1)`) + s, err := vm.Compile("test.js", `x(1)`) + require.NoError(t, err) if _, err := vm.Run(s); err != nil { t.Logf("err should have been nil; was %s\n", err.Error()) @@ -774,15 +1008,17 @@ func TestNativeCallWithIntVariadic3(t *testing.T) { called := false - vm.Set("x", func(a ...int) { + err := vm.Set("x", func(a ...int) { if !reflect.DeepEqual(a, []int{1, 2, 3}) { t.Fail() } called = true }) + require.NoError(t, err) - s, _ := vm.Compile("test.js", `x(1, 2, 3)`) + s, err := vm.Compile("test.js", `x(1, 2, 3)`) + require.NoError(t, err) if _, err := vm.Run(s); err != nil { t.Logf("err should have been nil; was %s\n", err.Error()) @@ -799,15 +1035,17 @@ func TestNativeCallWithIntVariadic10(t *testing.T) { called := false - vm.Set("x", func(a ...int) { + err := vm.Set("x", func(a ...int) { if !reflect.DeepEqual(a, []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}) { t.Fail() } called = true }) + require.NoError(t, err) - s, _ := vm.Compile("test.js", `x(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)`) + s, err := vm.Compile("test.js", `x(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)`) + require.NoError(t, err) if _, err := vm.Run(s); err != nil { t.Logf("err should have been nil; was %s\n", err.Error()) @@ -824,15 +1062,17 @@ func TestNativeCallWithIntArray0(t *testing.T) { called := false - vm.Set("x", func(a []int) { + err := vm.Set("x", func(a []int) { if !reflect.DeepEqual(a, []int{}) { t.Fail() } called = true }) + require.NoError(t, err) - s, _ := vm.Compile("test.js", `x([])`) + s, err := vm.Compile("test.js", `x([])`) + require.NoError(t, err) if _, err := vm.Run(s); err != nil { t.Logf("err should have been nil; was %s\n", err.Error()) @@ -849,15 +1089,17 @@ func TestNativeCallWithIntArray1(t *testing.T) { called := false - vm.Set("x", func(a []int) { + err := vm.Set("x", func(a []int) { if !reflect.DeepEqual(a, []int{1}) { t.Fail() } called = true }) + require.NoError(t, err) - s, _ := vm.Compile("test.js", `x([1])`) + s, err := vm.Compile("test.js", `x([1])`) + require.NoError(t, err) if _, err := vm.Run(s); err != nil { t.Logf("err should have been nil; was %s\n", err.Error()) @@ -874,15 +1116,17 @@ func TestNativeCallWithIntArray3(t *testing.T) { called := false - vm.Set("x", func(a []int) { + err := vm.Set("x", func(a []int) { if !reflect.DeepEqual(a, []int{1, 2, 3}) { t.Fail() } called = true }) + require.NoError(t, err) - s, _ := vm.Compile("test.js", `x([1, 2, 3])`) + s, err := vm.Compile("test.js", `x([1, 2, 3])`) + require.NoError(t, err) if _, err := vm.Run(s); err != nil { t.Logf("err should have been nil; was %s\n", err.Error()) @@ -899,15 +1143,17 @@ func TestNativeCallWithIntArray10(t *testing.T) { called := false - vm.Set("x", func(a []int) { + err := vm.Set("x", func(a []int) { if !reflect.DeepEqual(a, []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}) { t.Fail() } called = true }) + require.NoError(t, err) - s, _ := vm.Compile("test.js", `x([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])`) + s, err := vm.Compile("test.js", `x([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])`) + require.NoError(t, err) if _, err := vm.Run(s); err != nil { t.Logf("err should have been nil; was %s\n", err.Error()) @@ -924,15 +1170,17 @@ func TestNativeCallWithIntVariadicArray0(t *testing.T) { called := false - vm.Set("x", func(a ...int) { + err := vm.Set("x", func(a ...int) { if !reflect.DeepEqual(a, []int{}) { t.Fail() } called = true }) + require.NoError(t, err) - s, _ := vm.Compile("test.js", `x([])`) + s, err := vm.Compile("test.js", `x([])`) + require.NoError(t, err) if _, err := vm.Run(s); err != nil { t.Logf("err should have been nil; was %s\n", err.Error()) @@ -949,15 +1197,17 @@ func TestNativeCallWithIntVariadicArray1(t *testing.T) { called := false - vm.Set("x", func(a ...int) { + err := vm.Set("x", func(a ...int) { if !reflect.DeepEqual(a, []int{1}) { t.Fail() } called = true }) + require.NoError(t, err) - s, _ := vm.Compile("test.js", `x([1])`) + s, err := vm.Compile("test.js", `x([1])`) + require.NoError(t, err) if _, err := vm.Run(s); err != nil { t.Logf("err should have been nil; was %s\n", err.Error()) @@ -974,15 +1224,17 @@ func TestNativeCallWithIntVariadicArray3(t *testing.T) { called := false - vm.Set("x", func(a ...int) { + err := vm.Set("x", func(a ...int) { if !reflect.DeepEqual(a, []int{1, 2, 3}) { t.Fail() } called = true }) + require.NoError(t, err) - s, _ := vm.Compile("test.js", `x([1, 2, 3])`) + s, err := vm.Compile("test.js", `x([1, 2, 3])`) + require.NoError(t, err) if _, err := vm.Run(s); err != nil { t.Logf("err should have been nil; was %s\n", err.Error()) @@ -999,15 +1251,17 @@ func TestNativeCallWithIntVariadicArray10(t *testing.T) { called := false - vm.Set("x", func(a ...int) { + err := vm.Set("x", func(a ...int) { if !reflect.DeepEqual(a, []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}) { t.Fail() } called = true }) + require.NoError(t, err) - s, _ := vm.Compile("test.js", `x([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])`) + s, err := vm.Compile("test.js", `x([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])`) + require.NoError(t, err) if _, err := vm.Run(s); err != nil { t.Logf("err should have been nil; was %s\n", err.Error()) @@ -1024,15 +1278,17 @@ func TestNativeCallWithStringIntVariadic0(t *testing.T) { called := false - vm.Set("x", func(a1 string, a2 ...int) { + err := vm.Set("x", func(a1 string, a2 ...int) { if a1 != "a" || !reflect.DeepEqual(a2, []int{}) { t.Fail() } called = true }) + require.NoError(t, err) - s, _ := vm.Compile("test.js", `x("a")`) + s, err := vm.Compile("test.js", `x("a")`) + require.NoError(t, err) if _, err := vm.Run(s); err != nil { t.Logf("err should have been nil; was %s\n", err.Error()) @@ -1049,15 +1305,17 @@ func TestNativeCallWithStringIntVariadic1(t *testing.T) { called := false - vm.Set("x", func(a1 string, a2 ...int) { + err := vm.Set("x", func(a1 string, a2 ...int) { if a1 != "a" || !reflect.DeepEqual(a2, []int{1}) { t.Fail() } called = true }) + require.NoError(t, err) - s, _ := vm.Compile("test.js", `x("a", 1)`) + s, err := vm.Compile("test.js", `x("a", 1)`) + require.NoError(t, err) if _, err := vm.Run(s); err != nil { t.Logf("err should have been nil; was %s\n", err.Error()) @@ -1074,15 +1332,17 @@ func TestNativeCallWithStringIntVariadic3(t *testing.T) { called := false - vm.Set("x", func(a1 string, a2 ...int) { + err := vm.Set("x", func(a1 string, a2 ...int) { if a1 != "a" || !reflect.DeepEqual(a2, []int{1, 2, 3}) { t.Fail() } called = true }) + require.NoError(t, err) - s, _ := vm.Compile("test.js", `x("a", 1, 2, 3)`) + s, err := vm.Compile("test.js", `x("a", 1, 2, 3)`) + require.NoError(t, err) if _, err := vm.Run(s); err != nil { t.Logf("err should have been nil; was %s\n", err.Error()) @@ -1099,15 +1359,17 @@ func TestNativeCallWithStringIntVariadic10(t *testing.T) { called := false - vm.Set("x", func(a1 string, a2 ...int) { + err := vm.Set("x", func(a1 string, a2 ...int) { if a1 != "a" || !reflect.DeepEqual(a2, []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}) { t.Fail() } called = true }) + require.NoError(t, err) - s, _ := vm.Compile("test.js", `x("a", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10)`) + s, err := vm.Compile("test.js", `x("a", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10)`) + require.NoError(t, err) if _, err := vm.Run(s); err != nil { t.Logf("err should have been nil; was %s\n", err.Error()) @@ -1124,15 +1386,17 @@ func TestNativeCallWithStringIntVariadicArray0(t *testing.T) { called := false - vm.Set("x", func(a1 string, a2 ...int) { + err := vm.Set("x", func(a1 string, a2 ...int) { if a1 != "a" || !reflect.DeepEqual(a2, []int{}) { t.Fail() } called = true }) + require.NoError(t, err) - s, _ := vm.Compile("test.js", `x("a", [])`) + s, err := vm.Compile("test.js", `x("a", [])`) + require.NoError(t, err) if _, err := vm.Run(s); err != nil { t.Logf("err should have been nil; was %s\n", err.Error()) @@ -1149,15 +1413,17 @@ func TestNativeCallWithStringIntVariadicArray1(t *testing.T) { called := false - vm.Set("x", func(a1 string, a2 ...int) { + err := vm.Set("x", func(a1 string, a2 ...int) { if a1 != "a" || !reflect.DeepEqual(a2, []int{1}) { t.Fail() } called = true }) + require.NoError(t, err) - s, _ := vm.Compile("test.js", `x("a", [1])`) + s, err := vm.Compile("test.js", `x("a", [1])`) + require.NoError(t, err) if _, err := vm.Run(s); err != nil { t.Logf("err should have been nil; was %s\n", err.Error()) @@ -1174,15 +1440,17 @@ func TestNativeCallWithStringIntVariadicArray3(t *testing.T) { called := false - vm.Set("x", func(a1 string, a2 ...int) { + err := vm.Set("x", func(a1 string, a2 ...int) { if a1 != "a" || !reflect.DeepEqual(a2, []int{1, 2, 3}) { t.Fail() } called = true }) + require.NoError(t, err) - s, _ := vm.Compile("test.js", `x("a", [1, 2, 3])`) + s, err := vm.Compile("test.js", `x("a", [1, 2, 3])`) + require.NoError(t, err) if _, err := vm.Run(s); err != nil { t.Logf("err should have been nil; was %s\n", err.Error()) @@ -1199,15 +1467,17 @@ func TestNativeCallWithStringIntVariadicArray10(t *testing.T) { called := false - vm.Set("x", func(a1 string, a2 ...int) { + err := vm.Set("x", func(a1 string, a2 ...int) { if a1 != "a" || !reflect.DeepEqual(a2, []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}) { t.Fail() } called = true }) + require.NoError(t, err) - s, _ := vm.Compile("test.js", `x("a", [1, 2, 3, 4, 5, 6, 7, 8, 9, 10])`) + s, err := vm.Compile("test.js", `x("a", [1, 2, 3, 4, 5, 6, 7, 8, 9, 10])`) + require.NoError(t, err) if _, err := vm.Run(s); err != nil { t.Logf("err should have been nil; was %s\n", err.Error()) @@ -1224,15 +1494,17 @@ func TestNativeCallWithMap(t *testing.T) { called := false - vm.Set("x", func(a map[string]string) { + err := vm.Set("x", func(a map[string]string) { if !reflect.DeepEqual(a, map[string]string{"a": "b", "c": "d"}) { t.Fail() } called = true }) + require.NoError(t, err) - s, _ := vm.Compile("test.js", `x({a: "b", c: "d"})`) + s, err := vm.Compile("test.js", `x({a: "b", c: "d"})`) + require.NoError(t, err) if _, err := vm.Run(s); err != nil { t.Logf("err should have been nil; was %s\n", err.Error()) @@ -1249,15 +1521,17 @@ func TestNativeCallWithMapVariadic(t *testing.T) { called := false - vm.Set("x", func(a ...map[string]string) { + err := vm.Set("x", func(a ...map[string]string) { if !reflect.DeepEqual(a, []map[string]string{{"a": "b", "c": "d"}, {"w": "x", "y": "z"}}) { t.Fail() } called = true }) + require.NoError(t, err) - s, _ := vm.Compile("test.js", `x({a: "b", c: "d"}, {w: "x", y: "z"})`) + s, err := vm.Compile("test.js", `x({a: "b", c: "d"}, {w: "x", y: "z"})`) + require.NoError(t, err) if _, err := vm.Run(s); err != nil { t.Logf("err should have been nil; was %s\n", err.Error()) @@ -1274,15 +1548,17 @@ func TestNativeCallWithMapVariadicArray(t *testing.T) { called := false - vm.Set("x", func(a ...map[string]string) { + err := vm.Set("x", func(a ...map[string]string) { if !reflect.DeepEqual(a, []map[string]string{{"a": "b", "c": "d"}, {"w": "x", "y": "z"}}) { t.Fail() } called = true }) + require.NoError(t, err) - s, _ := vm.Compile("test.js", `x([{a: "b", c: "d"}, {w: "x", y: "z"}])`) + s, err := vm.Compile("test.js", `x([{a: "b", c: "d"}, {w: "x", y: "z"}])`) + require.NoError(t, err) if _, err := vm.Run(s); err != nil { t.Logf("err should have been nil; was %s\n", err.Error()) @@ -1299,15 +1575,17 @@ func TestNativeCallWithFunctionVoidBool(t *testing.T) { called := false - vm.Set("x", func(fn func() bool) { + err := vm.Set("x", func(fn func() bool) { if !fn() { t.Fail() } called = true }) + require.NoError(t, err) - s, _ := vm.Compile("test.js", `x(function() { return true; })`) + s, err := vm.Compile("test.js", `x(function() { return true; })`) + require.NoError(t, err) if _, err := vm.Run(s); err != nil { t.Logf("err should have been nil; was %s\n", err.Error()) @@ -1324,15 +1602,17 @@ func TestNativeCallWithFunctionIntInt(t *testing.T) { called := false - vm.Set("x", func(fn func(int) int) { + err := vm.Set("x", func(fn func(int) int) { if fn(5) != 5 { t.Fail() } called = true }) + require.NoError(t, err) - s, _ := vm.Compile("test.js", `x(function(n) { return n; })`) + s, err := vm.Compile("test.js", `x(function(n) { return n; })`) + require.NoError(t, err) if _, err := vm.Run(s); err != nil { t.Logf("err should have been nil; was %s\n", err.Error()) @@ -1349,15 +1629,17 @@ func TestNativeCallWithFunctionStringString(t *testing.T) { called := false - vm.Set("x", func(fn func(string) string) { + err := vm.Set("x", func(fn func(string) string) { if fn("zzz") != "zzz" { t.Fail() } called = true }) + require.NoError(t, err) - s, _ := vm.Compile("test.js", `x(function(n) { return n; })`) + s, err := vm.Compile("test.js", `x(function(n) { return n; })`) + require.NoError(t, err) if _, err := vm.Run(s); err != nil { t.Logf("err should have been nil; was %s\n", err.Error()) @@ -1405,18 +1687,20 @@ func TestNativeCallMethodWithStruct(t *testing.T) { vm := New() called := false + err := vm.Set("x", testNativeCallWithStruct{Prefix: "a"}) + require.NoError(t, err) - vm.Set("x", testNativeCallWithStruct{Prefix: "a"}) - - vm.Set("t", func(s string) { + err = vm.Set("t", func(s string) { if s != testAb { t.Fail() } called = true }) + require.NoError(t, err) - s, _ := vm.Compile("test.js", `t(x.CallWithStruct(x.MakeStruct("b")))`) + s, err := vm.Compile("test.js", `t(x.CallWithStruct(x.MakeStruct("b")))`) + require.NoError(t, err) if _, err := vm.Run(s); err != nil { t.Logf("err should have been nil; was %s\n", err.Error()) @@ -1432,18 +1716,20 @@ func TestNativeCallPointerMethodWithStruct(t *testing.T) { vm := New() called := false + err := vm.Set("x", &testNativeCallWithStruct{Prefix: "a"}) + require.NoError(t, err) - vm.Set("x", &testNativeCallWithStruct{Prefix: "a"}) - - vm.Set("t", func(s string) { + err = vm.Set("t", func(s string) { if s != testAb { t.Fail() } called = true }) + require.NoError(t, err) - s, _ := vm.Compile("test.js", `t(x.CallPointerWithStruct(x.MakeStruct("b")))`) + s, err := vm.Compile("test.js", `t(x.CallPointerWithStruct(x.MakeStruct("b")))`) + require.NoError(t, err) if _, err := vm.Run(s); err != nil { t.Logf("err should have been nil; was %s\n", err.Error()) @@ -1459,18 +1745,20 @@ func TestNativeCallMethodWithStructPointer(t *testing.T) { vm := New() called := false + err := vm.Set("x", testNativeCallWithStruct{Prefix: "a"}) + require.NoError(t, err) - vm.Set("x", testNativeCallWithStruct{Prefix: "a"}) - - vm.Set("t", func(s string) { + err = vm.Set("t", func(s string) { if s != testAb { t.Fail() } called = true }) + require.NoError(t, err) - s, _ := vm.Compile("test.js", `t(x.CallWithStructPointer(x.MakeStructPointer("b")))`) + s, err := vm.Compile("test.js", `t(x.CallWithStructPointer(x.MakeStructPointer("b")))`) + require.NoError(t, err) if _, err := vm.Run(s); err != nil { t.Logf("err should have been nil; was %s\n", err.Error()) @@ -1486,18 +1774,20 @@ func TestNativeCallPointerMethodWithStructPointer(t *testing.T) { vm := New() called := false + err := vm.Set("x", &testNativeCallWithStruct{Prefix: "a"}) + require.NoError(t, err) - vm.Set("x", &testNativeCallWithStruct{Prefix: "a"}) - - vm.Set("t", func(s string) { + err = vm.Set("t", func(s string) { if s != testAb { t.Fail() } called = true }) + require.NoError(t, err) - s, _ := vm.Compile("test.js", `t(x.CallPointerWithStructPointer(x.MakeStructPointer("b")))`) + s, err := vm.Compile("test.js", `t(x.CallPointerWithStructPointer(x.MakeStructPointer("b")))`) + require.NoError(t, err) if _, err := vm.Run(s); err != nil { t.Logf("err should have been nil; was %s\n", err.Error()) @@ -1511,6 +1801,9 @@ func TestNativeCallPointerMethodWithStructPointer(t *testing.T) { func TestNativeCallNilInterfaceArg(t *testing.T) { vm := New() - vm.Set("f1", func(v interface{}) {}) - vm.Call("f1", nil, nil) + err := vm.Set("f1", func(v interface{}) {}) + require.NoError(t, err) + + _, err = vm.Call("f1", nil, nil) + require.NoError(t, err) } diff --git a/clone.go b/clone.go index 0e1e879b..edc28459 100644 --- a/clone.go +++ b/clone.go @@ -4,158 +4,157 @@ import ( "fmt" ) -type _clone struct { - runtime *_runtime - _object map[*_object]*_object - _objectStash map[*_objectStash]*_objectStash - _dclStash map[*_dclStash]*_dclStash - _fnStash map[*_fnStash]*_fnStash +type cloner struct { + runtime *runtime + obj 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() +func (rt *runtime) clone() *runtime { + rt.lck.Lock() + defer rt.lck.Unlock() - out := &_runtime{ - debugger: in.debugger, - random: in.random, - stackLimit: in.stackLimit, - traceLimit: in.traceLimit, + out := &runtime{ + debugger: rt.debugger, + random: rt.random, + stackLimit: rt.stackLimit, + traceLimit: rt.traceLimit, } - clone := _clone{ - runtime: out, - _object: make(map[*_object]*_object), - _objectStash: make(map[*_objectStash]*_objectStash), - _dclStash: make(map[*_dclStash]*_dclStash), - _fnStash: make(map[*_fnStash]*_fnStash), + c := cloner{ + runtime: out, + obj: make(map[*object]*object), + objectstash: make(map[*objectStash]*objectStash), + dclstash: make(map[*dclStash]*dclStash), + fnstash: make(map[*fnStash]*fnStash), } - globalObject := clone.object(in.globalObject) + globalObject := c.object(rt.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.global = global{ + c.object(rt.global.Object), + c.object(rt.global.Function), + c.object(rt.global.Array), + c.object(rt.global.String), + c.object(rt.global.Boolean), + c.object(rt.global.Number), + c.object(rt.global.Math), + c.object(rt.global.Date), + c.object(rt.global.RegExp), + c.object(rt.global.Error), + c.object(rt.global.EvalError), + c.object(rt.global.TypeError), + c.object(rt.global.RangeError), + c.object(rt.global.ReferenceError), + c.object(rt.global.SyntaxError), + c.object(rt.global.URIError), + c.object(rt.global.JSON), + + c.object(rt.global.ObjectPrototype), + c.object(rt.global.FunctionPrototype), + c.object(rt.global.ArrayPrototype), + c.object(rt.global.StringPrototype), + c.object(rt.global.BooleanPrototype), + c.object(rt.global.NumberPrototype), + c.object(rt.global.DatePrototype), + c.object(rt.global.RegExpPrototype), + c.object(rt.global.ErrorPrototype), + c.object(rt.global.EvalErrorPrototype), + c.object(rt.global.TypeErrorPrototype), + c.object(rt.global.RangeErrorPrototype), + c.object(rt.global.ReferenceErrorPrototype), + c.object(rt.global.SyntaxErrorPrototype), + c.object(rt.global.URIErrorPrototype), } - out.eval = out.globalObject.property["eval"].value.(Value).value.(*_object) + 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 + c.runtime = nil + c.obj = nil + c.objectstash = nil + c.dclstash = nil + c.fnstash = nil return out } -func (clone *_clone) object(in *_object) *_object { - if out, exists := clone._object[in]; exists { +func (c *cloner) object(in *object) *object { + if out, exists := c.obj[in]; exists { return out } - out := &_object{} - clone._object[in] = out - return in.objectClass.clone(in, out, clone) + out := &object{} + c.obj[in] = out + return in.objectClass.clone(in, out, c) } -func (clone *_clone) dclStash(in *_dclStash) (*_dclStash, bool) { - if out, exists := clone._dclStash[in]; exists { +func (c *cloner) dclStash(in *dclStash) (*dclStash, bool) { + if out, exists := c.dclstash[in]; exists { return out, true } - out := &_dclStash{} - clone._dclStash[in] = out + out := &dclStash{} + c.dclstash[in] = out return out, false } -func (clone *_clone) objectStash(in *_objectStash) (*_objectStash, bool) { - if out, exists := clone._objectStash[in]; exists { +func (c *cloner) objectStash(in *objectStash) (*objectStash, bool) { + if out, exists := c.objectstash[in]; exists { return out, true } - out := &_objectStash{} - clone._objectStash[in] = out + out := &objectStash{} + c.objectstash[in] = out return out, false } -func (clone *_clone) fnStash(in *_fnStash) (*_fnStash, bool) { - if out, exists := clone._fnStash[in]; exists { +func (c *cloner) fnStash(in *fnStash) (*fnStash, bool) { + if out, exists := c.fnstash[in]; exists { return out, true } - out := &_fnStash{} - clone._fnStash[in] = out + out := &fnStash{} + c.fnstash[in] = out return out, false } -func (clone *_clone) value(in Value) Value { +func (c *cloner) value(in Value) Value { out := in - switch value := in.value.(type) { - case *_object: - out.value = clone.object(value) + if value, ok := in.value.(*object); ok { + out.value = c.object(value) } return out } -func (clone *_clone) valueArray(in []Value) []Value { +func (c *cloner) valueArray(in []Value) []Value { out := make([]Value, len(in)) for index, value := range in { - out[index] = clone.value(value) + out[index] = c.value(value) } return out } -func (clone *_clone) stash(in _stash) _stash { +func (c *cloner) stash(in stasher) stasher { if in == nil { return nil } - return in.clone(clone) + return in.clone(c) } -func (clone *_clone) property(in _property) _property { +func (c *cloner) property(in property) property { out := in switch value := in.value.(type) { case Value: - out.value = clone.value(value) - case _propertyGetSet: - p := _propertyGetSet{} + out.value = c.value(value) + case propertyGetSet: + p := propertyGetSet{} if value[0] != nil { - p[0] = clone.object(value[0]) + p[0] = c.object(value[0]) } if value[1] != nil { - p[1] = clone.object(value[1]) + p[1] = c.object(value[1]) } out.value = p default: @@ -165,8 +164,8 @@ func (clone *_clone) property(in _property) _property { return out } -func (clone *_clone) dclProperty(in _dclProperty) _dclProperty { +func (c *cloner) dclProperty(in dclProperty) dclProperty { out := in - out.value = clone.value(in.value) + out.value = c.value(in.value) return out } diff --git a/clone_test.go b/clone_test.go index 8e60464a..f069022b 100644 --- a/clone_test.go +++ b/clone_test.go @@ -2,17 +2,21 @@ package otto import ( "testing" + + "github.com/stretchr/testify/require" ) func TestCloneGetterSetter(t *testing.T) { vm := New() - vm.Run(`var x = Object.create(null, { + _, err := vm.Run(`var x = Object.create(null, { x: { get: function() {}, set: function() {}, }, })`) - - vm.Copy() + require.NoError(t, err) + require.NotPanics(t, func() { + vm.Copy() + }) } diff --git a/cmpl.go b/cmpl.go index 0153159c..e81cd50b 100644 --- a/cmpl.go +++ b/cmpl.go @@ -5,14 +5,7 @@ import ( "github.com/robertkrimen/otto/file" ) -type _compiler struct { +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/cmpl_evaluate.go b/cmpl_evaluate.go index 692c6721..a29b7d88 100644 --- a/cmpl_evaluate.go +++ b/cmpl_evaluate.go @@ -4,20 +4,18 @@ import ( "strconv" ) -func (self *_runtime) cmpl_evaluate_nodeProgram(node *_nodeProgram, eval bool) Value { +func (rt *runtime) cmplEvaluateNodeProgram(node *nodeProgram, eval bool) Value { if !eval { - self.enterGlobalScope() - defer func() { - self.leaveScope() - }() + rt.enterGlobalScope() + defer rt.leaveScope() } - self.cmpl_functionDeclaration(node.functionList) - self.cmpl_variableDeclaration(node.varList) - self.scope.frame.file = node.file - return self.cmpl_evaluate_nodeStatementList(node.body) + rt.cmplFunctionDeclaration(node.functionList) + rt.cmplVariableDeclaration(node.varList) + rt.scope.frame.file = node.file + return rt.cmplEvaluateNodeStatementList(node.body) } -func (self *_runtime) cmpl_call_nodeFunction(function *_object, stash *_fnStash, node *_nodeFunctionLiteral, this Value, argumentList []Value) Value { +func (rt *runtime) cmplCallNodeFunction(function *object, stash *fnStash, node *nodeFunctionLiteral, argumentList []Value) Value { indexOfParameterName := make([]string, len(argumentList)) // function(abc, def, ghi) // indexOfParameterName[0] = "abc" @@ -36,28 +34,28 @@ func (self *_runtime) cmpl_call_nodeFunction(function *_object, stash *_fnStash, indexOfParameterName[index] = name } // strict = false - self.scope.lexical.setValue(name, value, false) + rt.scope.lexical.setValue(name, value, false) } if !argumentsFound { - arguments := self.newArgumentsObject(indexOfParameterName, stash, len(argumentList)) - arguments.defineProperty("callee", toValue_object(function), 0101, false) + arguments := rt.newArgumentsObject(indexOfParameterName, stash, len(argumentList)) + arguments.defineProperty("callee", objectValue(function), 0o101, false) stash.arguments = arguments // strict = false - self.scope.lexical.setValue("arguments", toValue_object(arguments), false) - for index, _ := range argumentList { + rt.scope.lexical.setValue("arguments", objectValue(arguments), false) + for index := range argumentList { if index < len(node.parameterList) { continue } indexAsString := strconv.FormatInt(int64(index), 10) - arguments.defineProperty(indexAsString, argumentList[index], 0111, false) + arguments.defineProperty(indexAsString, argumentList[index], 0o111, false) } } - self.cmpl_functionDeclaration(node.functionList) - self.cmpl_variableDeclaration(node.varList) + rt.cmplFunctionDeclaration(node.functionList) + rt.cmplVariableDeclaration(node.varList) - result := self.cmpl_evaluate_nodeStatement(node.body) + result := rt.cmplEvaluateNodeStatement(node.body) if result.kind == valueResult { return result } @@ -65,16 +63,16 @@ func (self *_runtime) cmpl_call_nodeFunction(function *_object, stash *_fnStash, return Value{} } -func (self *_runtime) cmpl_functionDeclaration(list []*_nodeFunctionLiteral) { - executionContext := self.scope +func (rt *runtime) cmplFunctionDeclaration(list []*nodeFunctionLiteral) { + executionContext := rt.scope eval := executionContext.eval stash := executionContext.variable for _, function := range list { name := function.name - value := self.cmpl_evaluate_nodeExpression(function) + value := rt.cmplEvaluateNodeExpression(function) if !stash.hasBinding(name) { - stash.createBinding(name, eval == true, value) + stash.createBinding(name, eval, value) } else { // TODO 10.5.5.e stash.setBinding(name, value, false) // TODO strict @@ -82,14 +80,14 @@ func (self *_runtime) cmpl_functionDeclaration(list []*_nodeFunctionLiteral) { } } -func (self *_runtime) cmpl_variableDeclaration(list []string) { - executionContext := self.scope +func (rt *runtime) cmplVariableDeclaration(list []string) { + executionContext := rt.scope eval := executionContext.eval stash := executionContext.variable for _, name := range list { if !stash.hasBinding(name) { - stash.createBinding(name, eval == true, Value{}) // TODO strict? + stash.createBinding(name, eval, Value{}) // TODO strict? } } } diff --git a/cmpl_evaluate_expression.go b/cmpl_evaluate_expression.go index 325a7e81..27964dcc 100644 --- a/cmpl_evaluate_expression.go +++ b/cmpl_evaluate_expression.go @@ -3,136 +3,135 @@ package otto import ( "fmt" "math" - "runtime" + goruntime "runtime" "github.com/robertkrimen/otto/token" ) -func (self *_runtime) cmpl_evaluate_nodeExpression(node _nodeExpression) Value { +func (rt *runtime) cmplEvaluateNodeExpression(node nodeExpression) Value { // Allow interpreter interruption // If the Interrupt channel is nil, then // we avoid runtime.Gosched() overhead (if any) // FIXME: Test this - if self.otto.Interrupt != nil { - runtime.Gosched() + if rt.otto.Interrupt != nil { + goruntime.Gosched() select { - case value := <-self.otto.Interrupt: + case value := <-rt.otto.Interrupt: value() default: } } switch node := node.(type) { - case *_nodeArrayLiteral: - return self.cmpl_evaluate_nodeArrayLiteral(node) + case *nodeArrayLiteral: + return rt.cmplEvaluateNodeArrayLiteral(node) - case *_nodeAssignExpression: - return self.cmpl_evaluate_nodeAssignExpression(node) + case *nodeAssignExpression: + return rt.cmplEvaluateNodeAssignExpression(node) - case *_nodeBinaryExpression: + case *nodeBinaryExpression: if node.comparison { - return self.cmpl_evaluate_nodeBinaryExpression_comparison(node) - } else { - return self.cmpl_evaluate_nodeBinaryExpression(node) + return rt.cmplEvaluateNodeBinaryExpressionComparison(node) } + return rt.cmplEvaluateNodeBinaryExpression(node) - case *_nodeBracketExpression: - return self.cmpl_evaluate_nodeBracketExpression(node) + case *nodeBracketExpression: + return rt.cmplEvaluateNodeBracketExpression(node) - case *_nodeCallExpression: - return self.cmpl_evaluate_nodeCallExpression(node, nil) + case *nodeCallExpression: + return rt.cmplEvaluateNodeCallExpression(node, nil) - case *_nodeConditionalExpression: - return self.cmpl_evaluate_nodeConditionalExpression(node) + case *nodeConditionalExpression: + return rt.cmplEvaluateNodeConditionalExpression(node) - case *_nodeDotExpression: - return self.cmpl_evaluate_nodeDotExpression(node) + case *nodeDotExpression: + return rt.cmplEvaluateNodeDotExpression(node) - case *_nodeFunctionLiteral: - var local = self.scope.lexical + case *nodeFunctionLiteral: + local := rt.scope.lexical if node.name != "" { - local = self.newDeclarationStash(local) + local = rt.newDeclarationStash(local) } - value := toValue_object(self.newNodeFunction(node, local)) + value := objectValue(rt.newNodeFunction(node, local)) if node.name != "" { local.createBinding(node.name, false, value) } return value - case *_nodeIdentifier: + case *nodeIdentifier: name := node.name // 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, self.scope.lexical, name, false, _at(node.idx)) + reference := getIdentifierReference(rt, rt.scope.lexical, name, false, at(node.idx)) if reference == nil { // Should never get here! panic(hereBeDragons("referenceError == nil: " + name)) } return toValue(reference) - case *_nodeLiteral: + case *nodeLiteral: return node.value - case *_nodeNewExpression: - return self.cmpl_evaluate_nodeNewExpression(node) + case *nodeNewExpression: + return rt.cmplEvaluateNodeNewExpression(node) - case *_nodeObjectLiteral: - return self.cmpl_evaluate_nodeObjectLiteral(node) + case *nodeObjectLiteral: + return rt.cmplEvaluateNodeObjectLiteral(node) - case *_nodeRegExpLiteral: - return toValue_object(self._newRegExp(node.pattern, node.flags)) + case *nodeRegExpLiteral: + return objectValue(rt.newRegExpDirect(node.pattern, node.flags)) - case *_nodeSequenceExpression: - return self.cmpl_evaluate_nodeSequenceExpression(node) + case *nodeSequenceExpression: + return rt.cmplEvaluateNodeSequenceExpression(node) - case *_nodeThisExpression: - return toValue_object(self.scope.this) + case *nodeThisExpression: + return objectValue(rt.scope.this) - case *_nodeUnaryExpression: - return self.cmpl_evaluate_nodeUnaryExpression(node) + case *nodeUnaryExpression: + return rt.cmplEvaluateNodeUnaryExpression(node) - case *_nodeVariableExpression: - return self.cmpl_evaluate_nodeVariableExpression(node) + case *nodeVariableExpression: + return rt.cmplEvaluateNodeVariableExpression(node) + default: + panic(fmt.Sprintf("unknown node type: %T", node)) } - - panic(fmt.Errorf("Here be dragons: evaluate_nodeExpression(%T)", node)) } -func (self *_runtime) cmpl_evaluate_nodeArrayLiteral(node *_nodeArrayLiteral) Value { +func (rt *runtime) cmplEvaluateNodeArrayLiteral(node *nodeArrayLiteral) Value { valueArray := []Value{} for _, node := range node.value { if node == nil { valueArray = append(valueArray, emptyValue) } else { - valueArray = append(valueArray, self.cmpl_evaluate_nodeExpression(node).resolve()) + valueArray = append(valueArray, rt.cmplEvaluateNodeExpression(node).resolve()) } } - result := self.newArrayOf(valueArray) + result := rt.newArrayOf(valueArray) - return toValue_object(result) + return objectValue(result) } -func (self *_runtime) cmpl_evaluate_nodeAssignExpression(node *_nodeAssignExpression) Value { - left := self.cmpl_evaluate_nodeExpression(node.left) - right := self.cmpl_evaluate_nodeExpression(node.right) +func (rt *runtime) cmplEvaluateNodeAssignExpression(node *nodeAssignExpression) Value { + left := rt.cmplEvaluateNodeExpression(node.left) + right := rt.cmplEvaluateNodeExpression(node.right) rightValue := right.resolve() result := rightValue if node.operator != token.ASSIGN { - result = self.calculateBinaryExpression(node.operator, left, rightValue) + result = rt.calculateBinaryExpression(node.operator, left, rightValue) } - self.putValue(left.reference(), result) + rt.putValue(left.reference(), result) return result } -func (self *_runtime) cmpl_evaluate_nodeBinaryExpression(node *_nodeBinaryExpression) Value { - left := self.cmpl_evaluate_nodeExpression(node.left) +func (rt *runtime) cmplEvaluateNodeBinaryExpression(node *nodeBinaryExpression) Value { + left := rt.cmplEvaluateNodeExpression(node.left) leftValue := left.resolve() switch node.operator { @@ -141,67 +140,62 @@ func (self *_runtime) cmpl_evaluate_nodeBinaryExpression(node *_nodeBinaryExpres if !leftValue.bool() { return leftValue } - right := self.cmpl_evaluate_nodeExpression(node.right) + right := rt.cmplEvaluateNodeExpression(node.right) return right.resolve() case token.LOGICAL_OR: if leftValue.bool() { return leftValue } - right := self.cmpl_evaluate_nodeExpression(node.right) + right := rt.cmplEvaluateNodeExpression(node.right) return right.resolve() } - return self.calculateBinaryExpression(node.operator, leftValue, self.cmpl_evaluate_nodeExpression(node.right)) + return rt.calculateBinaryExpression(node.operator, leftValue, rt.cmplEvaluateNodeExpression(node.right)) } -func (self *_runtime) cmpl_evaluate_nodeBinaryExpression_comparison(node *_nodeBinaryExpression) Value { - left := self.cmpl_evaluate_nodeExpression(node.left).resolve() - right := self.cmpl_evaluate_nodeExpression(node.right).resolve() +func (rt *runtime) cmplEvaluateNodeBinaryExpressionComparison(node *nodeBinaryExpression) Value { + left := rt.cmplEvaluateNodeExpression(node.left).resolve() + right := rt.cmplEvaluateNodeExpression(node.right).resolve() - return toValue_bool(self.calculateComparison(node.operator, left, right)) + return boolValue(rt.calculateComparison(node.operator, left, right)) } -func (self *_runtime) cmpl_evaluate_nodeBracketExpression(node *_nodeBracketExpression) Value { - target := self.cmpl_evaluate_nodeExpression(node.left) +func (rt *runtime) cmplEvaluateNodeBracketExpression(node *nodeBracketExpression) Value { + target := rt.cmplEvaluateNodeExpression(node.left) targetValue := target.resolve() - member := self.cmpl_evaluate_nodeExpression(node.member) + member := rt.cmplEvaluateNodeExpression(node.member) memberValue := member.resolve() // TODO Pass in base value as-is, and defer toObject till later? - object, err := self.objectCoerce(targetValue) + obj, err := rt.objectCoerce(targetValue) if err != nil { - panic(self.panicTypeError("Cannot access member '%s' of %s", memberValue.string(), err.Error(), _at(node.idx))) + panic(rt.panicTypeError("Cannot access member '%s' of %s", memberValue.string(), err.Error(), at(node.idx))) } - return toValue(newPropertyReference(self, object, memberValue.string(), false, _at(node.idx))) + return toValue(newPropertyReference(rt, obj, memberValue.string(), false, at(node.idx))) } -func (self *_runtime) cmpl_evaluate_nodeCallExpression(node *_nodeCallExpression, withArgumentList []interface{}) Value { - rt := self +func (rt *runtime) cmplEvaluateNodeCallExpression(node *nodeCallExpression, withArgumentList []interface{}) Value { this := Value{} - callee := self.cmpl_evaluate_nodeExpression(node.callee) + callee := rt.cmplEvaluateNodeExpression(node.callee) argumentList := []Value{} if withArgumentList != nil { - argumentList = self.toValueArray(withArgumentList...) + argumentList = rt.toValueArray(withArgumentList...) } else { for _, argumentNode := range node.argumentList { - argumentList = append(argumentList, self.cmpl_evaluate_nodeExpression(argumentNode).resolve()) + argumentList = append(argumentList, rt.cmplEvaluateNodeExpression(argumentNode).resolve()) } } - rf := callee.reference() - vl := callee.resolve() - eval := false // Whether this call is a (candidate for) direct call to eval name := "" - if rf != nil { + if rf := callee.reference(); rf != nil { switch rf := rf.(type) { - case *_propertyReference: + case *propertyReference: name = rf.name - object := rf.base - this = toValue_object(object) + this = objectValue(rf.base) eval = rf.name == "eval" // Possible direct eval - case *_stashReference: + case *stashReference: // TODO ImplicitThisValue name = rf.name eval = rf.name == "eval" // Possible direct eval @@ -211,144 +205,141 @@ func (self *_runtime) cmpl_evaluate_nodeCallExpression(node *_nodeCallExpression } } - at := _at(-1) + atv := 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) + case *nodeIdentifier: + atv = at(callee.idx) + case *nodeDotExpression: + atv = at(callee.idx) + case *nodeBracketExpression: + atv = at(callee.idx) } - frame := _frame{ + frm := frame{ callee: name, - file: self.scope.frame.file, + file: rt.scope.frame.file, } + vl := callee.resolve() if !vl.IsFunction() { if name == "" { // FIXME Maybe typeof? - panic(rt.panicTypeError("%v is not a function", vl, at)) + panic(rt.panicTypeError("%v is not a function", vl, atv)) } - panic(rt.panicTypeError("'%s' is not a function", name, at)) + panic(rt.panicTypeError("'%s' is not a function", name, atv)) } - self.scope.frame.offset = int(at) + rt.scope.frame.offset = int(atv) - return vl._object().call(this, argumentList, eval, frame) + return vl.object().call(this, argumentList, eval, frm) } -func (self *_runtime) cmpl_evaluate_nodeConditionalExpression(node *_nodeConditionalExpression) Value { - test := self.cmpl_evaluate_nodeExpression(node.test) +func (rt *runtime) cmplEvaluateNodeConditionalExpression(node *nodeConditionalExpression) Value { + test := rt.cmplEvaluateNodeExpression(node.test) testValue := test.resolve() if testValue.bool() { - return self.cmpl_evaluate_nodeExpression(node.consequent) + return rt.cmplEvaluateNodeExpression(node.consequent) } - return self.cmpl_evaluate_nodeExpression(node.alternate) + return rt.cmplEvaluateNodeExpression(node.alternate) } -func (self *_runtime) cmpl_evaluate_nodeDotExpression(node *_nodeDotExpression) Value { - target := self.cmpl_evaluate_nodeExpression(node.left) +func (rt *runtime) cmplEvaluateNodeDotExpression(node *nodeDotExpression) Value { + target := rt.cmplEvaluateNodeExpression(node.left) targetValue := target.resolve() // TODO Pass in base value as-is, and defer toObject till later? - object, err := self.objectCoerce(targetValue) + obj, err := rt.objectCoerce(targetValue) if err != nil { - panic(self.panicTypeError("Cannot access member '%s' of %s", node.identifier, err.Error(), _at(node.idx))) + panic(rt.panicTypeError("Cannot access member '%s' of %s", node.identifier, err.Error(), at(node.idx))) } - return toValue(newPropertyReference(self, object, node.identifier, false, _at(node.idx))) + return toValue(newPropertyReference(rt, obj, node.identifier, false, at(node.idx))) } -func (self *_runtime) cmpl_evaluate_nodeNewExpression(node *_nodeNewExpression) Value { - rt := self - callee := self.cmpl_evaluate_nodeExpression(node.callee) +func (rt *runtime) cmplEvaluateNodeNewExpression(node *nodeNewExpression) Value { + callee := rt.cmplEvaluateNodeExpression(node.callee) argumentList := []Value{} for _, argumentNode := range node.argumentList { - argumentList = append(argumentList, self.cmpl_evaluate_nodeExpression(argumentNode).resolve()) + argumentList = append(argumentList, rt.cmplEvaluateNodeExpression(argumentNode).resolve()) } - rf := callee.reference() - vl := callee.resolve() - - name := "" - if rf != nil { + var name string + if rf := callee.reference(); rf != nil { switch rf := rf.(type) { - case *_propertyReference: + case *propertyReference: name = rf.name - case *_stashReference: + case *stashReference: name = rf.name default: panic(rt.panicTypeError("Here be dragons")) } } - at := _at(-1) + atv := 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) + case *nodeIdentifier: + atv = at(callee.idx) + case *nodeDotExpression: + atv = at(callee.idx) + case *nodeBracketExpression: + atv = at(callee.idx) } + vl := callee.resolve() if !vl.IsFunction() { if name == "" { // FIXME Maybe typeof? - panic(rt.panicTypeError("%v is not a function", vl, at)) + panic(rt.panicTypeError("%v is not a function", vl, atv)) } - panic(rt.panicTypeError("'%s' is not a function", name, at)) + panic(rt.panicTypeError("'%s' is not a function", name, atv)) } - self.scope.frame.offset = int(at) + rt.scope.frame.offset = int(atv) - return vl._object().construct(argumentList) + return vl.object().construct(argumentList) } -func (self *_runtime) cmpl_evaluate_nodeObjectLiteral(node *_nodeObjectLiteral) Value { - result := self.newObject() - - for _, property := range node.value { - switch property.kind { +func (rt *runtime) cmplEvaluateNodeObjectLiteral(node *nodeObjectLiteral) Value { + result := rt.newObject() + for _, prop := range node.value { + switch prop.kind { case "value": - result.defineProperty(property.key, self.cmpl_evaluate_nodeExpression(property.value).resolve(), 0111, false) + result.defineProperty(prop.key, rt.cmplEvaluateNodeExpression(prop.value).resolve(), 0o111, false) case "get": - 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) + getter := rt.newNodeFunction(prop.value.(*nodeFunctionLiteral), rt.scope.lexical) + descriptor := property{} + descriptor.mode = 0o211 + descriptor.value = propertyGetSet{getter, nil} + result.defineOwnProperty(prop.key, descriptor, false) case "set": - setter := self.newNodeFunction(property.value.(*_nodeFunctionLiteral), self.scope.lexical) - descriptor := _property{} - descriptor.mode = 0211 - descriptor.value = _propertyGetSet{nil, setter} - result.defineOwnProperty(property.key, descriptor, false) + setter := rt.newNodeFunction(prop.value.(*nodeFunctionLiteral), rt.scope.lexical) + descriptor := property{} + descriptor.mode = 0o211 + descriptor.value = propertyGetSet{nil, setter} + result.defineOwnProperty(prop.key, descriptor, false) default: - panic(fmt.Errorf("Here be dragons: evaluate_nodeObjectLiteral: invalid property.Kind: %v", property.kind)) + panic(fmt.Sprintf("unknown node object literal property kind %T", prop.kind)) } } - return toValue_object(result) + return objectValue(result) } -func (self *_runtime) cmpl_evaluate_nodeSequenceExpression(node *_nodeSequenceExpression) Value { +func (rt *runtime) cmplEvaluateNodeSequenceExpression(node *nodeSequenceExpression) Value { var result Value for _, node := range node.sequence { - result = self.cmpl_evaluate_nodeExpression(node) + result = rt.cmplEvaluateNodeExpression(node) result = result.resolve() } return result } -func (self *_runtime) cmpl_evaluate_nodeUnaryExpression(node *_nodeUnaryExpression) Value { - target := self.cmpl_evaluate_nodeExpression(node.operand) +func (rt *runtime) cmplEvaluateNodeUnaryExpression(node *nodeUnaryExpression) Value { + target := rt.cmplEvaluateNodeExpression(node.operand) switch node.operator { case token.TYPEOF, token.DELETE: if target.kind == valueReference && target.reference().invalid() { if node.operator == token.TYPEOF { - return toValue_string("undefined") + return stringValue("undefined") } return trueValue } @@ -364,10 +355,10 @@ func (self *_runtime) cmpl_evaluate_nodeUnaryExpression(node *_nodeUnaryExpressi case token.BITWISE_NOT: targetValue := target.resolve() integerValue := toInt32(targetValue) - return toValue_int32(^integerValue) + return int32Value(^integerValue) case token.PLUS: targetValue := target.resolve() - return toValue_float64(targetValue.float64()) + return float64Value(targetValue.float64()) case token.MINUS: targetValue := target.resolve() value := targetValue.float64() @@ -376,35 +367,35 @@ func (self *_runtime) cmpl_evaluate_nodeUnaryExpression(node *_nodeUnaryExpressi if math.Signbit(value) { sign = 1 } - return toValue_float64(math.Copysign(value, sign)) + return float64Value(math.Copysign(value, sign)) case token.INCREMENT: targetValue := target.resolve() if node.postfix { // Postfix++ oldValue := targetValue.float64() - newValue := toValue_float64(+1 + oldValue) - self.putValue(target.reference(), newValue) - return toValue_float64(oldValue) - } else { - // ++Prefix - newValue := toValue_float64(+1 + targetValue.float64()) - self.putValue(target.reference(), newValue) - return newValue + newValue := float64Value(+1 + oldValue) + rt.putValue(target.reference(), newValue) + return float64Value(oldValue) } + + // ++Prefix + newValue := float64Value(+1 + targetValue.float64()) + rt.putValue(target.reference(), newValue) + return newValue case token.DECREMENT: targetValue := target.resolve() if node.postfix { // Postfix-- oldValue := targetValue.float64() - newValue := toValue_float64(-1 + oldValue) - self.putValue(target.reference(), newValue) - return toValue_float64(oldValue) - } else { - // --Prefix - newValue := toValue_float64(-1 + targetValue.float64()) - self.putValue(target.reference(), newValue) - return newValue + newValue := float64Value(-1 + oldValue) + rt.putValue(target.reference(), newValue) + return float64Value(oldValue) } + + // --Prefix + newValue := float64Value(-1 + targetValue.float64()) + rt.putValue(target.reference(), newValue) + return newValue case token.VOID: target.resolve() // FIXME Side effect? return Value{} @@ -413,25 +404,25 @@ func (self *_runtime) cmpl_evaluate_nodeUnaryExpression(node *_nodeUnaryExpressi if reference == nil { return trueValue } - return toValue_bool(target.reference().delete()) + return boolValue(target.reference().delete()) case token.TYPEOF: targetValue := target.resolve() switch targetValue.kind { case valueUndefined: - return toValue_string("undefined") + return stringValue("undefined") case valueNull: - return toValue_string("object") + return stringValue("object") case valueBoolean: - return toValue_string("boolean") + return stringValue("boolean") case valueNumber: - return toValue_string("number") + return stringValue("number") case valueString: - return toValue_string("string") + return stringValue("string") case valueObject: - if targetValue._object().isCall() { - return toValue_string("function") + if targetValue.object().isCall() { + return stringValue("function") } - return toValue_string("object") + return stringValue("object") default: // FIXME ? } @@ -440,14 +431,14 @@ func (self *_runtime) cmpl_evaluate_nodeUnaryExpression(node *_nodeUnaryExpressi panic(hereBeDragons()) } -func (self *_runtime) cmpl_evaluate_nodeVariableExpression(node *_nodeVariableExpression) Value { +func (rt *runtime) cmplEvaluateNodeVariableExpression(node *nodeVariableExpression) Value { if node.initializer != nil { // FIXME If reference is nil - left := getIdentifierReference(self, self.scope.lexical, node.name, false, _at(node.idx)) - right := self.cmpl_evaluate_nodeExpression(node.initializer) + left := getIdentifierReference(rt, rt.scope.lexical, node.name, false, at(node.idx)) + right := rt.cmplEvaluateNodeExpression(node.initializer) rightValue := right.resolve() - self.putValue(left, rightValue) + rt.putValue(left, rightValue) } - return toValue_string(node.name) + return stringValue(node.name) } diff --git a/cmpl_evaluate_statement.go b/cmpl_evaluate_statement.go index 6dc46764..e0a05ee5 100644 --- a/cmpl_evaluate_statement.go +++ b/cmpl_evaluate_statement.go @@ -2,121 +2,121 @@ package otto import ( "fmt" - "runtime" + goruntime "runtime" "github.com/robertkrimen/otto/token" ) -func (self *_runtime) cmpl_evaluate_nodeStatement(node _nodeStatement) Value { +func (rt *runtime) cmplEvaluateNodeStatement(node nodeStatement) Value { // Allow interpreter interruption // If the Interrupt channel is nil, then // we avoid runtime.Gosched() overhead (if any) // FIXME: Test this - if self.otto.Interrupt != nil { - runtime.Gosched() + if rt.otto.Interrupt != nil { + goruntime.Gosched() select { - case value := <-self.otto.Interrupt: + case value := <-rt.otto.Interrupt: value() default: } } switch node := node.(type) { - case *_nodeBlockStatement: - labels := self.labels - self.labels = nil + case *nodeBlockStatement: + labels := rt.labels + rt.labels = nil - value := self.cmpl_evaluate_nodeStatementList(node.list) - switch value.kind { - case valueResult: - switch value.evaluateBreak(labels) { - case resultBreak: + value := rt.cmplEvaluateNodeStatementList(node.list) + if value.kind == valueResult { + if value.evaluateBreak(labels) == resultBreak { return emptyValue } } return value - case *_nodeBranchStatement: + case *nodeBranchStatement: target := node.label switch node.branch { // FIXME Maybe node.kind? node.operator? case token.BREAK: return toValue(newBreakResult(target)) case token.CONTINUE: return toValue(newContinueResult(target)) + default: + panic(fmt.Errorf("unknown node branch token %T", node)) } - case *_nodeDebuggerStatement: - if self.debugger != nil { - self.debugger(self.otto) + case *nodeDebuggerStatement: + if rt.debugger != nil { + rt.debugger(rt.otto) } return emptyValue // Nothing happens. - case *_nodeDoWhileStatement: - return self.cmpl_evaluate_nodeDoWhileStatement(node) + case *nodeDoWhileStatement: + return rt.cmplEvaluateNodeDoWhileStatement(node) - case *_nodeEmptyStatement: + case *nodeEmptyStatement: return emptyValue - case *_nodeExpressionStatement: - return self.cmpl_evaluate_nodeExpression(node.expression) + case *nodeExpressionStatement: + return rt.cmplEvaluateNodeExpression(node.expression) - case *_nodeForInStatement: - return self.cmpl_evaluate_nodeForInStatement(node) + case *nodeForInStatement: + return rt.cmplEvaluateNodeForInStatement(node) - case *_nodeForStatement: - return self.cmpl_evaluate_nodeForStatement(node) + case *nodeForStatement: + return rt.cmplEvaluateNodeForStatement(node) - case *_nodeIfStatement: - return self.cmpl_evaluate_nodeIfStatement(node) + case *nodeIfStatement: + return rt.cmplEvaluateNodeIfStatement(node) - case *_nodeLabelledStatement: - self.labels = append(self.labels, node.label) + case *nodeLabelledStatement: + rt.labels = append(rt.labels, node.label) defer func() { - if len(self.labels) > 0 { - self.labels = self.labels[:len(self.labels)-1] // Pop the label + if len(rt.labels) > 0 { + rt.labels = rt.labels[:len(rt.labels)-1] // Pop the label } else { - self.labels = nil + rt.labels = nil } }() - return self.cmpl_evaluate_nodeStatement(node.statement) + return rt.cmplEvaluateNodeStatement(node.statement) - case *_nodeReturnStatement: + case *nodeReturnStatement: if node.argument != nil { - return toValue(newReturnResult(self.cmpl_evaluate_nodeExpression(node.argument).resolve())) + return toValue(newReturnResult(rt.cmplEvaluateNodeExpression(node.argument).resolve())) } return toValue(newReturnResult(Value{})) - case *_nodeSwitchStatement: - return self.cmpl_evaluate_nodeSwitchStatement(node) + case *nodeSwitchStatement: + return rt.cmplEvaluateNodeSwitchStatement(node) - case *_nodeThrowStatement: - value := self.cmpl_evaluate_nodeExpression(node.argument).resolve() + case *nodeThrowStatement: + value := rt.cmplEvaluateNodeExpression(node.argument).resolve() panic(newException(value)) - case *_nodeTryStatement: - return self.cmpl_evaluate_nodeTryStatement(node) + case *nodeTryStatement: + return rt.cmplEvaluateNodeTryStatement(node) - case *_nodeVariableStatement: + case *nodeVariableStatement: // Variables are already defined, this is initialization only for _, variable := range node.list { - self.cmpl_evaluate_nodeVariableExpression(variable.(*_nodeVariableExpression)) + rt.cmplEvaluateNodeVariableExpression(variable.(*nodeVariableExpression)) } return emptyValue - case *_nodeWhileStatement: - return self.cmpl_evaluate_nodeWhileStatement(node) + case *nodeWhileStatement: + return rt.cmplEvaluateModeWhileStatement(node) - case *_nodeWithStatement: - return self.cmpl_evaluate_nodeWithStatement(node) + case *nodeWithStatement: + return rt.cmplEvaluateNodeWithStatement(node) + default: + panic(fmt.Errorf("unknown node statement type %T", node)) } - - panic(fmt.Errorf("Here be dragons: evaluate_nodeStatement(%T)", node)) } -func (self *_runtime) cmpl_evaluate_nodeStatementList(list []_nodeStatement) Value { +func (rt *runtime) cmplEvaluateNodeStatementList(list []nodeStatement) Value { var result Value for _, node := range list { - value := self.cmpl_evaluate_nodeStatement(node) + value := rt.cmplEvaluateNodeStatement(node) switch value.kind { case valueResult: return value @@ -133,9 +133,9 @@ func (self *_runtime) cmpl_evaluate_nodeStatementList(list []_nodeStatement) Val return result } -func (self *_runtime) cmpl_evaluate_nodeDoWhileStatement(node *_nodeDoWhileStatement) Value { - labels := append(self.labels, "") - self.labels = nil +func (rt *runtime) cmplEvaluateNodeDoWhileStatement(node *nodeDoWhileStatement) Value { + labels := append(rt.labels, "") //nolint: gocritic + rt.labels = nil test := node.test @@ -143,7 +143,7 @@ func (self *_runtime) cmpl_evaluate_nodeDoWhileStatement(node *_nodeDoWhileState resultBreak: for { for _, node := range node.body { - value := self.cmpl_evaluate_nodeStatement(node) + value := rt.cmplEvaluateNodeStatement(node) switch value.kind { case valueResult: switch value.evaluateBreakContinue(labels) { @@ -160,7 +160,7 @@ resultBreak: } } resultContinue: - if !self.cmpl_evaluate_nodeExpression(test).resolve().bool() { + if !rt.cmplEvaluateNodeExpression(test).resolve().bool() { // Stahp: do ... while (false) break } @@ -168,11 +168,11 @@ resultBreak: return result } -func (self *_runtime) cmpl_evaluate_nodeForInStatement(node *_nodeForInStatement) Value { - labels := append(self.labels, "") - self.labels = nil +func (rt *runtime) cmplEvaluateNodeForInStatement(node *nodeForInStatement) Value { + labels := append(rt.labels, "") //nolint: gocritic + rt.labels = nil - source := self.cmpl_evaluate_nodeExpression(node.source) + source := rt.cmplEvaluateNodeExpression(node.source) sourceValue := source.resolve() switch sourceValue.kind { @@ -180,26 +180,26 @@ func (self *_runtime) cmpl_evaluate_nodeForInStatement(node *_nodeForInStatement return emptyValue } - sourceObject := self.toObject(sourceValue) + sourceObject := rt.toObject(sourceValue) into := node.into body := node.body result := emptyValue - object := sourceObject - for object != nil { + obj := sourceObject + for obj != nil { enumerateValue := emptyValue - object.enumerate(false, func(name string) bool { - into := self.cmpl_evaluate_nodeExpression(into) + obj.enumerate(false, func(name string) bool { + into := rt.cmplEvaluateNodeExpression(into) // In the case of: for (var abc in def) ... if into.reference() == nil { identifier := into.string() // TODO Should be true or false (strictness) depending on context - into = toValue(getIdentifierReference(self, self.scope.lexical, identifier, false, -1)) + into = toValue(getIdentifierReference(rt, rt.scope.lexical, identifier, false, -1)) } - self.putValue(into.reference(), toValue_string(name)) + rt.putValue(into.reference(), stringValue(name)) for _, node := range body { - value := self.cmpl_evaluate_nodeStatement(node) + value := rt.cmplEvaluateNodeStatement(node) switch value.kind { case valueResult: switch value.evaluateBreakContinue(labels) { @@ -207,7 +207,7 @@ func (self *_runtime) cmpl_evaluate_nodeForInStatement(node *_nodeForInStatement enumerateValue = value return false case resultBreak: - object = nil + obj = nil return false case resultContinue: return true @@ -219,10 +219,10 @@ func (self *_runtime) cmpl_evaluate_nodeForInStatement(node *_nodeForInStatement } return true }) - if object == nil { + if obj == nil { break } - object = object.prototype + obj = obj.prototype if !enumerateValue.isEmpty() { result = enumerateValue } @@ -230,9 +230,9 @@ func (self *_runtime) cmpl_evaluate_nodeForInStatement(node *_nodeForInStatement return result } -func (self *_runtime) cmpl_evaluate_nodeForStatement(node *_nodeForStatement) Value { - labels := append(self.labels, "") - self.labels = nil +func (rt *runtime) cmplEvaluateNodeForStatement(node *nodeForStatement) Value { + labels := append(rt.labels, "") //nolint: gocritic + rt.labels = nil initializer := node.initializer test := node.test @@ -240,7 +240,7 @@ func (self *_runtime) cmpl_evaluate_nodeForStatement(node *_nodeForStatement) Va body := node.body if initializer != nil { - initialResult := self.cmpl_evaluate_nodeExpression(initializer) + initialResult := rt.cmplEvaluateNodeExpression(initializer) initialResult.resolve() // Side-effect trigger } @@ -248,25 +248,25 @@ func (self *_runtime) cmpl_evaluate_nodeForStatement(node *_nodeForStatement) Va resultBreak: for { if test != nil { - testResult := self.cmpl_evaluate_nodeExpression(test) + testResult := rt.cmplEvaluateNodeExpression(test) testResultValue := testResult.resolve() - if testResultValue.bool() == false { + if !testResultValue.bool() { break } } // this is to prevent for cycles with no body from running forever - if len(body) == 0 && self.otto.Interrupt != nil { - runtime.Gosched() + if len(body) == 0 && rt.otto.Interrupt != nil { + goruntime.Gosched() select { - case value := <-self.otto.Interrupt: + case value := <-rt.otto.Interrupt: value() default: } } for _, node := range body { - value := self.cmpl_evaluate_nodeStatement(node) + value := rt.cmplEvaluateNodeStatement(node) switch value.kind { case valueResult: switch value.evaluateBreakContinue(labels) { @@ -284,36 +284,36 @@ resultBreak: } resultContinue: if update != nil { - updateResult := self.cmpl_evaluate_nodeExpression(update) + updateResult := rt.cmplEvaluateNodeExpression(update) updateResult.resolve() // Side-effect trigger } } return result } -func (self *_runtime) cmpl_evaluate_nodeIfStatement(node *_nodeIfStatement) Value { - test := self.cmpl_evaluate_nodeExpression(node.test) +func (rt *runtime) cmplEvaluateNodeIfStatement(node *nodeIfStatement) Value { + test := rt.cmplEvaluateNodeExpression(node.test) testValue := test.resolve() if testValue.bool() { - return self.cmpl_evaluate_nodeStatement(node.consequent) + return rt.cmplEvaluateNodeStatement(node.consequent) } else if node.alternate != nil { - return self.cmpl_evaluate_nodeStatement(node.alternate) + return rt.cmplEvaluateNodeStatement(node.alternate) } return emptyValue } -func (self *_runtime) cmpl_evaluate_nodeSwitchStatement(node *_nodeSwitchStatement) Value { - labels := append(self.labels, "") - self.labels = nil +func (rt *runtime) cmplEvaluateNodeSwitchStatement(node *nodeSwitchStatement) Value { + labels := append(rt.labels, "") //nolint: gocritic + rt.labels = nil - discriminantResult := self.cmpl_evaluate_nodeExpression(node.discriminant) - target := node.default_ + discriminantResult := rt.cmplEvaluateNodeExpression(node.discriminant) + target := node.defaultIdx for index, clause := range node.body { test := clause.test if test != nil { - if self.calculateComparison(token.STRICT_EQUAL, discriminantResult, self.cmpl_evaluate_nodeExpression(test)) { + if rt.calculateComparison(token.STRICT_EQUAL, discriminantResult, rt.cmplEvaluateNodeExpression(test)) { target = index break } @@ -324,7 +324,7 @@ func (self *_runtime) cmpl_evaluate_nodeSwitchStatement(node *_nodeSwitchStateme if target != -1 { for _, clause := range node.body[target:] { for _, statement := range clause.consequent { - value := self.cmpl_evaluate_nodeStatement(statement) + value := rt.cmplEvaluateNodeStatement(statement) switch value.kind { case valueResult: switch value.evaluateBreak(labels) { @@ -344,58 +344,58 @@ func (self *_runtime) cmpl_evaluate_nodeSwitchStatement(node *_nodeSwitchStateme return result } -func (self *_runtime) cmpl_evaluate_nodeTryStatement(node *_nodeTryStatement) Value { - tryCatchValue, exception := self.tryCatchEvaluate(func() Value { - return self.cmpl_evaluate_nodeStatement(node.body) +func (rt *runtime) cmplEvaluateNodeTryStatement(node *nodeTryStatement) Value { + tryCatchValue, exep := rt.tryCatchEvaluate(func() Value { + return rt.cmplEvaluateNodeStatement(node.body) }) - if exception && node.catch != nil { - outer := self.scope.lexical - self.scope.lexical = self.newDeclarationStash(outer) + if exep && node.catch != nil { + outer := rt.scope.lexical + rt.scope.lexical = rt.newDeclarationStash(outer) defer func() { - self.scope.lexical = outer + rt.scope.lexical = outer }() // TODO If necessary, convert TypeError => TypeError // That, is, such errors can be thrown despite not being JavaScript "native" // strict = false - self.scope.lexical.setValue(node.catch.parameter, tryCatchValue, false) + rt.scope.lexical.setValue(node.catch.parameter, tryCatchValue, false) // FIXME node.CatchParameter // FIXME node.Catch - tryCatchValue, exception = self.tryCatchEvaluate(func() Value { - return self.cmpl_evaluate_nodeStatement(node.catch.body) + tryCatchValue, exep = rt.tryCatchEvaluate(func() Value { + return rt.cmplEvaluateNodeStatement(node.catch.body) }) } if node.finally != nil { - finallyValue := self.cmpl_evaluate_nodeStatement(node.finally) + finallyValue := rt.cmplEvaluateNodeStatement(node.finally) if finallyValue.kind == valueResult { return finallyValue } } - if exception { + if exep { panic(newException(tryCatchValue)) } return tryCatchValue } -func (self *_runtime) cmpl_evaluate_nodeWhileStatement(node *_nodeWhileStatement) Value { +func (rt *runtime) cmplEvaluateModeWhileStatement(node *nodeWhileStatement) Value { test := node.test body := node.body - labels := append(self.labels, "") - self.labels = nil + labels := append(rt.labels, "") //nolint: gocritic + rt.labels = nil result := emptyValue resultBreakContinue: for { - if !self.cmpl_evaluate_nodeExpression(test).resolve().bool() { + if !rt.cmplEvaluateNodeExpression(test).resolve().bool() { // Stahp: while (false) ... break } for _, node := range body { - value := self.cmpl_evaluate_nodeStatement(node) + value := rt.cmplEvaluateNodeStatement(node) switch value.kind { case valueResult: switch value.evaluateBreakContinue(labels) { @@ -415,14 +415,14 @@ resultBreakContinue: return result } -func (self *_runtime) cmpl_evaluate_nodeWithStatement(node *_nodeWithStatement) Value { - object := self.cmpl_evaluate_nodeExpression(node.object) - outer := self.scope.lexical - lexical := self.newObjectStash(self.toObject(object.resolve()), outer) - self.scope.lexical = lexical +func (rt *runtime) cmplEvaluateNodeWithStatement(node *nodeWithStatement) Value { + obj := rt.cmplEvaluateNodeExpression(node.object) + outer := rt.scope.lexical + lexical := rt.newObjectStash(rt.toObject(obj.resolve()), outer) + rt.scope.lexical = lexical defer func() { - self.scope.lexical = outer + rt.scope.lexical = outer }() - return self.cmpl_evaluate_nodeStatement(node.body) + return rt.cmplEvaluateNodeStatement(node.body) } diff --git a/cmpl_parse.go b/cmpl_parse.go index 1cb47bba..3844ceca 100644 --- a/cmpl_parse.go +++ b/cmpl_parse.go @@ -2,83 +2,84 @@ package otto import ( "fmt" - "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 emptyStatement = &_nodeEmptyStatement{} +var ( + trueLiteral = &nodeLiteral{value: boolValue(true)} + falseLiteral = &nodeLiteral{value: boolValue(false)} + nullLiteral = &nodeLiteral{value: nullValue} + emptyStatement = &nodeEmptyStatement{} +) -func (cmpl *_compiler) parseExpression(in ast.Expression) _nodeExpression { - if in == nil { +func (cmpl *compiler) parseExpression(expr ast.Expression) nodeExpression { + if expr == nil { return nil } - switch in := in.(type) { + switch expr := expr.(type) { case *ast.ArrayLiteral: - out := &_nodeArrayLiteral{ - value: make([]_nodeExpression, len(in.Value)), + out := &nodeArrayLiteral{ + value: make([]nodeExpression, len(expr.Value)), } - for i, value := range in.Value { + for i, value := range expr.Value { out.value[i] = cmpl.parseExpression(value) } return out case *ast.AssignExpression: - return &_nodeAssignExpression{ - operator: in.Operator, - left: cmpl.parseExpression(in.Left), - right: cmpl.parseExpression(in.Right), + return &nodeAssignExpression{ + operator: expr.Operator, + left: cmpl.parseExpression(expr.Left), + right: cmpl.parseExpression(expr.Right), } case *ast.BinaryExpression: - return &_nodeBinaryExpression{ - operator: in.Operator, - left: cmpl.parseExpression(in.Left), - right: cmpl.parseExpression(in.Right), - comparison: in.Comparison, + return &nodeBinaryExpression{ + operator: expr.Operator, + left: cmpl.parseExpression(expr.Left), + right: cmpl.parseExpression(expr.Right), + comparison: expr.Comparison, } case *ast.BooleanLiteral: - if in.Value { + if expr.Value { return trueLiteral } return falseLiteral case *ast.BracketExpression: - return &_nodeBracketExpression{ - idx: in.Left.Idx0(), - left: cmpl.parseExpression(in.Left), - member: cmpl.parseExpression(in.Member), + return &nodeBracketExpression{ + idx: expr.Left.Idx0(), + left: cmpl.parseExpression(expr.Left), + member: cmpl.parseExpression(expr.Member), } case *ast.CallExpression: - out := &_nodeCallExpression{ - callee: cmpl.parseExpression(in.Callee), - argumentList: make([]_nodeExpression, len(in.ArgumentList)), + out := &nodeCallExpression{ + callee: cmpl.parseExpression(expr.Callee), + argumentList: make([]nodeExpression, len(expr.ArgumentList)), } - for i, value := range in.ArgumentList { + for i, value := range expr.ArgumentList { out.argumentList[i] = cmpl.parseExpression(value) } return out case *ast.ConditionalExpression: - return &_nodeConditionalExpression{ - test: cmpl.parseExpression(in.Test), - consequent: cmpl.parseExpression(in.Consequent), - alternate: cmpl.parseExpression(in.Alternate), + return &nodeConditionalExpression{ + test: cmpl.parseExpression(expr.Test), + consequent: cmpl.parseExpression(expr.Consequent), + alternate: cmpl.parseExpression(expr.Alternate), } case *ast.DotExpression: - return &_nodeDotExpression{ - idx: in.Left.Idx0(), - left: cmpl.parseExpression(in.Left), - identifier: in.Identifier.Name, + return &nodeDotExpression{ + idx: expr.Left.Idx0(), + left: cmpl.parseExpression(expr.Left), + identifier: expr.Identifier.Name, } case *ast.EmptyExpression: @@ -86,48 +87,48 @@ func (cmpl *_compiler) parseExpression(in ast.Expression) _nodeExpression { case *ast.FunctionLiteral: name := "" - if in.Name != nil { - name = in.Name.Name + if expr.Name != nil { + name = expr.Name.Name } - out := &_nodeFunctionLiteral{ + out := &nodeFunctionLiteral{ name: name, - body: cmpl.parseStatement(in.Body), - source: in.Source, + body: cmpl.parseStatement(expr.Body), + source: expr.Source, file: cmpl.file, } - if in.ParameterList != nil { - list := in.ParameterList.List + if expr.ParameterList != nil { + list := expr.ParameterList.List out.parameterList = make([]string, len(list)) for i, value := range list { out.parameterList[i] = value.Name } } - for _, value := range in.DeclarationList { + for _, value := range expr.DeclarationList { switch value := value.(type) { case *ast.FunctionDeclaration: - out.functionList = append(out.functionList, cmpl.parseExpression(value.Function).(*_nodeFunctionLiteral)) + out.functionList = append(out.functionList, cmpl.parseExpression(value.Function).(*nodeFunctionLiteral)) case *ast.VariableDeclaration: for _, value := range value.List { out.varList = append(out.varList, value.Name) } default: - panic(fmt.Errorf("Here be dragons: parseProgram.declaration(%T)", value)) + panic(fmt.Sprintf("parse expression unknown function declaration type %T", value)) } } return out case *ast.Identifier: - return &_nodeIdentifier{ - idx: in.Idx, - name: in.Name, + return &nodeIdentifier{ + idx: expr.Idx, + name: expr.Name, } case *ast.NewExpression: - out := &_nodeNewExpression{ - callee: cmpl.parseExpression(in.Callee), - argumentList: make([]_nodeExpression, len(in.ArgumentList)), + out := &nodeNewExpression{ + callee: cmpl.parseExpression(expr.Callee), + argumentList: make([]nodeExpression, len(expr.ArgumentList)), } - for i, value := range in.ArgumentList { + for i, value := range expr.ArgumentList { out.argumentList[i] = cmpl.parseExpression(value) } return out @@ -136,16 +137,16 @@ func (cmpl *_compiler) parseExpression(in ast.Expression) _nodeExpression { return nullLiteral case *ast.NumberLiteral: - return &_nodeLiteral{ - value: toValue(in.Value), + return &nodeLiteral{ + value: toValue(expr.Value), } case *ast.ObjectLiteral: - out := &_nodeObjectLiteral{ - value: make([]_nodeProperty, len(in.Value)), + out := &nodeObjectLiteral{ + value: make([]nodeProperty, len(expr.Value)), } - for i, value := range in.Value { - out.value[i] = _nodeProperty{ + for i, value := range expr.Value { + out.value[i] = nodeProperty{ key: value.Key, kind: value.Kind, value: cmpl.parseExpression(value.Value), @@ -154,79 +155,79 @@ func (cmpl *_compiler) parseExpression(in ast.Expression) _nodeExpression { return out case *ast.RegExpLiteral: - return &_nodeRegExpLiteral{ - flags: in.Flags, - pattern: in.Pattern, + return &nodeRegExpLiteral{ + flags: expr.Flags, + pattern: expr.Pattern, } case *ast.SequenceExpression: - out := &_nodeSequenceExpression{ - sequence: make([]_nodeExpression, len(in.Sequence)), + out := &nodeSequenceExpression{ + sequence: make([]nodeExpression, len(expr.Sequence)), } - for i, value := range in.Sequence { + for i, value := range expr.Sequence { out.sequence[i] = cmpl.parseExpression(value) } return out case *ast.StringLiteral: - return &_nodeLiteral{ - value: toValue_string(in.Value), + return &nodeLiteral{ + value: stringValue(expr.Value), } case *ast.ThisExpression: - return &_nodeThisExpression{} + return &nodeThisExpression{} case *ast.UnaryExpression: - return &_nodeUnaryExpression{ - operator: in.Operator, - operand: cmpl.parseExpression(in.Operand), - postfix: in.Postfix, + return &nodeUnaryExpression{ + operator: expr.Operator, + operand: cmpl.parseExpression(expr.Operand), + postfix: expr.Postfix, } case *ast.VariableExpression: - return &_nodeVariableExpression{ - idx: in.Idx0(), - name: in.Name, - initializer: cmpl.parseExpression(in.Initializer), + return &nodeVariableExpression{ + idx: expr.Idx0(), + name: expr.Name, + initializer: cmpl.parseExpression(expr.Initializer), } + default: + panic(fmt.Errorf("parse expression unknown node type %T", expr)) } - - panic(fmt.Errorf("Here be dragons: cmpl.parseExpression(%T)", in)) } -func (cmpl *_compiler) parseStatement(in ast.Statement) _nodeStatement { - if in == nil { +func (cmpl *compiler) parseStatement(stmt ast.Statement) nodeStatement { + if stmt == nil { return nil } - switch in := in.(type) { + switch stmt := stmt.(type) { case *ast.BlockStatement: - out := &_nodeBlockStatement{ - list: make([]_nodeStatement, len(in.List)), + out := &nodeBlockStatement{ + list: make([]nodeStatement, len(stmt.List)), } - for i, value := range in.List { + for i, value := range stmt.List { out.list[i] = cmpl.parseStatement(value) } return out case *ast.BranchStatement: - out := &_nodeBranchStatement{ - branch: in.Token, + out := &nodeBranchStatement{ + branch: stmt.Token, } - if in.Label != nil { - out.label = in.Label.Name + if stmt.Label != nil { + out.label = stmt.Label.Name } return out case *ast.DebuggerStatement: - return &_nodeDebuggerStatement{} + return &nodeDebuggerStatement{} case *ast.DoWhileStatement: - out := &_nodeDoWhileStatement{ - test: cmpl.parseExpression(in.Test), + out := &nodeDoWhileStatement{ + test: cmpl.parseExpression(stmt.Test), } - body := cmpl.parseStatement(in.Body) - if block, ok := body.(*_nodeBlockStatement); ok { + body := cmpl.parseStatement(stmt.Body) + if block, ok := body.(*nodeBlockStatement); ok { out.body = block.list } else { out.body = append(out.body, body) @@ -237,17 +238,17 @@ func (cmpl *_compiler) parseStatement(in ast.Statement) _nodeStatement { return emptyStatement case *ast.ExpressionStatement: - return &_nodeExpressionStatement{ - expression: cmpl.parseExpression(in.Expression), + return &nodeExpressionStatement{ + expression: cmpl.parseExpression(stmt.Expression), } case *ast.ForInStatement: - out := &_nodeForInStatement{ - into: cmpl.parseExpression(in.Into), - source: cmpl.parseExpression(in.Source), + out := &nodeForInStatement{ + into: cmpl.parseExpression(stmt.Into), + source: cmpl.parseExpression(stmt.Source), } - body := cmpl.parseStatement(in.Body) - if block, ok := body.(*_nodeBlockStatement); ok { + body := cmpl.parseStatement(stmt.Body) + if block, ok := body.(*nodeBlockStatement); ok { out.body = block.list } else { out.body = append(out.body, body) @@ -255,13 +256,13 @@ func (cmpl *_compiler) parseStatement(in ast.Statement) _nodeStatement { return out case *ast.ForStatement: - out := &_nodeForStatement{ - initializer: cmpl.parseExpression(in.Initializer), - update: cmpl.parseExpression(in.Update), - test: cmpl.parseExpression(in.Test), + out := &nodeForStatement{ + initializer: cmpl.parseExpression(stmt.Initializer), + update: cmpl.parseExpression(stmt.Update), + test: cmpl.parseExpression(stmt.Test), } - body := cmpl.parseStatement(in.Body) - if block, ok := body.(*_nodeBlockStatement); ok { + body := cmpl.parseStatement(stmt.Body) + if block, ok := body.(*nodeBlockStatement); ok { out.body = block.list } else { out.body = append(out.body, body) @@ -272,33 +273,33 @@ func (cmpl *_compiler) parseStatement(in ast.Statement) _nodeStatement { return emptyStatement case *ast.IfStatement: - return &_nodeIfStatement{ - test: cmpl.parseExpression(in.Test), - consequent: cmpl.parseStatement(in.Consequent), - alternate: cmpl.parseStatement(in.Alternate), + return &nodeIfStatement{ + test: cmpl.parseExpression(stmt.Test), + consequent: cmpl.parseStatement(stmt.Consequent), + alternate: cmpl.parseStatement(stmt.Alternate), } case *ast.LabelledStatement: - return &_nodeLabelledStatement{ - label: in.Label.Name, - statement: cmpl.parseStatement(in.Statement), + return &nodeLabelledStatement{ + label: stmt.Label.Name, + statement: cmpl.parseStatement(stmt.Statement), } case *ast.ReturnStatement: - return &_nodeReturnStatement{ - argument: cmpl.parseExpression(in.Argument), + return &nodeReturnStatement{ + argument: cmpl.parseExpression(stmt.Argument), } case *ast.SwitchStatement: - out := &_nodeSwitchStatement{ - discriminant: cmpl.parseExpression(in.Discriminant), - default_: in.Default, - body: make([]*_nodeCaseStatement, len(in.Body)), + out := &nodeSwitchStatement{ + discriminant: cmpl.parseExpression(stmt.Discriminant), + defaultIdx: stmt.Default, + body: make([]*nodeCaseStatement, len(stmt.Body)), } - for i, clause := range in.Body { - out.body[i] = &_nodeCaseStatement{ + for i, clause := range stmt.Body { + out.body[i] = &nodeCaseStatement{ test: cmpl.parseExpression(clause.Test), - consequent: make([]_nodeStatement, len(clause.Consequent)), + consequent: make([]nodeStatement, len(clause.Consequent)), } for j, value := range clause.Consequent { out.body[i].consequent[j] = cmpl.parseStatement(value) @@ -307,38 +308,38 @@ func (cmpl *_compiler) parseStatement(in ast.Statement) _nodeStatement { return out case *ast.ThrowStatement: - return &_nodeThrowStatement{ - argument: cmpl.parseExpression(in.Argument), + return &nodeThrowStatement{ + argument: cmpl.parseExpression(stmt.Argument), } case *ast.TryStatement: - 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), + out := &nodeTryStatement{ + body: cmpl.parseStatement(stmt.Body), + finally: cmpl.parseStatement(stmt.Finally), + } + if stmt.Catch != nil { + out.catch = &nodeCatchStatement{ + parameter: stmt.Catch.Parameter.Name, + body: cmpl.parseStatement(stmt.Catch.Body), } } return out case *ast.VariableStatement: - out := &_nodeVariableStatement{ - list: make([]_nodeExpression, len(in.List)), + out := &nodeVariableStatement{ + list: make([]nodeExpression, len(stmt.List)), } - for i, value := range in.List { + for i, value := range stmt.List { out.list[i] = cmpl.parseExpression(value) } return out case *ast.WhileStatement: - out := &_nodeWhileStatement{ - test: cmpl.parseExpression(in.Test), + out := &nodeWhileStatement{ + test: cmpl.parseExpression(stmt.Test), } - body := cmpl.parseStatement(in.Body) - if block, ok := body.(*_nodeBlockStatement); ok { + body := cmpl.parseStatement(stmt.Body) + if block, ok := body.(*nodeBlockStatement); ok { out.body = block.list } else { out.body = append(out.body, body) @@ -346,307 +347,298 @@ func (cmpl *_compiler) parseStatement(in ast.Statement) _nodeStatement { return out case *ast.WithStatement: - return &_nodeWithStatement{ - object: cmpl.parseExpression(in.Object), - body: cmpl.parseStatement(in.Body), + return &nodeWithStatement{ + object: cmpl.parseExpression(stmt.Object), + body: cmpl.parseStatement(stmt.Body), } + default: + panic(fmt.Sprintf("parse statement: unknown type %T", stmt)) } - - panic(fmt.Errorf("Here be dragons: cmpl.parseStatement(%T)", in)) } -func cmpl_parse(in *ast.Program) *_nodeProgram { - cmpl := _compiler{ +func cmplParse(in *ast.Program) *nodeProgram { + cmpl := compiler{ program: in, } + if cmpl.program != nil { + cmpl.file = cmpl.program.File + } + return cmpl.parse() } -func (cmpl *_compiler) _parse(in *ast.Program) *_nodeProgram { - out := &_nodeProgram{ - body: make([]_nodeStatement, len(in.Body)), - file: in.File, +func (cmpl *compiler) parse() *nodeProgram { + out := &nodeProgram{ + body: make([]nodeStatement, len(cmpl.program.Body)), + file: cmpl.program.File, } - for i, value := range in.Body { + for i, value := range cmpl.program.Body { out.body[i] = cmpl.parseStatement(value) } - for _, value := range in.DeclarationList { + for _, value := range cmpl.program.DeclarationList { switch value := value.(type) { case *ast.FunctionDeclaration: - out.functionList = append(out.functionList, cmpl.parseExpression(value.Function).(*_nodeFunctionLiteral)) + out.functionList = append(out.functionList, cmpl.parseExpression(value.Function).(*nodeFunctionLiteral)) case *ast.VariableDeclaration: for _, value := range value.List { out.varList = append(out.varList, value.Name) } default: - panic(fmt.Errorf("Here be dragons: cmpl.parseProgram.DeclarationList(%T)", value)) + panic(fmt.Sprintf("Here be dragons: cmpl.parseProgram.DeclarationList(%T)", value)) } } return out } -type _nodeProgram struct { - body []_nodeStatement +type nodeProgram struct { + body []nodeStatement varList []string - functionList []*_nodeFunctionLiteral - - variableList []_nodeDeclaration + functionList []*nodeFunctionLiteral file *file.File } -type _nodeDeclaration struct { - name string - definition _node -} - -type _node interface { -} +type node interface{} type ( - _nodeExpression interface { - _node - _expressionNode() + nodeExpression interface { + node + expressionNode() } - _nodeArrayLiteral struct { - value []_nodeExpression + nodeArrayLiteral struct { + value []nodeExpression } - _nodeAssignExpression struct { + nodeAssignExpression struct { operator token.Token - left _nodeExpression - right _nodeExpression + left nodeExpression + right nodeExpression } - _nodeBinaryExpression struct { + nodeBinaryExpression struct { operator token.Token - left _nodeExpression - right _nodeExpression + left nodeExpression + right nodeExpression comparison bool } - _nodeBracketExpression struct { + nodeBracketExpression struct { idx file.Idx - left _nodeExpression - member _nodeExpression + left nodeExpression + member nodeExpression } - _nodeCallExpression struct { - callee _nodeExpression - argumentList []_nodeExpression + nodeCallExpression struct { + callee nodeExpression + argumentList []nodeExpression } - _nodeConditionalExpression struct { - test _nodeExpression - consequent _nodeExpression - alternate _nodeExpression + nodeConditionalExpression struct { + test nodeExpression + consequent nodeExpression + alternate nodeExpression } - _nodeDotExpression struct { + nodeDotExpression struct { idx file.Idx - left _nodeExpression + left nodeExpression identifier string } - _nodeFunctionLiteral struct { + nodeFunctionLiteral struct { name string - body _nodeStatement + body nodeStatement source string parameterList []string varList []string - functionList []*_nodeFunctionLiteral + functionList []*nodeFunctionLiteral file *file.File } - _nodeIdentifier struct { + nodeIdentifier struct { idx file.Idx name string } - _nodeLiteral struct { + nodeLiteral struct { value Value } - _nodeNewExpression struct { - callee _nodeExpression - argumentList []_nodeExpression + nodeNewExpression struct { + callee nodeExpression + argumentList []nodeExpression } - _nodeObjectLiteral struct { - value []_nodeProperty + nodeObjectLiteral struct { + value []nodeProperty } - _nodeProperty struct { + nodeProperty struct { key string kind string - value _nodeExpression + value nodeExpression } - _nodeRegExpLiteral struct { + nodeRegExpLiteral struct { flags string pattern string // Value? - regexp *regexp.Regexp } - _nodeSequenceExpression struct { - sequence []_nodeExpression + nodeSequenceExpression struct { + sequence []nodeExpression } - _nodeThisExpression struct { - } + nodeThisExpression struct{} - _nodeUnaryExpression struct { + nodeUnaryExpression struct { operator token.Token - operand _nodeExpression + operand nodeExpression postfix bool } - _nodeVariableExpression struct { + nodeVariableExpression struct { idx file.Idx name string - initializer _nodeExpression + initializer nodeExpression } ) type ( - _nodeStatement interface { - _node - _statementNode() + nodeStatement interface { + node + statementNode() } - _nodeBlockStatement struct { - list []_nodeStatement + nodeBlockStatement struct { + list []nodeStatement } - _nodeBranchStatement struct { + nodeBranchStatement struct { branch token.Token label string } - _nodeCaseStatement struct { - test _nodeExpression - consequent []_nodeStatement + nodeCaseStatement struct { + test nodeExpression + consequent []nodeStatement } - _nodeCatchStatement struct { + nodeCatchStatement struct { parameter string - body _nodeStatement + body nodeStatement } - _nodeDebuggerStatement struct { - } + nodeDebuggerStatement struct{} - _nodeDoWhileStatement struct { - test _nodeExpression - body []_nodeStatement + nodeDoWhileStatement struct { + test nodeExpression + body []nodeStatement } - _nodeEmptyStatement struct { - } + nodeEmptyStatement struct{} - _nodeExpressionStatement struct { - expression _nodeExpression + nodeExpressionStatement struct { + expression nodeExpression } - _nodeForInStatement struct { - into _nodeExpression - source _nodeExpression - body []_nodeStatement + nodeForInStatement struct { + into nodeExpression + source nodeExpression + body []nodeStatement } - _nodeForStatement struct { - initializer _nodeExpression - update _nodeExpression - test _nodeExpression - body []_nodeStatement + nodeForStatement struct { + initializer nodeExpression + update nodeExpression + test nodeExpression + body []nodeStatement } - _nodeIfStatement struct { - test _nodeExpression - consequent _nodeStatement - alternate _nodeStatement + nodeIfStatement struct { + test nodeExpression + consequent nodeStatement + alternate nodeStatement } - _nodeLabelledStatement struct { + nodeLabelledStatement struct { label string - statement _nodeStatement + statement nodeStatement } - _nodeReturnStatement struct { - argument _nodeExpression + nodeReturnStatement struct { + argument nodeExpression } - _nodeSwitchStatement struct { - discriminant _nodeExpression - default_ int - body []*_nodeCaseStatement + nodeSwitchStatement struct { + discriminant nodeExpression + defaultIdx int + body []*nodeCaseStatement } - _nodeThrowStatement struct { - argument _nodeExpression + nodeThrowStatement struct { + argument nodeExpression } - _nodeTryStatement struct { - body _nodeStatement - catch *_nodeCatchStatement - finally _nodeStatement + nodeTryStatement struct { + body nodeStatement + catch *nodeCatchStatement + finally nodeStatement } - _nodeVariableStatement struct { - list []_nodeExpression + nodeVariableStatement struct { + list []nodeExpression } - _nodeWhileStatement struct { - test _nodeExpression - body []_nodeStatement + nodeWhileStatement struct { + test nodeExpression + body []nodeStatement } - _nodeWithStatement struct { - object _nodeExpression - body _nodeStatement + nodeWithStatement struct { + object nodeExpression + body nodeStatement } ) -// _expressionNode - -func (*_nodeArrayLiteral) _expressionNode() {} -func (*_nodeAssignExpression) _expressionNode() {} -func (*_nodeBinaryExpression) _expressionNode() {} -func (*_nodeBracketExpression) _expressionNode() {} -func (*_nodeCallExpression) _expressionNode() {} -func (*_nodeConditionalExpression) _expressionNode() {} -func (*_nodeDotExpression) _expressionNode() {} -func (*_nodeFunctionLiteral) _expressionNode() {} -func (*_nodeIdentifier) _expressionNode() {} -func (*_nodeLiteral) _expressionNode() {} -func (*_nodeNewExpression) _expressionNode() {} -func (*_nodeObjectLiteral) _expressionNode() {} -func (*_nodeRegExpLiteral) _expressionNode() {} -func (*_nodeSequenceExpression) _expressionNode() {} -func (*_nodeThisExpression) _expressionNode() {} -func (*_nodeUnaryExpression) _expressionNode() {} -func (*_nodeVariableExpression) _expressionNode() {} - -// _statementNode - -func (*_nodeBlockStatement) _statementNode() {} -func (*_nodeBranchStatement) _statementNode() {} -func (*_nodeCaseStatement) _statementNode() {} -func (*_nodeCatchStatement) _statementNode() {} -func (*_nodeDebuggerStatement) _statementNode() {} -func (*_nodeDoWhileStatement) _statementNode() {} -func (*_nodeEmptyStatement) _statementNode() {} -func (*_nodeExpressionStatement) _statementNode() {} -func (*_nodeForInStatement) _statementNode() {} -func (*_nodeForStatement) _statementNode() {} -func (*_nodeIfStatement) _statementNode() {} -func (*_nodeLabelledStatement) _statementNode() {} -func (*_nodeReturnStatement) _statementNode() {} -func (*_nodeSwitchStatement) _statementNode() {} -func (*_nodeThrowStatement) _statementNode() {} -func (*_nodeTryStatement) _statementNode() {} -func (*_nodeVariableStatement) _statementNode() {} -func (*_nodeWhileStatement) _statementNode() {} -func (*_nodeWithStatement) _statementNode() {} +// expressionNode. +func (*nodeArrayLiteral) expressionNode() {} +func (*nodeAssignExpression) expressionNode() {} +func (*nodeBinaryExpression) expressionNode() {} +func (*nodeBracketExpression) expressionNode() {} +func (*nodeCallExpression) expressionNode() {} +func (*nodeConditionalExpression) expressionNode() {} +func (*nodeDotExpression) expressionNode() {} +func (*nodeFunctionLiteral) expressionNode() {} +func (*nodeIdentifier) expressionNode() {} +func (*nodeLiteral) expressionNode() {} +func (*nodeNewExpression) expressionNode() {} +func (*nodeObjectLiteral) expressionNode() {} +func (*nodeRegExpLiteral) expressionNode() {} +func (*nodeSequenceExpression) expressionNode() {} +func (*nodeThisExpression) expressionNode() {} +func (*nodeUnaryExpression) expressionNode() {} +func (*nodeVariableExpression) expressionNode() {} + +// statementNode + +func (*nodeBlockStatement) statementNode() {} +func (*nodeBranchStatement) statementNode() {} +func (*nodeCaseStatement) statementNode() {} +func (*nodeCatchStatement) statementNode() {} +func (*nodeDebuggerStatement) statementNode() {} +func (*nodeDoWhileStatement) statementNode() {} +func (*nodeEmptyStatement) statementNode() {} +func (*nodeExpressionStatement) statementNode() {} +func (*nodeForInStatement) statementNode() {} +func (*nodeForStatement) statementNode() {} +func (*nodeIfStatement) statementNode() {} +func (*nodeLabelledStatement) statementNode() {} +func (*nodeReturnStatement) statementNode() {} +func (*nodeSwitchStatement) statementNode() {} +func (*nodeThrowStatement) statementNode() {} +func (*nodeTryStatement) statementNode() {} +func (*nodeVariableStatement) statementNode() {} +func (*nodeWhileStatement) statementNode() {} +func (*nodeWithStatement) statementNode() {} diff --git a/cmpl_test.go b/cmpl_test.go index 15c03bdf..ad8ccfd3 100644 --- a/cmpl_test.go +++ b/cmpl_test.go @@ -14,8 +14,8 @@ func Test_cmpl(t *testing.T) { program, err := parser.ParseFile(nil, "", src, 0) is(err, nil) { - program := cmpl_parse(program) - value := vm.runtime.cmpl_evaluate_nodeProgram(program, false) + program := cmplParse(program) + value := vm.runtime.cmplEvaluateNodeProgram(program, false) if len(expect) > 0 { is(value, expect[0]) } @@ -37,7 +37,7 @@ func TestParse_cmpl(t *testing.T) { test := func(src string) { program, err := parser.ParseFile(nil, "", src, 0) is(err, nil) - is(cmpl_parse(program), "!=", nil) + is(cmplParse(program), "!=", nil) } test(``) diff --git a/console.go b/console.go index 8fba6cc1..842fe2ca 100644 --- a/console.go +++ b/console.go @@ -14,37 +14,33 @@ func formatForConsole(argumentList []Value) string { return strings.Join(output, " ") } -func builtinConsole_log(call FunctionCall) Value { +func builtinConsoleLog(call FunctionCall) Value { fmt.Fprintln(os.Stdout, formatForConsole(call.ArgumentList)) return Value{} } -func builtinConsole_error(call FunctionCall) Value { +func builtinConsoleError(call FunctionCall) Value { fmt.Fprintln(os.Stdout, formatForConsole(call.ArgumentList)) return Value{} } // Nothing happens. -func builtinConsole_dir(call FunctionCall) Value { +func builtinConsoleDir(call FunctionCall) Value { return Value{} } -func builtinConsole_time(call FunctionCall) Value { +func builtinConsoleTime(call FunctionCall) Value { return Value{} } -func builtinConsole_timeEnd(call FunctionCall) Value { +func builtinConsoleTimeEnd(call FunctionCall) Value { return Value{} } -func builtinConsole_trace(call FunctionCall) Value { +func builtinConsoleTrace(call FunctionCall) Value { return Value{} } -func builtinConsole_assert(call FunctionCall) Value { +func builtinConsoleAssert(call FunctionCall) Value { return Value{} } - -func (runtime *_runtime) newConsole() *_object { - return newConsoleObject(runtime) -} diff --git a/consts.go b/consts.go index d8a8e6d0..669735ef 100644 --- a/consts.go +++ b/consts.go @@ -2,18 +2,33 @@ package otto const ( // Common classes. - classString = "String" - classGoArray = "GoArray" - classGoSlice = "GoSlice" - classNumber = "Number" - classDate = "Date" - classArray = "Array" - classFunction = "Function" - classObject = "Object" - classRegExp = "RegExp" - classBoolean = "Boolean" - classError = "Error" + classStringName = "String" + classGoArrayName = "GoArray" + classGoSliceName = "GoSlice" + classNumberName = "Number" + classDateName = "Date" + classArrayName = "Array" + classFunctionName = "Function" + classObjectName = "Object" + classRegExpName = "RegExp" + classBooleanName = "Boolean" + classMathName = "Math" + classJSONName = "JSON" + + // Error classes. + classErrorName = "Error" + classEvalErrorName = "EvalError" + classTypeErrorName = "TypeError" + classRangeErrorName = "RangeError" + classReferenceErrorName = "ReferenceError" + classSyntaxErrorName = "SyntaxError" + classURIErrorName = "URIError" // Common properties. - propertyLength = "length" + propertyLength = "length" + propertyPrototype = "prototype" + propertyConstructor = "constructor" + + // Common methods. + methodToString = "toString" ) diff --git a/date_test.go b/date_test.go index 2fdffbd5..46ce362f 100644 --- a/date_test.go +++ b/date_test.go @@ -14,7 +14,7 @@ func mockTimeLocal(location *time.Location) func() { } } -// Passing or failing should not be dependent on what time zone we're in +// Passing or failing should not be dependent on what time zone we're in. func mockUTC() func() { return mockTimeLocal(time.UTC) } @@ -69,8 +69,6 @@ func TestDate(t *testing.T) { format := "Mon, 2 Jan 2006 15:04:05 MST" time1 := time.Unix(1256450400, 0) - time0 = time.Date(time1.Year(), time1.Month(), time1.Day(), time1.Hour(), time1.Minute(), time1.Second(), time1.Nanosecond(), time1.Location()).In(utcTimeZone) - time0 = time.Date(time1.Year(), time1.Month(), time1.Day(), time1.Hour(), time1.Minute(), time1.Second(), 2001*1000*1000, time1.Location()).In(utcTimeZone) test(`abc = new Date(12564504e5); abc.setMilliseconds(2001); abc.toUTCString()`, time0.Format(format)) diff --git a/dbg/dbg.go b/dbg/dbg.go index 8c27fa29..f0916572 100644 --- a/dbg/dbg.go +++ b/dbg/dbg.go @@ -3,56 +3,55 @@ /* Package dbg is a println/printf/log-debugging utility library. - import ( - Dbg "github.com/robertkrimen/dbg" - ) + import ( + Dbg "github.com/robertkrimen/dbg" + ) - dbg, dbgf := Dbg.New() + 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" + 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("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("%/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("%/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("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("%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 %@)" + 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) - }) - + 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 @@ -63,7 +62,7 @@ import ( "log" "os" "regexp" - "runtime" + goruntime "runtime" "strings" "unicode" ) @@ -130,30 +129,28 @@ func parseFormat(format string) (frmt _frmt) { } type Dbgr struct { - emit _emit + emit emit } type DbgFunction func(values ...interface{}) func NewDbgr() *Dbgr { - self := &Dbgr{} - return self + return &Dbgr{} } /* 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) - }) + 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() @@ -165,26 +162,25 @@ func New(options ...interface{}) (dbg DbgFunction, dbgf DbgFunction) { return dbgr.DbgDbgf() } -func (self Dbgr) Dbg(values ...interface{}) { - self.getEmit().emit(_frmt{}, "", values...) +func (d Dbgr) Dbg(values ...interface{}) { + d.getEmit().emit(_frmt{}, "", values...) } -func (self Dbgr) Dbgf(values ...interface{}) { - self.dbgf(values...) +func (d Dbgr) Dbgf(values ...interface{}) { + d.dbgf(values...) } -func (self Dbgr) DbgDbgf() (dbg DbgFunction, dbgf DbgFunction) { +func (d Dbgr) DbgDbgf() (dbg DbgFunction, dbgf DbgFunction) { dbg = func(vl ...interface{}) { - self.Dbg(vl...) + d.Dbg(vl...) } dbgf = func(vl ...interface{}) { - self.dbgf(vl...) + d.dbgf(vl...) } return dbg, dbgf // Redundant, but... } -func (self Dbgr) dbgf(values ...interface{}) { - +func (d Dbgr) dbgf(values ...interface{}) { var frmt _frmt if len(values) > 0 { tmp := fmt.Sprint(values[0]) @@ -192,7 +188,7 @@ func (self Dbgr) dbgf(values ...interface{}) { values = values[1:] } - buffer_f := bytes.Buffer{} + buf := bytes.Buffer{} format := frmt.format end := len(format) for at := 0; at < end; { @@ -201,7 +197,7 @@ func (self Dbgr) dbgf(values ...interface{}) { at++ } if at > last { - buffer_f.WriteString(format[last:at]) + buf.WriteString(format[last:at]) } if at >= end { break @@ -211,100 +207,97 @@ func (self Dbgr) dbgf(values ...interface{}) { // format[at] == ? if format[at] == '@' { depth := 2 - pc, _, _, _ := runtime.Caller(depth) - name := runtime.FuncForPC(pc).Name() - buffer_f.WriteString(name) + pc, _, _, _ := goruntime.Caller(depth) + name := goruntime.FuncForPC(pc).Name() + buf.WriteString(name) } else { - buffer_f.WriteString(format[at-1 : at+1]) + buf.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 { + //valuesF := append([]interface{}{}, values[0:frmt.operandCount]...) + valuesF := values[0:frmt.operandCount] + valuesDbg := values[frmt.operandCount:] + if len(valuesDbg) > 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 + tmp := format + if len(tmp) > 0 { + if unicode.IsSpace(rune(tmp[len(tmp)-1])) { + buf.WriteString("%v") } else { - buffer_f.WriteString("%v") + buf.WriteString(" %v") } + } else if frmt.check { + // Performing a check, so no output + } else { + buf.WriteString("%v") } - // Adjust values_f: + // Adjust valuesF: if !frmt.check { tmp := []string{} - for _, value := range values_dbg { + for _, value := range valuesDbg { 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, " ")) + // First, make a copy of valuesF, so we avoid overwriting valuesDbg when appending + valuesF = append([]interface{}{}, valuesF...) + valuesF = append(valuesF, strings.Join(tmp, " ")) } } - format = buffer_f.String() + format = buf.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 { + for _, value := range valuesDbg { if value != nil { if format == "" { panic(value) } else { - panic(fmt.Sprintf(format, append(values_f, value)...)) + panic(fmt.Sprintf(format, append(valuesF, value)...)) } } } } else { - self.getEmit().emit(frmt, format, values_f...) + d.getEmit().emit(frmt, format, valuesF...) } } // Idiot-proof &Dbgr{}, etc. -func (self *Dbgr) getEmit() _emit { - if self.emit == nil { - self.emit = standardEmit() +func (d *Dbgr) getEmit() emit { + if d.emit == nil { + d.emit = standardEmit() } - return self.emit + return d.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{}) { +// *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 (d *Dbgr) SetOutput(output interface{}) { if output == nil { - self.emit = standardEmit() + d.emit = standardEmit() return } switch output := output.(type) { case *log.Logger: - self.emit = _emitLogger{ + d.emit = emitLogger{ logger: output, } return case io.Writer: - self.emit = _emitWriter{ + d.emit = emitWriter{ writer: output, } return case string: if output == "log" { - self.emit = _emitLog{} + d.emit = emitLog{} return } } @@ -315,8 +308,8 @@ func (self *Dbgr) SetOutput(output interface{}) { // = emit = // // ======== // -func standardEmit() _emit { - return _emitWriter{ +func standardEmit() emit { + return emitWriter{ writer: os.Stderr, } } @@ -329,50 +322,50 @@ func ln(tmp string) string { return tmp } -type _emit interface { +type emit interface { emit(_frmt, string, ...interface{}) } -type _emitWriter struct { +type emitWriter struct { writer io.Writer } -func (self _emitWriter) emit(frmt _frmt, format string, values ...interface{}) { +func (ew emitWriter) emit(frmt _frmt, format string, values ...interface{}) { if format == "" { - fmt.Fprintln(self.writer, values...) + fmt.Fprintln(ew.writer, values...) } else { if frmt.panic { panic(fmt.Sprintf(format, values...)) } - fmt.Fprintf(self.writer, ln(format), values...) + fmt.Fprintf(ew.writer, ln(format), values...) if frmt.fatal { os.Exit(1) } } } -type _emitLogger struct { +type emitLogger struct { logger *log.Logger } -func (self _emitLogger) emit(frmt _frmt, format string, values ...interface{}) { +func (el emitLogger) emit(frmt _frmt, format string, values ...interface{}) { if format == "" { - self.logger.Println(values...) + el.logger.Println(values...) } else { if frmt.panic { - self.logger.Panicf(format, values...) + el.logger.Panicf(format, values...) } else if frmt.fatal { - self.logger.Fatalf(format, values...) + el.logger.Fatalf(format, values...) } else { - self.logger.Printf(format, values...) + el.logger.Printf(format, values...) } } } -type _emitLog struct { +type emitLog struct { } -func (self _emitLog) emit(frmt _frmt, format string, values ...interface{}) { +func (el emitLog) emit(frmt _frmt, format string, values ...interface{}) { if format == "" { log.Println(values...) } else { diff --git a/documentation_test.go b/documentation_test.go index c9a76259..a7f8341e 100644 --- a/documentation_test.go +++ b/documentation_test.go @@ -2,58 +2,105 @@ package otto import ( "fmt" + "os" ) func ExampleSynopsis() { //nolint: govet vm := New() - vm.Run(` + _, err := vm.Run(` abc = 2 + 2; console.log("The value of abc is " + abc); // 4 `) + if err != nil { + fmt.Fprintln(os.Stderr, err) + return + } - value, _ := vm.Get("abc") - { - value, _ := value.ToInteger() - fmt.Println(value) + value, err := vm.Get("abc") + if err != nil { + fmt.Fprintln(os.Stderr, err) + return } - vm.Set("def", 11) - vm.Run(` + iv, err := value.ToInteger() + if err != nil { + fmt.Fprintln(os.Stderr, err) + return + } + fmt.Println(iv) + + err = vm.Set("def", 11) + if err != nil { + fmt.Fprintln(os.Stderr, err) + return + } + _, err = vm.Run(` console.log("The value of def is " + def); `) + if err != nil { + fmt.Fprintln(os.Stderr, err) + return + } - vm.Set("xyzzy", "Nothing happens.") - vm.Run(` + err = vm.Set("xyzzy", "Nothing happens.") + if err != nil { + fmt.Fprintln(os.Stderr, err) + return + } + _, err = vm.Run(` console.log(xyzzy.length); `) + if err != nil { + fmt.Fprintln(os.Stderr, err) + return + } + + value, err = vm.Run("xyzzy.length") + if err != nil { + fmt.Fprintln(os.Stderr, err) + return + } - value, _ = vm.Run("xyzzy.length") - { - value, _ := value.ToInteger() - fmt.Println(value) + iv, err = value.ToInteger() + if err != nil { + fmt.Fprintln(os.Stderr, err) + return } + fmt.Println(iv) - value, err := vm.Run("abcdefghijlmnopqrstuvwxyz.length") + value, err = vm.Run("abcdefghijlmnopqrstuvwxyz.length") fmt.Println(value) - fmt.Println(err) + fmt.Println(err) // Expected error. - vm.Set("sayHello", func(call FunctionCall) Value { + err = vm.Set("sayHello", func(call FunctionCall) Value { fmt.Printf("Hello, %s.\n", call.Argument(0).String()) return UndefinedValue() }) + if err != nil { + fmt.Fprintln(os.Stderr, err) + return + } - vm.Set("twoPlus", func(call FunctionCall) Value { + err = vm.Set("twoPlus", func(call FunctionCall) Value { right, _ := call.Argument(0).ToInteger() result, _ := vm.ToValue(2 + right) return result }) + if err != nil { + fmt.Fprintln(os.Stderr, err) + return + } - value, _ = vm.Run(` + value, err = vm.Run(` sayHello("Xyzzy"); sayHello(); result = twoPlus(2.0); `) + if err != nil { + fmt.Fprintln(os.Stderr, err) + return + } fmt.Println(value) // Output: diff --git a/error.go b/error.go index 16e96ba0..7f1bbafc 100644 --- a/error.go +++ b/error.go @@ -7,49 +7,49 @@ import ( "github.com/robertkrimen/otto/file" ) -type _exception struct { +type exception struct { value interface{} } -func newException(value interface{}) *_exception { - return &_exception{ +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 +func (e *exception) eject() interface{} { + value := e.value + e.value = nil // Prevent Go from holding on to the value, whatever it is return value } -type _error struct { +type ottoError struct { name string message string - trace []_frame + trace []frame offset int } -func (err _error) format() string { - if len(err.name) == 0 { - return err.message +func (e ottoError) format() string { + if len(e.name) == 0 { + return e.message } - if len(err.message) == 0 { - return err.name + if len(e.message) == 0 { + return e.name } - return fmt.Sprintf("%s: %s", err.name, err.message) + return fmt.Sprintf("%s: %s", e.name, e.message) } -func (err _error) formatWithStack() string { - str := err.format() + "\n" - for _, frame := range err.trace { - str += " at " + frame.location() + "\n" +func (e ottoError) formatWithStack() string { + str := e.format() + "\n" + for _, frm := range e.trace { + str += " at " + frm.location() + "\n" } return str } -type _frame struct { +type frame struct { native bool nativeFile string nativeLine int @@ -59,13 +59,11 @@ type _frame struct { fn interface{} } -var ( - nativeFrame = _frame{} -) +var nativeFrame = frame{} -type _at int +type at int -func (fr _frame) location() string { +func (fr frame) location() string { str := "" switch { @@ -95,14 +93,14 @@ func (fr _frame) location() string { // An Error represents a runtime error, e.g. a TypeError, a ReferenceError, etc. type Error struct { - _error + ottoError } // Error returns a description of the error // // TypeError: 'def' is not a function -func (err Error) Error() string { - return err.format() +func (e Error) Error() string { + return e.format() } // String returns a description of the error and a trace of where the @@ -111,36 +109,36 @@ func (err Error) Error() string { // TypeError: 'def' is not a function // at xyz (:3:9) // at :7:1/ -func (err Error) String() string { - return err.formatWithStack() +func (e Error) String() string { + return e.formatWithStack() } // GoString returns a description of the error and a trace of where the // error occurred. Printing with %#v will trigger this behaviour. -func (err Error) GoString() string { - return err.formatWithStack() +func (e Error) GoString() string { + return e.formatWithStack() } -func (err _error) describe(format string, in ...interface{}) string { +func (e ottoError) describe(format string, in ...interface{}) string { return fmt.Sprintf(format, in...) } -func (self _error) messageValue() Value { - if self.message == "" { +func (e ottoError) messageValue() Value { + if e.message == "" { return Value{} } - return toValue_string(self.message) + return stringValue(e.message) } -func (rt *_runtime) typeErrorResult(throw bool) bool { +func (rt *runtime) typeErrorResult(throw bool) bool { if throw { panic(rt.panicTypeError()) } return false } -func newError(rt *_runtime, name string, stackFramesToPop int, in ...interface{}) _error { - err := _error{ +func newError(rt *runtime, name string, stackFramesToPop int, in ...interface{}) ottoError { + err := ottoError{ name: name, offset: -1, } @@ -148,21 +146,21 @@ func newError(rt *_runtime, name string, stackFramesToPop int, in ...interface{} length := len(in) if rt != nil && rt.scope != nil { - scope := rt.scope + curScope := rt.scope for i := 0; i < stackFramesToPop; i++ { - if scope.outer != nil { - scope = scope.outer + if curScope.outer != nil { + curScope = curScope.outer } } - frame := scope.frame + frm := curScope.frame if length > 0 { - if at, ok := in[length-1].(_at); ok { + if atv, ok := in[length-1].(at); ok { in = in[0 : length-1] - if scope != nil { - frame.offset = int(at) + if curScope != nil { + frm.offset = int(atv) } length-- } @@ -173,54 +171,52 @@ func newError(rt *_runtime, name string, stackFramesToPop int, in ...interface{} limit := rt.traceLimit - err.trace = append(err.trace, frame) - if scope != nil { - for scope = scope.outer; scope != nil; scope = scope.outer { + err.trace = append(err.trace, frm) + if curScope != nil { + for curScope = curScope.outer; curScope != nil; curScope = curScope.outer { if limit--; limit == 0 { break } - if scope.frame.offset >= 0 { - err.trace = append(err.trace, scope.frame) + if curScope.frame.offset >= 0 { + err.trace = append(err.trace, curScope.frame) } } } - } else { - if length > 0 { - description, in = in[0].(string), in[1:] - } + } 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{ +func (rt *runtime) panicTypeError(argumentList ...interface{}) *exception { + return &exception{ value: newError(rt, "TypeError", 0, argumentList...), } } -func (rt *_runtime) panicReferenceError(argumentList ...interface{}) *_exception { - return &_exception{ +func (rt *runtime) panicReferenceError(argumentList ...interface{}) *exception { + return &exception{ value: newError(rt, "ReferenceError", 0, argumentList...), } } -func (rt *_runtime) panicURIError(argumentList ...interface{}) *_exception { - return &_exception{ +func (rt *runtime) panicURIError(argumentList ...interface{}) *exception { + return &exception{ value: newError(rt, "URIError", 0, argumentList...), } } -func (rt *_runtime) panicSyntaxError(argumentList ...interface{}) *_exception { - return &_exception{ +func (rt *runtime) panicSyntaxError(argumentList ...interface{}) *exception { + return &exception{ value: newError(rt, "SyntaxError", 0, argumentList...), } } -func (rt *_runtime) panicRangeError(argumentList ...interface{}) *_exception { - return &_exception{ +func (rt *runtime) panicRangeError(argumentList ...interface{}) *exception { + return &exception{ value: newError(rt, "RangeError", 0, argumentList...), } } @@ -228,20 +224,19 @@ func (rt *_runtime) panicRangeError(argumentList ...interface{}) *_exception { func catchPanic(function func()) (err error) { defer func() { if caught := recover(); caught != nil { - if exception, ok := caught.(*_exception); ok { - caught = exception.eject() + if excep, ok := caught.(*exception); ok { + caught = excep.eject() } switch caught := caught.(type) { case *Error: err = caught return - case _error: + case ottoError: err = &Error{caught} return case Value: - if vl := caught._object(); vl != nil { - switch vl := vl.value.(type) { - case _error: + if vl := caught.object(); vl != nil { + if vl, ok := vl.value.(ottoError); ok { err = &Error{vl} return } diff --git a/error_native_test.go b/error_native_test.go index f6579ca0..9fcce79b 100644 --- a/error_native_test.go +++ b/error_native_test.go @@ -2,6 +2,8 @@ package otto import ( "testing" + + "github.com/stretchr/testify/require" ) // this is its own file because the tests in it rely on the line numbers of @@ -12,28 +14,33 @@ func TestErrorContextNative(t *testing.T) { tt(t, func() { vm := New() - vm.Set("N", func(c FunctionCall) Value { + err := vm.Set("N", func(c FunctionCall) Value { v, err := c.Argument(0).Call(NullValue()) if err != nil { panic(err) } return v }) + require.NoError(t, err) - s, _ := vm.Compile("test.js", ` + s, err := vm.Compile("test.js", ` function F() { throw new Error('wow'); } function G() { return N(F); } `) + require.NoError(t, err) - vm.Run(s) + _, err = vm.Run(s) + require.NoError(t, err) - f1, _ := vm.Get("G") - _, err := f1.Call(NullValue()) - err1 := err.(*Error) + f1, err := vm.Get("G") + require.NoError(t, err) + _, err = f1.Call(NullValue()) + require.Error(t, err) + err1 := asError(t, err) is(err1.message, "wow") is(len(err1.trace), 3) is(err1.trace[0].location(), "F (test.js:2:29)") - is(err1.trace[1].location(), "github.com/robertkrimen/otto.TestErrorContextNative.func1.1 (error_native_test.go:15)") + is(err1.trace[1].location(), "github.com/robertkrimen/otto.TestErrorContextNative.func1.1 (error_native_test.go:17)") is(err1.trace[2].location(), "G (test.js:3:26)") }) } diff --git a/error_test.go b/error_test.go index 0715d543..1a40c889 100644 --- a/error_test.go +++ b/error_test.go @@ -1,7 +1,10 @@ package otto import ( + "errors" "testing" + + "github.com/stretchr/testify/require" ) func TestError(t *testing.T) { @@ -61,6 +64,13 @@ func Test_catchPanic(t *testing.T) { }) } +func asError(t *testing.T, err error) *Error { + t.Helper() + var oerr *Error + require.True(t, errors.As(err, &oerr)) + return oerr +} + func TestErrorContext(t *testing.T) { tt(t, func() { vm := New() @@ -69,7 +79,7 @@ func TestErrorContext(t *testing.T) { undefined(); `) { - err := err.(*Error) + err := asError(t, err) is(err.message, "'undefined' is not a function") is(len(err.trace), 1) is(err.trace[0].location(), ":2:13") @@ -79,7 +89,7 @@ func TestErrorContext(t *testing.T) { ({}).abc(); `) { - err := err.(*Error) + err := asError(t, err) is(err.message, "'abc' is not a function") is(len(err.trace), 1) is(err.trace[0].location(), ":2:14") @@ -89,7 +99,7 @@ func TestErrorContext(t *testing.T) { ("abc").abc(); `) { - err := err.(*Error) + err := asError(t, err) is(err.message, "'abc' is not a function") is(len(err.trace), 1) is(err.trace[0].location(), ":2:14") @@ -100,7 +110,7 @@ func TestErrorContext(t *testing.T) { ghi(); `) { - err := err.(*Error) + err := asError(t, err) is(err.message, "'ghi' is not a function") is(len(err.trace), 1) is(err.trace[0].location(), ":3:13") @@ -116,7 +126,7 @@ func TestErrorContext(t *testing.T) { abc(); `) { - err := err.(*Error) + err := asError(t, err) is(err.message, "'undefined' is not a function") is(len(err.trace), 3) is(err.trace[0].location(), "def (:3:17)") @@ -131,7 +141,7 @@ func TestErrorContext(t *testing.T) { abc(); `) { - err := err.(*Error) + err := asError(t, err) is(err.message, "'xyz' is not defined") is(len(err.trace), 2) is(err.trace[0].location(), "abc (:3:17)") @@ -142,7 +152,7 @@ func TestErrorContext(t *testing.T) { mno + 1; `) { - err := err.(*Error) + err := asError(t, err) is(err.message, "'mno' is not defined") is(len(err.trace), 1) is(err.trace[0].location(), ":2:13") @@ -152,7 +162,7 @@ func TestErrorContext(t *testing.T) { eval("xyz();"); `) { - err := err.(*Error) + err := asError(t, err) is(err.message, "'xyz' is not defined") is(len(err.trace), 1) is(err.trace[0].location(), ":1:1") @@ -163,7 +173,7 @@ func TestErrorContext(t *testing.T) { eval("xyzzy();"); `) { - err := err.(*Error) + err := asError(t, err) is(err.message, "'xyzzy' is not a function") is(len(err.trace), 1) is(err.trace[0].location(), ":1:1") @@ -173,7 +183,7 @@ func TestErrorContext(t *testing.T) { throw Error("xyzzy"); `) { - err := err.(*Error) + err := asError(t, err) is(err.message, "xyzzy") is(len(err.trace), 1) is(err.trace[0].location(), ":2:19") @@ -183,7 +193,7 @@ func TestErrorContext(t *testing.T) { throw new Error("xyzzy"); `) { - err := err.(*Error) + err := asError(t, err) is(err.message, "xyzzy") is(len(err.trace), 1) is(err.trace[0].location(), ":2:23") @@ -219,7 +229,7 @@ func TestErrorContext(t *testing.T) { _, err = vm.Run(script3) { - err := err.(*Error) + err := asError(t, err) is(err.message, "test") is(len(err.trace), 3) is(err.trace[0].location(), "A (file1.js:2:15)") @@ -230,7 +240,7 @@ func TestErrorContext(t *testing.T) { { f, _ := vm.Get("B") _, err := f.Call(UndefinedValue()) - err1 := err.(*Error) + err1 := asError(t, err) is(err1.message, "test") is(len(err1.trace), 2) is(err1.trace[0].location(), "A (file1.js:2:15)") @@ -240,7 +250,7 @@ func TestErrorContext(t *testing.T) { { f, _ := vm.Get("C") _, err := f.Call(UndefinedValue()) - err1 := err.(*Error) + err1 := asError(t, err) is(err1.message, "Cannot access member 'prop' of null") is(len(err1.trace), 1) is(err1.trace[0].location(), "C (file1.js:7:5)") @@ -252,49 +262,40 @@ func TestMakeCustomErrorReturn(t *testing.T) { tt(t, func() { vm := New() - vm.Set("A", func(c FunctionCall) Value { + err := vm.Set("A", func(c FunctionCall) Value { return vm.MakeCustomError("CarrotError", "carrots is life, carrots is love") }) + require.NoError(t, err) - s, _ := vm.Compile("test.js", ` + s, err := vm.Compile("test.js", ` function B() { return A(); } function C() { return B(); } function D() { return C(); } `) + require.NoError(t, err) - if _, err := vm.Run(s); err != nil { - panic(err) - } + _, err = vm.Run(s) + require.NoError(t, err) v, err := vm.Call("D", nil) - if err != nil { - panic(err) - } + require.NoError(t, err) - is(v.Class(), classError) + is(v.Class(), classErrorName) name, err := v.Object().Get("name") - if err != nil { - panic(err) - } + require.NoError(t, err) is(name.String(), "CarrotError") message, err := v.Object().Get("message") - if err != nil { - panic(err) - } + require.NoError(t, err) is(message.String(), "carrots is life, carrots is love") str, err := v.Object().Call("toString") - if err != nil { - panic(err) - } + require.NoError(t, err) is(str, "CarrotError: carrots is life, carrots is love") i, err := v.Export() - if err != nil { - panic(err) - } + require.NoError(t, err) t.Logf("%#v\n", i) }) } @@ -303,29 +304,25 @@ func TestMakeCustomError(t *testing.T) { tt(t, func() { vm := New() - vm.Set("A", func(c FunctionCall) Value { + err := vm.Set("A", func(c FunctionCall) Value { panic(vm.MakeCustomError("CarrotError", "carrots is life, carrots is love")) }) + require.NoError(t, err) - s, _ := vm.Compile("test.js", ` + s, err := vm.Compile("test.js", ` function B() { A(); } function C() { B(); } function D() { C(); } `) + require.NoError(t, err) - if _, err := vm.Run(s); err != nil { - panic(err) - } - - _, err := vm.Call("D", nil) - if err == nil { - panic("error should not be nil") - } - - is(err.Error(), "CarrotError: carrots is life, carrots is love") + _, err = vm.Run(s) + require.NoError(t, err) - er := err.(*Error) + _, err = vm.Call("D", nil) + require.EqualError(t, err, "CarrotError: carrots is life, carrots is love") + er := asError(t, err) is(er.name, "CarrotError") is(er.message, "carrots is life, carrots is love") }) @@ -337,9 +334,7 @@ func TestMakeCustomErrorFreshVM(t *testing.T) { e := vm.MakeCustomError("CarrotError", "carrots is life, carrots is love") str, err := e.ToString() - if err != nil { - panic(err) - } + require.NoError(t, err) is(str, "CarrotError: carrots is life, carrots is love") }) @@ -349,29 +344,25 @@ func TestMakeTypeError(t *testing.T) { tt(t, func() { vm := New() - vm.Set("A", func(c FunctionCall) Value { + err := vm.Set("A", func(c FunctionCall) Value { panic(vm.MakeTypeError("these aren't my glasses")) }) + require.NoError(t, err) - s, _ := vm.Compile("test.js", ` + s, err := vm.Compile("test.js", ` function B() { A(); } function C() { B(); } function D() { C(); } `) + require.NoError(t, err) - if _, err := vm.Run(s); err != nil { - panic(err) - } - - _, err := vm.Call("D", nil) - if err == nil { - panic("error should not be nil") - } - - is(err.Error(), "TypeError: these aren't my glasses") + _, err = vm.Run(s) + require.NoError(t, err) - er := err.(*Error) + _, err = vm.Call("D", nil) + require.EqualError(t, err, "TypeError: these aren't my glasses") + er := asError(t, err) is(er.name, "TypeError") is(er.message, "these aren't my glasses") }) @@ -381,29 +372,25 @@ func TestMakeRangeError(t *testing.T) { tt(t, func() { vm := New() - vm.Set("A", func(c FunctionCall) Value { + err := vm.Set("A", func(c FunctionCall) Value { panic(vm.MakeRangeError("too many")) }) + require.NoError(t, err) - s, _ := vm.Compile("test.js", ` + s, err := vm.Compile("test.js", ` function B() { A(); } function C() { B(); } function D() { C(); } `) + require.NoError(t, err) - if _, err := vm.Run(s); err != nil { - panic(err) - } - - _, err := vm.Call("D", nil) - if err == nil { - panic("error should not be nil") - } - - is(err.Error(), "RangeError: too many") + _, err = vm.Run(s) + require.NoError(t, err) - er := err.(*Error) + _, err = vm.Call("D", nil) + require.EqualError(t, err, "RangeError: too many") + er := asError(t, err) is(er.name, "RangeError") is(er.message, "too many") }) @@ -413,29 +400,25 @@ func TestMakeSyntaxError(t *testing.T) { tt(t, func() { vm := New() - vm.Set("A", func(c FunctionCall) Value { + err := vm.Set("A", func(c FunctionCall) Value { panic(vm.MakeSyntaxError("i think you meant \"you're\"")) }) + require.NoError(t, err) - s, _ := vm.Compile("test.js", ` + s, err := vm.Compile("test.js", ` function B() { A(); } function C() { B(); } function D() { C(); } `) + require.NoError(t, err) - if _, err := vm.Run(s); err != nil { - panic(err) - } - - _, err := vm.Call("D", nil) - if err == nil { - panic("error should not be nil") - } - - is(err.Error(), "SyntaxError: i think you meant \"you're\"") + _, err = vm.Run(s) + require.NoError(t, err) - er := err.(*Error) + _, err = vm.Call("D", nil) + require.EqualError(t, err, "SyntaxError: i think you meant \"you're\"") + er := asError(t, err) is(er.name, "SyntaxError") is(er.message, "i think you meant \"you're\"") }) @@ -456,14 +439,10 @@ func TestErrorStackProperty(t *testing.T) { s; `) - if err != nil { - panic(err) - } + require.NoError(t, err) v, err := vm.Run(s) - if err != nil { - panic(err) - } + require.NoError(t, err) is(v.String(), "TypeError: uh oh\n at A (test.js:2:29)\n at B (test.js:3:26)\n at C (test.js:4:26)\n at test.js:8:10\n") }) diff --git a/evaluate.go b/evaluate.go index 8995273c..aba7276b 100644 --- a/evaluate.go +++ b/evaluate.go @@ -8,12 +8,12 @@ import ( "github.com/robertkrimen/otto/token" ) -func (self *_runtime) evaluateMultiply(left float64, right float64) Value { +func (rt *runtime) evaluateMultiply(left float64, right float64) Value { //nolint: unused // TODO 11.5.1 return Value{} } -func (self *_runtime) evaluateDivide(left float64, right float64) Value { +func (rt *runtime) evaluateDivide(left float64, right float64) Value { if math.IsNaN(left) || math.IsNaN(right) { return NaNValue() } @@ -26,61 +26,57 @@ func (self *_runtime) evaluateDivide(left float64, right float64) Value { if math.IsInf(left, 0) { if math.Signbit(left) == math.Signbit(right) { return positiveInfinityValue() - } else { - return negativeInfinityValue() } + return negativeInfinityValue() } if math.IsInf(right, 0) { if math.Signbit(left) == math.Signbit(right) { return positiveZeroValue() - } else { - return negativeZeroValue() } + return negativeZeroValue() } if right == 0 { if math.Signbit(left) == math.Signbit(right) { return positiveInfinityValue() - } else { - return negativeInfinityValue() } + return negativeInfinityValue() } - return toValue_float64(left / right) + return float64Value(left / right) } -func (self *_runtime) evaluateModulo(left float64, right float64) Value { +func (rt *runtime) evaluateModulo(left float64, right float64) Value { //nolint: unused // TODO 11.5.3 return Value{} } -func (self *_runtime) calculateBinaryExpression(operator token.Token, left Value, right Value) Value { +func (rt *runtime) calculateBinaryExpression(operator token.Token, left Value, right Value) Value { leftValue := left.resolve() switch operator { // Additive case token.PLUS: - leftValue = toPrimitive(leftValue) + leftValue = toPrimitiveValue(leftValue) rightValue := right.resolve() - rightValue = toPrimitive(rightValue) + rightValue = toPrimitiveValue(rightValue) if leftValue.IsString() || rightValue.IsString() { - return toValue_string(strings.Join([]string{leftValue.string(), rightValue.string()}, "")) - } else { - return toValue_float64(leftValue.float64() + rightValue.float64()) + return stringValue(strings.Join([]string{leftValue.string(), rightValue.string()}, "")) } + return float64Value(leftValue.float64() + rightValue.float64()) case token.MINUS: rightValue := right.resolve() - return toValue_float64(leftValue.float64() - rightValue.float64()) + return float64Value(leftValue.float64() - rightValue.float64()) // Multiplicative case token.MULTIPLY: rightValue := right.resolve() - return toValue_float64(leftValue.float64() * rightValue.float64()) + return float64Value(leftValue.float64() * rightValue.float64()) case token.SLASH: rightValue := right.resolve() - return self.evaluateDivide(leftValue.float64(), rightValue.float64()) + return rt.evaluateDivide(leftValue.float64(), rightValue.float64()) case token.REMAINDER: rightValue := right.resolve() - return toValue_float64(math.Mod(leftValue.float64(), rightValue.float64())) + return float64Value(math.Mod(leftValue.float64(), rightValue.float64())) // Logical case token.LOGICAL_AND: @@ -88,65 +84,65 @@ func (self *_runtime) calculateBinaryExpression(operator token.Token, left Value if !left { return falseValue } - return toValue_bool(right.resolve().bool()) + return boolValue(right.resolve().bool()) case token.LOGICAL_OR: left := leftValue.bool() if left { return trueValue } - return toValue_bool(right.resolve().bool()) + return boolValue(right.resolve().bool()) // Bitwise case token.AND: rightValue := right.resolve() - return toValue_int32(toInt32(leftValue) & toInt32(rightValue)) + return int32Value(toInt32(leftValue) & toInt32(rightValue)) case token.OR: rightValue := right.resolve() - return toValue_int32(toInt32(leftValue) | toInt32(rightValue)) + return int32Value(toInt32(leftValue) | toInt32(rightValue)) case token.EXCLUSIVE_OR: rightValue := right.resolve() - return toValue_int32(toInt32(leftValue) ^ toInt32(rightValue)) + return int32Value(toInt32(leftValue) ^ toInt32(rightValue)) // Shift // (Masking of 0x1f is to restrict the shift to a maximum of 31 places) case token.SHIFT_LEFT: rightValue := right.resolve() - return toValue_int32(toInt32(leftValue) << (toUint32(rightValue) & 0x1f)) + return int32Value(toInt32(leftValue) << (toUint32(rightValue) & 0x1f)) case token.SHIFT_RIGHT: rightValue := right.resolve() - return toValue_int32(toInt32(leftValue) >> (toUint32(rightValue) & 0x1f)) + return int32Value(toInt32(leftValue) >> (toUint32(rightValue) & 0x1f)) case token.UNSIGNED_SHIFT_RIGHT: rightValue := right.resolve() // Shifting an unsigned integer is a logical shift - return toValue_uint32(toUint32(leftValue) >> (toUint32(rightValue) & 0x1f)) + return uint32Value(toUint32(leftValue) >> (toUint32(rightValue) & 0x1f)) case token.INSTANCEOF: rightValue := right.resolve() if !rightValue.IsObject() { - panic(self.panicTypeError("Expecting a function in instanceof check, but got: %v", rightValue)) + panic(rt.panicTypeError("Expecting a function in instanceof check, but got: %v", rightValue)) } - return toValue_bool(rightValue._object().hasInstance(leftValue)) + return boolValue(rightValue.object().hasInstance(leftValue)) case token.IN: rightValue := right.resolve() if !rightValue.IsObject() { - panic(self.panicTypeError()) + panic(rt.panicTypeError()) } - return toValue_bool(rightValue._object().hasProperty(leftValue.string())) + return boolValue(rightValue.object().hasProperty(leftValue.string())) } panic(hereBeDragons(operator)) } -type _lessThanResult int +type lessThanResult int const ( - lessThanFalse _lessThanResult = iota + lessThanFalse lessThanResult = iota lessThanTrue lessThanUndefined ) -func calculateLessThan(left Value, right Value, leftFirst bool) _lessThanResult { +func calculateLessThan(left Value, right Value, leftFirst bool) lessThanResult { var x, y Value if leftFirst { x = toNumberPrimitive(left) @@ -175,46 +171,46 @@ 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){ +// 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{ + map[lessThanResult]bool{ lessThanFalse: false, lessThanTrue: true, lessThanUndefined: false, }, // > - map[_lessThanResult]bool{ + map[lessThanResult]bool{ lessThanFalse: false, lessThanTrue: true, lessThanUndefined: false, }, // <= - map[_lessThanResult]bool{ + map[lessThanResult]bool{ lessThanFalse: true, lessThanTrue: false, lessThanUndefined: false, }, // >= - map[_lessThanResult]bool{ + map[lessThanResult]bool{ lessThanFalse: true, lessThanTrue: false, lessThanUndefined: false, }, } -func (self *_runtime) calculateComparison(comparator token.Token, left Value, right Value) bool { +func (rt *runtime) calculateComparison(comparator token.Token, left Value, right Value) bool { // FIXME Use strictEqualityComparison? // TODO This might be redundant now (with regards to evaluateComparison) x := left.resolve() y := right.resolve() - kindEqualKind := false + var kindEqualKind bool + var negate bool result := true - negate := false switch comparator { case token.LESS: @@ -238,27 +234,28 @@ func (self *_runtime) calculateComparison(comparator token.Token, left Value, ri negate = true fallthrough case token.EQUAL: - if x.kind == y.kind { + switch { + case x.kind == y.kind: kindEqualKind = true - } else if x.kind <= valueNull && y.kind <= valueNull { + case x.kind <= valueNull && y.kind <= valueNull: result = true - } else if x.kind <= valueNull || y.kind <= valueNull { + case x.kind <= valueNull || y.kind <= valueNull: result = false - } else if x.kind <= valueString && y.kind <= valueString { + case 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.kind == valueObject { - result = self.calculateComparison(token.EQUAL, x, toPrimitive(y)) - } else { - panic(hereBeDragons("Unable to test for equality: %v ==? %v", x, y)) + case x.kind == valueBoolean: + result = rt.calculateComparison(token.EQUAL, float64Value(x.float64()), y) + case y.kind == valueBoolean: + result = rt.calculateComparison(token.EQUAL, x, float64Value(y.float64())) + case x.kind == valueObject: + result = rt.calculateComparison(token.EQUAL, toPrimitiveValue(x), y) + case y.kind == valueObject: + result = rt.calculateComparison(token.EQUAL, x, toPrimitiveValue(y)) + default: + panic(fmt.Sprintf("unknown types for equal: %v ==? %v", x, y)) } default: - panic(fmt.Errorf("Unknown comparator %s", comparator.String())) + panic(fmt.Sprintf("unknown comparator %s", comparator.String())) } if kindEqualKind { @@ -278,7 +275,7 @@ func (self *_runtime) calculateComparison(comparator token.Token, left Value, ri case valueBoolean: result = x.bool() == y.bool() case valueObject: - result = x._object() == y._object() + result = x.object() == y.object() default: goto ERROR } diff --git a/file/file.go b/file/file.go index 2884e999..3dda8938 100644 --- a/file/file.go +++ b/file/file.go @@ -20,13 +20,12 @@ type Position struct { 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 +func (p *Position) isValid() bool { + return p.Line > 0 } // String returns a string in one of several forms: @@ -35,13 +34,13 @@ func (self *Position) isValid() bool { // 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() { +func (p *Position) String() string { + str := p.Filename + if p.isValid() { if str != "" { str += ":" } - str += fmt.Sprintf("%d:%d", self.Line, self.Column) + str += fmt.Sprintf("%d:%d", p.Line, p.Column) } if str == "" { str = "-" @@ -49,10 +48,8 @@ func (self *Position) String() string { return str } -// FileSet - // A FileSet represents a set of source files. -type FileSet struct { +type FileSet struct { //nolint: golint files []*File last *File } @@ -60,27 +57,28 @@ type FileSet struct { // 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() +func (fs *FileSet) AddFile(filename, src string) int { + base := fs.nextBase() file := &File{ name: filename, src: src, base: base, } - self.files = append(self.files, file) - self.last = file + fs.files = append(fs.files, file) + fs.last = file return base } -func (self *FileSet) nextBase() int { - if self.last == nil { +func (fs *FileSet) nextBase() int { + if fs.last == nil { return 1 } - return self.last.base + len(self.last.src) + 1 + return fs.last.base + len(fs.last.src) + 1 } -func (self *FileSet) File(idx Idx) *File { - for _, file := range self.files { +// File returns the File at idx or nil if not found. +func (fs *FileSet) File(idx Idx) *File { + for _, file := range fs.files { if idx <= Idx(file.base+len(file.src)) { return file } @@ -89,8 +87,8 @@ func (self *FileSet) File(idx Idx) *File { } // Position converts an Idx in the FileSet into a Position. -func (self *FileSet) Position(idx Idx) *Position { - for _, file := range self.files { +func (fs *FileSet) Position(idx Idx) *Position { + for _, file := range fs.files { if idx <= Idx(file.base+len(file.src)) { return file.Position(idx - Idx(file.base)) } @@ -99,6 +97,7 @@ func (self *FileSet) Position(idx Idx) *Position { return nil } +// File represents a file to parse. type File struct { name string src string @@ -106,6 +105,7 @@ type File struct { sm *sourcemap.Consumer } +// NewFile returns a new file with the given filename, src and base. func NewFile(filename, src string, base int) *File { return &File{ name: filename, @@ -114,23 +114,28 @@ func NewFile(filename, src string, base int) *File { } } +// WithSourceMap sets the source map of fl. func (fl *File) WithSourceMap(sm *sourcemap.Consumer) *File { fl.sm = sm return fl } +// Name returns the name of fl. func (fl *File) Name() string { return fl.name } +// Source returns the source of fl. func (fl *File) Source() string { return fl.src } +// Base returns the base of fl. func (fl *File) Base() int { return fl.base } +// Position returns the position at idx or nil if not valid. func (fl *File) Position(idx Idx) *Position { position := &Position{} diff --git a/function_stack_test.go b/function_stack_test.go index 83302df1..db5eb5c4 100644 --- a/function_stack_test.go +++ b/function_stack_test.go @@ -2,6 +2,8 @@ package otto import ( "testing" + + "github.com/stretchr/testify/require" ) // this is its own file because the tests in it rely on the line numbers of @@ -12,32 +14,36 @@ func TestFunction_stack(t *testing.T) { tt(t, func() { vm := New() - s, _ := vm.Compile("fake.js", `function X(fn1, fn2, fn3) { fn1(fn2, fn3); }`) - vm.Run(s) + s, err := vm.Compile("fake.js", `function X(fn1, fn2, fn3) { fn1(fn2, fn3); }`) + require.NoError(t, err) + _, err = vm.Run(s) + require.NoError(t, err) - expected := []_frame{ - {native: true, nativeFile: "function_stack_test.go", nativeLine: 30, offset: 0, callee: "github.com/robertkrimen/otto.TestFunction_stack.func1.2"}, - {native: true, nativeFile: "function_stack_test.go", nativeLine: 25, offset: 0, callee: "github.com/robertkrimen/otto.TestFunction_stack.func1.1"}, + expected := []frame{ + {native: true, nativeFile: "function_stack_test.go", nativeLine: 36, offset: 0, callee: "github.com/robertkrimen/otto.TestFunction_stack.func1.2"}, + {native: true, nativeFile: "function_stack_test.go", nativeLine: 29, offset: 0, callee: "github.com/robertkrimen/otto.TestFunction_stack.func1.1"}, {native: false, nativeFile: "", nativeLine: 0, offset: 29, callee: "X", file: s.program.file}, {native: false, nativeFile: "", nativeLine: 0, offset: 29, callee: "X", file: s.program.file}, } - vm.Set("A", func(c FunctionCall) Value { - c.Argument(0).Call(UndefinedValue()) + err = vm.Set("A", func(c FunctionCall) Value { + _, err := c.Argument(0).Call(UndefinedValue()) + require.NoError(t, err) return UndefinedValue() }) + require.NoError(t, err) - vm.Set("B", func(c FunctionCall) Value { + err = vm.Set("B", func(c FunctionCall) Value { depth := 0 - for scope := c.Otto.runtime.scope; scope != nil; scope = scope.outer { + for s := c.Otto.runtime.scope; s != nil; s = s.outer { // these properties are tested explicitly so that we don't test `.fn`, // which will differ from run to run - is(scope.frame.native, expected[depth].native) - is(scope.frame.nativeFile, expected[depth].nativeFile) - is(scope.frame.nativeLine, expected[depth].nativeLine) - is(scope.frame.offset, expected[depth].offset) - is(scope.frame.callee, expected[depth].callee) - is(scope.frame.file, expected[depth].file) + is(s.frame.native, expected[depth].native) + is(s.frame.nativeFile, expected[depth].nativeFile) + is(s.frame.nativeLine, expected[depth].nativeLine) + is(s.frame.offset, expected[depth].offset) + is(s.frame.callee, expected[depth].callee) + is(s.frame.file, expected[depth].file) depth++ } @@ -45,11 +51,16 @@ func TestFunction_stack(t *testing.T) { return UndefinedValue() }) + require.NoError(t, err) - x, _ := vm.Get("X") - a, _ := vm.Get("A") - b, _ := vm.Get("B") + x, err := vm.Get("X") + require.NoError(t, err) + a, err := vm.Get("A") + require.NoError(t, err) + b, err := vm.Get("B") + require.NoError(t, err) - x.Call(UndefinedValue(), x, a, b) + _, err = x.Call(UndefinedValue(), x, a, b) + require.NoError(t, err) }) } diff --git a/function_test.go b/function_test.go index d823127c..030bac3d 100644 --- a/function_test.go +++ b/function_test.go @@ -28,7 +28,7 @@ func TestFunction_new(t *testing.T) { test(`raise: new Function({}); - `, "SyntaxError: Unexpected identifier") + `, "SyntaxError: (anonymous): Line 2:9 Unexpected identifier") test(` var abc = Function("def, ghi", "jkl", "return def+ghi+jkl"); @@ -54,14 +54,14 @@ func TestFunction_new(t *testing.T) { var def = "return this"; var ghi = new Function(abc, def); ghi; - `, "SyntaxError: Unexpected token ;") + `, "SyntaxError: (anonymous): Line 1:12 Unexpected token ;") test(`raise: var abc; var def = "return true"; var ghi = new Function(null, def); ghi; - `, "SyntaxError: Unexpected token null") + `, "SyntaxError: (anonymous): Line 1:11 Unexpected token null") }) } diff --git a/functional_benchmark_test.go b/functional_benchmark_test.go index b088f76b..58ccbfa5 100644 --- a/functional_benchmark_test.go +++ b/functional_benchmark_test.go @@ -5,6 +5,8 @@ import ( "math/rand" "strings" "testing" + + "github.com/stretchr/testify/require" ) func TestGoSliceQuickSort(t *testing.T) { @@ -62,7 +64,8 @@ func BenchmarkCryptoAES(b *testing.B) { b.ResetTimer() for i := 0; i < b.N; i++ { - vm.Run(jsCryptoAES) + _, err := vm.Run(jsCryptoAES) + require.NoError(b, err) } } @@ -100,11 +103,13 @@ func testJsArraySort(t *testing.T, sortFuncCall string, sortCode string) { test, vm := test() // inject quicksort code - vm.Run(sortCode) + _, err := vm.Run(sortCode) + require.NoError(t, err) - vm.Run("var testSlice = [5, 3, 2, 4, 1];") - _, err := vm.Run(sortFuncCall) - is(err, nil) + _, err = vm.Run("var testSlice = [5, 3, 2, 4, 1];") + require.NoError(t, err) + _, err = vm.Run(sortFuncCall) + require.NoError(t, err) is(test(`testSlice[0]`).export(), 1) is(test(`testSlice[1]`).export(), 2) @@ -119,19 +124,21 @@ func benchmarkGoSliceSort(b *testing.B, size int, sortFuncCall string, sortCode // generate arbitrary slice of 'size' testSlice := make([]int, size) for i := 0; i < size; i++ { - testSlice[i] = rand.Int() + testSlice[i] = rand.Int() //nolint: gosec } vm := New() // inject the sorting code - vm.Run(sortCode) + _, err := vm.Run(sortCode) + require.NoError(b, err) // Reset timer - everything until this point may have taken a long time b.ResetTimer() for i := 0; i < b.N; i++ { - vm.Run(sortFuncCall) + _, err = vm.Run(sortFuncCall) + require.NoError(b, err) } } @@ -139,8 +146,8 @@ func benchmarkJsArraySort(b *testing.B, size int, sortFuncCall string, sortCode b.Helper() // generate arbitrary slice of 'size' testSlice := make([]string, size) - for i, _ := range testSlice { - testSlice[i] = fmt.Sprintf("%d", rand.Int()) + for i := range testSlice { + testSlice[i] = fmt.Sprintf("%d", rand.Int()) //nolint: gosec } jsArrayString := "[" + strings.Join(testSlice, ",") + "]" @@ -148,16 +155,19 @@ func benchmarkJsArraySort(b *testing.B, size int, sortFuncCall string, sortCode vm := New() // inject the test array - vm.Run("testSlice = " + jsArrayString) + _, err := vm.Run("testSlice = " + jsArrayString) + require.NoError(b, err) // inject the sorting code - vm.Run(sortCode) + _, err = vm.Run(sortCode) + require.NoError(b, err) // Reset timer - everything until this point may have taken a long time b.ResetTimer() for i := 0; i < b.N; i++ { - vm.Run(sortFuncCall) + _, err = vm.Run(sortFuncCall) + require.NoError(b, err) } } diff --git a/global.go b/global.go index 3159c862..e15dd832 100644 --- a/global.go +++ b/global.go @@ -7,12 +7,12 @@ import ( var ( prototypeValueObject = interface{}(nil) - prototypeValueFunction = _nativeFunctionObject{ + prototypeValueFunction = nativeFunctionObject{ call: func(_ FunctionCall) Value { return Value{} }, } - prototypeValueString = _stringASCII("") + prototypeValueString = stringASCII("") // TODO Make this just false? prototypeValueBoolean = Value{ kind: valueBoolean, @@ -22,7 +22,7 @@ var ( kind: valueNumber, value: 0, } - prototypeValueDate = _dateObject{ + prototypeValueDate = dateObject{ epoch: 0, isNaN: false, time: time.Unix(0, 0).UTC(), @@ -31,7 +31,7 @@ var ( value: 0, }, } - prototypeValueRegExp = _regExpObject{ + prototypeValueRegExp = regExpObject{ regularExpression: nil, global: false, ignoreCase: false, @@ -41,102 +41,101 @@ var ( } ) -func newContext() *_runtime { - self := &_runtime{} +func newContext() *runtime { + rt := &runtime{} - self.globalStash = self.newObjectStash(nil, nil) - self.globalObject = self.globalStash.object + rt.globalStash = rt.newObjectStash(nil, nil) + rt.globalObject = rt.globalStash.object - _newContext(self) + rt.newContext() - self.eval = self.globalObject.property["eval"].value.(Value).value.(*_object) - self.globalObject.prototype = self.global.ObjectPrototype + rt.eval = rt.globalObject.property["eval"].value.(Value).value.(*object) + rt.globalObject.prototype = rt.global.ObjectPrototype - return self + return rt } -func (runtime *_runtime) newBaseObject() *_object { - self := newObject(runtime, "") - return self +func (rt *runtime) newBaseObject() *object { + return newObject(rt, "") } -func (runtime *_runtime) newClassObject(class string) *_object { - return newObject(runtime, class) +func (rt *runtime) newClassObject(class string) *object { + return newObject(rt, class) } -func (runtime *_runtime) newPrimitiveObject(class string, value Value) *_object { - self := runtime.newClassObject(class) - self.value = value - return self +func (rt *runtime) newPrimitiveObject(class string, value Value) *object { + o := rt.newClassObject(class) + o.value = value + return o } -func (self *_object) primitiveValue() Value { - switch value := self.value.(type) { +func (o *object) primitiveValue() Value { + switch value := o.value.(type) { case Value: return value - case _stringObject: - return toValue_string(value.String()) + case stringObjecter: + return stringValue(value.String()) } return Value{} } -func (self *_object) hasPrimitive() bool { - switch self.value.(type) { - case Value, _stringObject: +func (o *object) hasPrimitive() bool { //nolint: unused + switch o.value.(type) { + case Value, stringObjecter: return true } return false } -func (runtime *_runtime) newObject() *_object { - self := runtime.newClassObject(classObject) - self.prototype = runtime.global.ObjectPrototype - return self +func (rt *runtime) newObject() *object { + o := rt.newClassObject(classObjectName) + o.prototype = rt.global.ObjectPrototype + return o } -func (runtime *_runtime) newArray(length uint32) *_object { - self := runtime.newArrayObject(length) - self.prototype = runtime.global.ArrayPrototype - return self +func (rt *runtime) newArray(length uint32) *object { + o := rt.newArrayObject(length) + o.prototype = rt.global.ArrayPrototype + return o } -func (runtime *_runtime) newArrayOf(valueArray []Value) *_object { - self := runtime.newArray(uint32(len(valueArray))) +func (rt *runtime) newArrayOf(valueArray []Value) *object { + o := rt.newArray(uint32(len(valueArray))) for index, value := range valueArray { if value.isEmpty() { continue } - self.defineProperty(strconv.FormatInt(int64(index), 10), value, 0111, false) + o.defineProperty(strconv.FormatInt(int64(index), 10), value, 0o111, false) } - return self + return o } -func (runtime *_runtime) newString(value Value) *_object { - self := runtime.newStringObject(value) - self.prototype = runtime.global.StringPrototype - return self +func (rt *runtime) newString(value Value) *object { + o := rt.newStringObject(value) + o.prototype = rt.global.StringPrototype + return o } -func (runtime *_runtime) newBoolean(value Value) *_object { - self := runtime.newBooleanObject(value) - self.prototype = runtime.global.BooleanPrototype - return self +func (rt *runtime) newBoolean(value Value) *object { + o := rt.newBooleanObject(value) + o.prototype = rt.global.BooleanPrototype + return o } -func (runtime *_runtime) newNumber(value Value) *_object { - self := runtime.newNumberObject(value) - self.prototype = runtime.global.NumberPrototype - return self +func (rt *runtime) newNumber(value Value) *object { + o := rt.newNumberObject(value) + o.prototype = rt.global.NumberPrototype + return o } -func (runtime *_runtime) newRegExp(patternValue Value, flagsValue Value) *_object { +func (rt *runtime) newRegExp(patternValue Value, flagsValue Value) *object { pattern := "" flags := "" - if object := patternValue._object(); object != nil && object.class == classRegExp { + if obj := patternValue.object(); obj != nil && obj.class == classRegExpName { if flagsValue.IsDefined() { - panic(runtime.panicTypeError("Cannot supply flags when constructing one RegExp from another")) + panic(rt.panicTypeError("Cannot supply flags when constructing one RegExp from another")) } - regExp := object.regExpValue() + regExp := obj.regExpValue() pattern = regExp.source flags = regExp.flags } else { @@ -148,71 +147,71 @@ func (runtime *_runtime) newRegExp(patternValue Value, flagsValue Value) *_objec } } - return runtime._newRegExp(pattern, flags) + return rt.newRegExpDirect(pattern, flags) } -func (runtime *_runtime) _newRegExp(pattern string, flags string) *_object { - self := runtime.newRegExpObject(pattern, flags) - self.prototype = runtime.global.RegExpPrototype - return self +func (rt *runtime) newRegExpDirect(pattern string, flags string) *object { + o := rt.newRegExpObject(pattern, flags) + o.prototype = rt.global.RegExpPrototype + return o } -// 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 - return self +// TODO Should (probably) be one argument, right? This is redundant. +func (rt *runtime) newDate(epoch float64) *object { + o := rt.newDateObject(epoch) + o.prototype = rt.global.DatePrototype + return o } -func (runtime *_runtime) newError(name string, message Value, stackFramesToPop int) *_object { +func (rt *runtime) newError(name string, message Value, stackFramesToPop int) *object { switch name { case "EvalError": - return runtime.newEvalError(message) + return rt.newEvalError(message) case "TypeError": - return runtime.newTypeError(message) + return rt.newTypeError(message) case "RangeError": - return runtime.newRangeError(message) + return rt.newRangeError(message) case "ReferenceError": - return runtime.newReferenceError(message) + return rt.newReferenceError(message) case "SyntaxError": - return runtime.newSyntaxError(message) + return rt.newSyntaxError(message) case "URIError": - return runtime.newURIError(message) + return rt.newURIError(message) } - self := runtime.newErrorObject(name, message, stackFramesToPop) - self.prototype = runtime.global.ErrorPrototype + obj := rt.newErrorObject(name, message, stackFramesToPop) + obj.prototype = rt.global.ErrorPrototype if name != "" { - self.defineProperty("name", toValue_string(name), 0111, false) + obj.defineProperty("name", stringValue(name), 0o111, false) } - return self + return obj } -func (runtime *_runtime) newNativeFunction(name, file string, line int, _nativeFunction _nativeFunction) *_object { - self := runtime.newNativeFunctionObject(name, file, line, _nativeFunction, 0) - 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 (rt *runtime) newNativeFunction(name, file string, line int, fn nativeFunction) *object { + o := rt.newNativeFunctionObject(name, file, line, fn, 0) + o.prototype = rt.global.FunctionPrototype + prototype := rt.newObject() + o.defineProperty("prototype", objectValue(prototype), 0o100, false) + prototype.defineProperty("constructor", objectValue(o), 0o100, false) + return o } -func (runtime *_runtime) newNodeFunction(node *_nodeFunctionLiteral, scopeEnvironment _stash) *_object { +func (rt *runtime) newNodeFunction(node *nodeFunctionLiteral, scopeEnvironment stasher) *object { // TODO Implement 13.2 fully - self := runtime.newNodeFunctionObject(node, scopeEnvironment) - 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 + o := rt.newNodeFunctionObject(node, scopeEnvironment) + o.prototype = rt.global.FunctionPrototype + prototype := rt.newObject() + o.defineProperty("prototype", objectValue(prototype), 0o100, false) + prototype.defineProperty("constructor", objectValue(o), 0o101, false) + return o } // 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 +func (rt *runtime) newBoundFunction(target *object, this Value, argumentList []Value) *object { + o := rt.newBoundFunctionObject(target, this, argumentList) + o.prototype = rt.global.FunctionPrototype + prototype := rt.newObject() + o.defineProperty("prototype", objectValue(prototype), 0o100, false) + prototype.defineProperty("constructor", objectValue(o), 0o100, false) + return o } diff --git a/global_test.go b/global_test.go index 37168d38..6169a715 100644 --- a/global_test.go +++ b/global_test.go @@ -14,15 +14,15 @@ func TestGlobal(t *testing.T) { runtime := vm.vm.runtime { - call := func(object interface{}, src string, argumentList ...interface{}) Value { + call := func(obj interface{}, src string, argumentList ...interface{}) Value { var tgt *Object - switch object := object.(type) { + switch obj := obj.(type) { case Value: - tgt = object.Object() + tgt = obj.Object() case *Object: - tgt = object - case *_object: - tgt = toValue_object(object).Object() + tgt = obj + case *object: + tgt = objectValue(obj).Object() default: panic("Here be dragons.") } @@ -33,35 +33,32 @@ func TestGlobal(t *testing.T) { // FIXME enterGlobalScope if false { - value := runtime.scope.lexical.getBinding(classObject, false)._object().call(UndefinedValue(), []Value{toValue(runtime.newObject())}, false, nativeFrame) + value := runtime.scope.lexical.getBinding(classObjectName, 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(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().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.object(), "propertyIsEnumerable", "isPrototypeOf"), false) + value.object().put("xyzzy", stringValue("Nothing happens."), false) is(call(value, "propertyIsEnumerable", "isPrototypeOf"), false) is(call(value, "propertyIsEnumerable", "xyzzy"), true) - is(value._object().get("xyzzy"), "Nothing happens.") + is(value.object().get("xyzzy"), "Nothing happens.") - is(call(runtime.scope.lexical.getBinding(classObject, false), "isPrototypeOf", value), false) - is(call(runtime.scope.lexical.getBinding(classObject, false)._object().get("prototype"), "isPrototypeOf", value), true) - is(call(runtime.scope.lexical.getBinding(classFunction, false), "isPrototypeOf", value), false) + is(call(runtime.scope.lexical.getBinding(classObjectName, false), "isPrototypeOf", value), false) + is(call(runtime.scope.lexical.getBinding(classObjectName, false).object().get("prototype"), "isPrototypeOf", value), true) + is(call(runtime.scope.lexical.getBinding(classFunctionName, false), "isPrototypeOf", value), false) - is(runtime.newObject().prototype == runtime.global.Object.get("prototype")._object(), true) + 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(classBoolean)._object().Construct(UndefinedValue(), []Value{}) - //is(def, "false") // TODO Call primitive? + abc := runtime.newBoolean(boolValue(true)) + is(objectValue(abc), "true") // TODO Call primitive? } } @@ -208,7 +205,7 @@ func Test_parseInt(t *testing.T) { test(`parseInt(" 11\n")`, 11) test(`parseInt(" 11\n", 16)`, 17) - test(`parseInt("Xyzzy")`, _NaN) + test(`parseInt("Xyzzy")`, naN) test(`parseInt(" 0x11\n", 16)`, 17) test(`parseInt("0x0aXyzzy", 16)`, 10) @@ -233,16 +230,16 @@ func Test_parseFloat(t *testing.T) { test(`parseFloat(" 11\n", 16)`, 11) test(`parseFloat("11.1")`, 11.1) - test(`parseFloat("Xyzzy")`, _NaN) + test(`parseFloat("Xyzzy")`, naN) test(`parseFloat(" 0x11\n", 16)`, 0) test(`parseFloat("0x0a")`, 0) test(`parseFloat("0x0aXyzzy")`, 0) - test(`parseFloat("Infinity")`, _Infinity) - test(`parseFloat("infinity")`, _NaN) + test(`parseFloat("Infinity")`, infinity) + test(`parseFloat("infinity")`, naN) test(`parseFloat("0x")`, 0) test(`parseFloat("11x")`, 11) - test(`parseFloat("Infinity1")`, _Infinity) + test(`parseFloat("Infinity1")`, infinity) test(`parseFloat.length === 1`, true) test(`parseFloat.prototype === undefined`, true) diff --git a/inline.go b/inline.go index d599b17e..f6954c1a 100644 --- a/inline.go +++ b/inline.go @@ -4,6633 +4,6399 @@ import ( "math" ) -func _newContext(runtime *_runtime) { - { - runtime.global.ObjectPrototype = &_object{ - runtime: runtime, - class: classObject, - objectClass: _classObject, - prototype: nil, - extensible: true, - value: prototypeValueObject, - } +func (rt *runtime) newContext() { + rt.global.ObjectPrototype = &object{ + runtime: rt, + class: classObjectName, + objectClass: classObject, + prototype: nil, + extensible: true, + value: prototypeValueObject, } - { - runtime.global.FunctionPrototype = &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.ObjectPrototype, - extensible: true, - value: prototypeValueFunction, - } + rt.global.FunctionPrototype = &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.ObjectPrototype, + extensible: true, + value: prototypeValueFunction, } - { - valueOf_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "valueOf", - call: builtinObject_valueOf, - }, - } - toString_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "toString", - call: builtinObject_toString, - }, - } - toLocaleString_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "toLocaleString", - call: builtinObject_toLocaleString, - }, - } - hasOwnProperty_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "hasOwnProperty", - call: builtinObject_hasOwnProperty, - }, - } - isPrototypeOf_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "isPrototypeOf", - call: builtinObject_isPrototypeOf, - }, - } - propertyIsEnumerable_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "propertyIsEnumerable", - call: builtinObject_propertyIsEnumerable, - }, - } - runtime.global.ObjectPrototype.property = map[string]_property{ - "valueOf": _property{ - mode: 0101, + rt.global.ObjectPrototype.property = map[string]property{ + "valueOf": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "valueOf", + call: builtinObjectValueOf, + }, + }, + }, + }, + methodToString: { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: methodToString, + call: builtinObjectToString, + }, + }, + }, + }, + "toLocaleString": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "toLocaleString", + call: builtinObjectToLocaleString, + }, + }, + }, + }, + "hasOwnProperty": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "hasOwnProperty", + call: builtinObjectHasOwnProperty, + }, + }, + }, + }, + "isPrototypeOf": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "isPrototypeOf", + call: builtinObjectIsPrototypeOf, + }, + }, + }, + }, + "propertyIsEnumerable": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "propertyIsEnumerable", + call: builtinObjectPropertyIsEnumerable, + }, + }, + }, + }, + propertyConstructor: { + mode: 0o101, + value: Value{}, + }, + } + rt.global.ObjectPrototype.propertyOrder = []string{ + "valueOf", + methodToString, + "toLocaleString", + "hasOwnProperty", + "isPrototypeOf", + "propertyIsEnumerable", + propertyConstructor, + } + rt.global.FunctionPrototype.property = map[string]property{ + methodToString: { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: methodToString, + call: builtinFunctionToString, + }, + }, + }, + }, + "apply": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 2, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "apply", + call: builtinFunctionApply, + }, + }, + }, + }, + "call": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "call", + call: builtinFunctionCall, + }, + }, + }, + }, + "bind": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "bind", + call: builtinFunctionBind, + }, + }, + }, + }, + propertyConstructor: { + mode: 0o101, + value: Value{}, + }, + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + } + rt.global.FunctionPrototype.propertyOrder = []string{ + methodToString, + "apply", + "call", + "bind", + propertyConstructor, + propertyLength, + } + rt.global.Object = &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + value: nativeFunctionObject{ + name: classObjectName, + call: builtinObject, + construct: builtinNewObject, + }, + property: map[string]property{ + propertyLength: { + mode: 0, value: Value{ - kind: valueObject, - value: valueOf_function, + kind: valueNumber, + value: 1, }, }, - "toString": _property{ - mode: 0101, + propertyPrototype: { + mode: 0, value: Value{ kind: valueObject, - value: toString_function, + value: rt.global.ObjectPrototype, }, }, - "toLocaleString": _property{ - mode: 0101, + "getPrototypeOf": { + mode: 0o101, value: Value{ - kind: valueObject, - value: toLocaleString_function, - }, - }, - "hasOwnProperty": _property{ - mode: 0101, + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "getPrototypeOf", + call: builtinObjectGetPrototypeOf, + }, + }, + }, + }, + "getOwnPropertyDescriptor": { + mode: 0o101, value: Value{ - kind: valueObject, - value: hasOwnProperty_function, - }, - }, - "isPrototypeOf": _property{ - mode: 0101, + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 2, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "getOwnPropertyDescriptor", + call: builtinObjectGetOwnPropertyDescriptor, + }, + }, + }, + }, + "defineProperty": { + mode: 0o101, value: Value{ - kind: valueObject, - value: isPrototypeOf_function, - }, - }, - "propertyIsEnumerable": _property{ - mode: 0101, + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 3, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "defineProperty", + call: builtinObjectDefineProperty, + }, + }, + }, + }, + "defineProperties": { + mode: 0o101, value: Value{ - kind: valueObject, - value: propertyIsEnumerable_function, - }, - }, - "constructor": _property{ - mode: 0101, - value: Value{}, - }, - } - runtime.global.ObjectPrototype.propertyOrder = []string{ - "valueOf", - "toString", - "toLocaleString", - "hasOwnProperty", - "isPrototypeOf", - "propertyIsEnumerable", - "constructor", - } + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 2, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "defineProperties", + call: builtinObjectDefineProperties, + }, + }, + }, + }, + "create": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 2, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "create", + call: builtinObjectCreate, + }, + }, + }, + }, + "isExtensible": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "isExtensible", + call: builtinObjectIsExtensible, + }, + }, + }, + }, + "preventExtensions": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "preventExtensions", + call: builtinObjectPreventExtensions, + }, + }, + }, + }, + "isSealed": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "isSealed", + call: builtinObjectIsSealed, + }, + }, + }, + }, + "seal": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "seal", + call: builtinObjectSeal, + }, + }, + }, + }, + "isFrozen": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "isFrozen", + call: builtinObjectIsFrozen, + }, + }, + }, + }, + "freeze": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "freeze", + call: builtinObjectFreeze, + }, + }, + }, + }, + "keys": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "keys", + call: builtinObjectKeys, + }, + }, + }, + }, + "getOwnPropertyNames": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "getOwnPropertyNames", + call: builtinObjectGetOwnPropertyNames, + }, + }, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyPrototype, + "getPrototypeOf", + "getOwnPropertyDescriptor", + "defineProperty", + "defineProperties", + "create", + "isExtensible", + "preventExtensions", + "isSealed", + "seal", + "isFrozen", + "freeze", + "keys", + "getOwnPropertyNames", + }, } - { - toString_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "toString", - call: builtinFunction_toString, - }, - } - apply_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 2, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "apply", - call: builtinFunction_apply, - }, - } - call_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "call", - call: builtinFunction_call, - }, - } - bind_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "bind", - call: builtinFunction_bind, - }, - } - runtime.global.FunctionPrototype.property = map[string]_property{ - "toString": _property{ - mode: 0101, + rt.global.ObjectPrototype.property[propertyConstructor] = property{ + mode: 0o101, + value: Value{ + kind: valueObject, + value: rt.global.Object, + }, + } + rt.global.Function = &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + value: nativeFunctionObject{ + name: classFunctionName, + call: builtinFunction, + construct: builtinNewFunction, + }, + property: map[string]property{ + propertyLength: { + mode: 0, value: Value{ - kind: valueObject, - value: toString_function, + kind: valueNumber, + value: 1, }, }, - "apply": _property{ - mode: 0101, + propertyPrototype: { + mode: 0, value: Value{ kind: valueObject, - value: apply_function, + value: rt.global.FunctionPrototype, }, }, - "call": _property{ - mode: 0101, + }, + propertyOrder: []string{ + propertyLength, + propertyPrototype, + }, + } + rt.global.FunctionPrototype.property[propertyConstructor] = property{ + mode: 0o101, + value: Value{ + kind: valueObject, + value: rt.global.Function, + }, + } + rt.global.ArrayPrototype = &object{ + runtime: rt, + class: classArrayName, + objectClass: classArray, + prototype: rt.global.ObjectPrototype, + extensible: true, + value: nil, + property: map[string]property{ + propertyLength: { + mode: 0o100, value: Value{ - kind: valueObject, - value: call_function, + kind: valueNumber, + value: uint32(0), }, }, - "bind": _property{ - mode: 0101, + methodToString: { + mode: 0o101, value: Value{ - kind: valueObject, - value: bind_function, + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: methodToString, + call: builtinArrayToString, + }, + }, + }, + }, + "toLocaleString": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "toLocaleString", + call: builtinArrayToLocaleString, + }, + }, + }, + }, + "concat": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "concat", + call: builtinArrayConcat, + }, + }, + }, + }, + "join": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "join", + call: builtinArrayJoin, + }, + }, + }, + }, + "splice": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 2, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "splice", + call: builtinArraySplice, + }, + }, + }, + }, + "shift": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "shift", + call: builtinArrayShift, + }, + }, + }, + }, + "pop": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "pop", + call: builtinArrayPop, + }, + }, + }, + }, + "push": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "push", + call: builtinArrayPush, + }, + }, + }, + }, + "slice": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 2, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "slice", + call: builtinArraySlice, + }, + }, + }, + }, + "unshift": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "unshift", + call: builtinArrayUnshift, + }, + }, + }, + }, + "reverse": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "reverse", + call: builtinArrayReverse, + }, + }, + }, + }, + "sort": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "sort", + call: builtinArraySort, + }, + }, + }, + }, + "indexOf": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "indexOf", + call: builtinArrayIndexOf, + }, + }, + }, + }, + "lastIndexOf": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "lastIndexOf", + call: builtinArrayLastIndexOf, + }, + }, + }, + }, + "every": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "every", + call: builtinArrayEvery, + }, + }, + }, + }, + "some": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "some", + call: builtinArraySome, + }, + }, + }, + }, + "forEach": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "forEach", + call: builtinArrayForEach, + }, + }, + }, + }, + "map": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "map", + call: builtinArrayMap, + }, + }, + }, + }, + "filter": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "filter", + call: builtinArrayFilter, + }, + }, + }, + }, + "reduce": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "reduce", + call: builtinArrayReduce, + }, + }, + }, + }, + "reduceRight": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "reduceRight", + call: builtinArrayReduceRight, + }, + }, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + methodToString, + "toLocaleString", + "concat", + "join", + "splice", + "shift", + "pop", + "push", + "slice", + "unshift", + "reverse", + "sort", + "indexOf", + "lastIndexOf", + "every", + "some", + "forEach", + "map", + "filter", + "reduce", + "reduceRight", + }, + } + rt.global.Array = &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + value: nativeFunctionObject{ + name: classArrayName, + call: builtinArray, + construct: builtinNewArray, + }, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, }, }, - "constructor": _property{ - mode: 0101, - value: Value{}, - }, - propertyLength: _property{ + propertyPrototype: { mode: 0, value: Value{ - kind: valueNumber, - value: 0, + kind: valueObject, + value: rt.global.ArrayPrototype, }, }, - } - runtime.global.FunctionPrototype.propertyOrder = []string{ - "toString", - "apply", - "call", - "bind", - "constructor", + "isArray": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "isArray", + call: builtinArrayIsArray, + }, + }, + }, + }, + }, + propertyOrder: []string{ propertyLength, - } + propertyPrototype, + "isArray", + }, } - { - getPrototypeOf_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "getPrototypeOf", - call: builtinObject_getPrototypeOf, - }, - } - getOwnPropertyDescriptor_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 2, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "getOwnPropertyDescriptor", - call: builtinObject_getOwnPropertyDescriptor, - }, - } - defineProperty_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 3, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "defineProperty", - call: builtinObject_defineProperty, - }, - } - defineProperties_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 2, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "defineProperties", - call: builtinObject_defineProperties, - }, - } - create_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 2, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "create", - call: builtinObject_create, - }, - } - isExtensible_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "isExtensible", - call: builtinObject_isExtensible, - }, - } - preventExtensions_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "preventExtensions", - call: builtinObject_preventExtensions, - }, - } - isSealed_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "isSealed", - call: builtinObject_isSealed, - }, - } - seal_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "seal", - call: builtinObject_seal, - }, - } - isFrozen_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "isFrozen", - call: builtinObject_isFrozen, - }, - } - freeze_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "freeze", - call: builtinObject_freeze, - }, - } - keys_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "keys", - call: builtinObject_keys, - }, - } - getOwnPropertyNames_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "getOwnPropertyNames", - call: builtinObject_getOwnPropertyNames, - }, - } - runtime.global.Object = &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - value: _nativeFunctionObject{ - name: classObject, - call: builtinObject, - construct: builtinNewObject, - }, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - "prototype": _property{ - mode: 0, - value: Value{ - kind: valueObject, - value: runtime.global.ObjectPrototype, - }, - }, - "getPrototypeOf": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: getPrototypeOf_function, - }, - }, - "getOwnPropertyDescriptor": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: getOwnPropertyDescriptor_function, - }, - }, - "defineProperty": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: defineProperty_function, - }, - }, - "defineProperties": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: defineProperties_function, - }, - }, - "create": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: create_function, - }, - }, - "isExtensible": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: isExtensible_function, - }, - }, - "preventExtensions": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: preventExtensions_function, - }, - }, - "isSealed": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: isSealed_function, - }, - }, - "seal": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: seal_function, - }, - }, - "isFrozen": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: isFrozen_function, - }, - }, - "freeze": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: freeze_function, - }, - }, - "keys": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: keys_function, - }, - }, - "getOwnPropertyNames": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: getOwnPropertyNames_function, - }, + rt.global.ArrayPrototype.property[propertyConstructor] = property{ + mode: 0o101, + value: Value{ + kind: valueObject, + value: rt.global.Array, + }, + } + rt.global.StringPrototype = &object{ + runtime: rt, + class: classStringName, + objectClass: classString, + prototype: rt.global.ObjectPrototype, + extensible: true, + value: prototypeValueString, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: int(0), }, }, - propertyOrder: []string{ - propertyLength, - "prototype", - "getPrototypeOf", - "getOwnPropertyDescriptor", - "defineProperty", - "defineProperties", - "create", - "isExtensible", - "preventExtensions", - "isSealed", - "seal", - "isFrozen", - "freeze", - "keys", - "getOwnPropertyNames", - }, - } - runtime.global.ObjectPrototype.property["constructor"] = - _property{ - mode: 0101, + methodToString: { + mode: 0o101, value: Value{ - kind: valueObject, - value: runtime.global.Object, - }, - } - } - { - Function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - value: _nativeFunctionObject{ - name: classFunction, - call: builtinFunction, - construct: builtinNewFunction, - }, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - "prototype": _property{ - mode: 0, - value: Value{ - kind: valueObject, - value: runtime.global.FunctionPrototype, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - "prototype", - }, - } - runtime.global.Function = Function - runtime.global.FunctionPrototype.property["constructor"] = - _property{ - mode: 0101, + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: methodToString, + call: builtinStringToString, + }, + }, + }, + }, + "valueOf": { + mode: 0o101, value: Value{ - kind: valueObject, - value: runtime.global.Function, - }, - } + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "valueOf", + call: builtinStringValueOf, + }, + }, + }, + }, + "charAt": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "charAt", + call: builtinStringCharAt, + }, + }, + }, + }, + "charCodeAt": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "charCodeAt", + call: builtinStringCharCodeAt, + }, + }, + }, + }, + "concat": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "concat", + call: builtinStringConcat, + }, + }, + }, + }, + "indexOf": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "indexOf", + call: builtinStringIndexOf, + }, + }, + }, + }, + "lastIndexOf": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "lastIndexOf", + call: builtinStringLastIndexOf, + }, + }, + }, + }, + "match": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "match", + call: builtinStringMatch, + }, + }, + }, + }, + "replace": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 2, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "replace", + call: builtinStringReplace, + }, + }, + }, + }, + "search": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "search", + call: builtinStringSearch, + }, + }, + }, + }, + "split": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 2, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "split", + call: builtinStringSplit, + }, + }, + }, + }, + "slice": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 2, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "slice", + call: builtinStringSlice, + }, + }, + }, + }, + "substring": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 2, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "substring", + call: builtinStringSubstring, + }, + }, + }, + }, + "toLowerCase": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "toLowerCase", + call: builtinStringToLowerCase, + }, + }, + }, + }, + "toUpperCase": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "toUpperCase", + call: builtinStringToUpperCase, + }, + }, + }, + }, + "substr": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 2, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "substr", + call: builtinStringSubstr, + }, + }, + }, + }, + "trim": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "trim", + call: builtinStringTrim, + }, + }, + }, + }, + "trimLeft": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "trimLeft", + call: builtinStringTrimLeft, + }, + }, + }, + }, + "trimRight": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "trimRight", + call: builtinStringTrimRight, + }, + }, + }, + }, + "localeCompare": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "localeCompare", + call: builtinStringLocaleCompare, + }, + }, + }, + }, + "toLocaleLowerCase": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "toLocaleLowerCase", + call: builtinStringToLocaleLowerCase, + }, + }, + }, + }, + "toLocaleUpperCase": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "toLocaleUpperCase", + call: builtinStringToLocaleUpperCase, + }, + }, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + methodToString, + "valueOf", + "charAt", + "charCodeAt", + "concat", + "indexOf", + "lastIndexOf", + "match", + "replace", + "search", + "split", + "slice", + "substring", + "toLowerCase", + "toUpperCase", + "substr", + "trim", + "trimLeft", + "trimRight", + "localeCompare", + "toLocaleLowerCase", + "toLocaleUpperCase", + }, } - { - toString_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "toString", - call: builtinArray_toString, - }, - } - toLocaleString_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "toLocaleString", - call: builtinArray_toLocaleString, - }, - } - concat_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "concat", - call: builtinArray_concat, - }, - } - join_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "join", - call: builtinArray_join, - }, - } - splice_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 2, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "splice", - call: builtinArray_splice, - }, - } - shift_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "shift", - call: builtinArray_shift, - }, - } - pop_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "pop", - call: builtinArray_pop, - }, - } - push_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "push", - call: builtinArray_push, - }, - } - slice_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 2, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "slice", - call: builtinArray_slice, - }, - } - unshift_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "unshift", - call: builtinArray_unshift, - }, - } - reverse_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "reverse", - call: builtinArray_reverse, - }, - } - sort_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "sort", - call: builtinArray_sort, - }, - } - indexOf_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "indexOf", - call: builtinArray_indexOf, - }, - } - lastIndexOf_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "lastIndexOf", - call: builtinArray_lastIndexOf, - }, - } - every_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "every", - call: builtinArray_every, - }, - } - some_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "some", - call: builtinArray_some, - }, - } - forEach_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "forEach", - call: builtinArray_forEach, - }, - } - map_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "map", - call: builtinArray_map, - }, - } - filter_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "filter", - call: builtinArray_filter, - }, - } - reduce_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "reduce", - call: builtinArray_reduce, - }, - } - reduceRight_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "reduceRight", - call: builtinArray_reduceRight, - }, - } - isArray_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "isArray", - call: builtinArray_isArray, - }, - } - runtime.global.ArrayPrototype = &_object{ - runtime: runtime, - class: classArray, - objectClass: _classArray, - prototype: runtime.global.ObjectPrototype, - extensible: true, - value: nil, - property: map[string]_property{ - propertyLength: _property{ - mode: 0100, - value: Value{ - kind: valueNumber, - value: uint32(0), - }, - }, - "toString": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: toString_function, - }, - }, - "toLocaleString": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: toLocaleString_function, - }, - }, - "concat": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: concat_function, - }, - }, - "join": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: join_function, - }, - }, - "splice": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: splice_function, - }, - }, - "shift": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: shift_function, - }, - }, - "pop": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: pop_function, - }, - }, - "push": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: push_function, - }, - }, - "slice": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: slice_function, - }, - }, - "unshift": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: unshift_function, - }, - }, - "reverse": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: reverse_function, - }, - }, - "sort": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: sort_function, - }, - }, - "indexOf": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: indexOf_function, - }, - }, - "lastIndexOf": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: lastIndexOf_function, - }, - }, - "every": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: every_function, - }, - }, - "some": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: some_function, - }, - }, - "forEach": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: forEach_function, - }, - }, - "map": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: map_function, - }, - }, - "filter": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: filter_function, - }, - }, - "reduce": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: reduce_function, - }, - }, - "reduceRight": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: reduceRight_function, - }, + rt.global.String = &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + value: nativeFunctionObject{ + name: classStringName, + call: builtinString, + construct: builtinNewString, + }, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, }, }, - propertyOrder: []string{ - propertyLength, - "toString", - "toLocaleString", - "concat", - "join", - "splice", - "shift", - "pop", - "push", - "slice", - "unshift", - "reverse", - "sort", - "indexOf", - "lastIndexOf", - "every", - "some", - "forEach", - "map", - "filter", - "reduce", - "reduceRight", - }, - } - runtime.global.Array = &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - value: _nativeFunctionObject{ - name: classArray, - call: builtinArray, - construct: builtinNewArray, - }, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - "prototype": _property{ - mode: 0, - value: Value{ - kind: valueObject, - value: runtime.global.ArrayPrototype, - }, - }, - "isArray": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: isArray_function, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - "prototype", - "isArray", - }, - } - runtime.global.ArrayPrototype.property["constructor"] = - _property{ - mode: 0101, + propertyPrototype: { + mode: 0, value: Value{ kind: valueObject, - value: runtime.global.Array, - }, - } - } - { - toString_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "toString", - call: builtinString_toString, - }, - } - valueOf_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "valueOf", - call: builtinString_valueOf, - }, - } - charAt_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "charAt", - call: builtinString_charAt, - }, - } - charCodeAt_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "charCodeAt", - call: builtinString_charCodeAt, - }, - } - concat_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "concat", - call: builtinString_concat, - }, - } - indexOf_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "indexOf", - call: builtinString_indexOf, - }, - } - lastIndexOf_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "lastIndexOf", - call: builtinString_lastIndexOf, - }, - } - match_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "match", - call: builtinString_match, - }, - } - replace_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 2, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "replace", - call: builtinString_replace, - }, - } - search_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "search", - call: builtinString_search, - }, - } - split_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 2, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "split", - call: builtinString_split, - }, - } - slice_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 2, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "slice", - call: builtinString_slice, - }, - } - substring_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 2, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "substring", - call: builtinString_substring, - }, - } - toLowerCase_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "toLowerCase", - call: builtinString_toLowerCase, - }, - } - toUpperCase_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "toUpperCase", - call: builtinString_toUpperCase, - }, - } - substr_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 2, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "substr", - call: builtinString_substr, - }, - } - trim_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "trim", - call: builtinString_trim, - }, - } - trimLeft_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "trimLeft", - call: builtinString_trimLeft, - }, - } - trimRight_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "trimRight", - call: builtinString_trimRight, - }, - } - localeCompare_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "localeCompare", - call: builtinString_localeCompare, - }, - } - toLocaleLowerCase_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "toLocaleLowerCase", - call: builtinString_toLocaleLowerCase, - }, - } - toLocaleUpperCase_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "toLocaleUpperCase", - call: builtinString_toLocaleUpperCase, - }, - } - fromCharCode_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "fromCharCode", - call: builtinString_fromCharCode, - }, - } - runtime.global.StringPrototype = &_object{ - runtime: runtime, - class: classString, - objectClass: _classString, - prototype: runtime.global.ObjectPrototype, - extensible: true, - value: prototypeValueString, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: int(0), - }, - }, - "toString": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: toString_function, - }, - }, - "valueOf": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: valueOf_function, - }, - }, - "charAt": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: charAt_function, - }, - }, - "charCodeAt": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: charCodeAt_function, - }, - }, - "concat": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: concat_function, - }, - }, - "indexOf": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: indexOf_function, - }, - }, - "lastIndexOf": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: lastIndexOf_function, - }, - }, - "match": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: match_function, - }, - }, - "replace": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: replace_function, - }, - }, - "search": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: search_function, - }, - }, - "split": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: split_function, - }, - }, - "slice": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: slice_function, - }, - }, - "substring": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: substring_function, - }, - }, - "toLowerCase": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: toLowerCase_function, - }, - }, - "toUpperCase": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: toUpperCase_function, - }, - }, - "substr": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: substr_function, - }, - }, - "trim": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: trim_function, - }, - }, - "trimLeft": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: trimLeft_function, - }, - }, - "trimRight": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: trimRight_function, - }, - }, - "localeCompare": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: localeCompare_function, - }, - }, - "toLocaleLowerCase": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: toLocaleLowerCase_function, - }, - }, - "toLocaleUpperCase": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: toLocaleUpperCase_function, - }, + value: rt.global.StringPrototype, }, }, - propertyOrder: []string{ - propertyLength, - "toString", - "valueOf", - "charAt", - "charCodeAt", - "concat", - "indexOf", - "lastIndexOf", - "match", - "replace", - "search", - "split", - "slice", - "substring", - "toLowerCase", - "toUpperCase", - "substr", - "trim", - "trimLeft", - "trimRight", - "localeCompare", - "toLocaleLowerCase", - "toLocaleUpperCase", - }, - } - runtime.global.String = &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - value: _nativeFunctionObject{ - name: classString, - call: builtinString, - construct: builtinNewString, - }, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - "prototype": _property{ - mode: 0, - value: Value{ - kind: valueObject, - value: runtime.global.StringPrototype, - }, - }, - "fromCharCode": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: fromCharCode_function, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - "prototype", - "fromCharCode", - }, - } - runtime.global.StringPrototype.property["constructor"] = - _property{ - mode: 0101, + "fromCharCode": { + mode: 0o101, value: Value{ - kind: valueObject, - value: runtime.global.String, - }, - } + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "fromCharCode", + call: builtinStringFromCharCode, + }, + }, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyPrototype, + "fromCharCode", + }, } - { - toString_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "toString", - call: builtinBoolean_toString, - }, - } - valueOf_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "valueOf", - call: builtinBoolean_valueOf, - }, - } - runtime.global.BooleanPrototype = &_object{ - runtime: runtime, - class: classBoolean, - objectClass: _classObject, - prototype: runtime.global.ObjectPrototype, - extensible: true, - value: prototypeValueBoolean, - property: map[string]_property{ - "toString": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: toString_function, - }, - }, - "valueOf": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: valueOf_function, - }, - }, - }, - propertyOrder: []string{ - "toString", - "valueOf", - }, - } - runtime.global.Boolean = &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - value: _nativeFunctionObject{ - name: classBoolean, - call: builtinBoolean, - construct: builtinNewBoolean, - }, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - "prototype": _property{ - mode: 0, - value: Value{ - kind: valueObject, - value: runtime.global.BooleanPrototype, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - "prototype", - }, - } - runtime.global.BooleanPrototype.property["constructor"] = - _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: runtime.global.Boolean, - }, - } + rt.global.StringPrototype.property[propertyConstructor] = property{ + mode: 0o101, + value: Value{ + kind: valueObject, + value: rt.global.String, + }, } - { - toString_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "toString", - call: builtinNumber_toString, - }, - } - valueOf_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "valueOf", - call: builtinNumber_valueOf, - }, - } - toFixed_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "toFixed", - call: builtinNumber_toFixed, - }, - } - toExponential_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "toExponential", - call: builtinNumber_toExponential, - }, - } - toPrecision_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "toPrecision", - call: builtinNumber_toPrecision, - }, - } - toLocaleString_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "toLocaleString", - call: builtinNumber_toLocaleString, - }, - } - isNaN_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "isNaN", - call: builtinNumber_isNaN, - }, - } - runtime.global.NumberPrototype = &_object{ - runtime: runtime, - class: classNumber, - objectClass: _classObject, - prototype: runtime.global.ObjectPrototype, - extensible: true, - value: prototypeValueNumber, - property: map[string]_property{ - "toString": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: toString_function, - }, - }, - "valueOf": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: valueOf_function, - }, - }, - "toFixed": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: toFixed_function, - }, - }, - "toExponential": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: toExponential_function, - }, - }, - "toPrecision": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: toPrecision_function, - }, - }, - "toLocaleString": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: toLocaleString_function, - }, - }, - }, - propertyOrder: []string{ - "toString", - "valueOf", - "toFixed", - "toExponential", - "toPrecision", - "toLocaleString", - }, - } - runtime.global.Number = &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - value: _nativeFunctionObject{ - name: classNumber, - call: builtinNumber, - construct: builtinNewNumber, - }, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - "prototype": _property{ - mode: 0, - value: Value{ - kind: valueObject, - value: runtime.global.NumberPrototype, - }, - }, - "isNaN": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: isNaN_function, - }, - }, - "MAX_VALUE": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: math.MaxFloat64, - }, - }, - "MIN_VALUE": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: math.SmallestNonzeroFloat64, - }, - }, - "NaN": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: math.NaN(), - }, - }, - "NEGATIVE_INFINITY": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: math.Inf(-1), - }, - }, - "POSITIVE_INFINITY": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: math.Inf(+1), - }, - }, - }, - propertyOrder: []string{ - propertyLength, - "prototype", - "isNaN", - "MAX_VALUE", - "MIN_VALUE", - "NaN", - "NEGATIVE_INFINITY", - "POSITIVE_INFINITY", - }, - } - runtime.global.NumberPrototype.property["constructor"] = - _property{ - mode: 0101, + rt.global.BooleanPrototype = &object{ + runtime: rt, + class: classBooleanName, + objectClass: classObject, + prototype: rt.global.ObjectPrototype, + extensible: true, + value: prototypeValueBoolean, + property: map[string]property{ + methodToString: { + mode: 0o101, value: Value{ - kind: valueObject, - value: runtime.global.Number, - }, - } + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: methodToString, + call: builtinBooleanToString, + }, + }, + }, + }, + "valueOf": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "valueOf", + call: builtinBooleanValueOf, + }, + }, + }, + }, + }, + propertyOrder: []string{ + methodToString, + "valueOf", + }, } - { - abs_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "abs", - call: builtinMath_abs, - }, - } - acos_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "acos", - call: builtinMath_acos, - }, - } - asin_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "asin", - call: builtinMath_asin, - }, - } - atan_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "atan", - call: builtinMath_atan, - }, - } - atan2_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "atan2", - call: builtinMath_atan2, - }, - } - ceil_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "ceil", - call: builtinMath_ceil, - }, - } - cos_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "cos", - call: builtinMath_cos, - }, - } - exp_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "exp", - call: builtinMath_exp, - }, - } - floor_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "floor", - call: builtinMath_floor, - }, - } - log_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "log", - call: builtinMath_log, - }, - } - max_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 2, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "max", - call: builtinMath_max, - }, - } - min_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 2, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "min", - call: builtinMath_min, - }, - } - pow_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 2, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "pow", - call: builtinMath_pow, - }, - } - random_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "random", - call: builtinMath_random, - }, - } - round_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "round", - call: builtinMath_round, - }, - } - sin_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "sin", - call: builtinMath_sin, - }, - } - sqrt_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "sqrt", - call: builtinMath_sqrt, - }, - } - tan_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "tan", - call: builtinMath_tan, - }, - } - runtime.global.Math = &_object{ - runtime: runtime, - class: "Math", - objectClass: _classObject, - prototype: runtime.global.ObjectPrototype, - extensible: true, - property: map[string]_property{ - "abs": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: abs_function, - }, - }, - "acos": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: acos_function, - }, - }, - "asin": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: asin_function, - }, - }, - "atan": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: atan_function, - }, - }, - "atan2": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: atan2_function, - }, - }, - "ceil": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: ceil_function, - }, - }, - "cos": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: cos_function, - }, - }, - "exp": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: exp_function, - }, - }, - "floor": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: floor_function, - }, - }, - "log": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: log_function, - }, - }, - "max": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: max_function, - }, - }, - "min": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: min_function, - }, - }, - "pow": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: pow_function, - }, - }, - "random": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: random_function, - }, - }, - "round": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: round_function, - }, - }, - "sin": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: sin_function, - }, - }, - "sqrt": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: sqrt_function, - }, - }, - "tan": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: tan_function, - }, - }, - "E": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: math.E, - }, - }, - "LN10": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: math.Ln10, - }, - }, - "LN2": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: math.Ln2, - }, - }, - "LOG2E": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: math.Log2E, - }, - }, - "LOG10E": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: math.Log10E, - }, - }, - "PI": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: math.Pi, - }, - }, - "SQRT1_2": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: sqrt1_2, - }, - }, - "SQRT2": _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: math.Sqrt2, - }, + rt.global.Boolean = &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + value: nativeFunctionObject{ + name: classBooleanName, + call: builtinBoolean, + construct: builtinNewBoolean, + }, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, }, }, - propertyOrder: []string{ - "abs", - "acos", - "asin", - "atan", - "atan2", - "ceil", - "cos", - "exp", - "floor", - "log", - "max", - "min", - "pow", - "random", - "round", - "sin", - "sqrt", - "tan", - "E", - "LN10", - "LN2", - "LOG2E", - "LOG10E", - "PI", - "SQRT1_2", - "SQRT2", - }, - } - } - { - toString_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "toString", - call: builtinDate_toString, - }, - } - toDateString_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "toDateString", - call: builtinDate_toDateString, - }, - } - toTimeString_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "toTimeString", - call: builtinDate_toTimeString, - }, - } - toUTCString_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "toUTCString", - call: builtinDate_toUTCString, - }, - } - toISOString_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "toISOString", - call: builtinDate_toISOString, - }, - } - toJSON_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "toJSON", - call: builtinDate_toJSON, - }, - } - toGMTString_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "toGMTString", - call: builtinDate_toGMTString, - }, - } - toLocaleString_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "toLocaleString", - call: builtinDate_toLocaleString, - }, - } - toLocaleDateString_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "toLocaleDateString", - call: builtinDate_toLocaleDateString, - }, - } - toLocaleTimeString_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "toLocaleTimeString", - call: builtinDate_toLocaleTimeString, - }, - } - valueOf_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "valueOf", - call: builtinDate_valueOf, - }, - } - getTime_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "getTime", - call: builtinDate_getTime, - }, - } - getYear_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "getYear", - call: builtinDate_getYear, - }, - } - getFullYear_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "getFullYear", - call: builtinDate_getFullYear, - }, - } - getUTCFullYear_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "getUTCFullYear", - call: builtinDate_getUTCFullYear, - }, - } - getMonth_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "getMonth", - call: builtinDate_getMonth, - }, - } - getUTCMonth_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "getUTCMonth", - call: builtinDate_getUTCMonth, - }, - } - getDate_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "getDate", - call: builtinDate_getDate, - }, - } - getUTCDate_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "getUTCDate", - call: builtinDate_getUTCDate, - }, - } - getDay_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "getDay", - call: builtinDate_getDay, - }, - } - getUTCDay_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "getUTCDay", - call: builtinDate_getUTCDay, - }, - } - getHours_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "getHours", - call: builtinDate_getHours, - }, - } - getUTCHours_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "getUTCHours", - call: builtinDate_getUTCHours, - }, - } - getMinutes_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "getMinutes", - call: builtinDate_getMinutes, - }, - } - getUTCMinutes_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "getUTCMinutes", - call: builtinDate_getUTCMinutes, - }, - } - getSeconds_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "getSeconds", - call: builtinDate_getSeconds, - }, - } - getUTCSeconds_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "getUTCSeconds", - call: builtinDate_getUTCSeconds, - }, - } - getMilliseconds_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "getMilliseconds", - call: builtinDate_getMilliseconds, - }, - } - getUTCMilliseconds_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "getUTCMilliseconds", - call: builtinDate_getUTCMilliseconds, - }, - } - getTimezoneOffset_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "getTimezoneOffset", - call: builtinDate_getTimezoneOffset, - }, - } - setTime_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "setTime", - call: builtinDate_setTime, - }, - } - setMilliseconds_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "setMilliseconds", - call: builtinDate_setMilliseconds, - }, - } - setUTCMilliseconds_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "setUTCMilliseconds", - call: builtinDate_setUTCMilliseconds, - }, - } - setSeconds_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 2, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "setSeconds", - call: builtinDate_setSeconds, - }, - } - setUTCSeconds_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 2, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "setUTCSeconds", - call: builtinDate_setUTCSeconds, - }, - } - setMinutes_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 3, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "setMinutes", - call: builtinDate_setMinutes, - }, - } - setUTCMinutes_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 3, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "setUTCMinutes", - call: builtinDate_setUTCMinutes, - }, - } - setHours_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 4, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "setHours", - call: builtinDate_setHours, - }, - } - setUTCHours_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 4, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "setUTCHours", - call: builtinDate_setUTCHours, - }, - } - setDate_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "setDate", - call: builtinDate_setDate, - }, - } - setUTCDate_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "setUTCDate", - call: builtinDate_setUTCDate, - }, - } - setMonth_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 2, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "setMonth", - call: builtinDate_setMonth, - }, - } - setUTCMonth_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 2, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "setUTCMonth", - call: builtinDate_setUTCMonth, - }, - } - setYear_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "setYear", - call: builtinDate_setYear, - }, - } - setFullYear_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 3, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "setFullYear", - call: builtinDate_setFullYear, - }, - } - setUTCFullYear_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 3, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "setUTCFullYear", - call: builtinDate_setUTCFullYear, - }, - } - parse_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "parse", - call: builtinDate_parse, - }, - } - UTC_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 7, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "UTC", - call: builtinDate_UTC, - }, - } - now_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "now", - call: builtinDate_now, - }, - } - runtime.global.DatePrototype = &_object{ - runtime: runtime, - class: classDate, - objectClass: _classObject, - prototype: runtime.global.ObjectPrototype, - extensible: true, - value: prototypeValueDate, - property: map[string]_property{ - "toString": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: toString_function, - }, - }, - "toDateString": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: toDateString_function, - }, - }, - "toTimeString": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: toTimeString_function, - }, - }, - "toUTCString": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: toUTCString_function, - }, - }, - "toISOString": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: toISOString_function, - }, - }, - "toJSON": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: toJSON_function, - }, - }, - "toGMTString": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: toGMTString_function, - }, - }, - "toLocaleString": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: toLocaleString_function, - }, - }, - "toLocaleDateString": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: toLocaleDateString_function, - }, - }, - "toLocaleTimeString": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: toLocaleTimeString_function, - }, - }, - "valueOf": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: valueOf_function, - }, - }, - "getTime": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: getTime_function, - }, - }, - "getYear": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: getYear_function, - }, - }, - "getFullYear": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: getFullYear_function, - }, - }, - "getUTCFullYear": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: getUTCFullYear_function, - }, - }, - "getMonth": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: getMonth_function, - }, - }, - "getUTCMonth": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: getUTCMonth_function, - }, - }, - "getDate": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: getDate_function, - }, - }, - "getUTCDate": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: getUTCDate_function, - }, - }, - "getDay": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: getDay_function, - }, - }, - "getUTCDay": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: getUTCDay_function, - }, - }, - "getHours": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: getHours_function, - }, - }, - "getUTCHours": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: getUTCHours_function, - }, - }, - "getMinutes": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: getMinutes_function, - }, - }, - "getUTCMinutes": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: getUTCMinutes_function, - }, - }, - "getSeconds": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: getSeconds_function, - }, - }, - "getUTCSeconds": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: getUTCSeconds_function, - }, - }, - "getMilliseconds": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: getMilliseconds_function, - }, - }, - "getUTCMilliseconds": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: getUTCMilliseconds_function, - }, - }, - "getTimezoneOffset": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: getTimezoneOffset_function, - }, - }, - "setTime": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: setTime_function, - }, - }, - "setMilliseconds": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: setMilliseconds_function, - }, - }, - "setUTCMilliseconds": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: setUTCMilliseconds_function, - }, - }, - "setSeconds": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: setSeconds_function, - }, - }, - "setUTCSeconds": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: setUTCSeconds_function, - }, - }, - "setMinutes": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: setMinutes_function, - }, - }, - "setUTCMinutes": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: setUTCMinutes_function, - }, - }, - "setHours": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: setHours_function, - }, - }, - "setUTCHours": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: setUTCHours_function, - }, - }, - "setDate": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: setDate_function, - }, - }, - "setUTCDate": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: setUTCDate_function, - }, - }, - "setMonth": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: setMonth_function, - }, - }, - "setUTCMonth": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: setUTCMonth_function, - }, - }, - "setYear": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: setYear_function, - }, - }, - "setFullYear": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: setFullYear_function, - }, - }, - "setUTCFullYear": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: setUTCFullYear_function, - }, - }, - }, - propertyOrder: []string{ - "toString", - "toDateString", - "toTimeString", - "toUTCString", - "toISOString", - "toJSON", - "toGMTString", - "toLocaleString", - "toLocaleDateString", - "toLocaleTimeString", - "valueOf", - "getTime", - "getYear", - "getFullYear", - "getUTCFullYear", - "getMonth", - "getUTCMonth", - "getDate", - "getUTCDate", - "getDay", - "getUTCDay", - "getHours", - "getUTCHours", - "getMinutes", - "getUTCMinutes", - "getSeconds", - "getUTCSeconds", - "getMilliseconds", - "getUTCMilliseconds", - "getTimezoneOffset", - "setTime", - "setMilliseconds", - "setUTCMilliseconds", - "setSeconds", - "setUTCSeconds", - "setMinutes", - "setUTCMinutes", - "setHours", - "setUTCHours", - "setDate", - "setUTCDate", - "setMonth", - "setUTCMonth", - "setYear", - "setFullYear", - "setUTCFullYear", - }, - } - runtime.global.Date = &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - value: _nativeFunctionObject{ - name: classDate, - call: builtinDate, - construct: builtinNewDate, - }, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 7, - }, - }, - "prototype": _property{ - mode: 0, - value: Value{ - kind: valueObject, - value: runtime.global.DatePrototype, - }, - }, - "parse": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: parse_function, - }, - }, - "UTC": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: UTC_function, - }, - }, - "now": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: now_function, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - "prototype", - "parse", - "UTC", - "now", - }, - } - runtime.global.DatePrototype.property["constructor"] = - _property{ - mode: 0101, + propertyPrototype: { + mode: 0, value: Value{ kind: valueObject, - value: runtime.global.Date, + value: rt.global.BooleanPrototype, }, - } + }, + }, + propertyOrder: []string{ + propertyLength, + propertyPrototype, + }, } - { - toString_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "toString", - call: builtinRegExp_toString, - }, - } - exec_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "exec", - call: builtinRegExp_exec, - }, - } - test_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "test", - call: builtinRegExp_test, - }, - } - compile_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "compile", - call: builtinRegExp_compile, - }, - } - runtime.global.RegExpPrototype = &_object{ - runtime: runtime, - class: classRegExp, - objectClass: _classObject, - prototype: runtime.global.ObjectPrototype, - extensible: true, - value: prototypeValueRegExp, - property: map[string]_property{ - "toString": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: toString_function, - }, - }, - "exec": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: exec_function, - }, - }, - "test": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: test_function, - }, - }, - "compile": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: compile_function, - }, - }, - }, - propertyOrder: []string{ - "toString", - "exec", - "test", - "compile", - }, - } - runtime.global.RegExp = &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - value: _nativeFunctionObject{ - name: classRegExp, - call: builtinRegExp, - construct: builtinNewRegExp, - }, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 2, - }, - }, - "prototype": _property{ - mode: 0, - value: Value{ - kind: valueObject, - value: runtime.global.RegExpPrototype, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - "prototype", - }, - } - runtime.global.RegExpPrototype.property["constructor"] = - _property{ - mode: 0101, + rt.global.BooleanPrototype.property[propertyConstructor] = property{ + mode: 0o101, + value: Value{ + kind: valueObject, + value: rt.global.Boolean, + }, + } + rt.global.NumberPrototype = &object{ + runtime: rt, + class: classNumberName, + objectClass: classObject, + prototype: rt.global.ObjectPrototype, + extensible: true, + value: prototypeValueNumber, + property: map[string]property{ + methodToString: { + mode: 0o101, value: Value{ - kind: valueObject, - value: runtime.global.RegExp, - }, - } + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: methodToString, + call: builtinNumberToString, + }, + }, + }, + }, + "valueOf": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "valueOf", + call: builtinNumberValueOf, + }, + }, + }, + }, + "toFixed": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "toFixed", + call: builtinNumberToFixed, + }, + }, + }, + }, + "toExponential": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "toExponential", + call: builtinNumberToExponential, + }, + }, + }, + }, + "toPrecision": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "toPrecision", + call: builtinNumberToPrecision, + }, + }, + }, + }, + "toLocaleString": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "toLocaleString", + call: builtinNumberToLocaleString, + }, + }, + }, + }, + }, + propertyOrder: []string{ + methodToString, + "valueOf", + "toFixed", + "toExponential", + "toPrecision", + "toLocaleString", + }, } - { - toString_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "toString", - call: builtinError_toString, - }, - } - runtime.global.ErrorPrototype = &_object{ - runtime: runtime, - class: classError, - objectClass: _classObject, - prototype: runtime.global.ObjectPrototype, - extensible: true, - value: nil, - property: map[string]_property{ - "toString": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: toString_function, - }, - }, - "name": _property{ - mode: 0101, - value: Value{ - kind: valueString, - value: classError, - }, - }, - "message": _property{ - mode: 0101, - value: Value{ - kind: valueString, - value: "", - }, - }, - }, - propertyOrder: []string{ - "toString", - "name", - "message", - }, - } - runtime.global.Error = &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - value: _nativeFunctionObject{ - name: classError, - call: builtinError, - construct: builtinNewError, - }, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - "prototype": _property{ - mode: 0, - value: Value{ - kind: valueObject, - value: runtime.global.ErrorPrototype, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - "prototype", - }, - } - runtime.global.ErrorPrototype.property["constructor"] = - _property{ - mode: 0101, + rt.global.Number = &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + value: nativeFunctionObject{ + name: classNumberName, + call: builtinNumber, + construct: builtinNewNumber, + }, + property: map[string]property{ + propertyLength: { + mode: 0, value: Value{ - kind: valueObject, - value: runtime.global.Error, + kind: valueNumber, + value: 1, }, - } - } - { - runtime.global.EvalErrorPrototype = &_object{ - runtime: runtime, - class: "EvalError", - objectClass: _classObject, - prototype: runtime.global.ErrorPrototype, - extensible: true, - value: nil, - property: map[string]_property{ - "name": _property{ - mode: 0101, - value: Value{ - kind: valueString, - value: "EvalError", - }, - }, - }, - propertyOrder: []string{ - "name", - }, - } - runtime.global.EvalError = &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - value: _nativeFunctionObject{ - name: "EvalError", - call: builtinEvalError, - construct: builtinNewEvalError, - }, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - "prototype": _property{ - mode: 0, - value: Value{ - kind: valueObject, - value: runtime.global.EvalErrorPrototype, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - "prototype", - }, - } - runtime.global.EvalErrorPrototype.property["constructor"] = - _property{ - mode: 0101, + }, + propertyPrototype: { + mode: 0, value: Value{ kind: valueObject, - value: runtime.global.EvalError, + value: rt.global.NumberPrototype, }, - } - } - { - runtime.global.TypeErrorPrototype = &_object{ - runtime: runtime, - class: "TypeError", - objectClass: _classObject, - prototype: runtime.global.ErrorPrototype, - extensible: true, - value: nil, - property: map[string]_property{ - "name": _property{ - mode: 0101, - value: Value{ - kind: valueString, - value: "TypeError", - }, - }, - }, - propertyOrder: []string{ - "name", - }, - } - runtime.global.TypeError = &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - value: _nativeFunctionObject{ - name: "TypeError", - call: builtinTypeError, - construct: builtinNewTypeError, - }, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - "prototype": _property{ - mode: 0, - value: Value{ - kind: valueObject, - value: runtime.global.TypeErrorPrototype, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - "prototype", - }, - } - runtime.global.TypeErrorPrototype.property["constructor"] = - _property{ - mode: 0101, + }, + "isNaN": { + mode: 0o101, value: Value{ - kind: valueObject, - value: runtime.global.TypeError, + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "isNaN", + call: builtinNumberIsNaN, + }, + }, + }, + }, + "MAX_VALUE": { + mode: 0, + value: Value{ + kind: valueNumber, + value: math.MaxFloat64, }, - } - } - { - runtime.global.RangeErrorPrototype = &_object{ - runtime: runtime, - class: "RangeError", - objectClass: _classObject, - prototype: runtime.global.ErrorPrototype, - extensible: true, - value: nil, - property: map[string]_property{ - "name": _property{ - mode: 0101, - value: Value{ - kind: valueString, - value: "RangeError", - }, - }, - }, - propertyOrder: []string{ - "name", - }, - } - runtime.global.RangeError = &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - value: _nativeFunctionObject{ - name: "RangeError", - call: builtinRangeError, - construct: builtinNewRangeError, - }, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - "prototype": _property{ - mode: 0, - value: Value{ - kind: valueObject, - value: runtime.global.RangeErrorPrototype, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - "prototype", - }, - } - runtime.global.RangeErrorPrototype.property["constructor"] = - _property{ - mode: 0101, + }, + "MIN_VALUE": { + mode: 0, value: Value{ - kind: valueObject, - value: runtime.global.RangeError, + kind: valueNumber, + value: math.SmallestNonzeroFloat64, }, - } - } - { - runtime.global.ReferenceErrorPrototype = &_object{ - runtime: runtime, - class: "ReferenceError", - objectClass: _classObject, - prototype: runtime.global.ErrorPrototype, - extensible: true, - value: nil, - property: map[string]_property{ - "name": _property{ - mode: 0101, - value: Value{ - kind: valueString, - value: "ReferenceError", - }, - }, - }, - propertyOrder: []string{ - "name", - }, - } - runtime.global.ReferenceError = &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - value: _nativeFunctionObject{ - name: "ReferenceError", - call: builtinReferenceError, - construct: builtinNewReferenceError, - }, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - "prototype": _property{ - mode: 0, - value: Value{ - kind: valueObject, - value: runtime.global.ReferenceErrorPrototype, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - "prototype", - }, - } - runtime.global.ReferenceErrorPrototype.property["constructor"] = - _property{ - mode: 0101, + }, + "NaN": { + mode: 0, value: Value{ - kind: valueObject, - value: runtime.global.ReferenceError, + kind: valueNumber, + value: math.NaN(), }, - } - } - { - runtime.global.SyntaxErrorPrototype = &_object{ - runtime: runtime, - class: "SyntaxError", - objectClass: _classObject, - prototype: runtime.global.ErrorPrototype, - extensible: true, - value: nil, - property: map[string]_property{ - "name": _property{ - mode: 0101, - value: Value{ - kind: valueString, - value: "SyntaxError", - }, - }, - }, - propertyOrder: []string{ - "name", - }, - } - runtime.global.SyntaxError = &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - value: _nativeFunctionObject{ - name: "SyntaxError", - call: builtinSyntaxError, - construct: builtinNewSyntaxError, - }, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - "prototype": _property{ - mode: 0, - value: Value{ - kind: valueObject, - value: runtime.global.SyntaxErrorPrototype, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - "prototype", - }, - } - runtime.global.SyntaxErrorPrototype.property["constructor"] = - _property{ - mode: 0101, + }, + "NEGATIVE_INFINITY": { + mode: 0, value: Value{ - kind: valueObject, - value: runtime.global.SyntaxError, + kind: valueNumber, + value: math.Inf(-1), }, - } - } - { - runtime.global.URIErrorPrototype = &_object{ - runtime: runtime, - class: "URIError", - objectClass: _classObject, - prototype: runtime.global.ErrorPrototype, - extensible: true, - value: nil, - property: map[string]_property{ - "name": _property{ - mode: 0101, - value: Value{ - kind: valueString, - value: "URIError", - }, - }, - }, - propertyOrder: []string{ - "name", - }, - } - runtime.global.URIError = &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - value: _nativeFunctionObject{ - name: "URIError", - call: builtinURIError, - construct: builtinNewURIError, - }, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - "prototype": _property{ - mode: 0, - value: Value{ - kind: valueObject, - value: runtime.global.URIErrorPrototype, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - "prototype", - }, - } - runtime.global.URIErrorPrototype.property["constructor"] = - _property{ - mode: 0101, + }, + "POSITIVE_INFINITY": { + mode: 0, value: Value{ - kind: valueObject, - value: runtime.global.URIError, + kind: valueNumber, + value: math.Inf(+1), }, - } + }, + }, + propertyOrder: []string{ + propertyLength, + propertyPrototype, + "isNaN", + "MAX_VALUE", + "MIN_VALUE", + "NaN", + "NEGATIVE_INFINITY", + "POSITIVE_INFINITY", + }, } - { - parse_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 2, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "parse", - call: builtinJSON_parse, - }, - } - stringify_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 3, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "stringify", - call: builtinJSON_stringify, - }, - } - runtime.global.JSON = &_object{ - runtime: runtime, - class: "JSON", - objectClass: _classObject, - prototype: runtime.global.ObjectPrototype, - extensible: true, - property: map[string]_property{ - "parse": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: parse_function, - }, - }, - "stringify": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: stringify_function, - }, - }, - }, - propertyOrder: []string{ - "parse", - "stringify", - }, - } + rt.global.NumberPrototype.property[propertyConstructor] = property{ + mode: 0o101, + value: Value{ + kind: valueObject, + value: rt.global.Number, + }, } - { - eval_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "eval", - call: builtinGlobal_eval, - }, - } - parseInt_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 2, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "parseInt", - call: builtinGlobal_parseInt, - }, - } - parseFloat_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "parseFloat", - call: builtinGlobal_parseFloat, - }, - } - isNaN_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "isNaN", - call: builtinGlobal_isNaN, - }, - } - isFinite_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "isFinite", - call: builtinGlobal_isFinite, - }, - } - decodeURI_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "decodeURI", - call: builtinGlobal_decodeURI, - }, - } - decodeURIComponent_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "decodeURIComponent", - call: builtinGlobal_decodeURIComponent, - }, - } - encodeURI_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "encodeURI", - call: builtinGlobal_encodeURI, - }, - } - encodeURIComponent_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "encodeURIComponent", - call: builtinGlobal_encodeURIComponent, - }, - } - escape_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "escape", - call: builtinGlobal_escape, - }, - } - unescape_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 1, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "unescape", - call: builtinGlobal_unescape, - }, - } - runtime.globalObject.property = map[string]_property{ - "eval": _property{ - mode: 0101, + rt.global.Math = &object{ + runtime: rt, + class: classMathName, + objectClass: classObject, + prototype: rt.global.ObjectPrototype, + extensible: true, + property: map[string]property{ + "abs": { + mode: 0o101, value: Value{ - kind: valueObject, - value: eval_function, + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "abs", + call: builtinMathAbs, + }, + }, + }, + }, + "acos": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "acos", + call: builtinMathAcos, + }, + }, + }, + }, + "asin": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "asin", + call: builtinMathAsin, + }, + }, + }, + }, + "atan": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "atan", + call: builtinMathAtan, + }, + }, + }, + }, + "atan2": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "atan2", + call: builtinMathAtan2, + }, + }, + }, + }, + "ceil": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "ceil", + call: builtinMathCeil, + }, + }, + }, + }, + "cos": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "cos", + call: builtinMathCos, + }, + }, + }, + }, + "exp": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "exp", + call: builtinMathExp, + }, + }, + }, + }, + "floor": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "floor", + call: builtinMathFloor, + }, + }, + }, + }, + "log": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "log", + call: builtinMathLog, + }, + }, + }, + }, + "max": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 2, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "max", + call: builtinMathMax, + }, + }, + }, + }, + "min": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 2, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "min", + call: builtinMathMin, + }, + }, + }, + }, + "pow": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 2, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "pow", + call: builtinMathPow, + }, + }, + }, + }, + "random": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "random", + call: builtinMathRandom, + }, + }, + }, + }, + "round": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "round", + call: builtinMathRound, + }, + }, + }, + }, + "sin": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "sin", + call: builtinMathSin, + }, + }, + }, + }, + "sqrt": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "sqrt", + call: builtinMathSqrt, + }, + }, + }, + }, + "tan": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "tan", + call: builtinMathTan, + }, + }, + }, + }, + "E": { + mode: 0, + value: Value{ + kind: valueNumber, + value: math.E, }, }, - "parseInt": _property{ - mode: 0101, + "LN10": { + mode: 0, value: Value{ - kind: valueObject, - value: parseInt_function, + kind: valueNumber, + value: math.Ln10, }, }, - "parseFloat": _property{ - mode: 0101, + "LN2": { + mode: 0, value: Value{ - kind: valueObject, - value: parseFloat_function, + kind: valueNumber, + value: math.Ln2, }, }, - "isNaN": _property{ - mode: 0101, + "LOG2E": { + mode: 0, value: Value{ - kind: valueObject, - value: isNaN_function, + kind: valueNumber, + value: math.Log2E, }, }, - "isFinite": _property{ - mode: 0101, + "LOG10E": { + mode: 0, value: Value{ - kind: valueObject, - value: isFinite_function, + kind: valueNumber, + value: math.Log10E, }, }, - "decodeURI": _property{ - mode: 0101, + "PI": { + mode: 0, value: Value{ - kind: valueObject, - value: decodeURI_function, + kind: valueNumber, + value: math.Pi, }, }, - "decodeURIComponent": _property{ - mode: 0101, + "SQRT1_2": { + mode: 0, value: Value{ - kind: valueObject, - value: decodeURIComponent_function, + kind: valueNumber, + value: sqrt1_2, }, }, - "encodeURI": _property{ - mode: 0101, + "SQRT2": { + mode: 0, value: Value{ - kind: valueObject, - value: encodeURI_function, + kind: valueNumber, + value: math.Sqrt2, + }, + }, + }, + propertyOrder: []string{ + "abs", + "acos", + "asin", + "atan", + "atan2", + "ceil", + "cos", + "exp", + "floor", + "log", + "max", + "min", + "pow", + "random", + "round", + "sin", + "sqrt", + "tan", + "E", + "LN10", + "LN2", + "LOG2E", + "LOG10E", + "PI", + "SQRT1_2", + "SQRT2", + }, + } + rt.global.DatePrototype = &object{ + runtime: rt, + class: classDateName, + objectClass: classObject, + prototype: rt.global.ObjectPrototype, + extensible: true, + value: prototypeValueDate, + property: map[string]property{ + methodToString: { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: methodToString, + call: builtinDateToString, + }, + }, + }, + }, + "toDateString": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "toDateString", + call: builtinDateToDateString, + }, + }, + }, + }, + "toTimeString": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "toTimeString", + call: builtinDateToTimeString, + }, + }, + }, + }, + "toUTCString": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "toUTCString", + call: builtinDateToUTCString, + }, + }, + }, + }, + "toISOString": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "toISOString", + call: builtinDateToISOString, + }, + }, + }, + }, + "toJSON": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "toJSON", + call: builtinDateToJSON, + }, + }, + }, + }, + "toGMTString": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "toGMTString", + call: builtinDateToGMTString, + }, + }, + }, + }, + "toLocaleString": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "toLocaleString", + call: builtinDateToLocaleString, + }, + }, + }, + }, + "toLocaleDateString": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "toLocaleDateString", + call: builtinDateToLocaleDateString, + }, + }, + }, + }, + "toLocaleTimeString": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "toLocaleTimeString", + call: builtinDateToLocaleTimeString, + }, + }, + }, + }, + "valueOf": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "valueOf", + call: builtinDateValueOf, + }, + }, + }, + }, + "getTime": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "getTime", + call: builtinDateGetTime, + }, + }, + }, + }, + "getYear": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "getYear", + call: builtinDateGetYear, + }, + }, + }, + }, + "getFullYear": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "getFullYear", + call: builtinDateGetFullYear, + }, + }, + }, + }, + "getUTCFullYear": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "getUTCFullYear", + call: builtinDateGetUTCFullYear, + }, + }, + }, + }, + "getMonth": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "getMonth", + call: builtinDateGetMonth, + }, + }, + }, + }, + "getUTCMonth": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "getUTCMonth", + call: builtinDateGetUTCMonth, + }, + }, + }, + }, + "getDate": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "getDate", + call: builtinDateGetDate, + }, + }, + }, + }, + "getUTCDate": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "getUTCDate", + call: builtinDateGetUTCDate, + }, + }, + }, + }, + "getDay": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "getDay", + call: builtinDateGetDay, + }, + }, + }, + }, + "getUTCDay": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "getUTCDay", + call: builtinDateGetUTCDay, + }, + }, + }, + }, + "getHours": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "getHours", + call: builtinDateGetHours, + }, + }, + }, + }, + "getUTCHours": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "getUTCHours", + call: builtinDateGetUTCHours, + }, + }, + }, + }, + "getMinutes": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "getMinutes", + call: builtinDateGetMinutes, + }, + }, + }, + }, + "getUTCMinutes": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "getUTCMinutes", + call: builtinDateGetUTCMinutes, + }, + }, + }, + }, + "getSeconds": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "getSeconds", + call: builtinDateGetSeconds, + }, + }, + }, + }, + "getUTCSeconds": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "getUTCSeconds", + call: builtinDateGetUTCSeconds, + }, + }, + }, + }, + "getMilliseconds": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "getMilliseconds", + call: builtinDateGetMilliseconds, + }, + }, + }, + }, + "getUTCMilliseconds": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "getUTCMilliseconds", + call: builtinDateGetUTCMilliseconds, + }, + }, + }, + }, + "getTimezoneOffset": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "getTimezoneOffset", + call: builtinDateGetTimezoneOffset, + }, + }, + }, + }, + "setTime": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "setTime", + call: builtinDateSetTime, + }, + }, + }, + }, + "setMilliseconds": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "setMilliseconds", + call: builtinDateSetMilliseconds, + }, + }, + }, + }, + "setUTCMilliseconds": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "setUTCMilliseconds", + call: builtinDateSetUTCMilliseconds, + }, + }, + }, + }, + "setSeconds": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 2, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "setSeconds", + call: builtinDateSetSeconds, + }, + }, + }, + }, + "setUTCSeconds": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 2, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "setUTCSeconds", + call: builtinDateSetUTCSeconds, + }, + }, + }, + }, + "setMinutes": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 3, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "setMinutes", + call: builtinDateSetMinutes, + }, + }, + }, + }, + "setUTCMinutes": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 3, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "setUTCMinutes", + call: builtinDateSetUTCMinutes, + }, + }, + }, + }, + "setHours": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 4, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "setHours", + call: builtinDateSetHours, + }, + }, + }, + }, + "setUTCHours": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 4, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "setUTCHours", + call: builtinDateSetUTCHours, + }, + }, + }, + }, + "setDate": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "setDate", + call: builtinDateSetDate, + }, + }, + }, + }, + "setUTCDate": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "setUTCDate", + call: builtinDateSetUTCDate, + }, + }, + }, + }, + "setMonth": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 2, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "setMonth", + call: builtinDateSetMonth, + }, + }, + }, + }, + "setUTCMonth": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 2, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "setUTCMonth", + call: builtinDateSetUTCMonth, + }, + }, + }, + }, + "setYear": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "setYear", + call: builtinDateSetYear, + }, + }, + }, + }, + "setFullYear": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 3, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "setFullYear", + call: builtinDateSetFullYear, + }, + }, + }, + }, + "setUTCFullYear": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 3, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "setUTCFullYear", + call: builtinDateSetUTCFullYear, + }, + }, + }, + }, + }, + propertyOrder: []string{ + methodToString, + "toDateString", + "toTimeString", + "toUTCString", + "toISOString", + "toJSON", + "toGMTString", + "toLocaleString", + "toLocaleDateString", + "toLocaleTimeString", + "valueOf", + "getTime", + "getYear", + "getFullYear", + "getUTCFullYear", + "getMonth", + "getUTCMonth", + "getDate", + "getUTCDate", + "getDay", + "getUTCDay", + "getHours", + "getUTCHours", + "getMinutes", + "getUTCMinutes", + "getSeconds", + "getUTCSeconds", + "getMilliseconds", + "getUTCMilliseconds", + "getTimezoneOffset", + "setTime", + "setMilliseconds", + "setUTCMilliseconds", + "setSeconds", + "setUTCSeconds", + "setMinutes", + "setUTCMinutes", + "setHours", + "setUTCHours", + "setDate", + "setUTCDate", + "setMonth", + "setUTCMonth", + "setYear", + "setFullYear", + "setUTCFullYear", + }, + } + rt.global.Date = &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + value: nativeFunctionObject{ + name: classDateName, + call: builtinDate, + construct: builtinNewDate, + }, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 7, }, }, - "encodeURIComponent": _property{ - mode: 0101, + propertyPrototype: { + mode: 0, value: Value{ kind: valueObject, - value: encodeURIComponent_function, + value: rt.global.DatePrototype, }, }, - "escape": _property{ - mode: 0101, + "parse": { + mode: 0o101, value: Value{ - kind: valueObject, - value: escape_function, + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "parse", + call: builtinDateParse, + }, + }, + }, + }, + "UTC": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 7, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "UTC", + call: builtinDateUTC, + }, + }, + }, + }, + "now": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "now", + call: builtinDateNow, + }, + }, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyPrototype, + "parse", + "UTC", + "now", + }, + } + rt.global.DatePrototype.property[propertyConstructor] = property{ + mode: 0o101, + value: Value{ + kind: valueObject, + value: rt.global.Date, + }, + } + rt.global.RegExpPrototype = &object{ + runtime: rt, + class: classRegExpName, + objectClass: classObject, + prototype: rt.global.ObjectPrototype, + extensible: true, + value: prototypeValueRegExp, + property: map[string]property{ + methodToString: { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: methodToString, + call: builtinRegExpToString, + }, + }, + }, + }, + "exec": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "exec", + call: builtinRegExpExec, + }, + }, + }, + }, + "test": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "test", + call: builtinRegExpTest, + }, + }, + }, + }, + "compile": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "compile", + call: builtinRegExpCompile, + }, + }, + }, + }, + }, + propertyOrder: []string{ + methodToString, + "exec", + "test", + "compile", + }, + } + rt.global.RegExp = &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + value: nativeFunctionObject{ + name: classRegExpName, + call: builtinRegExp, + construct: builtinNewRegExp, + }, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 2, }, }, - "unescape": _property{ - mode: 0101, + propertyPrototype: { + mode: 0, value: Value{ kind: valueObject, - value: unescape_function, + value: rt.global.RegExpPrototype, }, }, - classObject: _property{ - mode: 0101, + }, + propertyOrder: []string{ + propertyLength, + propertyPrototype, + }, + } + rt.global.RegExpPrototype.property[propertyConstructor] = property{ + mode: 0o101, + value: Value{ + kind: valueObject, + value: rt.global.RegExp, + }, + } + rt.global.ErrorPrototype = &object{ + runtime: rt, + class: classErrorName, + objectClass: classObject, + prototype: rt.global.ObjectPrototype, + extensible: true, + value: nil, + property: map[string]property{ + methodToString: { + mode: 0o101, value: Value{ - kind: valueObject, - value: runtime.global.Object, + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: methodToString, + call: builtinErrorToString, + }, + }, + }, + }, + "name": { + mode: 0o101, + value: Value{ + kind: valueString, + value: classErrorName, }, }, - classFunction: _property{ - mode: 0101, + "message": { + mode: 0o101, value: Value{ - kind: valueObject, - value: runtime.global.Function, + kind: valueString, + value: "", }, }, - classArray: _property{ - mode: 0101, + }, + propertyOrder: []string{ + methodToString, + "name", + "message", + }, + } + rt.global.Error = &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + value: nativeFunctionObject{ + name: classErrorName, + call: builtinError, + construct: builtinNewError, + }, + property: map[string]property{ + propertyLength: { + mode: 0, value: Value{ - kind: valueObject, - value: runtime.global.Array, + kind: valueNumber, + value: 1, }, }, - classString: _property{ - mode: 0101, + propertyPrototype: { + mode: 0, value: Value{ kind: valueObject, - value: runtime.global.String, + value: rt.global.ErrorPrototype, }, }, - classBoolean: _property{ - mode: 0101, + }, + propertyOrder: []string{ + propertyLength, + propertyPrototype, + }, + } + rt.global.ErrorPrototype.property[propertyConstructor] = property{ + mode: 0o101, + value: Value{ + kind: valueObject, + value: rt.global.Error, + }, + } + rt.global.EvalErrorPrototype = &object{ + runtime: rt, + class: classEvalErrorName, + objectClass: classObject, + prototype: rt.global.ErrorPrototype, + extensible: true, + value: nil, + property: map[string]property{ + "name": { + mode: 0o101, value: Value{ - kind: valueObject, - value: runtime.global.Boolean, + kind: valueString, + value: classEvalErrorName, }, }, - classNumber: _property{ - mode: 0101, + }, + propertyOrder: []string{ + "name", + }, + } + rt.global.EvalError = &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + value: nativeFunctionObject{ + name: classEvalErrorName, + call: builtinEvalError, + construct: builtinNewEvalError, + }, + property: map[string]property{ + propertyLength: { + mode: 0, value: Value{ - kind: valueObject, - value: runtime.global.Number, + kind: valueNumber, + value: 1, }, }, - "Math": _property{ - mode: 0101, + propertyPrototype: { + mode: 0, value: Value{ kind: valueObject, - value: runtime.global.Math, + value: rt.global.EvalErrorPrototype, }, }, - classDate: _property{ - mode: 0101, + }, + propertyOrder: []string{ + propertyLength, + propertyPrototype, + }, + } + rt.global.EvalErrorPrototype.property[propertyConstructor] = property{ + mode: 0o101, + value: Value{ + kind: valueObject, + value: rt.global.EvalError, + }, + } + rt.global.TypeErrorPrototype = &object{ + runtime: rt, + class: classTypeErrorName, + objectClass: classObject, + prototype: rt.global.ErrorPrototype, + extensible: true, + value: nil, + property: map[string]property{ + "name": { + mode: 0o101, value: Value{ - kind: valueObject, - value: runtime.global.Date, + kind: valueString, + value: classTypeErrorName, }, }, - classRegExp: _property{ - mode: 0101, + }, + propertyOrder: []string{ + "name", + }, + } + rt.global.TypeError = &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + value: nativeFunctionObject{ + name: classTypeErrorName, + call: builtinTypeError, + construct: builtinNewTypeError, + }, + property: map[string]property{ + propertyLength: { + mode: 0, value: Value{ - kind: valueObject, - value: runtime.global.RegExp, + kind: valueNumber, + value: 1, }, }, - classError: _property{ - mode: 0101, + propertyPrototype: { + mode: 0, value: Value{ kind: valueObject, - value: runtime.global.Error, + value: rt.global.TypeErrorPrototype, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + propertyPrototype, + }, + } + rt.global.TypeErrorPrototype.property[propertyConstructor] = property{ + mode: 0o101, + value: Value{ + kind: valueObject, + value: rt.global.TypeError, + }, + } + rt.global.RangeErrorPrototype = &object{ + runtime: rt, + class: classRangeErrorName, + objectClass: classObject, + prototype: rt.global.ErrorPrototype, + extensible: true, + value: nil, + property: map[string]property{ + "name": { + mode: 0o101, + value: Value{ + kind: valueString, + value: classRangeErrorName, }, }, - "EvalError": _property{ - mode: 0101, + }, + propertyOrder: []string{ + "name", + }, + } + rt.global.RangeError = &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + value: nativeFunctionObject{ + name: classRangeErrorName, + call: builtinRangeError, + construct: builtinNewRangeError, + }, + property: map[string]property{ + propertyLength: { + mode: 0, value: Value{ - kind: valueObject, - value: runtime.global.EvalError, + kind: valueNumber, + value: 1, }, }, - "TypeError": _property{ - mode: 0101, + propertyPrototype: { + mode: 0, value: Value{ kind: valueObject, - value: runtime.global.TypeError, + value: rt.global.RangeErrorPrototype, }, }, - "RangeError": _property{ - mode: 0101, + }, + propertyOrder: []string{ + propertyLength, + propertyPrototype, + }, + } + rt.global.RangeErrorPrototype.property[propertyConstructor] = property{ + mode: 0o101, + value: Value{ + kind: valueObject, + value: rt.global.RangeError, + }, + } + rt.global.ReferenceErrorPrototype = &object{ + runtime: rt, + class: classReferenceErrorName, + objectClass: classObject, + prototype: rt.global.ErrorPrototype, + extensible: true, + value: nil, + property: map[string]property{ + "name": { + mode: 0o101, value: Value{ - kind: valueObject, - value: runtime.global.RangeError, + kind: valueString, + value: classReferenceErrorName, }, }, - "ReferenceError": _property{ - mode: 0101, + }, + propertyOrder: []string{ + "name", + }, + } + rt.global.ReferenceError = &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + value: nativeFunctionObject{ + name: classReferenceErrorName, + call: builtinReferenceError, + construct: builtinNewReferenceError, + }, + property: map[string]property{ + propertyLength: { + mode: 0, value: Value{ - kind: valueObject, - value: runtime.global.ReferenceError, + kind: valueNumber, + value: 1, }, }, - "SyntaxError": _property{ - mode: 0101, + propertyPrototype: { + mode: 0, value: Value{ kind: valueObject, - value: runtime.global.SyntaxError, + value: rt.global.ReferenceErrorPrototype, }, }, - "URIError": _property{ - mode: 0101, + }, + propertyOrder: []string{ + propertyLength, + propertyPrototype, + }, + } + rt.global.ReferenceErrorPrototype.property[propertyConstructor] = property{ + mode: 0o101, + value: Value{ + kind: valueObject, + value: rt.global.ReferenceError, + }, + } + rt.global.SyntaxErrorPrototype = &object{ + runtime: rt, + class: classSyntaxErrorName, + objectClass: classObject, + prototype: rt.global.ErrorPrototype, + extensible: true, + value: nil, + property: map[string]property{ + "name": { + mode: 0o101, value: Value{ - kind: valueObject, - value: runtime.global.URIError, + kind: valueString, + value: classSyntaxErrorName, + }, + }, + }, + propertyOrder: []string{ + "name", + }, + } + rt.global.SyntaxError = &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + value: nativeFunctionObject{ + name: classSyntaxErrorName, + call: builtinSyntaxError, + construct: builtinNewSyntaxError, + }, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, }, }, - "JSON": _property{ - mode: 0101, + propertyPrototype: { + mode: 0, value: Value{ kind: valueObject, - value: runtime.global.JSON, + value: rt.global.SyntaxErrorPrototype, }, }, - "undefined": _property{ - mode: 0, + }, + propertyOrder: []string{ + propertyLength, + propertyPrototype, + }, + } + rt.global.SyntaxErrorPrototype.property[propertyConstructor] = property{ + mode: 0o101, + value: Value{ + kind: valueObject, + value: rt.global.SyntaxError, + }, + } + rt.global.URIErrorPrototype = &object{ + runtime: rt, + class: classURIErrorName, + objectClass: classObject, + prototype: rt.global.ErrorPrototype, + extensible: true, + value: nil, + property: map[string]property{ + "name": { + mode: 0o101, value: Value{ - kind: valueUndefined, + kind: valueString, + value: classURIErrorName, }, }, - "NaN": _property{ + }, + propertyOrder: []string{ + "name", + }, + } + rt.global.URIError = &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + value: nativeFunctionObject{ + name: classURIErrorName, + call: builtinURIError, + construct: builtinNewURIError, + }, + property: map[string]property{ + propertyLength: { mode: 0, value: Value{ kind: valueNumber, - value: math.NaN(), + value: 1, }, }, - "Infinity": _property{ + propertyPrototype: { mode: 0, value: Value{ - kind: valueNumber, - value: math.Inf(+1), + kind: valueObject, + value: rt.global.URIErrorPrototype, }, }, - } - runtime.globalObject.propertyOrder = []string{ - "eval", - "parseInt", - "parseFloat", - "isNaN", - "isFinite", - "decodeURI", - "decodeURIComponent", - "encodeURI", - "encodeURIComponent", - "escape", - "unescape", - classObject, - classFunction, - classArray, - classString, - classBoolean, - classNumber, - "Math", - classDate, - classRegExp, - classError, - "EvalError", - "TypeError", - "RangeError", - "ReferenceError", - "SyntaxError", - "URIError", - "JSON", - "undefined", - "NaN", - "Infinity", - } + }, + propertyOrder: []string{ + propertyLength, + propertyPrototype, + }, + } + rt.global.URIErrorPrototype.property[propertyConstructor] = property{ + mode: 0o101, + value: Value{ + kind: valueObject, + value: rt.global.URIError, + }, + } + rt.global.JSON = &object{ + runtime: rt, + class: classJSONName, + objectClass: classObject, + prototype: rt.global.ObjectPrototype, + extensible: true, + property: map[string]property{ + "parse": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 2, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "parse", + call: builtinJSONParse, + }, + }, + }, + }, + "stringify": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 3, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "stringify", + call: builtinJSONStringify, + }, + }, + }, + }, + }, + propertyOrder: []string{ + "parse", + "stringify", + }, + } + rt.globalObject.property = map[string]property{ + "eval": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "eval", + call: builtinGlobalEval, + }, + }, + }, + }, + "parseInt": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 2, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "parseInt", + call: builtinGlobalParseInt, + }, + }, + }, + }, + "parseFloat": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "parseFloat", + call: builtinGlobalParseFloat, + }, + }, + }, + }, + "isNaN": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "isNaN", + call: builtinGlobalIsNaN, + }, + }, + }, + }, + "isFinite": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "isFinite", + call: builtinGlobalIsFinite, + }, + }, + }, + }, + "decodeURI": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "decodeURI", + call: builtinGlobalDecodeURI, + }, + }, + }, + }, + "decodeURIComponent": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "decodeURIComponent", + call: builtinGlobalDecodeURIComponent, + }, + }, + }, + }, + "encodeURI": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "encodeURI", + call: builtinGlobalEncodeURI, + }, + }, + }, + }, + "encodeURIComponent": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "encodeURIComponent", + call: builtinGlobalEncodeURIComponent, + }, + }, + }, + }, + "escape": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "escape", + call: builtinGlobalEscape, + }, + }, + }, + }, + "unescape": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 1, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "unescape", + call: builtinGlobalUnescape, + }, + }, + }, + }, + classObjectName: { + mode: 0o101, + value: Value{ + kind: valueObject, + value: rt.global.Object, + }, + }, + classFunctionName: { + mode: 0o101, + value: Value{ + kind: valueObject, + value: rt.global.Function, + }, + }, + classArrayName: { + mode: 0o101, + value: Value{ + kind: valueObject, + value: rt.global.Array, + }, + }, + classStringName: { + mode: 0o101, + value: Value{ + kind: valueObject, + value: rt.global.String, + }, + }, + classBooleanName: { + mode: 0o101, + value: Value{ + kind: valueObject, + value: rt.global.Boolean, + }, + }, + classNumberName: { + mode: 0o101, + value: Value{ + kind: valueObject, + value: rt.global.Number, + }, + }, + classMathName: { + mode: 0o101, + value: Value{ + kind: valueObject, + value: rt.global.Math, + }, + }, + classDateName: { + mode: 0o101, + value: Value{ + kind: valueObject, + value: rt.global.Date, + }, + }, + classRegExpName: { + mode: 0o101, + value: Value{ + kind: valueObject, + value: rt.global.RegExp, + }, + }, + classErrorName: { + mode: 0o101, + value: Value{ + kind: valueObject, + value: rt.global.Error, + }, + }, + classEvalErrorName: { + mode: 0o101, + value: Value{ + kind: valueObject, + value: rt.global.EvalError, + }, + }, + classTypeErrorName: { + mode: 0o101, + value: Value{ + kind: valueObject, + value: rt.global.TypeError, + }, + }, + classRangeErrorName: { + mode: 0o101, + value: Value{ + kind: valueObject, + value: rt.global.RangeError, + }, + }, + classReferenceErrorName: { + mode: 0o101, + value: Value{ + kind: valueObject, + value: rt.global.ReferenceError, + }, + }, + classSyntaxErrorName: { + mode: 0o101, + value: Value{ + kind: valueObject, + value: rt.global.SyntaxError, + }, + }, + classURIErrorName: { + mode: 0o101, + value: Value{ + kind: valueObject, + value: rt.global.URIError, + }, + }, + classJSONName: { + mode: 0o101, + value: Value{ + kind: valueObject, + value: rt.global.JSON, + }, + }, + "undefined": { + mode: 0, + value: Value{ + kind: valueUndefined, + }, + }, + "NaN": { + mode: 0, + value: Value{ + kind: valueNumber, + value: math.NaN(), + }, + }, + "Infinity": { + mode: 0, + value: Value{ + kind: valueNumber, + value: math.Inf(+1), + }, + }, + } + rt.globalObject.propertyOrder = []string{ + "eval", + "parseInt", + "parseFloat", + "isNaN", + "isFinite", + "decodeURI", + "decodeURIComponent", + "encodeURI", + "encodeURIComponent", + "escape", + "unescape", + classObjectName, + classFunctionName, + classArrayName, + classStringName, + classBooleanName, + classNumberName, + classMathName, + classDateName, + classRegExpName, + classErrorName, + classEvalErrorName, + classTypeErrorName, + classRangeErrorName, + classReferenceErrorName, + classSyntaxErrorName, + classURIErrorName, + classJSONName, + "undefined", + "NaN", + "Infinity", } } -func newConsoleObject(runtime *_runtime) *_object { - { - log_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "log", - call: builtinConsole_log, - }, - } - debug_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "debug", - call: builtinConsole_log, - }, - } - info_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "info", - call: builtinConsole_log, - }, - } - error_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "error", - call: builtinConsole_error, - }, - } - warn_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "warn", - call: builtinConsole_error, - }, - } - dir_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "dir", - call: builtinConsole_dir, - }, - } - time_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "time", - call: builtinConsole_time, - }, - } - timeEnd_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "timeEnd", - call: builtinConsole_timeEnd, - }, - } - trace_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "trace", - call: builtinConsole_trace, - }, - } - assert_function := &_object{ - runtime: runtime, - class: classFunction, - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, - extensible: true, - property: map[string]_property{ - propertyLength: _property{ - mode: 0, - value: Value{ - kind: valueNumber, - value: 0, - }, - }, - }, - propertyOrder: []string{ - propertyLength, - }, - value: _nativeFunctionObject{ - name: "assert", - call: builtinConsole_assert, - }, - } - return &_object{ - runtime: runtime, - class: classObject, - objectClass: _classObject, - prototype: runtime.global.ObjectPrototype, - extensible: true, - property: map[string]_property{ - "log": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: log_function, - }, - }, - "debug": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: debug_function, - }, - }, - "info": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: info_function, - }, - }, - "error": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: error_function, - }, - }, - "warn": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: warn_function, - }, - }, - "dir": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: dir_function, - }, - }, - "time": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: time_function, - }, - }, - "timeEnd": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: timeEnd_function, - }, - }, - "trace": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: trace_function, - }, - }, - "assert": _property{ - mode: 0101, - value: Value{ - kind: valueObject, - value: assert_function, - }, - }, - }, - propertyOrder: []string{ - "log", - "debug", - "info", - "error", - "warn", - "dir", - "time", - "timeEnd", - "trace", - "assert", - }, - } +func (rt *runtime) newConsole() *object { + return &object{ + runtime: rt, + class: classObjectName, + objectClass: classObject, + prototype: rt.global.ObjectPrototype, + extensible: true, + property: map[string]property{ + "log": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "log", + call: builtinConsoleLog, + }, + }, + }, + }, + "debug": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "debug", + call: builtinConsoleLog, + }, + }, + }, + }, + "info": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "info", + call: builtinConsoleLog, + }, + }, + }, + }, + "error": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "error", + call: builtinConsoleError, + }, + }, + }, + }, + "warn": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "warn", + call: builtinConsoleError, + }, + }, + }, + }, + "dir": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "dir", + call: builtinConsoleDir, + }, + }, + }, + }, + "time": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "time", + call: builtinConsoleTime, + }, + }, + }, + }, + "timeEnd": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "timeEnd", + call: builtinConsoleTimeEnd, + }, + }, + }, + }, + "trace": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "trace", + call: builtinConsoleTrace, + }, + }, + }, + }, + "assert": { + mode: 0o101, + value: Value{ + kind: valueObject, + value: &object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, + extensible: true, + property: map[string]property{ + propertyLength: { + mode: 0, + value: Value{ + kind: valueNumber, + value: 0, + }, + }, + }, + propertyOrder: []string{ + propertyLength, + }, + value: nativeFunctionObject{ + name: "assert", + call: builtinConsoleAssert, + }, + }, + }, + }, + }, + propertyOrder: []string{ + "log", + "debug", + "info", + "error", + "warn", + "dir", + "time", + "timeEnd", + "trace", + "assert", + }, } } -func toValue_int(value int) Value { +func intValue(value int) Value { return Value{ kind: valueNumber, value: value, } } -func toValue_int32(value int32) Value { +func int32Value(value int32) Value { return Value{ kind: valueNumber, value: value, } } -func toValue_int64(value int64) Value { +func int64Value(value int64) Value { return Value{ kind: valueNumber, value: value, } } -func toValue_uint16(value uint16) Value { +func uint16Value(value uint16) Value { return Value{ kind: valueNumber, value: value, } } -func toValue_uint32(value uint32) Value { +func uint32Value(value uint32) Value { return Value{ kind: valueNumber, value: value, } } -func toValue_float64(value float64) Value { +func float64Value(value float64) Value { return Value{ kind: valueNumber, value: value, } } -func toValue_string(value string) Value { +func stringValue(value string) Value { return Value{ kind: valueString, value: value, } } -func toValue_string16(value []uint16) Value { +func string16Value(value []uint16) Value { return Value{ kind: valueString, value: value, } } -func toValue_bool(value bool) Value { +func boolValue(value bool) Value { return Value{ kind: valueBoolean, value: value, } } -func toValue_object(value *_object) Value { +func objectValue(value *object) Value { return Value{ kind: valueObject, value: value, diff --git a/inline.pl b/inline.pl index e21444dd..83e5468e 100755 --- a/inline.pl +++ b/inline.pl @@ -10,8 +10,18 @@ my $self = __PACKAGE__; -sub functionLabel ($) { - return "$_[0]_function"; +sub label ($) { + my $name = shift; + + if ($name eq "toString") { + return "methodToString"; + } elsif ($name =~ /^(length|prototype|constructor)$/) { + return "property" . ucfirst $name; + } elsif ($name =~ /^class\w+Name$/) { + return $name; + } + + return qq{"${name}"}; } sub trim ($) { @@ -29,19 +39,19 @@ package otto "math" ) -func _newContext(runtime *_runtime) { +func (rt *runtime) newContext() { @{[ join "\n", $self->newContext() ]} } -func newConsoleObject(runtime *_runtime) *_object { -@{[ join "\n", $self->newConsoleObject() ]} +func (rt *runtime) newConsole() *object { +@{[ join "\n", $self->newConsole() ]} } _END_ -for (qw/int int8 int16 int32 int64 uint uint8 uint16 uint32 uint64 float32 float64/) { +for (qw/int int32 int64 uint16 uint32 float64/) { $fmt->print(<<_END_); -func toValue_$_(value $_) Value { +func ${_}Value(value $_) Value { return Value{ kind: valueNumber, value: value, @@ -52,28 +62,28 @@ package otto $fmt->print(<<_END_); -func toValue_string(value string) Value { +func stringValue(value string) Value { return Value{ kind: valueString, value: value, } } -func toValue_string16(value []uint16) Value { +func string16Value(value []uint16) Value { return Value{ kind: valueString, value: value, } } -func toValue_bool(value bool) Value { +func boolValue(value bool) Value { return Value{ kind: valueBoolean, value: value, } } -func toValue_object(value *_object) Value { +func objectValue(value *object) Value { return Value{ kind: valueObject, value: value, @@ -83,7 +93,7 @@ package otto close $fmt; -sub newConsoleObject { +sub newConsole { my $self = shift; return @@ -118,7 +128,7 @@ sub newContext { ".${class}Prototype =", $self->globalPrototype( $class, - "_classObject", + "classObject", undef, "prototypeValueObject", ), @@ -131,7 +141,7 @@ sub newContext { ".${class}Prototype =", $self->globalPrototype( $class, - "_classObject", + "classObject", ".ObjectPrototype", "prototypeValueFunction", ), @@ -151,7 +161,7 @@ sub newContext { ); my @propertyMap = $self->propertyMap( @got, - $self->property("constructor", undef), + $self->property("constructor", undef, undef), ); my $propertyOrder = $self->propertyOrder(@propertyMap); $propertyOrder =~ s/^propertyOrder: //; @@ -172,7 +182,7 @@ sub newContext { ); my @propertyMap = $self->propertyMap( @got, - $self->property("constructor", undef), + $self->property("constructor", undef, undef), $self->property("length", $self->numberValue(0), "0"), ); my $propertyOrder = $self->propertyOrder(@propertyMap); @@ -213,12 +223,10 @@ sub newContext { $self->block(sub { my $class = "Function"; return - "Function :=", - $self->globalFunction( + ".$class = " . $self->globalFunction( $class, 1, ), - ".$class = Function", }), # Array @@ -252,10 +260,10 @@ sub newContext { ".${class}Prototype =", $self->globalPrototype( $class, - "_classArray", + "classArray", ".ObjectPrototype", undef, - $self->property("length", $self->numberValue("uint32(0)"), "0100"), + $self->property("length", $self->numberValue("uint32(0)"), "0o100"), @got, ), ".$class =", @@ -301,7 +309,7 @@ sub newContext { ".${class}Prototype =", $self->globalPrototype( $class, - "_classString", + "classString", ".ObjectPrototype", "prototypeValueString", $self->property("length", $self->numberValue("int(0)"), "0"), @@ -330,7 +338,7 @@ sub newContext { ".${class}Prototype =", $self->globalPrototype( $class, - "_classObject", + "classObject", ".ObjectPrototype", "prototypeValueBoolean", @got, @@ -361,7 +369,7 @@ sub newContext { ".${class}Prototype =", $self->globalPrototype( $class, - "_classObject", + "classObject", ".ObjectPrototype", "prototypeValueNumber", @got, @@ -481,7 +489,7 @@ sub newContext { ".${class}Prototype =", $self->globalPrototype( $class, - "_classObject", + "classObject", ".ObjectPrototype", "prototypeValueDate", @got, @@ -513,7 +521,7 @@ sub newContext { ".${class}Prototype =", $self->globalPrototype( $class, - "_classObject", + "classObject", ".ObjectPrototype", "prototypeValueRegExp", @got, @@ -539,7 +547,7 @@ sub newContext { ".${class}Prototype =", $self->globalPrototype( $class, - "_classObject", + "classObject", ".ObjectPrototype", undef, @got, @@ -566,7 +574,7 @@ sub newContext { ".${class}Prototype =", $self->globalPrototype( $class, - "_classObject", + "classObject", ".ErrorPrototype", undef, @got, @@ -643,9 +651,9 @@ sub newContext { my $propertyOrder = $self->propertyOrder(@propertyMap); $propertyOrder =~ s/^propertyOrder: //; return - "runtime.globalObject.property =", + "rt.globalObject.property =", @propertyMap, - "runtime.globalObject.propertyOrder =", + "rt.globalObject.propertyOrder =", $propertyOrder, ; }), @@ -654,32 +662,32 @@ sub newContext { sub propertyMap { my $self = shift; - return "map[string]_property{", (join ",\n", @_, ""), "}", + return "map[string]property{", (join ",\n", @_, ""), "}", } -our (@preblock, @postblock); +our (@postblock, %funcs); sub block { my $self = shift; - local @preblock = (); local @postblock = (); + local %funcs = (); my @input = $_[0]->(); my @output; while (@input) { local $_ = shift @input; if (m/^\./) { - $_ = "runtime.global$_"; + $_ = "rt.global$_"; } if (m/ :?=$/) { $_ .= shift @input; } + foreach my $label (keys %funcs) { + $_ =~ s/value: $label,/value: $funcs{$label},/; + } push @output, $_; } return - "{", - @preblock, @output, @postblock, - "}", ; } @@ -702,7 +710,7 @@ sub functionDeclare { while (@_) { my $name = shift; my $length = shift; - $name = $self->newFunction($name, "${builtin}_", $length); + $name = $self->newFunction($name, $builtin, $length); push @got, $self->functionProperty($name), } return @got; @@ -713,7 +721,7 @@ sub globalDeclare { my @got; while (@_) { my $name = shift; - push @got, $self->property($name, $self->objectValue("runtime.global.$name"), "0101"), + push @got, $self->property("class${name}Name", $self->objectValue("rt.global.$name"), "0o101"), } return @got; } @@ -722,7 +730,7 @@ sub propertyOrder { my $self = shift; my $propertyMap = join "", @_; - my (@keys) = $propertyMap =~ m/("\w+"):/g; + my (@keys) = grep !/^(mode|value|kind)$/, $propertyMap =~ m/("?\w+"?):/g; my $propertyOrder = join "\n", "propertyOrder: []string{", (join ",\n", @keys, ""), "}"; return $propertyOrder; @@ -740,11 +748,11 @@ sub globalObject { } return trim <<_END_; -&_object{ - runtime: runtime, - class: "$name", - objectClass: _classObject, - prototype: runtime.global.ObjectPrototype, +&object{ + runtime: rt, + class: class${name}Name, + objectClass: classObject, + prototype: rt.global.ObjectPrototype, extensible: true, $propertyMap } @@ -758,7 +766,7 @@ sub globalFunction { my $builtin = "builtin${name}"; my $builtinNew = "builtinNew${name}"; - my $prototype = "runtime.global.${name}Prototype"; + my $prototype = "rt.global.${name}Prototype"; my $propertyMap = ""; unshift @_, $self->property("length", $self->numberValue($length), "0"), @@ -772,16 +780,16 @@ sub globalFunction { } push @postblock, $self->statement( - "$prototype.property[\"constructor\"] =", - $self->property(undef, $self->objectValue("runtime.global.${name}"), "0101"), + "$prototype.property[propertyConstructor] = " . + $self->property(undef, $self->objectValue("rt.global.${name}"), "0o101"), ); return trim <<_END_; -&_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, +&object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, extensible: true, value: @{[ $self->nativeFunctionOf($name, $builtin, $builtinNew) ]}, $propertyMap @@ -794,7 +802,7 @@ sub nativeCallFunction { my $name = shift; my $func = shift; return trim <<_END_; -_nativeCallFunction{ "$name", $func } +nativeCallFunction{ "$name", $func } _END_ } @@ -814,7 +822,7 @@ sub globalPrototype { } if ($prototype =~ m/^\./) { - $prototype = "runtime.global$prototype"; + $prototype = "rt.global$prototype"; } my $propertyMap = ""; @@ -825,9 +833,9 @@ sub globalPrototype { } return trim <<_END_; -&_object{ - runtime: runtime, - class: "$class", +&object{ + runtime: rt, + class: class${class}Name, objectClass: $classObject, prototype: $prototype, extensible: true, @@ -846,11 +854,11 @@ sub newFunction { my @name = ($name, $name); if ($name =~ m/^(\w+):(\w+)$/) { @name = ($1, $2); - $name = $name[0]; + $name = $1; } - if ($func =~ m/^builtin\w+_$/) { - $func = "$func$name[1]"; + if ($func =~ m/^builtin\w+$/) { + $func = $func . ucfirst $name[1]; } my $propertyOrder = ""; @@ -863,14 +871,14 @@ sub newFunction { $propertyOrder = "$propertyOrder,"; } - my $label = functionLabel($name); - push @preblock, $self->statement( - "$label := @{[ trim <<_END_ ]}", -&_object{ - runtime: runtime, - class: "Function", - objectClass: _classObject, - prototype: runtime.global.FunctionPrototype, + my $label = label($name); + $funcs{$label} = $self->statement( + "@{[ trim <<_END_ ]}", +&object{ + runtime: rt, + class: classFunctionName, + objectClass: classObject, + prototype: rt.global.FunctionPrototype, extensible: true, property: @{[ join "\n", $self->propertyMap(@propertyMap) ]}, $propertyOrder @@ -889,11 +897,11 @@ sub newObject { my $propertyOrder = $self->propertyOrder($propertyMap); return trim <<_END_; -&_object{ - runtime: runtime, - class: "Object", - objectClass: _classObject, - prototype: runtime.global.ObjectPrototype, +&object{ + runtime: rt, + class: classObjectName, + objectClass: classObject, + prototype: rt.global.ObjectPrototype, extensible: true, property: $propertyMap, $propertyOrder, @@ -914,11 +922,11 @@ sub newPrototypeObject { my $propertyOrder = $self->propertyOrder($propertyMap); return trim <<_END_; -&_object{ - runtime: runtime, - class: "$class", +&object{ + runtime: rt, + class: class${class}Name, objectClass: $objectClass, - prototype: runtime.global.ObjectPrototype, + prototype: rt.global.ObjectPrototype, extensible: true, property: $propertyMap, $propertyOrder, @@ -933,7 +941,7 @@ sub functionProperty { return $self->property( $name, - $self->objectValue(functionLabel($name)) + $self->objectValue(label($name)) ); } @@ -953,7 +961,7 @@ sub functionOf { } return trim <<_END_ -_functionObject{ +functionObject{ call: $call, $construct } @@ -967,32 +975,21 @@ sub nativeFunctionOf { my $construct = shift; if ($construct) { $construct = "construct: $construct,"; + $name = "class${name}Name"; } else { $construct = ""; + $name = label($name); } return trim <<_END_ -_nativeFunctionObject{ - name: "$name", +nativeFunctionObject{ + name: $name, call: $call, $construct } _END_ } -sub nameProperty { - my $self = shift; - my $name = shift; - my $value = shift; - - return trim <<_END_; -"$name": _property{ - mode: 0101, - value: $value, -} -_END_ -} - sub numberValue { my $self = shift; my $value = shift; @@ -1009,20 +1006,21 @@ sub property { my $name = shift; my $value = shift; my $mode = shift; - $mode = "0101" unless defined $mode; + $mode = "0o101" unless defined $mode; if (! defined $value) { $value = "Value{}"; } if (defined $name) { + $name = label($name); return trim <<_END_; -"$name": _property{ +$name: { mode: $mode, value: $value, } _END_ } else { return trim <<_END_; -_property{ +property{ mode: $mode, value: $value, } @@ -1031,19 +1029,6 @@ sub property { } -sub objectProperty { - my $self = shift; - my $name = shift; - my $value = shift; - - return trim <<_END_; -"$name": _property{ - mode: 0101, - value: @{[ $self->objectValue($value)]}, -} -_END_ -} - sub objectValue { my $self = shift; my $value = shift; @@ -1058,10 +1043,15 @@ sub objectValue { sub stringValue { my $self = shift; my $value = shift; + if ($value) { + $value = "class${value}Name"; + } else { + $value = q{""}; + } return trim <<_END_ Value{ kind: valueString, - value: "$value", + value: $value, } _END_ } diff --git a/issue_test.go b/issue_test.go index 41c9427a..de1cdceb 100644 --- a/issue_test.go +++ b/issue_test.go @@ -31,7 +31,7 @@ func Test_issue262(t *testing.T) { // 11.13.1-1-1 test(`raise: eval("42 = 42;"); - `, "ReferenceError: Invalid left-hand side in assignment") + `, "SyntaxError: (anonymous): Line 1:1 invalid left-hand side in assignment") }) } @@ -84,7 +84,8 @@ func Test_issue13(t *testing.T) { }, } - vm.Set("anything", anything) + err = vm.Set("anything", anything) + require.NoError(t, err) test(` [ anything, @@ -138,7 +139,7 @@ func Test_issue16(t *testing.T) { func Test_issue21(t *testing.T) { tt(t, func() { vm1 := New() - vm1.Run(` + _, err := vm1.Run(` abc = {} abc.ghi = "Nothing happens."; var jkl = 0; @@ -147,11 +148,13 @@ func Test_issue21(t *testing.T) { return 1; } `) + require.NoError(t, err) abc, err := vm1.Get("abc") - is(err, nil) + require.NoError(t, err) vm2 := New() - vm2.Set("cba", abc) + err = vm2.Set("cba", abc) + require.NoError(t, err) _, err = vm2.Run(` var pqr = 0; cba.mno = function() { @@ -162,10 +165,10 @@ func Test_issue21(t *testing.T) { cba.def(); cba.def(); `) - is(err, nil) + require.NoError(t, err) jkl, err := vm1.Get("jkl") - is(err, nil) + require.NoError(t, err) is(jkl, 3) _, err = vm1.Run(` @@ -173,10 +176,10 @@ func Test_issue21(t *testing.T) { abc.mno(); abc.mno(); `) - is(err, nil) + require.NoError(t, err) pqr, err := vm2.Get("pqr") - is(err, nil) + require.NoError(t, err) is(pqr, -3) }) } @@ -188,7 +191,7 @@ func Test_issue24(t *testing.T) { { vm.Set("abc", []string{"abc", "def", "ghi"}) value, err := vm.Get("abc") - is(err, nil) + require.NoError(t, err) export, _ := value.Export() { value, valid := export.([]string) @@ -202,7 +205,7 @@ func Test_issue24(t *testing.T) { { vm.Set("abc", [...]string{"abc", "def", "ghi"}) value, err := vm.Get("abc") - is(err, nil) + require.NoError(t, err) export, _ := value.Export() { value, valid := export.([3]string) @@ -216,7 +219,7 @@ func Test_issue24(t *testing.T) { { vm.Set("abc", &[...]string{"abc", "def", "ghi"}) value, err := vm.Get("abc") - is(err, nil) + require.NoError(t, err) export, _ := value.Export() { value, valid := export.(*[3]string) @@ -230,7 +233,7 @@ func Test_issue24(t *testing.T) { { vm.Set("abc", map[int]string{0: "abc", 1: "def", 2: "ghi"}) value, err := vm.Get("abc") - is(err, nil) + require.NoError(t, err) export, _ := value.Export() { value, valid := export.(map[int]string) @@ -242,12 +245,12 @@ func Test_issue24(t *testing.T) { } { - vm.Set("abc", _abcStruct{Abc: true, Ghi: "Nothing happens."}) + vm.Set("abc", abcStruct{Abc: true, Ghi: "Nothing happens."}) value, err := vm.Get("abc") - is(err, nil) + require.NoError(t, err) export, _ := value.Export() { - value, valid := export.(_abcStruct) + value, valid := export.(abcStruct) is(valid, true) is(value.Abc, true) @@ -256,12 +259,12 @@ func Test_issue24(t *testing.T) { } { - vm.Set("abc", &_abcStruct{Abc: true, Ghi: "Nothing happens."}) + vm.Set("abc", &abcStruct{Abc: true, Ghi: "Nothing happens."}) value, err := vm.Get("abc") - is(err, nil) + require.NoError(t, err) export, _ := value.Export() { - value, valid := export.(*_abcStruct) + value, valid := export.(*abcStruct) is(valid, true) is(value.Abc, true) @@ -360,7 +363,7 @@ func Test_S7_3_A2_1_T1(t *testing.T) { test(`raise: eval("'\u000Astr\u000Aing\u000A'") - `, "SyntaxError: Unexpected token ILLEGAL") + `, "SyntaxError: (anonymous): Line 1:1 Unexpected token ILLEGAL") }) } @@ -470,12 +473,12 @@ def" while (true) { eval("continue abc"); } - `, "SyntaxError: Undefined label 'abc'") + `, "SyntaxError: (anonymous): Line 1:1 Undefined label 'abc'") // S15.1.2.1_A3.3_T3 test(`raise: eval("return"); - `, "SyntaxError: Illegal return statement") + `, "SyntaxError: (anonymous): Line 1:1 Illegal return statement") // 15.2.3.3-2-33 test(` @@ -486,7 +489,7 @@ def" // S15.3_A2_T1 test(`raise: Function.call(this, "var x / = 1;"); - `, "SyntaxError: Unexpected token /") + `, "SyntaxError: (anonymous): Line 2:7 Unexpected token / (and 3 more errors)") // ? test(` @@ -530,7 +533,7 @@ func Test_issue79(t *testing.T) { tt(t, func() { test, vm := test() - vm.Set("abc", []_abcStruct{ + vm.Set("abc", []abcStruct{ { Ghi: "一", Def: 1, @@ -634,7 +637,7 @@ d[e>>>5]|=128<<24-e%32;d[(e+64>>>9<<4)+14]=h.floor(b/4294967296);d[(e+64>>>9<<4) (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 AccessorDescriptor - if !configurable { - goto Reject - } - } else if isDataDescriptor && descriptor.isDataDescriptor() { - // DataDescriptor <=> DataDescriptor - if !configurable { - if !property.writable() && descriptor.writable() { - goto Reject - } - if !property.writable() { - if descriptor.value != nil && !sameValue(value, descriptor.value.(Value)) { - goto Reject - } - } - } - } else { - // AccessorDescriptor <=> AccessorDescriptor - newGetSet, _ := descriptor.value.(_propertyGetSet) - presentGet, presentSet := true, true - if newGetSet[0] == &_nilGetSetObject { - // Present, but nil + if newGetSet, isAccessor := descriptor.value.(propertyGetSet); isAccessor { + if newGetSet[0] == &nilGetSetObject { newGetSet[0] = nil - } else if newGetSet[0] == nil { - // Missing, not even nil - newGetSet[0] = getSet[0] - presentGet = false } - if newGetSet[1] == &_nilGetSetObject { - // Present, but nil + if newGetSet[1] == &nilGetSetObject { newGetSet[1] = nil - } else if newGetSet[1] == nil { - // Missing, not even nil - newGetSet[1] = getSet[1] - presentSet = false - } - if !configurable { - if (presentGet && (getSet[0] != newGetSet[0])) || (presentSet && (getSet[1] != newGetSet[1])) { - goto Reject - } } descriptor.value = newGetSet } - { - // This section will preserve attributes of - // the original property, if necessary - value1 := descriptor.value - if value1 == nil { - value1 = property.value - } else if newGetSet, isAccessor := descriptor.value.(_propertyGetSet); isAccessor { - if newGetSet[0] == &_nilGetSetObject { - newGetSet[0] = nil - } - if newGetSet[1] == &_nilGetSetObject { - newGetSet[1] = nil - } - value1 = newGetSet + obj.writeProperty(name, descriptor.value, descriptor.mode) + return true + } + + if descriptor.isEmpty() { + return true + } + + // TODO Per 8.12.9.6 - We should shortcut here (returning true) if + // the current and new (define) properties are the same + + configurable := prop.configurable() + if !configurable { + if descriptor.configurable() { + return reject() + } + // Test that, if enumerable is set on the property descriptor, then it should + // be the same as the existing property + if descriptor.enumerateSet() && descriptor.enumerable() != prop.enumerable() { + return reject() + } + } + + value, isDataDescriptor := prop.value.(Value) + getSet, _ := prop.value.(propertyGetSet) + switch { + case descriptor.isGenericDescriptor(): + // GenericDescriptor + case isDataDescriptor != descriptor.isDataDescriptor(): + // DataDescriptor <=> AccessorDescriptor + if !configurable { + return reject() + } + case isDataDescriptor && descriptor.isDataDescriptor(): + // DataDescriptor <=> DataDescriptor + if !configurable { + if !prop.writable() && descriptor.writable() { + return reject() } - mode1 := descriptor.mode - if mode1&0222 != 0 { - // TODO Factor this out into somewhere testable - // (Maybe put into switch ...) - mode0 := property.mode - if mode1&0200 != 0 { - if descriptor.isDataDescriptor() { - mode1 &= ^0200 // Turn off "writable" missing - mode1 |= (mode0 & 0100) - } - } - if mode1&020 != 0 { - mode1 |= (mode0 & 010) - } - if mode1&02 != 0 { - mode1 |= (mode0 & 01) + if !prop.writable() { + if descriptor.value != nil && !sameValue(value, descriptor.value.(Value)) { + return reject() } - mode1 &= 0311 // 0311 to preserve the non-setting on "writable" } - self._write(name, value1, mode1) } - return true + default: + // AccessorDescriptor <=> AccessorDescriptor + newGetSet, _ := descriptor.value.(propertyGetSet) + presentGet, presentSet := true, true + if newGetSet[0] == &nilGetSetObject { + // Present, but nil + newGetSet[0] = nil + } else if newGetSet[0] == nil { + // Missing, not even nil + newGetSet[0] = getSet[0] + presentGet = false + } + if newGetSet[1] == &nilGetSetObject { + // Present, but nil + newGetSet[1] = nil + } else if newGetSet[1] == nil { + // Missing, not even nil + newGetSet[1] = getSet[1] + presentSet = false + } + if !configurable { + if (presentGet && (getSet[0] != newGetSet[0])) || (presentSet && (getSet[1] != newGetSet[1])) { + return reject() + } + } + descriptor.value = newGetSet } -Reject: - if throw { - panic(self.runtime.panicTypeError()) + + // This section will preserve attributes of + // the original property, if necessary + value1 := descriptor.value + if value1 == nil { + value1 = prop.value + } else if newGetSet, isAccessor := descriptor.value.(propertyGetSet); isAccessor { + if newGetSet[0] == &nilGetSetObject { + newGetSet[0] = nil + } + if newGetSet[1] == &nilGetSetObject { + newGetSet[1] = nil + } + value1 = newGetSet } - return false + mode1 := descriptor.mode + if mode1&0o222 != 0 { + // TODO Factor this out into somewhere testable + // (Maybe put into switch ...) + mode0 := prop.mode + if mode1&0o200 != 0 { + if descriptor.isDataDescriptor() { + mode1 &= ^0o200 // Turn off "writable" missing + mode1 |= (mode0 & 0o100) + } + } + if mode1&0o20 != 0 { + mode1 |= (mode0 & 0o10) + } + if mode1&0o2 != 0 { + mode1 |= (mode0 & 0o1) + } + mode1 &= 0o311 // 0311 to preserve the non-setting on "writable" + } + obj.writeProperty(name, value1, mode1) + + return true } -func objectDelete(self *_object, name string, throw bool) bool { - property_ := self.getOwnProperty(name) - if property_ == nil { +func objectDelete(obj *object, name string, throw bool) bool { + prop := obj.getOwnProperty(name) + if prop == nil { return true } - if property_.configurable() { - self._delete(name) + if prop.configurable() { + obj.deleteProperty(name) return true } - return self.runtime.typeErrorResult(throw) + return obj.runtime.typeErrorResult(throw) } -func objectClone(in *_object, out *_object, clone *_clone) *_object { +func objectClone(in *object, out *object, clone *cloner) *object { *out = *in out.runtime = clone.runtime if out.prototype != nil { out.prototype = clone.object(in.prototype) } - out.property = make(map[string]_property, len(in.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) + for index, prop := range in.property { + out.property[index] = clone.property(prop) } switch value := in.value.(type) { - case _nativeFunctionObject: + case nativeFunctionObject: out.value = value - case _bindFunctionObject: - out.value = _bindFunctionObject{ + 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{ + case nodeFunctionObject: + out.value = nodeFunctionObject{ node: value.node, stash: clone.stash(value.stash), } - case _argumentsObject: + case argumentsObject: out.value = value.clone(clone) } diff --git a/object_test.go b/object_test.go index d1e90680..8f806d57 100644 --- a/object_test.go +++ b/object_test.go @@ -8,11 +8,11 @@ func TestObject_(t *testing.T) { tt(t, func() { test, _ := test() - object := newObject(nil, "") - is(object != nil, true) + obj := newObject(nil, "") + is(obj != nil, true) - object.put("xyzzy", toValue("Nothing happens."), true) - is(object.get("xyzzy"), "Nothing happens.") + obj.put("xyzzy", toValue("Nothing happens."), true) + is(obj.get("xyzzy"), "Nothing happens.") test(` var abc = Object.getOwnPropertyDescriptor(Object, "prototype"); @@ -24,10 +24,10 @@ func TestObject_(t *testing.T) { func TestStringObject(t *testing.T) { tt(t, func() { - object := New().runtime.newStringObject(toValue("xyzzy")) - is(object.get("1"), "y") - is(object.get("10"), "undefined") - is(object.get("2"), "z") + obj := New().runtime.newStringObject(toValue("xyzzy")) + is(obj.get("1"), "y") + is(obj.get("10"), "undefined") + is(obj.get("2"), "z") }) } @@ -623,17 +623,17 @@ func TestObjectGetterSetter(t *testing.T) { func TestProperty(t *testing.T) { tt(t, func() { - property := _property{} - property.writeOn() - is(property.writeSet(), true) + prop := property{} + prop.writeOn() + is(prop.writeSet(), true) - property.writeClear() - is(property.writeSet(), false) + prop.writeClear() + is(prop.writeSet(), false) - property.writeOff() - is(property.writeSet(), true) + prop.writeOff() + is(prop.writeSet(), true) - property.writeClear() - is(property.writeSet(), false) + prop.writeClear() + is(prop.writeSet(), false) }) } diff --git a/otto.go b/otto.go index 567ac1b8..ca80bc5a 100644 --- a/otto.go +++ b/otto.go @@ -39,10 +39,8 @@ Set a string Get the value of an expression value, _ = vm.Run("xyzzy.length") - { - // value is an int64 with a value of 16 - value, _ := value.ToInteger() - } + // iv is an int64 with a value of 16 + iv, _ := value.ToInteger() An error happens @@ -216,9 +214,7 @@ http://github.com/robertkrimen/natto Here is some more discussion of the issue: * http://book.mixu.net/node/ch2.html - * http://en.wikipedia.org/wiki/Reentrancy_%28computing%29 - * http://aaroncrane.co.uk/2009/02/perl_safe_signals/ */ package otto @@ -232,36 +228,41 @@ import ( "github.com/robertkrimen/otto/registry" ) -// Otto is the representation of the JavaScript runtime. Each instance of Otto has a self-contained namespace. +// Otto is the representation of the JavaScript runtime. +// Each instance of Otto has a self-contained namespace. type Otto struct { // Interrupt is a channel for interrupting the runtime. You can use this to halt a long running execution, for example. // See "Halting Problem" for more information. Interrupt chan func() - runtime *_runtime + runtime *runtime } -// New will allocate a new JavaScript runtime +// New will allocate a new JavaScript runtime. func New() *Otto { - self := &Otto{ + o := &Otto{ runtime: newContext(), } - self.runtime.otto = self - self.runtime.traceLimit = 10 - self.Set("console", self.runtime.newConsole()) + o.runtime.otto = o + o.runtime.traceLimit = 10 + if err := o.Set("console", o.runtime.newConsole()); err != nil { + panic(err) + } registry.Apply(func(entry registry.Entry) { - self.Run(entry.Source()) + if _, err := o.Run(entry.Source()); err != nil { + panic(err) + } }) - return self + return o } -func (otto *Otto) clone() *Otto { - self := &Otto{ - runtime: otto.runtime.clone(), +func (o *Otto) clone() *Otto { + n := &Otto{ + runtime: o.runtime.clone(), } - self.runtime.otto = self - return self + n.runtime.otto = n + return n } // Run will allocate a new JavaScript runtime, run the given source @@ -289,8 +290,8 @@ func Run(src interface{}) (*Otto, Value, error) { // src may also be a Script. // // 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) { - value, err := self.runtime.cmpl_run(src, nil) +func (o Otto) Run(src interface{}) (Value, error) { + value, err := o.runtime.cmplRun(src, nil) if !value.safe() { value = Value{} } @@ -302,13 +303,13 @@ func (self Otto) Run(src interface{}) (Value, error) { // By staying in the same scope, the code evaluated has access to everything // already defined in the current stack frame. This is most useful in, for // example, a debugger call. -func (self Otto) Eval(src interface{}) (Value, error) { - if self.runtime.scope == nil { - self.runtime.enterGlobalScope() - defer self.runtime.leaveScope() +func (o Otto) Eval(src interface{}) (Value, error) { + if o.runtime.scope == nil { + o.runtime.enterGlobalScope() + defer o.runtime.leaveScope() } - value, err := self.runtime.cmpl_eval(src, nil) + value, err := o.runtime.cmplEval(src, nil) if !value.safe() { value = Value{} } @@ -319,10 +320,10 @@ func (self Otto) Eval(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) { +func (o Otto) Get(name string) (Value, error) { value := Value{} err := catchPanic(func() { - value = self.getValue(name) + value = o.getValue(name) }) if !value.safe() { value = Value{} @@ -330,8 +331,8 @@ func (self Otto) Get(name string) (Value, error) { return value, err } -func (self Otto) getValue(name string) Value { - return self.runtime.globalStash.getBinding(name, false) +func (o Otto) getValue(name string) Value { + return o.runtime.globalStash.getBinding(name, false) } // Set the top-level binding of the given name to the given value. @@ -343,29 +344,29 @@ func (self Otto) getValue(name string) Value { // fails), then an error is returned. // // If the top-level binding does not exist, it will be created. -func (self Otto) Set(name string, value interface{}) error { - { - value, err := self.ToValue(value) - if err != nil { - return err - } - err = catchPanic(func() { - self.setValue(name, value) - }) +func (o Otto) Set(name string, value interface{}) error { + val, err := o.ToValue(value) + if err != nil { return err } + + return catchPanic(func() { + o.setValue(name, val) + }) } -func (self Otto) setValue(name string, value Value) { - self.runtime.globalStash.setValue(name, value, false) +func (o Otto) setValue(name string, value Value) { + o.runtime.globalStash.setValue(name, value, false) } -func (self Otto) SetDebuggerHandler(fn func(vm *Otto)) { - self.runtime.debugger = fn +// SetDebuggerHandler sets the debugger handler to fn. +func (o Otto) SetDebuggerHandler(fn func(vm *Otto)) { + o.runtime.debugger = fn } -func (self Otto) SetRandomSource(fn func() float64) { - self.runtime.random = fn +// SetRandomSource sets the random source to fn. +func (o Otto) SetRandomSource(fn func() float64) { + o.runtime.random = fn } // SetStackDepthLimit sets an upper limit to the depth of the JavaScript @@ -376,41 +377,41 @@ func (self Otto) SetRandomSource(fn func() float64) { // JavaScript makes a call to a Go function, otto won't keep track of what // happens outside the interpreter. So if your Go function is infinitely // recursive, you're still in trouble. -func (self Otto) SetStackDepthLimit(limit int) { - self.runtime.stackLimit = limit +func (o Otto) SetStackDepthLimit(limit int) { + o.runtime.stackLimit = limit } // SetStackTraceLimit sets an upper limit to the number of stack frames that // otto will use when formatting an error's stack trace. By default, the limit // is 10. This is consistent with V8 and SpiderMonkey. // -// TODO: expose via `Error.stackTraceLimit` -func (self Otto) SetStackTraceLimit(limit int) { - self.runtime.traceLimit = limit +// TODO: expose via `Error.stackTraceLimit`. +func (o Otto) SetStackTraceLimit(limit int) { + o.runtime.traceLimit = limit } // MakeCustomError creates a new Error object with the given name and message, // returning it as a Value. -func (self Otto) MakeCustomError(name, message string) Value { - return self.runtime.toValue(self.runtime.newError(name, self.runtime.toValue(message), 0)) +func (o Otto) MakeCustomError(name, message string) Value { + return o.runtime.toValue(o.runtime.newError(name, o.runtime.toValue(message), 0)) } // MakeRangeError creates a new RangeError object with the given message, // returning it as a Value. -func (self Otto) MakeRangeError(message string) Value { - return self.runtime.toValue(self.runtime.newRangeError(self.runtime.toValue(message))) +func (o Otto) MakeRangeError(message string) Value { + return o.runtime.toValue(o.runtime.newRangeError(o.runtime.toValue(message))) } // MakeSyntaxError creates a new SyntaxError object with the given message, // returning it as a Value. -func (self Otto) MakeSyntaxError(message string) Value { - return self.runtime.toValue(self.runtime.newSyntaxError(self.runtime.toValue(message))) +func (o Otto) MakeSyntaxError(message string) Value { + return o.runtime.toValue(o.runtime.newSyntaxError(o.runtime.toValue(message))) } // MakeTypeError creates a new TypeError object with the given message, // returning it as a Value. -func (self Otto) MakeTypeError(message string) Value { - return self.runtime.toValue(self.runtime.newTypeError(self.runtime.toValue(message))) +func (o Otto) MakeTypeError(message string) Value { + return o.runtime.toValue(o.runtime.newTypeError(o.runtime.toValue(message))) } // Context is a structure that contains information about the current execution @@ -427,48 +428,49 @@ type Context struct { // Context returns the current execution context of the vm, traversing up to // ten stack frames, and skipping any innermost native function stack frames. -func (self Otto) Context() Context { - return self.ContextSkip(10, true) +func (o Otto) Context() Context { + return o.ContextSkip(10, true) } // ContextLimit returns the current execution context of the vm, with a // specific limit on the number of stack frames to traverse, skipping any // innermost native function stack frames. -func (self Otto) ContextLimit(limit int) Context { - return self.ContextSkip(limit, true) +func (o Otto) ContextLimit(limit int) Context { + return o.ContextSkip(limit, true) } // ContextSkip returns the current execution context of the vm, with a // specific limit on the number of stack frames to traverse, optionally // skipping any innermost native function stack frames. -func (self Otto) ContextSkip(limit int, skipNative bool) (ctx Context) { +func (o Otto) ContextSkip(limit int, skipNative bool) Context { // Ensure we are operating in a scope - if self.runtime.scope == nil { - self.runtime.enterGlobalScope() - defer self.runtime.leaveScope() + if o.runtime.scope == nil { + o.runtime.enterGlobalScope() + defer o.runtime.leaveScope() } - scope := self.runtime.scope - frame := scope.frame + curScope := o.runtime.scope + frm := curScope.frame - for skipNative && frame.native && scope.outer != nil { - scope = scope.outer - frame = scope.frame + for skipNative && frm.native && curScope.outer != nil { + curScope = curScope.outer + frm = curScope.frame } // Get location information + var ctx Context ctx.Filename = "" - ctx.Callee = frame.callee + ctx.Callee = frm.callee switch { - case frame.native: - ctx.Filename = frame.nativeFile - ctx.Line = frame.nativeLine + case frm.native: + ctx.Filename = frm.nativeFile + ctx.Line = frm.nativeLine ctx.Column = 0 - case frame.file != nil: + case frm.file != nil: ctx.Filename = "" - if p := frame.file.Position(file.Idx(frame.offset)); p != nil { + if p := frm.file.Position(file.Idx(frm.offset)); p != nil { ctx.Line = p.Line ctx.Column = p.Column @@ -479,14 +481,14 @@ func (self Otto) ContextSkip(limit int, skipNative bool) (ctx Context) { } // Get the current scope this Value - ctx.This = toValue_object(scope.this) + ctx.This = objectValue(curScope.this) // Build stacktrace (up to 10 levels deep) ctx.Symbols = make(map[string]Value) - ctx.Stacktrace = append(ctx.Stacktrace, frame.location()) + ctx.Stacktrace = append(ctx.Stacktrace, frm.location()) for limit != 0 { // Get variables - stash := scope.lexical + stash := curScope.lexical for { for _, name := range getStashProperties(stash) { if _, ok := ctx.Symbols[name]; !ok { @@ -499,17 +501,17 @@ func (self Otto) ContextSkip(limit int, skipNative bool) (ctx Context) { } } - scope = scope.outer - if scope == nil { + curScope = curScope.outer + if curScope == nil { break } - if scope.frame.offset >= 0 { - ctx.Stacktrace = append(ctx.Stacktrace, scope.frame.location()) + if curScope.frame.offset >= 0 { + ctx.Stacktrace = append(ctx.Stacktrace, curScope.frame.location()) } limit-- } - return + return ctx } // Call the given JavaScript with a given this and arguments. @@ -531,7 +533,7 @@ func (self Otto) ContextSkip(limit int, skipNative bool) (ctx Context) { // // This will perform a concat on the given array and return the result // // value is [ 1, 2, 3, undefined, 4, 5, 6, 7, "abc" ] // value, _ := vm.Call(`[ 1, 2, 3, undefined, 4 ].concat`, nil, 5, 6, 7, "abc") -func (self Otto) Call(source string, this interface{}, argumentList ...interface{}) (Value, error) { +func (o Otto) Call(source string, this interface{}, argumentList ...interface{}) (Value, error) { thisValue := Value{} construct := false @@ -541,19 +543,19 @@ func (self Otto) Call(source string, this interface{}, argumentList ...interface } // FIXME enterGlobalScope - self.runtime.enterGlobalScope() + o.runtime.enterGlobalScope() defer func() { - self.runtime.leaveScope() + o.runtime.leaveScope() }() if !construct && this == nil { - program, err := self.runtime.cmpl_parse("", source+"()", nil) + program, err := o.runtime.cmplParse("", source+"()", nil) if err == nil { - if node, ok := program.body[0].(*_nodeExpressionStatement); ok { - if node, ok := node.expression.(*_nodeCallExpression); ok { + if node, ok := program.body[0].(*nodeExpressionStatement); ok { + if node, ok := node.expression.(*nodeCallExpression); ok { var value Value err := catchPanic(func() { - value = self.runtime.cmpl_evaluate_nodeCallExpression(node, argumentList) + value = o.runtime.cmplEvaluateNodeCallExpression(node, argumentList) }) if err != nil { return Value{}, err @@ -563,35 +565,32 @@ func (self Otto) Call(source string, this interface{}, argumentList ...interface } } } else { - value, err := self.ToValue(this) + value, err := o.ToValue(this) if err != nil { return Value{}, err } thisValue = value } - { - this := thisValue - - fn, err := self.Run(source) - if err != nil { - return Value{}, err - } - - if construct { - result, err := fn.constructSafe(self.runtime, this, argumentList...) - if err != nil { - return Value{}, err - } - return result, nil - } + val := thisValue + fn, err := o.Run(source) + if err != nil { + return Value{}, err + } - result, err := fn.Call(this, argumentList...) + if construct { + result, err := fn.constructSafe(o.runtime, val, argumentList...) if err != nil { return Value{}, err } return result, nil } + + result, err := fn.Call(val, argumentList...) + if err != nil { + return Value{}, err + } + return result, nil } // Object will run the given source and return the result as an object. @@ -611,8 +610,8 @@ func (self Otto) Call(source string, this interface{}, argumentList ...interface // // If there is an error (like the source does not result in an object), then // nil and an error is returned. -func (self Otto) Object(source string) (*Object, error) { - value, err := self.runtime.cmpl_run(source, nil) +func (o Otto) Object(source string) (*Object, error) { + value, err := o.runtime.cmplRun(source, nil) if err != nil { return nil, err } @@ -623,8 +622,8 @@ 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.safeToValue(value) +func (o Otto) ToValue(value interface{}) (Value, error) { + return o.runtime.safeToValue(value) } // Copy will create a copy/clone of the runtime. @@ -635,30 +634,20 @@ func (self Otto) ToValue(value interface{}) (Value, error) { // etc. into a new runtime. // // Be on the lookout for memory leaks or inadvertent sharing of resources. -func (in *Otto) Copy() *Otto { +func (o *Otto) Copy() *Otto { out := &Otto{ - runtime: in.runtime.clone(), + runtime: o.runtime.clone(), } out.runtime.otto = out return out } -// Object{} - // Object is the representation of a JavaScript object. type Object struct { - object *_object + object *object value Value } -func _newObject(object *_object, value Value) *Object { - // value MUST contain object! - return &Object{ - object: object, - value: value, - } -} - // Call a method on the object. // // It is essentially equivalent to: @@ -671,27 +660,27 @@ func _newObject(object *_object, value Value) *Object { // 1. There is an error during conversion of the argument list // 2. The property is not actually a function // 3. An (uncaught) exception is thrown -func (self Object) Call(name string, argumentList ...interface{}) (Value, error) { +func (o Object) Call(name string, argumentList ...interface{}) (Value, error) { // TODO: Insert an example using JavaScript below... // e.g., Object("JSON").Call("stringify", ...) - function, err := self.Get(name) + function, err := o.Get(name) if err != nil { return Value{}, err } - return function.Call(self.Value(), argumentList...) + return function.Call(o.Value(), argumentList...) } -// Value will return self as a value. -func (self Object) Value() Value { - return self.value +// Value returns the value of o. +func (o Object) Value() Value { + return o.value } // Get the value of the property with the given name. -func (self Object) Get(name string) (Value, error) { +func (o Object) Get(name string) (Value, error) { value := Value{} err := catchPanic(func() { - value = self.object.get(name) + value = o.object.get(name) }) if !value.safe() { value = Value{} @@ -703,25 +692,23 @@ func (self Object) Get(name string) (Value, error) { // // An error will result if the setting the property triggers an exception (i.e. read-only), // 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.safeToValue(value) - if err != nil { - return err - } - err = catchPanic(func() { - self.object.put(name, value, true) - }) +func (o Object) Set(name string, value interface{}) error { + val, err := o.object.runtime.safeToValue(value) + if err != nil { return err } + + return catchPanic(func() { + o.object.put(name, val, true) + }) } // Keys gets the keys for the given object. // // Equivalent to calling Object.keys on the object. -func (self Object) Keys() []string { +func (o Object) Keys() []string { var keys []string - self.object.enumerate(false, func(name string) bool { + o.object.enumerate(false, func(name string) bool { keys = append(keys, name) return true }) @@ -730,10 +717,10 @@ func (self Object) Keys() []string { // KeysByParent gets the keys (and those of the parents) for the given object, // in order of "closest" to "furthest". -func (self Object) KeysByParent() [][]string { +func (o Object) KeysByParent() [][]string { var a [][]string - for o := self.object; o != nil; o = o.prototype { + for o := o.object; o != nil; o = o.prototype { var l []string o.enumerate(false, func(name string) bool { @@ -759,28 +746,29 @@ func (self Object) KeysByParent() [][]string { // Boolean // Date // RegExp -func (self Object) Class() string { - return self.object.class +func (o Object) Class() string { + return o.object.class } -func (self Object) MarshalJSON() ([]byte, error) { +// MarshalJSON implements json.Marshaller. +func (o Object) MarshalJSON() ([]byte, error) { var goValue interface{} - switch value := self.object.value.(type) { - case *_goStructObject: + switch value := o.object.value.(type) { + case *goStructObject: goValue = value.value.Interface() - case *_goMapObject: + case *goMapObject: goValue = value.value.Interface() - case *_goArrayObject: + case *goArrayObject: goValue = value.value.Interface() - case *_goSliceObject: + case *goSliceObject: goValue = value.value.Interface() default: // It's a JS object; pass it to JSON.stringify: var result []byte err := catchPanic(func() { - resultVal := builtinJSON_stringify(FunctionCall{ - runtime: self.object.runtime, - ArgumentList: []Value{self.value}, + resultVal := builtinJSONStringify(FunctionCall{ + runtime: o.object.runtime, + ArgumentList: []Value{o.value}, }) result = []byte(resultVal.String()) }) diff --git a/otto/main.go b/otto/main.go index f379e42a..7faacb68 100644 --- a/otto/main.go +++ b/otto/main.go @@ -1,28 +1,29 @@ package main import ( + "errors" "flag" "fmt" - "io/ioutil" + "io" "os" "github.com/robertkrimen/otto" "github.com/robertkrimen/otto/underscore" ) -var flag_underscore *bool = flag.Bool("underscore", true, "Load underscore into the runtime environment") +var flagUnderscore *bool = flag.Bool("underscore", true, "Load underscore into the runtime environment") func readSource(filename string) ([]byte, error) { if filename == "" || filename == "-" { - return ioutil.ReadAll(os.Stdin) + return io.ReadAll(os.Stdin) } - return ioutil.ReadFile(filename) + return os.ReadFile(filename) //nolint: gosec } func main() { flag.Parse() - if !*flag_underscore { + if !*flagUnderscore { underscore.Disable() } @@ -37,11 +38,11 @@ func main() { return err }() if err != nil { - switch err := err.(type) { - case *otto.Error: - fmt.Print(err.String()) - default: - fmt.Println(err) + var oerr *otto.Error + if errors.As(err, &oerr) { + fmt.Fprint(os.Stderr, oerr.String()) + } else { + fmt.Fprintln(os.Stderr, err) } os.Exit(64) } diff --git a/otto_.go b/otto_.go index f4f9193e..bf44679d 100644 --- a/otto_.go +++ b/otto_.go @@ -3,28 +3,28 @@ package otto import ( "fmt" "regexp" - runtime_ "runtime" + goruntime "runtime" "strconv" ) -var isIdentifier_Regexp *regexp.Regexp = regexp.MustCompile(`^[a-zA-Z\$][a-zA-Z0-9\$]*$`) +var isIdentifierRegexp *regexp.Regexp = regexp.MustCompile(`^[a-zA-Z\$][a-zA-Z0-9\$]*$`) -func isIdentifier(string_ string) bool { - return isIdentifier_Regexp.MatchString(string_) +func isIdentifier(value string) bool { + return isIdentifierRegexp.MatchString(value) } -func (self *_runtime) toValueArray(arguments ...interface{}) []Value { +func (rt *runtime) toValueArray(arguments ...interface{}) []Value { length := len(arguments) if length == 1 { if valueArray, ok := arguments[0].([]Value); ok { return valueArray } - return []Value{self.toValue(arguments[0])} + return []Value{rt.toValue(arguments[0])} } valueArray := make([]Value, length) for index, value := range arguments { - valueArray[index] = self.toValue(value) + valueArray[index] = rt.toValue(value) } return valueArray @@ -89,15 +89,13 @@ func valueToRangeIndex(indexValue Value, length int64, negativeIsZero bool) int6 if index < 0 { index = 0 } - } else { - if index > length { - index = length - } + } else if index > length { + index = length } return index } -func rangeStartEnd(array []Value, size int64, negativeIsZero bool) (start, end int64) { +func rangeStartEnd(array []Value, size int64, negativeIsZero bool) (start, end int64) { //nolint: nonamedreturns start = valueToRangeIndex(valueOfArrayIndex(array, 0), size, negativeIsZero) if len(array) == 1 { // If there is only the start argument, then end = size @@ -115,14 +113,14 @@ func rangeStartEnd(array []Value, size int64, negativeIsZero bool) (start, end i return } -func rangeStartLength(source []Value, size int64) (start, length int64) { +func rangeStartLength(source []Value, size int64) (start, length int64) { //nolint: nonamedreturns start = valueToRangeIndex(valueOfArrayIndex(source, 0), size, false) // Assume the second argument is missing or undefined - length = int64(size) + length = size if len(source) == 1 { // If there is only the start argument, then length = size - return + return start, length } lengthValue := valueOfArrayIndex(source, 1) @@ -130,12 +128,12 @@ func rangeStartLength(source []Value, size int64) (start, length int64) { // Which it is not, so get the value as an array index length = lengthValue.number().int64 } - return + return start, length } func hereBeDragons(arguments ...interface{}) string { - pc, _, _, _ := runtime_.Caller(1) //nolint: dogsled - name := runtime_.FuncForPC(pc).Name() + pc, _, _, _ := goruntime.Caller(1) //nolint: dogsled + name := goruntime.FuncForPC(pc).Name() message := fmt.Sprintf("Here be dragons -- %s", name) if len(arguments) > 0 { message += ": " diff --git a/otto_test.go b/otto_test.go index f53d2ed5..f4827316 100644 --- a/otto_test.go +++ b/otto_test.go @@ -3,7 +3,6 @@ package otto import ( "bytes" "errors" - "fmt" "io" "testing" "time" @@ -150,13 +149,15 @@ func TestCall(t *testing.T) { func TestRunFunctionWithSetArguments(t *testing.T) { tt(t, func() { vm := New() - vm.Run(`var sillyFunction = function(record){record.silly = true; record.answer *= -1};`) + _, err := vm.Run(`var sillyFunction = function(record){record.silly = true; record.answer *= -1};`) + require.NoError(t, err) record := map[string]interface{}{"foo": "bar", "answer": 42} // Set performs a conversion that allows the map to be addressed as a Javascript object - vm.Set("argument", record) - _, err := vm.Run("sillyFunction(argument)") + err = vm.Set("argument", record) + require.NoError(t, err) + _, err = vm.Run("sillyFunction(argument)") + require.NoError(t, err) - is(err, nil) is(record["answer"].(float64), -42) is(record["silly"].(bool), true) }) @@ -165,11 +166,12 @@ func TestRunFunctionWithSetArguments(t *testing.T) { func TestRunFunctionWithArgumentsPassedToCall(t *testing.T) { tt(t, func() { vm := New() - vm.Run(`var sillyFunction = function(record){record.silly = true; record.answer *= -1};`) + _, err := vm.Run(`var sillyFunction = function(record){record.silly = true; record.answer *= -1};`) + require.NoError(t, err) record := map[string]interface{}{"foo": "bar", "answer": 42} - _, err := vm.Call("sillyFunction", nil, record) + _, err = vm.Call("sillyFunction", nil, record) + require.NoError(t, err) - is(err, nil) is(record["answer"].(float64), -42) is(record["silly"].(bool), true) }) @@ -716,7 +718,7 @@ func Test_eval(t *testing.T) { return [ abc instanceof SyntaxError, abc.toString() ]; } })(); - `, "true,SyntaxError: Unexpected token ILLEGAL") + `, "true,SyntaxError: (anonymous): Line 1:12 Unexpected token ILLEGAL (and 1 more errors)") test(` function abc(){ @@ -814,18 +816,18 @@ func TestAPI(t *testing.T) { `, 16) abc, _ := vm.Get("abc") def, _ := vm.Get("def") - object := abc.Object() - result, _ := object.Call("xyzzy") + obj := abc.Object() + result, _ := obj.Call("xyzzy") is(result, 16) - result, _ = object.Call("xyzzy", 1) + result, _ = obj.Call("xyzzy", 1) is(result, 17) - value, _ := object.Get("xyzzy") + value, _ := obj.Get("xyzzy") result, _ = value.Call(def) is(result, 27) result, _ = value.Call(def, 3) is(result, 30) - object = value.Object() // Object xyzzy - result, _ = object.Value().Call(def, 3) + obj = value.Object() // Object xyzzy + result, _ = obj.Value().Call(def, 3) is(result, 30) test(` @@ -837,35 +839,39 @@ func TestAPI(t *testing.T) { abc['abc']; `, 1) abc, err := vm.Get("abc") - is(err, nil) - object = abc.Object() // Object abc - value, err = object.Get("abc") - is(err, nil) + require.NoError(t, err) + obj = abc.Object() // Object abc + value, err = obj.Get("abc") + require.NoError(t, err) is(value, 1) - is(object.Keys(), []string{"abc", "def", "3.14159"}) + is(obj.Keys(), []string{"abc", "def", "3.14159"}) test(` abc = [ 0, 1, 2, 3.14159, "abc", , ]; abc.def = true; `) abc, err = vm.Get("abc") - is(err, nil) - object = abc.Object() // Object abc - is(object.Keys(), []string{"0", "1", "2", "3", "4", "def"}) + require.NoError(t, err) + obj = abc.Object() // Object abc + is(obj.Keys(), []string{"0", "1", "2", "3", "4", "def"}) }) } func TestObjectKeys(t *testing.T) { tt(t, func() { vm := New() - vm.Eval(`var x = Object.create(null); x.a = 1`) - vm.Eval(`var y = Object.create(x); y.b = 2`) + _, err := vm.Eval(`var x = Object.create(null); x.a = 1`) + require.NoError(t, err) + _, err = vm.Eval(`var y = Object.create(x); y.b = 2`) + require.NoError(t, err) - o1, _ := vm.Object("x") + o1, err := vm.Object("x") + require.NoError(t, err) is(o1.Keys(), []string{"a"}) is(o1.KeysByParent(), [][]string{{"a"}}) - o2, _ := vm.Object("y") + o2, err := vm.Object("y") + require.NoError(t, err) is(o2.Keys(), []string{"b"}) is(o2.KeysByParent(), [][]string{{"b"}, {"a"}}) }) @@ -913,8 +919,8 @@ func TestDotMember(t *testing.T) { func Test_stringToFloat(t *testing.T) { tt(t, func() { - is(parseNumber("10e10000"), _Infinity) - is(parseNumber("10e10_."), _NaN) + is(parseNumber("10e10000"), infinity) + is(parseNumber("10e10_."), naN) }) } @@ -1020,14 +1026,14 @@ func TestOttoCall(t *testing.T) { return s.Val; } `) - is(err, nil) + require.NoError(t, err) value, err := vm.Call(`abc.def`, nil, 2) - is(err, nil) + require.NoError(t, err) is(value, "def: 6.14159") value, err = vm.Call(`abc.def`, "", 2) - is(err, nil) + require.NoError(t, err) is(value, "def: 5.14159") // Do not attempt to do a ToValue on a this of nil @@ -1036,12 +1042,12 @@ func TestOttoCall(t *testing.T) { is(value, "undefined") value, err = vm.Call(`[ 1, 2, 3, undefined, 4 ].concat`, nil, 5, 6, 7, "abc") - is(err, nil) + require.NoError(t, err) is(value, "1,2,3,,4,5,6,7,abc") s := struct{ Val int }{Val: 10} value, err = vm.Call("structFunc", nil, s) - is(err, nil) + require.NoError(t, err) is(value, 10) }) } @@ -1052,7 +1058,7 @@ func TestOttoCall_new(t *testing.T) { vm.Set("abc", func(call FunctionCall) Value { value, err := call.Otto.Call(`new Object`, nil, "Nothing happens.") - is(err, nil) + require.NoError(t, err) return value }) test(` @@ -1067,7 +1073,7 @@ func TestOttoCall_newWithBrackets(t *testing.T) { test, vm := test() _, err := vm.Run(`var a = {default: function B(x) { this.x = x; } }`) - is(err, nil) + require.NoError(t, err) test(`(new a['default'](1)).x`, 1) }) @@ -1087,9 +1093,11 @@ func TestOttoCall_throw(t *testing.T) { vm.Set("abc", func(call FunctionCall) Value { if false { - call.Otto.Call(`throw eval`, nil, "({ def: 3.14159 })") + _, err := call.Otto.Call(`throw eval`, nil, "({ def: 3.14159 })") + require.NoError(t, err) } - call.Otto.Call(`throw Error`, nil, "abcdef") + _, err := call.Otto.Call(`throw Error`, nil, "abcdef") + require.NoError(t, err) return Value{} }) // TODO try { abc(); } catch (err) { error = err } @@ -1108,7 +1116,8 @@ func TestOttoCall_throw(t *testing.T) { `, "true,abcdef,") vm.Set("def", func(call FunctionCall) Value { - call.Otto.Call(`throw new Object`, nil, 3.14159) + _, err := call.Otto.Call(`throw new Object`, nil, 3.14159) + require.NoError(t, err) return UndefinedValue() }) test(` @@ -1126,7 +1135,7 @@ func TestOttoCall_throw(t *testing.T) { func TestOttoCopy(t *testing.T) { tt(t, func() { vm0 := New() - vm0.Run(` + _, err := vm0.Run(` var abc = function() { return "Xyzzy"; }; @@ -1135,40 +1144,42 @@ func TestOttoCopy(t *testing.T) { return abc() + (0 + {}); } `) + require.NoError(t, err) value, err := vm0.Run(` def(); `) - is(err, nil) + require.NoError(t, err) is(value, "Xyzzy0[object Object]") vm1 := vm0.Copy() value, err = vm1.Run(` def(); `) - is(err, nil) + require.NoError(t, err) is(value, "Xyzzy0[object Object]") - vm1.Run(` + _, err = vm1.Run(` abc = function() { return 3.14159; }; `) + require.NoError(t, err) value, err = vm1.Run(` def(); `) - is(err, nil) + require.NoError(t, err) is(value, "3.141590[object Object]") value, err = vm0.Run(` def(); `) - is(err, nil) + require.NoError(t, err) is(value, "Xyzzy0[object Object]") { vm0 := New() - vm0.Run(` + _, err := vm0.Run(` var global = (function () {return this;}()) var abc = 0; var vm = "vm0"; @@ -1186,31 +1197,33 @@ func TestOttoCopy(t *testing.T) { }; })(); `) + require.NoError(t, err) value, err := vm0.Run(` def(); `) - is(err, nil) + require.NoError(t, err) is(value, "vm0,0,0,1") vm1 := vm0.Copy() - vm1.Set("vm", "vm1") + err = vm1.Set("vm", "vm1") + require.NoError(t, err) value, err = vm1.Run(` def(); `) - is(err, nil) + require.NoError(t, err) is(value, "vm1,1,1,1") value, err = vm0.Run(` def(); `) - is(err, nil) + require.NoError(t, err) is(value, "vm0,1,1,1") value, err = vm1.Run(` def(); `) - is(err, nil) + require.NoError(t, err) is(value, "vm1,2,2,1") } }) @@ -1227,29 +1240,29 @@ func TestOttoCall_clone(t *testing.T) { 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.get("prototype").object().runtime, rt) } { value, err := vm.Run(`[ 1, 2, 3 ].toString()`) - is(err, nil) + require.NoError(t, err) is(value, "1,2,3") } { value, err := vm.Run(`[ 1, 2, 3 ]`) - is(err, nil) + require.NoError(t, err) is(value, "1,2,3") - object := value._object() - is(object, "!=", nil) - is(object.prototype, rt.global.ArrayPrototype) + obj := value.object() + is(obj, "!=", nil) + is(obj.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) + require.NoError(t, err) + obj = value.object() + is(obj.runtime, rt) + is(obj, "!=", nil) + is(obj, rt.global.ArrayPrototype) } { @@ -1258,15 +1271,15 @@ func TestOttoCall_clone(t *testing.T) { var abc = 1; var def = 2; `) - is(err, nil) + require.NoError(t, err) otto2 := otto1.clone() value, err := otto2.Run(`abc += 1; abc;`) - is(err, nil) + require.NoError(t, err) is(value, 2) value, err = otto1.Run(`abc += 4; abc;`) - is(err, nil) + require.NoError(t, err) is(value, 5) } @@ -1279,15 +1292,15 @@ func TestOttoCall_clone(t *testing.T) { return abc; } `) - is(err, nil) + require.NoError(t, err) vm2 := vm1.clone() value, err := vm2.Run(`def(1)`) - is(err, nil) + require.NoError(t, err) is(value, 2) value, err = vm1.Run(`def(4)`) - is(err, nil) + require.NoError(t, err) is(value, 5) } @@ -1305,15 +1318,15 @@ func TestOttoCall_clone(t *testing.T) { abc: abc }; `) - is(err, nil) + require.NoError(t, err) otto2 := vm1.clone() value, err := otto2.Run(`def.abc.jkl(1)`) - is(err, nil) + require.NoError(t, err) is(value, 2) value, err = vm1.Run(`def.abc.jkl(4)`) - is(err, nil) + require.NoError(t, err) is(value, 5) } @@ -1323,30 +1336,30 @@ func TestOttoCall_clone(t *testing.T) { var abc = function() { return "abc"; }; var def = function() { return "def"; }; `) - is(err, nil) + require.NoError(t, err) vm2 := vm1.clone() value, err := vm2.Run(` [ abc.toString(), def.toString() ]; `) - is(err, nil) + require.NoError(t, err) is(value, `function() { return "abc"; },function() { return "def"; }`) _, err = vm2.Run(` var def = function() { return "ghi"; }; `) - is(err, nil) + require.NoError(t, err) value, err = vm1.Run(` [ abc.toString(), def.toString() ]; `) - is(err, nil) + require.NoError(t, err) is(value, `function() { return "abc"; },function() { return "def"; }`) value, err = vm2.Run(` [ abc.toString(), def.toString() ]; `) - is(err, nil) + require.NoError(t, err) is(value, `function() { return "abc"; },function() { return "ghi"; }`) } }) @@ -1357,57 +1370,57 @@ func TestOttoRun(t *testing.T) { vm := New() program, err := parser.ParseFile(nil, "", "", 0) - is(err, nil) + require.NoError(t, err) value, err := vm.Run(program) - is(err, nil) + require.NoError(t, err) is(value, UndefinedValue()) program, err = parser.ParseFile(nil, "", "2 + 2", 0) - is(err, nil) + require.NoError(t, err) value, err = vm.Run(program) - is(err, nil) + require.NoError(t, err) is(value, 4) value, err = vm.Run(program) - is(err, nil) + require.NoError(t, err) is(value, 4) program, err = parser.ParseFile(nil, "", "var abc; if (!abc) abc = 0; abc += 2; abc;", 0) - is(err, nil) + require.NoError(t, err) value, err = vm.Run(program) - is(err, nil) + require.NoError(t, err) is(value, 2) value, err = vm.Run(program) - is(err, nil) + require.NoError(t, err) is(value, 4) value, err = vm.Run(program) - is(err, nil) + require.NoError(t, err) is(value, 6) { src := []byte("var abc; if (!abc) abc = 0; abc += 2; abc;") value, err = vm.Run(src) - is(err, nil) + require.NoError(t, err) is(value, 8) value, err = vm.Run(bytes.NewBuffer(src)) - is(err, nil) + require.NoError(t, err) is(value, 10) value, err = vm.Run(io.Reader(bytes.NewBuffer(src))) - is(err, nil) + require.NoError(t, err) is(value, 12) } { script, err := vm.Compile("", `var abc; if (!abc) abc = 0; abc += 2; abc;`) - is(err, nil) + require.NoError(t, err) value, err = vm.Run(script) - is(err, nil) + require.NoError(t, err) is(value, 14) value, err = vm.Run(script) - is(err, nil) + require.NoError(t, err) is(value, 16) is(script.String(), "// \nvar abc; if (!abc) abc = 0; abc += 2; abc;") @@ -1418,19 +1431,14 @@ func TestOttoRun(t *testing.T) { // This generates functions to be used by the test below. The arguments are // `src`, which is something that otto can execute, and `expected`, which is // what the result of executing `src` should be. -func makeTestOttoEvalFunction(src, expected interface{}) func(c FunctionCall) Value { +func makeTestOttoEvalFunction(t *testing.T, src, expected interface{}) func(c FunctionCall) Value { + t.Helper() return func(c FunctionCall) Value { v, err := c.Otto.Eval(src) - is(err, nil) - if err != nil { - panic(err) - } + require.NoError(t, err) i, err := v.Export() - is(err, nil) - if err != nil { - panic(err) - } + require.NoError(t, err) is(i, expected) @@ -1442,13 +1450,20 @@ func TestOttoEval(t *testing.T) { tt(t, func() { vm := New() - vm.Set("x1", makeTestOttoEvalFunction(`a`, 1)) - vm.Set("y1", makeTestOttoEvalFunction(`b`, "hello")) - vm.Set("z1", makeTestOttoEvalFunction(`c`, true)) - vm.Set("w", makeTestOttoEvalFunction(`a = 2; b = 'what'; c = false; null`, nil)) - vm.Set("x2", makeTestOttoEvalFunction(`a`, 2)) - vm.Set("y2", makeTestOttoEvalFunction(`b`, "what")) - vm.Set("z2", makeTestOttoEvalFunction(`c`, false)) + err := vm.Set("x1", makeTestOttoEvalFunction(t, `a`, 1)) + require.NoError(t, err) + err = vm.Set("y1", makeTestOttoEvalFunction(t, `b`, "hello")) + require.NoError(t, err) + err = vm.Set("z1", makeTestOttoEvalFunction(t, `c`, true)) + require.NoError(t, err) + err = vm.Set("w", makeTestOttoEvalFunction(t, `a = 2; b = 'what'; c = false; null`, nil)) + require.NoError(t, err) + err = vm.Set("x2", makeTestOttoEvalFunction(t, `a`, 2)) + require.NoError(t, err) + err = vm.Set("y2", makeTestOttoEvalFunction(t, `b`, "what")) + require.NoError(t, err) + err = vm.Set("z2", makeTestOttoEvalFunction(t, `c`, false)) + require.NoError(t, err) // note that these variables are defined in the scope of function `t`, // so would not usually be available to the functions called below. @@ -1459,7 +1474,7 @@ func TestOttoEval(t *testing.T) { // technically valid, but completely insane. // // makes for a good test case though. - _, err := vm.Run(`(function t() { + _, err = vm.Run(`(function t() { var a = 1; var b = 'hello'; var c = true; @@ -1472,8 +1487,7 @@ func TestOttoEval(t *testing.T) { y2(); z2(); }())`) - - is(err, nil) + require.NoError(t, err) }) // this test makes sure that `Eval` doesn't explode if the VM doesn't have @@ -1482,15 +1496,17 @@ func TestOttoEval(t *testing.T) { vm := New() _, err := vm.Eval("null") - is(err, nil) + require.NoError(t, err) - vm.Set("a", 1) - vm.Set("b", 2) + err = vm.Set("a", 1) + require.NoError(t, err) + err = vm.Set("b", 2) + require.NoError(t, err) v, err := vm.Eval("a + b") - is(err, nil) + require.NoError(t, err) r, err := v.Export() - is(err, nil) + require.NoError(t, err) is(r, 3) }) } @@ -1500,7 +1516,7 @@ func TestOttoContext(t *testing.T) { builtins := []string{ "escape", "URIError", - classRegExp, + classRegExpName, "ReferenceError", "parseFloat", "parseInt", @@ -1512,23 +1528,23 @@ func TestOttoContext(t *testing.T) { "isNaN", "unescape", "decodeURI", - classObject, - classFunction, + classObjectName, + classFunctionName, "RangeError", - classError, + classErrorName, "get_context", "eval", - classNumber, + classNumberName, "Math", "NaN", - classDate, - classBoolean, + classDateName, + classBooleanName, "console", "encodeURI", "EvalError", - classArray, + classArrayName, "TypeError", - classString, + classStringName, "isFinite", "undefined", } @@ -1536,7 +1552,7 @@ func TestOttoContext(t *testing.T) { tt(t, func() { vm := New() - vm.Set("get_context", func(c FunctionCall) Value { + err := vm.Set("get_context", func(c FunctionCall) Value { ctx := c.Otto.Context() is(ctx.Callee, "f1") is(ctx.Filename, "") @@ -1562,8 +1578,9 @@ func TestOttoContext(t *testing.T) { return Value{} }) + require.NoError(t, err) - _, err := vm.Run(`(function t() { + _, err = vm.Run(`(function t() { var a = 1; var b = 'hello'; var c = true; @@ -1591,7 +1608,7 @@ func TestOttoContext(t *testing.T) { c = false; }())`) - is(err, nil) + require.NoError(t, err) }) // this test makes sure that `Context` works on global scope by default, if @@ -1599,7 +1616,7 @@ func TestOttoContext(t *testing.T) { tt(t, func() { vm := New() - vm.Set("get_context", func(c FunctionCall) Value { + err := vm.Set("get_context", func(c FunctionCall) Value { ctx := c.Otto.Context() is(ctx.Callee, "") is(ctx.Filename, "") @@ -1612,30 +1629,32 @@ func TestOttoContext(t *testing.T) { return Value{} }) + require.NoError(t, err) - _, err := vm.Run(` + _, err = vm.Run(` var a = 1; get_context() var b = 2; `) - is(err, nil) + require.NoError(t, err) }) // this test makes sure variables are shadowed correctly. tt(t, func() { vm := New() - vm.Set("check_context", func(c FunctionCall) Value { + err := vm.Set("check_context", func(c FunctionCall) Value { n, err := c.Argument(0).ToInteger() - is(err, nil) + require.NoError(t, err) ctx := c.Otto.Context() is(ctx.Symbols["a"], n) return Value{} }) + require.NoError(t, err) - _, err := vm.Run(` + _, err = vm.Run(` var a = 1; check_context(1); (function() { @@ -1650,7 +1669,7 @@ func TestOttoContext(t *testing.T) { }).call(null, 4); check_context(1); `) - is(err, nil) + require.NoError(t, err) }) } @@ -1659,16 +1678,16 @@ func Test_objectLength(t *testing.T) { _, vm := test() value := vm.Set("abc", []string{"jkl", "mno"}) - is(objectLength(value._object()), 2) + is(objectLength(value.object()), 2) value, _ = vm.Run(`[1, 2, 3]`) - is(objectLength(value._object()), 3) + is(objectLength(value.object()), 3) value, _ = vm.Run(`new String("abcdefghi")`) - is(objectLength(value._object()), 9) + is(objectLength(value.object()), 9) value, _ = vm.Run(`"abcdefghi"`) - is(objectLength(value._object()), 0) + is(objectLength(value.object()), 0) }) } @@ -1690,8 +1709,7 @@ func Test_stackLimit(t *testing.T) { _, vm := test() _, err := vm.Run(code) - - is(err == nil, true) + require.NoError(t, err) }) // has error @@ -1701,8 +1719,7 @@ func Test_stackLimit(t *testing.T) { vm.vm.SetStackDepthLimit(2) _, err := vm.Run(code) - - is(err == nil, false) + require.Error(t, err) }) // has error @@ -1712,8 +1729,7 @@ func Test_stackLimit(t *testing.T) { vm.vm.SetStackDepthLimit(5) _, err := vm.Run(code) - - is(err == nil, false) + require.Error(t, err) }) // has no error @@ -1723,8 +1739,7 @@ func Test_stackLimit(t *testing.T) { vm.vm.SetStackDepthLimit(6) _, err := vm.Run(code) - - is(err == nil, true) + require.NoError(t, err) }) // has no error @@ -1735,8 +1750,7 @@ func Test_stackLimit(t *testing.T) { vm.vm.SetStackDepthLimit(0) _, err := vm.Run(code) - - is(err == nil, true) + require.NoError(t, err) }) } @@ -1764,8 +1778,7 @@ func TestOttoInterrupt(t *testing.T) { go func() { defer func() { if caught := recover(); caught != nil { - if caught == halt { - fmt.Println(caught) + if caught == halt { //nolint: errorlint ec <- nil return } diff --git a/parser/comments_test.go b/parser/comments_test.go index d1f57ed8..a97c17e2 100644 --- a/parser/comments_test.go +++ b/parser/comments_test.go @@ -22,10 +22,10 @@ func checkComments(actual []*ast.Comment, expected []string, position ast.Commen for i, v := range comments { if v.Text != expected[i] { - return fmt.Errorf("comments do not match. \"%v\" != \"%v\"\n", v.Text, expected[i]) + return fmt.Errorf("comments do not match: %q != %q", v.Text, expected[i]) } if v.Position != position { - return fmt.Errorf("the comment is not %v, was %v\n", position, v.Position) + return fmt.Errorf("comment positions do not match: %d != %d", position, v.Position) } } @@ -33,11 +33,11 @@ func checkComments(actual []*ast.Comment, expected []string, position ast.Commen } func displayComments(m ast.CommentMap) { - fmt.Printf("Displaying comments:\n") + fmt.Printf("Displaying comments:\n") //nolint: forbidigo for n, comments := range m { - fmt.Printf("%v %v:\n", reflect.TypeOf(n), n) + fmt.Printf("%v %v:\n", reflect.TypeOf(n), n) //nolint: forbidigo for i, comment := range comments { - fmt.Printf(" [%v] %v @ %v\n", i, comment.Text, comment.Position) + fmt.Printf(" [%v] %v @ %v\n", i, comment.Text, comment.Position) //nolint: forbidigo } } } @@ -49,7 +49,7 @@ func TestParser_comments(t *testing.T) { is(firstErr(err), chk) // Check unresolved comments - //is(len(parser.comments), 0) + return parser, program } @@ -1436,7 +1436,7 @@ func TestParser_comments2(t *testing.T) { a = /*comment1*/new /*comment2*/ obj/*comment3*/() `, nil) n := program.Body[0] - fmt.Printf("FOUND NODE: %v, number of comments: %v\n", reflect.TypeOf(n), len(parser.comments.CommentMap[n])) + fmt.Printf("FOUND NODE: %v, number of comments: %v\n", reflect.TypeOf(n), len(parser.comments.CommentMap[n])) //nolint: forbidigo displayComments(parser.comments.CommentMap) }) } diff --git a/parser/error.go b/parser/error.go index 3fb58388..cae121bf 100644 --- a/parser/error.go +++ b/parser/error.go @@ -9,8 +9,8 @@ import ( ) const ( - err_UnexpectedToken = "Unexpected token %v" - err_UnexpectedEndOfInput = "Unexpected end of input" + errUnexpectedToken = "Unexpected token %v" + errUnexpectedEndOfInput = "Unexpected end of input" ) // UnexpectedNumber: 'Unexpected number', @@ -20,7 +20,7 @@ const ( // NewlineAfterThrow: 'Illegal newline after throw', // InvalidRegExp: 'Invalid regular expression', // UnterminatedRegExp: 'Invalid regular expression: missing /', -// InvalidLHSInAssignment: 'Invalid left-hand side in assignment', +// 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', @@ -55,27 +55,27 @@ type Error struct { // FIXME Should this be "SyntaxError"? -func (self Error) Error() string { - filename := self.Position.Filename +func (e Error) Error() string { + filename := e.Position.Filename if filename == "" { filename = "(anonymous)" } return fmt.Sprintf("%s: Line %d:%d %s", filename, - self.Position.Line, - self.Position.Column, - self.Message, + e.Position.Line, + e.Position.Column, + e.Message, ) } -func (self *_parser) error(place interface{}, msg string, msgValues ...interface{}) *Error { +func (p *_parser) error(place interface{}, msg string, msgValues ...interface{}) { var idx file.Idx switch place := place.(type) { case int: - idx = self.idxOf(place) + idx = p.idxOf(place) case file.Idx: if place == 0 { - idx = self.idxOf(self.chrOffset) + idx = p.idxOf(p.chrOffset) } else { idx = place } @@ -83,57 +83,69 @@ func (self *_parser) error(place interface{}, msg string, msgValues ...interface panic(fmt.Errorf("error(%T, ...)", place)) } - position := self.position(idx) + position := p.position(idx) msg = fmt.Sprintf(msg, msgValues...) - self.errors.Add(position, msg) - return self.errors[len(self.errors)-1] + p.errors.Add(position, msg) } -func (self *_parser) errorUnexpected(idx file.Idx, chr rune) error { +func (p *_parser) errorUnexpected(idx file.Idx, chr rune) { if chr == -1 { - return self.error(idx, err_UnexpectedEndOfInput) + p.error(idx, errUnexpectedEndOfInput) + return } - return self.error(idx, err_UnexpectedToken, token.ILLEGAL) + p.error(idx, errUnexpectedToken, token.ILLEGAL) } -func (self *_parser) errorUnexpectedToken(tkn token.Token) error { - switch tkn { - case token.EOF: - return self.error(file.Idx(0), err_UnexpectedEndOfInput) +func (p *_parser) errorUnexpectedToken(tkn token.Token) { + if tkn == token.EOF { + p.error(file.Idx(0), errUnexpectedEndOfInput) + return } value := tkn.String() switch tkn { case token.BOOLEAN, token.NULL: - value = self.literal + p.error(p.idx, errUnexpectedToken, p.literal) case token.IDENTIFIER: - return self.error(self.idx, "Unexpected identifier") + p.error(p.idx, "Unexpected identifier") case token.KEYWORD: // TODO Might be a future reserved word - return self.error(self.idx, "Unexpected reserved word") + p.error(p.idx, "Unexpected reserved word") case token.NUMBER: - return self.error(self.idx, "Unexpected number") + p.error(p.idx, "Unexpected number") case token.STRING: - return self.error(self.idx, "Unexpected string") + p.error(p.idx, "Unexpected string") + default: + p.error(p.idx, errUnexpectedToken, value) } - return self.error(self.idx, err_UnexpectedToken, value) } // ErrorList is a list of *Errors. type ErrorList []*Error //nolint: errname // 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}) +func (el *ErrorList) Add(position file.Position, msg string) { + *el = append(*el, &Error{position, msg}) } // Reset resets an ErrorList to no errors. -func (self *ErrorList) Reset() { *self = (*self)[0:0] } +func (el *ErrorList) Reset() { + *el = (*el)[0:0] +} + +// Len implement sort.Interface. +func (el *ErrorList) Len() int { + return len(*el) +} + +// Swap implement sort.Interface. +func (el *ErrorList) Swap(i, j int) { + (*el)[i], (*el)[j] = (*el)[j], (*el)[i] +} -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 +// Less implement sort.Interface. +func (el *ErrorList) Less(i, j int) bool { + x := (*el)[i].Position + y := (*el)[j].Position if x.Filename < y.Filename { return true } @@ -148,26 +160,28 @@ func (self ErrorList) Less(i, j int) bool { return false } -func (self ErrorList) Sort() { - sort.Sort(self) +// Sort sorts el. +func (el *ErrorList) Sort() { + sort.Sort(el) } // Error implements the Error interface. -func (self ErrorList) Error() string { - switch len(self) { +func (el *ErrorList) Error() string { + switch len(*el) { case 0: return "no errors" case 1: - return self[0].Error() + return (*el)[0].Error() + default: + return fmt.Sprintf("%s (and %d more errors)", (*el)[0].Error(), len(*el)-1) } - 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 { +func (el *ErrorList) Err() error { + if len(*el) == 0 { return nil } - return self + return el } diff --git a/parser/expression.go b/parser/expression.go index bbfd498d..9703f492 100644 --- a/parser/expression.go +++ b/parser/expression.go @@ -8,36 +8,36 @@ import ( "github.com/robertkrimen/otto/token" ) -func (self *_parser) parseIdentifier() *ast.Identifier { - literal := self.literal - idx := self.idx - if self.mode&StoreComments != 0 { - self.comments.MarkComments(ast.LEADING) +func (p *_parser) parseIdentifier() *ast.Identifier { + literal := p.literal + idx := p.idx + if p.mode&StoreComments != 0 { + p.comments.MarkComments(ast.LEADING) } - self.next() + p.next() exp := &ast.Identifier{ Name: literal, Idx: idx, } - if self.mode&StoreComments != 0 { - self.comments.SetExpression(exp) + if p.mode&StoreComments != 0 { + p.comments.SetExpression(exp) } return exp } -func (self *_parser) parsePrimaryExpression() ast.Expression { - literal := self.literal - idx := self.idx - switch self.token { +func (p *_parser) parsePrimaryExpression() ast.Expression { + literal := p.literal + idx := p.idx + switch p.token { case token.IDENTIFIER: - self.next() + p.next() if len(literal) > 1 { tkn, strict := token.IsKeyword(literal) if tkn == token.KEYWORD { if !strict { - self.error(idx, "Unexpected reserved word") + p.error(idx, "Unexpected reserved word") } } } @@ -46,13 +46,13 @@ func (self *_parser) parsePrimaryExpression() ast.Expression { Idx: idx, } case token.NULL: - self.next() + p.next() return &ast.NullLiteral{ Idx: idx, Literal: literal, } case token.BOOLEAN: - self.next() + p.next() value := false switch literal { case "true": @@ -60,7 +60,7 @@ func (self *_parser) parsePrimaryExpression() ast.Expression { case "false": value = false default: - self.error(idx, "Illegal boolean literal") + p.error(idx, "Illegal boolean literal") } return &ast.BooleanLiteral{ Idx: idx, @@ -68,10 +68,10 @@ func (self *_parser) parsePrimaryExpression() ast.Expression { Value: value, } case token.STRING: - self.next() + p.next() value, err := parseStringLiteral(literal[1 : len(literal)-1]) if err != nil { - self.error(idx, err.Error()) + p.error(idx, err.Error()) } return &ast.StringLiteral{ Idx: idx, @@ -79,10 +79,10 @@ func (self *_parser) parsePrimaryExpression() ast.Expression { Value: value, } case token.NUMBER: - self.next() + p.next() value, err := parseNumberLiteral(literal) if err != nil { - self.error(idx, err.Error()) + p.error(idx, err.Error()) value = 0 } return &ast.NumberLiteral{ @@ -91,77 +91,75 @@ func (self *_parser) parsePrimaryExpression() ast.Expression { Value: value, } case token.SLASH, token.QUOTIENT_ASSIGN: - return self.parseRegExpLiteral() + return p.parseRegExpLiteral() case token.LEFT_BRACE: - return self.parseObjectLiteral() + return p.parseObjectLiteral() case token.LEFT_BRACKET: - return self.parseArrayLiteral() + return p.parseArrayLiteral() case token.LEFT_PARENTHESIS: - self.expect(token.LEFT_PARENTHESIS) - expression := self.parseExpression() - if self.mode&StoreComments != 0 { - self.comments.Unset() + p.expect(token.LEFT_PARENTHESIS) + expression := p.parseExpression() + if p.mode&StoreComments != 0 { + p.comments.Unset() } - self.expect(token.RIGHT_PARENTHESIS) + p.expect(token.RIGHT_PARENTHESIS) return expression case token.THIS: - self.next() + p.next() return &ast.ThisExpression{ Idx: idx, } case token.FUNCTION: - return self.parseFunction(false) + return p.parseFunction(false) } - self.errorUnexpectedToken(self.token) - self.nextStatement() - return &ast.BadExpression{From: idx, To: self.idx} + p.errorUnexpectedToken(p.token) + p.nextStatement() + return &ast.BadExpression{From: idx, To: p.idx} } -func (self *_parser) parseRegExpLiteral() *ast.RegExpLiteral { - offset := self.chrOffset - 1 // Opening slash already gotten - if self.token == token.QUOTIENT_ASSIGN { - offset -= 1 // = +func (p *_parser) parseRegExpLiteral() *ast.RegExpLiteral { + offset := p.chrOffset - 1 // Opening slash already gotten + if p.token == token.QUOTIENT_ASSIGN { + offset-- // = } - idx := self.idxOf(offset) + idx := p.idxOf(offset) - pattern, err := self.scanString(offset) - endOffset := self.chrOffset + pattern, err := p.scanString(offset) + endOffset := p.chrOffset - self.next() + p.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 + if p.token == token.IDENTIFIER { // gim + flags = p.literal + p.next() + endOffset = p.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) + // Test during parsing that this is a valid regular expression + // Sorry, (?=) and (?!) are invalid (for now) + pat, err := TransformRegExp(pattern) + if err != nil { + if pat == "" || p.mode&IgnoreRegExpErrors == 0 { + p.error(idx, "Invalid regular expression: %s", err.Error()) + } + } else { + _, err = regexp.Compile(pat) if err != nil { - if pattern == "" || self.mode&IgnoreRegExpErrors == 0 { - self.error(idx, "Invalid regular expression: %s", err.Error()) - } + // We should not get here, ParseRegExp should catch any errors + p.error(idx, "Invalid regular expression: %s", err.Error()[22:]) // Skip redundant "parse regexp 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 - } + value = pat } } - literal := self.str[offset:endOffset] + literal := p.str[offset:endOffset] return &ast.RegExpLiteral{ Idx: idx, @@ -172,73 +170,73 @@ func (self *_parser) parseRegExpLiteral() *ast.RegExpLiteral { } } -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} +func (p *_parser) parseVariableDeclaration(declarationList *[]*ast.VariableExpression) ast.Expression { + if p.token != token.IDENTIFIER { + idx := p.expect(token.IDENTIFIER) + p.nextStatement() + return &ast.BadExpression{From: idx, To: p.idx} } - literal := self.literal - idx := self.idx - self.next() + literal := p.literal + idx := p.idx + p.next() node := &ast.VariableExpression{ Name: literal, Idx: idx, } - if self.mode&StoreComments != 0 { - self.comments.SetExpression(node) + if p.mode&StoreComments != 0 { + p.comments.SetExpression(node) } if declarationList != nil { *declarationList = append(*declarationList, node) } - if self.token == token.ASSIGN { - if self.mode&StoreComments != 0 { - self.comments.Unset() + if p.token == token.ASSIGN { + if p.mode&StoreComments != 0 { + p.comments.Unset() } - self.next() - node.Initializer = self.parseAssignmentExpression() + p.next() + node.Initializer = p.parseAssignmentExpression() } return node } -func (self *_parser) parseVariableDeclarationList(var_ file.Idx) []ast.Expression { +func (p *_parser) parseVariableDeclarationList(idx file.Idx) []ast.Expression { var declarationList []*ast.VariableExpression // Avoid bad expressions var list []ast.Expression for { - if self.mode&StoreComments != 0 { - self.comments.MarkComments(ast.LEADING) + if p.mode&StoreComments != 0 { + p.comments.MarkComments(ast.LEADING) } - decl := self.parseVariableDeclaration(&declarationList) + decl := p.parseVariableDeclaration(&declarationList) list = append(list, decl) - if self.token != token.COMMA { + if p.token != token.COMMA { break } - if self.mode&StoreComments != 0 { - self.comments.Unset() + if p.mode&StoreComments != 0 { + p.comments.Unset() } - self.next() + p.next() } - self.scope.declare(&ast.VariableDeclaration{ - Var: var_, + p.scope.declare(&ast.VariableDeclaration{ + Var: idx, List: declarationList, }) return list } -func (self *_parser) parseObjectPropertyKey() (string, string) { - idx, tkn, literal := self.idx, self.token, self.literal +func (p *_parser) parseObjectPropertyKey() (string, string) { + idx, tkn, literal := p.idx, p.token, p.literal value := "" - if self.mode&StoreComments != 0 { - self.comments.MarkComments(ast.KEY) + if p.mode&StoreComments != 0 { + p.comments.MarkComments(ast.KEY) } - self.next() + p.next() switch tkn { case token.IDENTIFIER: @@ -247,7 +245,7 @@ func (self *_parser) parseObjectPropertyKey() (string, string) { var err error _, err = parseNumberLiteral(literal) if err != nil { - self.error(idx, err.Error()) + p.error(idx, err.Error()) } else { value = literal } @@ -255,7 +253,7 @@ func (self *_parser) parseObjectPropertyKey() (string, string) { var err error value, err = parseStringLiteral(literal[1 : len(literal)-1]) if err != nil { - self.error(idx, err.Error()) + p.error(idx, err.Error()) } default: // null, false, class, etc. @@ -266,33 +264,33 @@ func (self *_parser) parseObjectPropertyKey() (string, string) { 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() +func (p *_parser) parseObjectProperty() ast.Property { + literal, value := p.parseObjectPropertyKey() + if literal == "get" && p.token != token.COLON { + idx := p.idx + _, value := p.parseObjectPropertyKey() + parameterList := p.parseFunctionParameterList() node := &ast.FunctionLiteral{ Function: idx, ParameterList: parameterList, } - self.parseFunctionBlock(node) + p.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() + } else if literal == "set" && p.token != token.COLON { + idx := p.idx + _, value := p.parseObjectPropertyKey() + parameterList := p.parseFunctionParameterList() node := &ast.FunctionLiteral{ Function: idx, ParameterList: parameterList, } - self.parseFunctionBlock(node) + p.parseFunctionBlock(node) return ast.Property{ Key: value, Kind: "set", @@ -300,40 +298,40 @@ func (self *_parser) parseObjectProperty() ast.Property { } } - if self.mode&StoreComments != 0 { - self.comments.MarkComments(ast.COLON) + if p.mode&StoreComments != 0 { + p.comments.MarkComments(ast.COLON) } - self.expect(token.COLON) + p.expect(token.COLON) exp := ast.Property{ Key: value, Kind: "value", - Value: self.parseAssignmentExpression(), + Value: p.parseAssignmentExpression(), } - if self.mode&StoreComments != 0 { - self.comments.SetExpression(exp.Value) + if p.mode&StoreComments != 0 { + p.comments.SetExpression(exp.Value) } return exp } -func (self *_parser) parseObjectLiteral() ast.Expression { +func (p *_parser) parseObjectLiteral() ast.Expression { var value []ast.Property - idx0 := self.expect(token.LEFT_BRACE) - for self.token != token.RIGHT_BRACE && self.token != token.EOF { - value = append(value, self.parseObjectProperty()) - if self.token == token.COMMA { - if self.mode&StoreComments != 0 { - self.comments.Unset() + idx0 := p.expect(token.LEFT_BRACE) + for p.token != token.RIGHT_BRACE && p.token != token.EOF { + value = append(value, p.parseObjectProperty()) + if p.token == token.COMMA { + if p.mode&StoreComments != 0 { + p.comments.Unset() } - self.next() + p.next() continue } } - if self.mode&StoreComments != 0 { - self.comments.MarkComments(ast.FINAL) + if p.mode&StoreComments != 0 { + p.comments.MarkComments(ast.FINAL) } - idx1 := self.expect(token.RIGHT_BRACE) + idx1 := p.expect(token.RIGHT_BRACE) return &ast.ObjectLiteral{ LeftBrace: idx0, @@ -342,37 +340,37 @@ func (self *_parser) parseObjectLiteral() ast.Expression { } } -func (self *_parser) parseArrayLiteral() ast.Expression { - idx0 := self.expect(token.LEFT_BRACKET) +func (p *_parser) parseArrayLiteral() ast.Expression { + idx0 := p.expect(token.LEFT_BRACKET) var value []ast.Expression - for self.token != token.RIGHT_BRACKET && self.token != token.EOF { - if self.token == token.COMMA { + for p.token != token.RIGHT_BRACKET && p.token != token.EOF { + if p.token == token.COMMA { // This kind of comment requires a special empty expression node. - empty := &ast.EmptyExpression{Begin: self.idx, End: self.idx} + empty := &ast.EmptyExpression{Begin: p.idx, End: p.idx} - if self.mode&StoreComments != 0 { - self.comments.SetExpression(empty) - self.comments.Unset() + if p.mode&StoreComments != 0 { + p.comments.SetExpression(empty) + p.comments.Unset() } value = append(value, empty) - self.next() + p.next() continue } - exp := self.parseAssignmentExpression() + exp := p.parseAssignmentExpression() value = append(value, exp) - if self.token != token.RIGHT_BRACKET { - if self.mode&StoreComments != 0 { - self.comments.Unset() + if p.token != token.RIGHT_BRACKET { + if p.mode&StoreComments != 0 { + p.comments.Unset() } - self.expect(token.COMMA) + p.expect(token.COMMA) } } - if self.mode&StoreComments != 0 { - self.comments.MarkComments(ast.FINAL) + if p.mode&StoreComments != 0 { + p.comments.MarkComments(ast.FINAL) } - idx1 := self.expect(token.RIGHT_BRACKET) + idx1 := p.expect(token.RIGHT_BRACKET) return &ast.ArrayLiteral{ LeftBracket: idx0, @@ -381,36 +379,36 @@ func (self *_parser) parseArrayLiteral() ast.Expression { } } -func (self *_parser) parseArgumentList() (argumentList []ast.Expression, idx0, idx1 file.Idx) { - if self.mode&StoreComments != 0 { - self.comments.Unset() +func (p *_parser) parseArgumentList() (argumentList []ast.Expression, idx0, idx1 file.Idx) { //nolint: nonamedreturns + if p.mode&StoreComments != 0 { + p.comments.Unset() } - idx0 = self.expect(token.LEFT_PARENTHESIS) - if self.token != token.RIGHT_PARENTHESIS { + idx0 = p.expect(token.LEFT_PARENTHESIS) + if p.token != token.RIGHT_PARENTHESIS { for { - exp := self.parseAssignmentExpression() - if self.mode&StoreComments != 0 { - self.comments.SetExpression(exp) + exp := p.parseAssignmentExpression() + if p.mode&StoreComments != 0 { + p.comments.SetExpression(exp) } argumentList = append(argumentList, exp) - if self.token != token.COMMA { + if p.token != token.COMMA { break } - if self.mode&StoreComments != 0 { - self.comments.Unset() + if p.mode&StoreComments != 0 { + p.comments.Unset() } - self.next() + p.next() } } - if self.mode&StoreComments != 0 { - self.comments.Unset() + if p.mode&StoreComments != 0 { + p.comments.Unset() } - idx1 = self.expect(token.RIGHT_PARENTHESIS) + idx1 = p.expect(token.RIGHT_PARENTHESIS) return } -func (self *_parser) parseCallExpression(left ast.Expression) ast.Expression { - argumentList, idx0, idx1 := self.parseArgumentList() +func (p *_parser) parseCallExpression(left ast.Expression) ast.Expression { + argumentList, idx0, idx1 := p.parseArgumentList() exp := &ast.CallExpression{ Callee: left, LeftParenthesis: idx0, @@ -418,25 +416,25 @@ func (self *_parser) parseCallExpression(left ast.Expression) ast.Expression { RightParenthesis: idx1, } - if self.mode&StoreComments != 0 { - self.comments.SetExpression(exp) + if p.mode&StoreComments != 0 { + p.comments.SetExpression(exp) } return exp } -func (self *_parser) parseDotMember(left ast.Expression) ast.Expression { - period := self.expect(token.PERIOD) +func (p *_parser) parseDotMember(left ast.Expression) ast.Expression { + period := p.expect(token.PERIOD) - literal := self.literal - idx := self.idx + literal := p.literal + idx := p.idx if !matchIdentifier.MatchString(literal) { - self.expect(token.IDENTIFIER) - self.nextStatement() - return &ast.BadExpression{From: period, To: self.idx} + p.expect(token.IDENTIFIER) + p.nextStatement() + return &ast.BadExpression{From: period, To: p.idx} } - self.next() + p.next() return &ast.DotExpression{ Left: left, @@ -447,10 +445,10 @@ func (self *_parser) parseDotMember(left ast.Expression) ast.Expression { } } -func (self *_parser) parseBracketMember(left ast.Expression) ast.Expression { - idx0 := self.expect(token.LEFT_BRACKET) - member := self.parseExpression() - idx1 := self.expect(token.RIGHT_BRACKET) +func (p *_parser) parseBracketMember(left ast.Expression) ast.Expression { + idx0 := p.expect(token.LEFT_BRACKET) + member := p.parseExpression() + idx1 := p.expect(token.RIGHT_BRACKET) return &ast.BracketExpression{ LeftBracket: idx0, Left: left, @@ -459,123 +457,121 @@ func (self *_parser) parseBracketMember(left ast.Expression) ast.Expression { } } -func (self *_parser) parseNewExpression() ast.Expression { - idx := self.expect(token.NEW) - callee := self.parseLeftHandSideExpression() +func (p *_parser) parseNewExpression() ast.Expression { + idx := p.expect(token.NEW) + callee := p.parseLeftHandSideExpression() node := &ast.NewExpression{ New: idx, Callee: callee, } - if self.token == token.LEFT_PARENTHESIS { - argumentList, idx0, idx1 := self.parseArgumentList() + if p.token == token.LEFT_PARENTHESIS { + argumentList, idx0, idx1 := p.parseArgumentList() node.ArgumentList = argumentList node.LeftParenthesis = idx0 node.RightParenthesis = idx1 } - if self.mode&StoreComments != 0 { - self.comments.SetExpression(node) + if p.mode&StoreComments != 0 { + p.comments.SetExpression(node) } return node } -func (self *_parser) parseLeftHandSideExpression() ast.Expression { +func (p *_parser) parseLeftHandSideExpression() ast.Expression { var left ast.Expression - if self.token == token.NEW { - left = self.parseNewExpression() + if p.token == token.NEW { + left = p.parseNewExpression() } else { - if self.mode&StoreComments != 0 { - self.comments.MarkComments(ast.LEADING) - self.comments.MarkPrimary() + if p.mode&StoreComments != 0 { + p.comments.MarkComments(ast.LEADING) + p.comments.MarkPrimary() } - left = self.parsePrimaryExpression() + left = p.parsePrimaryExpression() } - if self.mode&StoreComments != 0 { - self.comments.SetExpression(left) + if p.mode&StoreComments != 0 { + p.comments.SetExpression(left) } for { - if self.token == token.PERIOD { - left = self.parseDotMember(left) - } else if self.token == token.LEFT_BRACKET { - left = self.parseBracketMember(left) - } else { - break + switch p.token { + case token.PERIOD: + left = p.parseDotMember(left) + case token.LEFT_BRACKET: + left = p.parseBracketMember(left) + default: + return left } } - - return left } -func (self *_parser) parseLeftHandSideExpressionAllowCall() ast.Expression { - allowIn := self.scope.allowIn - self.scope.allowIn = true +func (p *_parser) parseLeftHandSideExpressionAllowCall() ast.Expression { + allowIn := p.scope.allowIn + p.scope.allowIn = true defer func() { - self.scope.allowIn = allowIn + p.scope.allowIn = allowIn }() var left ast.Expression - if self.token == token.NEW { + if p.token == token.NEW { var newComments []*ast.Comment - if self.mode&StoreComments != 0 { - newComments = self.comments.FetchAll() - self.comments.MarkComments(ast.LEADING) - self.comments.MarkPrimary() + if p.mode&StoreComments != 0 { + newComments = p.comments.FetchAll() + p.comments.MarkComments(ast.LEADING) + p.comments.MarkPrimary() } - left = self.parseNewExpression() - if self.mode&StoreComments != 0 { - self.comments.CommentMap.AddComments(left, newComments, ast.LEADING) + left = p.parseNewExpression() + if p.mode&StoreComments != 0 { + p.comments.CommentMap.AddComments(left, newComments, ast.LEADING) } } else { - if self.mode&StoreComments != 0 { - self.comments.MarkComments(ast.LEADING) - self.comments.MarkPrimary() + if p.mode&StoreComments != 0 { + p.comments.MarkComments(ast.LEADING) + p.comments.MarkPrimary() } - left = self.parsePrimaryExpression() + left = p.parsePrimaryExpression() } - if self.mode&StoreComments != 0 { - self.comments.SetExpression(left) + if p.mode&StoreComments != 0 { + p.comments.SetExpression(left) } 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 + switch p.token { + case token.PERIOD: + left = p.parseDotMember(left) + case token.LEFT_BRACKET: + left = p.parseBracketMember(left) + case token.LEFT_PARENTHESIS: + left = p.parseCallExpression(left) + default: + return left } } - - return left } -func (self *_parser) parsePostfixExpression() ast.Expression { - operand := self.parseLeftHandSideExpressionAllowCall() +func (p *_parser) parsePostfixExpression() ast.Expression { + operand := p.parseLeftHandSideExpressionAllowCall() - switch self.token { + switch p.token { case token.INCREMENT, token.DECREMENT: // Make sure there is no line terminator here - if self.implicitSemicolon { + if p.implicitSemicolon { break } - tkn := self.token - idx := self.idx - if self.mode&StoreComments != 0 { - self.comments.Unset() + tkn := p.token + idx := p.idx + if p.mode&StoreComments != 0 { + p.comments.Unset() } - self.next() + p.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} + p.error(idx, "invalid left-hand side in assignment") + p.nextStatement() + return &ast.BadExpression{From: idx, To: p.idx} } exp := &ast.UnaryExpression{ Operator: tkn, @@ -584,8 +580,8 @@ func (self *_parser) parsePostfixExpression() ast.Expression { Postfix: true, } - if self.mode&StoreComments != 0 { - self.comments.SetExpression(exp) + if p.mode&StoreComments != 0 { + p.comments.SetExpression(exp) } return exp @@ -594,37 +590,37 @@ func (self *_parser) parsePostfixExpression() ast.Expression { return operand } -func (self *_parser) parseUnaryExpression() ast.Expression { - switch self.token { +func (p *_parser) parseUnaryExpression() ast.Expression { + switch p.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 - if self.mode&StoreComments != 0 { - self.comments.Unset() + tkn := p.token + idx := p.idx + if p.mode&StoreComments != 0 { + p.comments.Unset() } - self.next() + p.next() return &ast.UnaryExpression{ Operator: tkn, Idx: idx, - Operand: self.parseUnaryExpression(), + Operand: p.parseUnaryExpression(), } case token.INCREMENT, token.DECREMENT: - tkn := self.token - idx := self.idx - if self.mode&StoreComments != 0 { - self.comments.Unset() + tkn := p.token + idx := p.idx + if p.mode&StoreComments != 0 { + p.comments.Unset() } - self.next() - operand := self.parseUnaryExpression() + p.next() + operand := p.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} + p.error(idx, "invalid left-hand side in assignment") + p.nextStatement() + return &ast.BadExpression{From: idx, To: p.idx} } return &ast.UnaryExpression{ Operator: tkn, @@ -633,20 +629,20 @@ func (self *_parser) parseUnaryExpression() ast.Expression { } } - return self.parsePostfixExpression() + return p.parsePostfixExpression() } -func (self *_parser) parseMultiplicativeExpression() ast.Expression { - next := self.parseUnaryExpression +func (p *_parser) parseMultiplicativeExpression() ast.Expression { + next := p.parseUnaryExpression left := next() - for self.token == token.MULTIPLY || self.token == token.SLASH || - self.token == token.REMAINDER { - tkn := self.token - if self.mode&StoreComments != 0 { - self.comments.Unset() + for p.token == token.MULTIPLY || p.token == token.SLASH || + p.token == token.REMAINDER { + tkn := p.token + if p.mode&StoreComments != 0 { + p.comments.Unset() } - self.next() + p.next() left = &ast.BinaryExpression{ Operator: tkn, @@ -658,16 +654,16 @@ func (self *_parser) parseMultiplicativeExpression() ast.Expression { return left } -func (self *_parser) parseAdditiveExpression() ast.Expression { - next := self.parseMultiplicativeExpression +func (p *_parser) parseAdditiveExpression() ast.Expression { + next := p.parseMultiplicativeExpression left := next() - for self.token == token.PLUS || self.token == token.MINUS { - tkn := self.token - if self.mode&StoreComments != 0 { - self.comments.Unset() + for p.token == token.PLUS || p.token == token.MINUS { + tkn := p.token + if p.mode&StoreComments != 0 { + p.comments.Unset() } - self.next() + p.next() left = &ast.BinaryExpression{ Operator: tkn, @@ -679,17 +675,17 @@ func (self *_parser) parseAdditiveExpression() ast.Expression { return left } -func (self *_parser) parseShiftExpression() ast.Expression { - next := self.parseAdditiveExpression +func (p *_parser) parseShiftExpression() ast.Expression { + next := p.parseAdditiveExpression left := next() - for self.token == token.SHIFT_LEFT || self.token == token.SHIFT_RIGHT || - self.token == token.UNSIGNED_SHIFT_RIGHT { - tkn := self.token - if self.mode&StoreComments != 0 { - self.comments.Unset() + for p.token == token.SHIFT_LEFT || p.token == token.SHIFT_RIGHT || + p.token == token.UNSIGNED_SHIFT_RIGHT { + tkn := p.token + if p.mode&StoreComments != 0 { + p.comments.Unset() } - self.next() + p.next() left = &ast.BinaryExpression{ Operator: tkn, @@ -701,58 +697,58 @@ func (self *_parser) parseShiftExpression() ast.Expression { return left } -func (self *_parser) parseRelationalExpression() ast.Expression { - next := self.parseShiftExpression +func (p *_parser) parseRelationalExpression() ast.Expression { + next := p.parseShiftExpression left := next() - allowIn := self.scope.allowIn - self.scope.allowIn = true + allowIn := p.scope.allowIn + p.scope.allowIn = true defer func() { - self.scope.allowIn = allowIn + p.scope.allowIn = allowIn }() - switch self.token { + switch p.token { case token.LESS, token.LESS_OR_EQUAL, token.GREATER, token.GREATER_OR_EQUAL: - tkn := self.token - if self.mode&StoreComments != 0 { - self.comments.Unset() + tkn := p.token + if p.mode&StoreComments != 0 { + p.comments.Unset() } - self.next() + p.next() exp := &ast.BinaryExpression{ Operator: tkn, Left: left, - Right: self.parseRelationalExpression(), + Right: p.parseRelationalExpression(), Comparison: true, } return exp case token.INSTANCEOF: - tkn := self.token - if self.mode&StoreComments != 0 { - self.comments.Unset() + tkn := p.token + if p.mode&StoreComments != 0 { + p.comments.Unset() } - self.next() + p.next() exp := &ast.BinaryExpression{ Operator: tkn, Left: left, - Right: self.parseRelationalExpression(), + Right: p.parseRelationalExpression(), } return exp case token.IN: if !allowIn { return left } - tkn := self.token - if self.mode&StoreComments != 0 { - self.comments.Unset() + tkn := p.token + if p.mode&StoreComments != 0 { + p.comments.Unset() } - self.next() + p.next() exp := &ast.BinaryExpression{ Operator: tkn, Left: left, - Right: self.parseRelationalExpression(), + Right: p.parseRelationalExpression(), } return exp } @@ -760,17 +756,17 @@ func (self *_parser) parseRelationalExpression() ast.Expression { return left } -func (self *_parser) parseEqualityExpression() ast.Expression { - next := self.parseRelationalExpression +func (p *_parser) parseEqualityExpression() ast.Expression { + next := p.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 - if self.mode&StoreComments != 0 { - self.comments.Unset() + for p.token == token.EQUAL || p.token == token.NOT_EQUAL || + p.token == token.STRICT_EQUAL || p.token == token.STRICT_NOT_EQUAL { + tkn := p.token + if p.mode&StoreComments != 0 { + p.comments.Unset() } - self.next() + p.next() left = &ast.BinaryExpression{ Operator: tkn, @@ -783,16 +779,16 @@ func (self *_parser) parseEqualityExpression() ast.Expression { return left } -func (self *_parser) parseBitwiseAndExpression() ast.Expression { - next := self.parseEqualityExpression +func (p *_parser) parseBitwiseAndExpression() ast.Expression { + next := p.parseEqualityExpression left := next() - for self.token == token.AND { - if self.mode&StoreComments != 0 { - self.comments.Unset() + for p.token == token.AND { + if p.mode&StoreComments != 0 { + p.comments.Unset() } - tkn := self.token - self.next() + tkn := p.token + p.next() left = &ast.BinaryExpression{ Operator: tkn, @@ -804,16 +800,16 @@ func (self *_parser) parseBitwiseAndExpression() ast.Expression { return left } -func (self *_parser) parseBitwiseExclusiveOrExpression() ast.Expression { - next := self.parseBitwiseAndExpression +func (p *_parser) parseBitwiseExclusiveOrExpression() ast.Expression { + next := p.parseBitwiseAndExpression left := next() - for self.token == token.EXCLUSIVE_OR { - if self.mode&StoreComments != 0 { - self.comments.Unset() + for p.token == token.EXCLUSIVE_OR { + if p.mode&StoreComments != 0 { + p.comments.Unset() } - tkn := self.token - self.next() + tkn := p.token + p.next() left = &ast.BinaryExpression{ Operator: tkn, @@ -825,16 +821,16 @@ func (self *_parser) parseBitwiseExclusiveOrExpression() ast.Expression { return left } -func (self *_parser) parseBitwiseOrExpression() ast.Expression { - next := self.parseBitwiseExclusiveOrExpression +func (p *_parser) parseBitwiseOrExpression() ast.Expression { + next := p.parseBitwiseExclusiveOrExpression left := next() - for self.token == token.OR { - if self.mode&StoreComments != 0 { - self.comments.Unset() + for p.token == token.OR { + if p.mode&StoreComments != 0 { + p.comments.Unset() } - tkn := self.token - self.next() + tkn := p.token + p.next() left = &ast.BinaryExpression{ Operator: tkn, @@ -846,16 +842,16 @@ func (self *_parser) parseBitwiseOrExpression() ast.Expression { return left } -func (self *_parser) parseLogicalAndExpression() ast.Expression { - next := self.parseBitwiseOrExpression +func (p *_parser) parseLogicalAndExpression() ast.Expression { + next := p.parseBitwiseOrExpression left := next() - for self.token == token.LOGICAL_AND { - if self.mode&StoreComments != 0 { - self.comments.Unset() + for p.token == token.LOGICAL_AND { + if p.mode&StoreComments != 0 { + p.comments.Unset() } - tkn := self.token - self.next() + tkn := p.token + p.next() left = &ast.BinaryExpression{ Operator: tkn, @@ -867,16 +863,16 @@ func (self *_parser) parseLogicalAndExpression() ast.Expression { return left } -func (self *_parser) parseLogicalOrExpression() ast.Expression { - next := self.parseLogicalAndExpression +func (p *_parser) parseLogicalOrExpression() ast.Expression { + next := p.parseLogicalAndExpression left := next() - for self.token == token.LOGICAL_OR { - if self.mode&StoreComments != 0 { - self.comments.Unset() + for p.token == token.LOGICAL_OR { + if p.mode&StoreComments != 0 { + p.comments.Unset() } - tkn := self.token - self.next() + tkn := p.token + p.next() left = &ast.BinaryExpression{ Operator: tkn, @@ -888,24 +884,24 @@ func (self *_parser) parseLogicalOrExpression() ast.Expression { return left } -func (self *_parser) parseConditionlExpression() ast.Expression { - left := self.parseLogicalOrExpression() +func (p *_parser) parseConditionlExpression() ast.Expression { + left := p.parseLogicalOrExpression() - if self.token == token.QUESTION_MARK { - if self.mode&StoreComments != 0 { - self.comments.Unset() + if p.token == token.QUESTION_MARK { + if p.mode&StoreComments != 0 { + p.comments.Unset() } - self.next() + p.next() - consequent := self.parseAssignmentExpression() - if self.mode&StoreComments != 0 { - self.comments.Unset() + consequent := p.parseAssignmentExpression() + if p.mode&StoreComments != 0 { + p.comments.Unset() } - self.expect(token.COLON) + p.expect(token.COLON) exp := &ast.ConditionalExpression{ Test: left, Consequent: consequent, - Alternate: self.parseAssignmentExpression(), + Alternate: p.parseAssignmentExpression(), } return exp @@ -914,12 +910,12 @@ func (self *_parser) parseConditionlExpression() ast.Expression { return left } -func (self *_parser) parseAssignmentExpression() ast.Expression { - left := self.parseConditionlExpression() +func (p *_parser) parseAssignmentExpression() ast.Expression { + left := p.parseConditionlExpression() var operator token.Token - switch self.token { + switch p.token { case token.ASSIGN: - operator = self.token + operator = p.token case token.ADD_ASSIGN: operator = token.PLUS case token.SUBTRACT_ASSIGN: @@ -947,27 +943,27 @@ func (self *_parser) parseAssignmentExpression() ast.Expression { } if operator != 0 { - idx := self.idx - if self.mode&StoreComments != 0 { - self.comments.Unset() + idx := p.idx + if p.mode&StoreComments != 0 { + p.comments.Unset() } - self.next() + p.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} + p.error(left.Idx0(), "invalid left-hand side in assignment") + p.nextStatement() + return &ast.BadExpression{From: idx, To: p.idx} } exp := &ast.AssignExpression{ Left: left, Operator: operator, - Right: self.parseAssignmentExpression(), + Right: p.parseAssignmentExpression(), } - if self.mode&StoreComments != 0 { - self.comments.SetExpression(exp) + if p.mode&StoreComments != 0 { + p.comments.SetExpression(exp) } return exp @@ -976,17 +972,17 @@ func (self *_parser) parseAssignmentExpression() ast.Expression { return left } -func (self *_parser) parseExpression() ast.Expression { - next := self.parseAssignmentExpression +func (p *_parser) parseExpression() ast.Expression { + next := p.parseAssignmentExpression left := next() - if self.token == token.COMMA { + if p.token == token.COMMA { sequence := []ast.Expression{left} for { - if self.token != token.COMMA { + if p.token != token.COMMA { break } - self.next() + p.next() sequence = append(sequence, next()) } return &ast.SequenceExpression{ diff --git a/parser/lexer.go b/parser/lexer.go index 0ddad654..2c30abdf 100644 --- a/parser/lexer.go +++ b/parser/lexer.go @@ -15,7 +15,7 @@ import ( "github.com/robertkrimen/otto/token" ) -type _chr struct { +type chr struct { //nolint: unused value rune width int } @@ -55,49 +55,50 @@ func isIdentifierPart(chr rune) bool { chr >= utf8.RuneSelf && (unicode.IsLetter(chr) || unicode.IsDigit(chr)) } -func (self *_parser) scanIdentifier() (string, error) { - offset := self.chrOffset +func (p *_parser) scanIdentifier() (string, error) { + offset := p.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)) + for isIdentifierPart(p.chr) { + if p.chr == '\\' { + distance := p.chrOffset - offset + p.read() + if p.chr != 'u' { + return "", fmt.Errorf("invalid identifier escape character: %c (%s)", p.chr, string(p.chr)) } parse = true var value rune for j := 0; j < 4; j++ { - self.read() - decimal, ok := hex2decimal(byte(self.chr)) + p.read() + decimal, ok := hex2decimal(byte(p.chr)) if !ok { - return "", fmt.Errorf("Invalid identifier escape character: %c (%s)", self.chr, string(self.chr)) + return "", fmt.Errorf("invalid identifier escape character: %c (%s)", p.chr, string(p.chr)) } value = value<<4 | decimal } - if value == '\\' { - return "", fmt.Errorf("Invalid identifier escape value: %c (%s)", value, string(value)) - } else if distance == 0 { + switch { + case value == '\\': + return "", fmt.Errorf("invalid identifier escape value: %c (%s)", value, string(value)) + case distance == 0: if !isIdentifierStart(value) { - return "", fmt.Errorf("Invalid identifier escape value: %c (%s)", value, string(value)) + return "", fmt.Errorf("invalid identifier escape value: %c (%s)", value, string(value)) } - } else if distance > 0 { + case distance > 0: if !isIdentifierPart(value) { - return "", fmt.Errorf("Invalid identifier escape value: %c (%s)", value, string(value)) + return "", fmt.Errorf("invalid identifier escape value: %c (%s)", value, string(value)) } } } - self.read() + p.read() } - literal := string(self.str[offset:self.chrOffset]) + literal := p.str[offset:p.chrOffset] if parse { return parseStringLiteral(literal) } return literal, nil } -// 7.2 -func isLineWhiteSpace(chr rune) bool { +// 7.2. +func isLineWhiteSpace(chr rune) bool { //nolint: unused, deadcode switch chr { case '\u0009', '\u000b', '\u000c', '\u0020', '\u00a0', '\ufeff': return true @@ -109,7 +110,7 @@ func isLineWhiteSpace(chr rune) bool { return unicode.IsSpace(chr) } -// 7.3 +// 7.3. func isLineTerminator(chr rune) bool { switch chr { case '\u000a', '\u000d', '\u2028', '\u2029': @@ -118,19 +119,19 @@ func isLineTerminator(chr rune) bool { return false } -func (self *_parser) scan() (tkn token.Token, literal string, idx file.Idx) { - self.implicitSemicolon = false +func (p *_parser) scan() (tkn token.Token, literal string, idx file.Idx) { //nolint: nonamedreturns + p.implicitSemicolon = false for { - self.skipWhiteSpace() + p.skipWhiteSpace() - idx = self.idxOf(self.chrOffset) + idx = p.idxOf(p.chrOffset) insertSemicolon := false - switch chr := self.chr; { + switch chr := p.chr; { case isIdentifierStart(chr): var err error - literal, err = self.scanIdentifier() + literal, err = p.scanIdentifier() if err != nil { tkn = token.ILLEGAL break @@ -143,11 +144,11 @@ func (self *_parser) scan() (tkn token.Token, literal string, idx file.Idx) { switch tkn { case 0: // Not a keyword if literal == "true" || literal == "false" { - self.insertSemicolon = true + p.insertSemicolon = true tkn = token.BOOLEAN return } else if literal == "null" { - self.insertSemicolon = true + p.insertSemicolon = true tkn = token.NULL return } @@ -167,40 +168,40 @@ func (self *_parser) scan() (tkn token.Token, literal string, idx file.Idx) { token.RETURN, token.CONTINUE, token.DEBUGGER: - self.insertSemicolon = true + p.insertSemicolon = true return default: return } } - self.insertSemicolon = true + p.insertSemicolon = true tkn = token.IDENTIFIER return case '0' <= chr && chr <= '9': - self.insertSemicolon = true - tkn, literal = self.scanNumericLiteral(false) + p.insertSemicolon = true + tkn, literal = p.scanNumericLiteral(false) return default: - self.read() + p.read() switch chr { case -1: - if self.insertSemicolon { - self.insertSemicolon = false - self.implicitSemicolon = true + if p.insertSemicolon { + p.insertSemicolon = false + p.implicitSemicolon = true } tkn = token.EOF case '\r', '\n', '\u2028', '\u2029': - self.insertSemicolon = false - self.implicitSemicolon = true - self.comments.AtLineBreak() + p.insertSemicolon = false + p.implicitSemicolon = true + p.comments.AtLineBreak() continue case ':': tkn = token.COLON case '.': - if digitValue(self.chr) < 10 { + if digitValue(p.chr) < 10 { insertSemicolon = true - tkn, literal = self.scanNumericLiteral(true) + tkn, literal = p.scanNumericLiteral(true) } else { tkn = token.PERIOD } @@ -224,68 +225,69 @@ func (self *_parser) scan() (tkn token.Token, literal string, idx file.Idx) { tkn = token.RIGHT_BRACE insertSemicolon = true case '+': - tkn = self.switch3(token.PLUS, token.ADD_ASSIGN, '+', token.INCREMENT) + tkn = p.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) + tkn = p.switch3(token.MINUS, token.SUBTRACT_ASSIGN, '-', token.DECREMENT) if tkn == token.DECREMENT { insertSemicolon = true } case '*': - tkn = self.switch2(token.MULTIPLY, token.MULTIPLY_ASSIGN) + tkn = p.switch2(token.MULTIPLY, token.MULTIPLY_ASSIGN) case '/': - if self.chr == '/' { - if self.mode&StoreComments != 0 { - literal := string(self.readSingleLineComment()) - self.comments.AddComment(ast.NewComment(literal, self.idx)) + switch p.chr { + case '/': + if p.mode&StoreComments != 0 { + literal := string(p.readSingleLineComment()) + p.comments.AddComment(ast.NewComment(literal, p.idx)) continue } - self.skipSingleLineComment() + p.skipSingleLineComment() continue - } else if self.chr == '*' { - if self.mode&StoreComments != 0 { - literal = string(self.readMultiLineComment()) - self.comments.AddComment(ast.NewComment(literal, self.idx)) + case '*': + if p.mode&StoreComments != 0 { + literal = string(p.readMultiLineComment()) + p.comments.AddComment(ast.NewComment(literal, p.idx)) continue } - self.skipMultiLineComment() + p.skipMultiLineComment() continue - } else { + default: // Could be division, could be RegExp literal - tkn = self.switch2(token.SLASH, token.QUOTIENT_ASSIGN) + tkn = p.switch2(token.SLASH, token.QUOTIENT_ASSIGN) insertSemicolon = true } case '%': - tkn = self.switch2(token.REMAINDER, token.REMAINDER_ASSIGN) + tkn = p.switch2(token.REMAINDER, token.REMAINDER_ASSIGN) case '^': - tkn = self.switch2(token.EXCLUSIVE_OR, token.EXCLUSIVE_OR_ASSIGN) + tkn = p.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) + tkn = p.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) + tkn = p.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 = p.switch2(token.ASSIGN, token.EQUAL) + if tkn == token.EQUAL && p.chr == '=' { + p.read() tkn = token.STRICT_EQUAL } case '!': - tkn = self.switch2(token.NOT, token.NOT_EQUAL) - if tkn == token.NOT_EQUAL && self.chr == '=' { - self.read() + tkn = p.switch2(token.NOT, token.NOT_EQUAL) + if tkn == token.NOT_EQUAL && p.chr == '=' { + p.read() tkn = token.STRICT_NOT_EQUAL } case '&': - if self.chr == '^' { - self.read() - tkn = self.switch2(token.AND_NOT, token.AND_NOT_ASSIGN) + if p.chr == '^' { + p.read() + tkn = p.switch2(token.AND_NOT, token.AND_NOT_ASSIGN) } else { - tkn = self.switch3(token.AND, token.AND_ASSIGN, '&', token.LOGICAL_AND) + tkn = p.switch3(token.AND, token.AND_ASSIGN, '&', token.LOGICAL_AND) } case '|': - tkn = self.switch3(token.OR, token.OR_ASSIGN, '|', token.LOGICAL_OR) + tkn = p.switch3(token.OR, token.OR_ASSIGN, '|', token.LOGICAL_OR) case '~': tkn = token.BITWISE_NOT case '?': @@ -294,49 +296,49 @@ func (self *_parser) scan() (tkn token.Token, literal string, idx file.Idx) { insertSemicolon = true tkn = token.STRING var err error - literal, err = self.scanString(self.chrOffset - 1) + literal, err = p.scanString(p.chrOffset - 1) if err != nil { tkn = token.ILLEGAL } default: - self.errorUnexpected(idx, chr) + p.errorUnexpected(idx, chr) tkn = token.ILLEGAL } } - self.insertSemicolon = insertSemicolon + p.insertSemicolon = insertSemicolon return } } -func (self *_parser) switch2(tkn0, tkn1 token.Token) token.Token { - if self.chr == '=' { - self.read() +func (p *_parser) switch2(tkn0, tkn1 token.Token) token.Token { + if p.chr == '=' { + p.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() +func (p *_parser) switch3(tkn0, tkn1 token.Token, chr2 rune, tkn2 token.Token) token.Token { + if p.chr == '=' { + p.read() return tkn1 } - if self.chr == chr2 { - self.read() + if p.chr == chr2 { + p.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() +func (p *_parser) switch4(tkn0, tkn1 token.Token, chr2 rune, tkn2, tkn3 token.Token) token.Token { + if p.chr == '=' { + p.read() return tkn1 } - if self.chr == chr2 { - self.read() - if self.chr == '=' { - self.read() + if p.chr == chr2 { + p.read() + if p.chr == '=' { + p.read() return tkn3 } return tkn2 @@ -344,21 +346,21 @@ func (self *_parser) switch4(tkn0, tkn1 token.Token, chr2 rune, tkn2, tkn3 token 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() +func (p *_parser) switch6(tkn0, tkn1 token.Token, chr2 rune, tkn2, tkn3 token.Token, chr3 rune, tkn4, tkn5 token.Token) token.Token { + if p.chr == '=' { + p.read() return tkn1 } - if self.chr == chr2 { - self.read() - if self.chr == '=' { - self.read() + if p.chr == chr2 { + p.read() + if p.chr == '=' { + p.read() return tkn3 } - if self.chr == chr3 { - self.read() - if self.chr == '=' { - self.read() + if p.chr == chr3 { + p.read() + if p.chr == '=' { + p.read() return tkn5 } return tkn4 @@ -368,137 +370,137 @@ func (self *_parser) switch6(tkn0, tkn1 token.Token, chr2 rune, tkn2, tkn3 token return tkn0 } -func (self *_parser) chrAt(index int) _chr { - value, width := utf8.DecodeRuneInString(self.str[index:]) - return _chr{ +func (p *_parser) chrAt(index int) chr { //nolint: unused + value, width := utf8.DecodeRuneInString(p.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]) +func (p *_parser) peek() rune { + if p.offset+1 < p.length { + return rune(p.str[p.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 +func (p *_parser) read() { + if p.offset < p.length { + p.chrOffset = p.offset + chr, width := rune(p.str[p.offset]), 1 if chr >= utf8.RuneSelf { // !ASCII - chr, width = utf8.DecodeRuneInString(self.str[self.offset:]) + chr, width = utf8.DecodeRuneInString(p.str[p.offset:]) if chr == utf8.RuneError && width == 1 { - self.error(self.chrOffset, "Invalid UTF-8 character") + p.error(p.chrOffset, "Invalid UTF-8 character") } } - self.offset += width - self.chr = chr + p.offset += width + p.chr = chr } else { - self.chrOffset = self.length - self.chr = -1 // EOF + p.chrOffset = p.length + p.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 +// This is here since the functions are so similar. +func (p *regExpParser) read() { + if p.offset < p.length { + p.chrOffset = p.offset + chr, width := rune(p.str[p.offset]), 1 if chr >= utf8.RuneSelf { // !ASCII - chr, width = utf8.DecodeRuneInString(self.str[self.offset:]) + chr, width = utf8.DecodeRuneInString(p.str[p.offset:]) if chr == utf8.RuneError && width == 1 { - self.error(self.chrOffset, "Invalid UTF-8 character") + p.error(p.chrOffset, "Invalid UTF-8 character") } } - self.offset += width - self.chr = chr + p.offset += width + p.chr = chr } else { - self.chrOffset = self.length - self.chr = -1 // EOF + p.chrOffset = p.length + p.chr = -1 // EOF } } -func (self *_parser) readSingleLineComment() (result []rune) { - for self.chr != -1 { - self.read() - if isLineTerminator(self.chr) { - return +func (p *_parser) readSingleLineComment() []rune { + var result []rune + for p.chr != -1 { + p.read() + if isLineTerminator(p.chr) { + return result } - result = append(result, self.chr) + result = append(result, p.chr) } // Get rid of the trailing -1 - result = result[:len(result)-1] - - return -} - -func (self *_parser) readMultiLineComment() (result []rune) { - self.read() - for self.chr >= 0 { - chr := self.chr - self.read() - if chr == '*' && self.chr == '/' { - self.read() - return + return result[:len(result)-1] +} + +func (p *_parser) readMultiLineComment() []rune { + var result []rune + p.read() + for p.chr >= 0 { + chr := p.chr + p.read() + if chr == '*' && p.chr == '/' { + p.read() + return result } result = append(result, chr) } - self.errorUnexpected(0, self.chr) + p.errorUnexpected(0, p.chr) - return + return result } -func (self *_parser) skipSingleLineComment() { - for self.chr != -1 { - self.read() - if isLineTerminator(self.chr) { +func (p *_parser) skipSingleLineComment() { + for p.chr != -1 { + p.read() + if isLineTerminator(p.chr) { return } } } -func (self *_parser) skipMultiLineComment() { - self.read() - for self.chr >= 0 { - chr := self.chr - self.read() - if chr == '*' && self.chr == '/' { - self.read() +func (p *_parser) skipMultiLineComment() { + p.read() + for p.chr >= 0 { + chr := p.chr + p.read() + if chr == '*' && p.chr == '/' { + p.read() return } } - self.errorUnexpected(0, self.chr) + p.errorUnexpected(0, p.chr) } -func (self *_parser) skipWhiteSpace() { +func (p *_parser) skipWhiteSpace() { for { - switch self.chr { + switch p.chr { case ' ', '\t', '\f', '\v', '\u00a0', '\ufeff': - self.read() + p.read() continue case '\r': - if self._peek() == '\n' { - self.comments.AtLineBreak() - self.read() + if p.peek() == '\n' { + p.comments.AtLineBreak() + p.read() } fallthrough case '\u2028', '\u2029', '\n': - if self.insertSemicolon { + if p.insertSemicolon { return } - self.comments.AtLineBreak() - self.read() + p.comments.AtLineBreak() + p.read() continue } - if self.chr >= utf8.RuneSelf { - if unicode.IsSpace(self.chr) { - self.read() + if p.chr >= utf8.RuneSelf { + if unicode.IsSpace(p.chr) { + p.read() continue } } @@ -506,121 +508,114 @@ func (self *_parser) skipWhiteSpace() { } } -func (self *_parser) skipLineWhiteSpace() { - for isLineWhiteSpace(self.chr) { - self.read() - } -} - -func (self *_parser) scanMantissa(base int) { - for digitValue(self.chr) < base { - self.read() +func (p *_parser) scanMantissa(base int) { + for digitValue(p.chr) < base { + p.read() } } -func (self *_parser) scanEscape(quote rune) { +func (p *_parser) scanEscape(quote rune) { var length, base uint32 - switch self.chr { - //case '0', '1', '2', '3', '4', '5', '6', '7': + switch p.chr { // Octal: // length, base, limit = 3, 8, 255 case 'a', 'b', 'f', 'n', 'r', 't', 'v', '\\', '"', '\'', '0': - self.read() + p.read() return case '\r', '\n', '\u2028', '\u2029': - self.scanNewline() + p.scanNewline() return case 'x': - self.read() + p.read() length, base = 2, 16 case 'u': - self.read() + p.read() length, base = 4, 16 default: - self.read() // Always make progress + p.read() // Always make progress return } var value uint32 - for ; length > 0 && self.chr != quote && self.chr >= 0; length-- { - digit := uint32(digitValue(self.chr)) + for ; length > 0 && p.chr != quote && p.chr >= 0; length-- { + digit := uint32(digitValue(p.chr)) if digit >= base { break } value = value*base + digit - self.read() + p.read() } } -func (self *_parser) scanString(offset int) (string, error) { +func (p *_parser) scanString(offset int) (string, error) { // " ' / - quote := rune(self.str[offset]) + quote := rune(p.str[offset]) - for self.chr != quote { - chr := self.chr + for p.chr != quote { + chr := p.chr if chr == '\n' || chr == '\r' || chr == '\u2028' || chr == '\u2029' || chr < 0 { goto newline } - self.read() - if chr == '\\' { + p.read() + switch { + case chr == '\\': if quote == '/' { - if self.chr == '\n' || self.chr == '\r' || self.chr == '\u2028' || self.chr == '\u2029' || self.chr < 0 { + if p.chr == '\n' || p.chr == '\r' || p.chr == '\u2028' || p.chr == '\u2029' || p.chr < 0 { goto newline } - self.read() + p.read() } else { - self.scanEscape(quote) + p.scanEscape(quote) } - } else if chr == '[' && quote == '/' { + case chr == '[' && quote == '/': // Allow a slash (/) in a bracket character class ([...]) // TODO Fix this, this is hacky... quote = -1 - } else if chr == ']' && quote == -1 { + case chr == ']' && quote == -1: quote = '/' } } // " ' / - self.read() + p.read() - return string(self.str[offset:self.chrOffset]), nil + return p.str[offset:p.chrOffset], nil newline: - self.scanNewline() + p.scanNewline() err := "String not terminated" if quote == '/' { err = "Invalid regular expression: missing /" - self.error(self.idxOf(offset), err) + p.error(p.idxOf(offset), err) } return "", errors.New(err) } -func (self *_parser) scanNewline() { - if self.chr == '\r' { - self.read() - if self.chr != '\n' { +func (p *_parser) scanNewline() { + if p.chr == '\r' { + p.read() + if p.chr != '\n' { return } } - self.read() + p.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 hex2decimal(chr byte) (rune, bool) { + r := rune(chr) + switch { + case '0' <= r && r <= '9': + return r - '0', true + case 'a' <= r && r <= 'f': + return r - 'a' + 10, true + case 'A' <= r && r <= 'F': + return r - 'A' + 10, true + default: + return 0, false } } -func parseNumberLiteral(literal string) (value interface{}, err error) { +func parseNumberLiteral(literal string) (value interface{}, err error) { //nolint: nonamedreturns // TODO Is Uint okay? What about -MAX_UINT value, err = strconv.ParseInt(literal, 0, 64) if err == nil { @@ -632,14 +627,16 @@ func parseNumberLiteral(literal string) (value interface{}, err error) { value, err = strconv.ParseFloat(literal, 64) if err == nil { return value, nil - } else if err.(*strconv.NumError).Err == strconv.ErrRange { + } else if errors.Is(err, strconv.ErrRange) { // Infinity, etc. return value, nil } + // TODO(steve): Fix as this is assigning to err so we know the type. + // Need to understand what this was trying to do? err = parseIntErr - if err.(*strconv.NumError).Err == strconv.ErrRange { + if errors.Is(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 @@ -647,7 +644,7 @@ func parseNumberLiteral(literal string) (value interface{}, err error) { for _, chr := range literal { digit := digitValue(chr) if digit >= 16 { - return nil, errors.New("Illegal numeric literal") + return nil, fmt.Errorf("illegal numeric literal: %v (>= 16)", digit) } value = value*16 + float64(digit) } @@ -655,7 +652,7 @@ func parseNumberLiteral(literal string) (value interface{}, err error) { } } - return nil, errors.New("Illegal numeric literal") + return nil, errors.New("illegal numeric literal") } func parseStringLiteral(literal string) (string, error) { @@ -783,78 +780,79 @@ func parseStringLiteral(literal string) (string, error) { return buffer.String(), nil } -func (self *_parser) scanNumericLiteral(decimalPoint bool) (token.Token, string) { - offset := self.chrOffset +func (p *_parser) scanNumericLiteral(decimalPoint bool) (token.Token, string) { + offset := p.chrOffset tkn := token.NUMBER if decimalPoint { offset-- - self.scanMantissa(10) + p.scanMantissa(10) goto exponent } - if self.chr == '0' { - offset := self.chrOffset - self.read() - if self.chr == 'x' || self.chr == 'X' { + if p.chr == '0' { + offset := p.chrOffset + p.read() + switch p.chr { + case 'x', 'X': // Hexadecimal - self.read() - if isDigit(self.chr, 16) { - self.read() + p.read() + if isDigit(p.chr, 16) { + p.read() } else { - return token.ILLEGAL, self.str[offset:self.chrOffset] + return token.ILLEGAL, p.str[offset:p.chrOffset] } - self.scanMantissa(16) + p.scanMantissa(16) - if self.chrOffset-offset <= 2 { + if p.chrOffset-offset <= 2 { // Only "0x" or "0X" - self.error(0, "Illegal hexadecimal number") + p.error(0, "Illegal hexadecimal number") } goto hexadecimal - } else if self.chr == '.' { + case '.': // Float goto float - } else { + default: // Octal, Float - if self.chr == 'e' || self.chr == 'E' { + if p.chr == 'e' || p.chr == 'E' { goto exponent } - self.scanMantissa(8) - if self.chr == '8' || self.chr == '9' { - return token.ILLEGAL, self.str[offset:self.chrOffset] + p.scanMantissa(8) + if p.chr == '8' || p.chr == '9' { + return token.ILLEGAL, p.str[offset:p.chrOffset] } goto octal } } - self.scanMantissa(10) + p.scanMantissa(10) float: - if self.chr == '.' { - self.read() - self.scanMantissa(10) + if p.chr == '.' { + p.read() + p.scanMantissa(10) } exponent: - if self.chr == 'e' || self.chr == 'E' { - self.read() - if self.chr == '-' || self.chr == '+' { - self.read() + if p.chr == 'e' || p.chr == 'E' { + p.read() + if p.chr == '-' || p.chr == '+' { + p.read() } - if isDecimalDigit(self.chr) { - self.read() - self.scanMantissa(10) + if isDecimalDigit(p.chr) { + p.read() + p.scanMantissa(10) } else { - return token.ILLEGAL, self.str[offset:self.chrOffset] + return token.ILLEGAL, p.str[offset:p.chrOffset] } } hexadecimal: octal: - if isIdentifierStart(self.chr) || isDecimalDigit(self.chr) { - return token.ILLEGAL, self.str[offset:self.chrOffset] + if isIdentifierStart(p.chr) || isDecimalDigit(p.chr) { + return token.ILLEGAL, p.str[offset:p.chrOffset] } - return tkn, self.str[offset:self.chrOffset] + return tkn, p.str[offset:p.chrOffset] } diff --git a/parser/lexer_test.go b/parser/lexer_test.go index 88cebf27..96804c77 100644 --- a/parser/lexer_test.go +++ b/parser/lexer_test.go @@ -8,13 +8,15 @@ import ( "github.com/robertkrimen/otto/token" ) -var tt = terst.Terst -var is = terst.Is +var ( + tt = terst.Terst + is = terst.Is +) func TestLexer(t *testing.T) { tt(t, func() { setup := func(src string) *_parser { - parser := _newParser("", src, 1, nil) + parser := newParser("", src, 1, nil) return parser } diff --git a/parser/marshal_test.go b/parser/marshal_test.go index a520c0f4..d2dfaa53 100644 --- a/parser/marshal_test.go +++ b/parser/marshal_test.go @@ -10,6 +10,7 @@ import ( "testing" "github.com/robertkrimen/otto/ast" + "github.com/stretchr/testify/require" ) func marshal(name string, children ...interface{}) interface{} { @@ -21,18 +22,18 @@ func marshal(name string, children ...interface{}) interface{} { name: children[0], } } - map_ := map[string]interface{}{} + ret := 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 + ret[name] = value } if name == "" { - return map_ + return ret } return map[string]interface{}{ - name: map_, + name: ret, } } @@ -130,14 +131,14 @@ func testMarshalNode(node interface{}) interface{} { return marshal("Identifier", node.Name) case *ast.IfStatement: - if_ := marshal("", + ret := marshal("", "Test", testMarshalNode(node.Test), "Consequent", testMarshalNode(node.Consequent), ).(map[string]interface{}) if node.Alternate != nil { - if_["Alternate"] = testMarshalNode(node.Alternate) + ret["Alternate"] = testMarshalNode(node.Alternate) } - return marshal("If", if_) + return marshal("If", ret) case *ast.LabelledStatement: return marshal("Label", @@ -199,8 +200,10 @@ func TestParserAST(t *testing.T) { 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", " ") + err = json.Indent(&tmp0, []byte(haveOutput), "\t\t", " ") + require.NoError(t, err) + err = json.Indent(&tmp1, []byte(wantOutput), "\t\t", " ") + require.NoError(t, err) is("\n\t\t"+tmp0.String(), "\n\t\t"+tmp1.String()) } diff --git a/parser/parser.go b/parser/parser.go index a1701476..e4e78795 100644 --- a/parser/parser.go +++ b/parser/parser.go @@ -35,9 +35,9 @@ package parser import ( "bytes" "encoding/base64" - "errors" + "fmt" "io" - "io/ioutil" + "os" "github.com/robertkrimen/otto/ast" "github.com/robertkrimen/otto/file" @@ -49,11 +49,14 @@ import ( type Mode uint const ( - IgnoreRegExpErrors Mode = 1 << iota // Ignore RegExp compatibility errors (allow backtracking) - StoreComments // Store the comments from source to the comments map + // IgnoreRegExpErrors ignores RegExp compatibility errors (allow backtracking). + IgnoreRegExpErrors Mode = 1 << iota + + // StoreComments stores the comments from source to the comments map. + StoreComments ) -type _parser struct { +type _parser struct { //nolint: maligned str string length int base int @@ -66,7 +69,7 @@ type _parser struct { token token.Token // The token literal string // The literal of the token, if any - scope *_scope + scope *scope insertSemicolon bool // If we see a newline, then insert an implicit semicolon implicitSemicolon bool // An implicit semicolon exists @@ -85,11 +88,12 @@ type _parser struct { comments *ast.Comments } +// Parser is implemented by types which can parse JavaScript Code. type Parser interface { Scan() (tkn token.Token, literal string, idx file.Idx) } -func _newParser(filename, src string, base int, sm *sourcemap.Consumer) *_parser { +func newParser(filename, src string, base int, sm *sourcemap.Consumer) *_parser { return &_parser{ chr: ' ', // This is set so we can start scanning by skipping whitespace str: src, @@ -100,11 +104,12 @@ func _newParser(filename, src string, base int, sm *sourcemap.Consumer) *_parser } } -// Returns a new Parser. +// NewParser returns a new Parser. func NewParser(filename, src string) Parser { - return _newParser(filename, src, 1, nil) + return newParser(filename, src, 1, nil) } +// ReadSource reads code from src if not nil, otherwise reads from filename. func ReadSource(filename string, src interface{}) ([]byte, error) { if src != nil { switch src := src.(type) { @@ -122,12 +127,14 @@ func ReadSource(filename string, src interface{}) ([]byte, error) { return nil, err } return bfr.Bytes(), nil + default: + return nil, fmt.Errorf("invalid src type %T", src) } - return nil, errors.New("invalid source") } - return ioutil.ReadFile(filename) + return os.ReadFile(filename) //nolint: gosec } +// ReadSourceMap reads the source map from src if not nil, otherwise is a noop. func ReadSourceMap(filename string, src interface{}) (*sourcemap.Consumer, error) { if src == nil { return nil, nil //nolint: nilnil @@ -139,9 +146,7 @@ func ReadSourceMap(filename string, src interface{}) (*sourcemap.Consumer, error case []byte: return sourcemap.Parse(filename, src) case *bytes.Buffer: - if src != nil { - return sourcemap.Parse(filename, src.Bytes()) - } + return sourcemap.Parse(filename, src.Bytes()) case io.Reader: var bfr bytes.Buffer if _, err := io.Copy(&bfr, src); err != nil { @@ -150,11 +155,12 @@ func ReadSourceMap(filename string, src interface{}) (*sourcemap.Consumer, error return sourcemap.Parse(filename, bfr.Bytes()) case *sourcemap.Consumer: return src, nil + default: + return nil, fmt.Errorf("invalid sourcemap type %T", src) } - - return nil, errors.New("invalid sourcemap type") } +// ParseFileWithSourceMap parses the sourcemap returning the resulting Program. func ParseFileWithSourceMap(fileSet *file.FileSet, filename string, javascriptSource, sourcemapSource interface{}, mode Mode) (*ast.Program, error) { src, err := ReadSource(filename, javascriptSource) if err != nil { @@ -184,7 +190,7 @@ func ParseFileWithSourceMap(fileSet *file.FileSet, filename string, javascriptSo base = fileSet.AddFile(filename, string(src)) } - parser := _newParser(filename, string(src), base, sm) + parser := newParser(filename, string(src), base, sm) parser.mode = mode program, err := parser.parse() program.Comments = parser.comments.CommentMap @@ -215,7 +221,7 @@ func ParseFile(fileSet *file.FileSet, filename string, src interface{}, mode Mod func ParseFunction(parameterList, body string) (*ast.FunctionLiteral, error) { src := "(function(" + parameterList + ") {\n" + body + "\n})" - parser := _newParser("", src, 1, nil) + parser := newParser("", src, 1, nil) program, err := parser.parse() if err != nil { return nil, err @@ -227,75 +233,75 @@ func ParseFunction(parameterList, body string) (*ast.FunctionLiteral, error) { // Scan reads a single token from the source at the current offset, increments the offset and // returns the token.Token token, a string literal representing the value of the token (if applicable) // and it's current file.Idx index. -func (self *_parser) Scan() (tkn token.Token, literal string, idx file.Idx) { - return self.scan() +func (p *_parser) Scan() (token.Token, string, file.Idx) { + return p.scan() } -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] +func (p *_parser) slice(idx0, idx1 file.Idx) string { + from := int(idx0) - p.base + to := int(idx1) - p.base + if from >= 0 && to <= len(p.str) { + return p.str[from:to] } return "" } -func (self *_parser) parse() (*ast.Program, error) { - self.next() - program := self.parseProgram() +func (p *_parser) parse() (*ast.Program, error) { + p.next() + program := p.parseProgram() if false { - self.errors.Sort() + p.errors.Sort() } - if self.mode&StoreComments != 0 { - self.comments.CommentMap.AddComments(program, self.comments.FetchAll(), ast.TRAILING) + if p.mode&StoreComments != 0 { + p.comments.CommentMap.AddComments(program, p.comments.FetchAll(), ast.TRAILING) } - return program, self.errors.Err() + return program, p.errors.Err() } -func (self *_parser) next() { - self.token, self.literal, self.idx = self.scan() +func (p *_parser) next() { + p.token, p.literal, p.idx = p.scan() } -func (self *_parser) optionalSemicolon() { - if self.token == token.SEMICOLON { - self.next() +func (p *_parser) optionalSemicolon() { + if p.token == token.SEMICOLON { + p.next() return } - if self.implicitSemicolon { - self.implicitSemicolon = false + if p.implicitSemicolon { + p.implicitSemicolon = false return } - if self.token != token.EOF && self.token != token.RIGHT_BRACE { - self.expect(token.SEMICOLON) + if p.token != token.EOF && p.token != token.RIGHT_BRACE { + p.expect(token.SEMICOLON) } } -func (self *_parser) semicolon() { - if self.token != token.RIGHT_PARENTHESIS && self.token != token.RIGHT_BRACE { - if self.implicitSemicolon { - self.implicitSemicolon = false +func (p *_parser) semicolon() { + if p.token != token.RIGHT_PARENTHESIS && p.token != token.RIGHT_BRACE { + if p.implicitSemicolon { + p.implicitSemicolon = false return } - self.expect(token.SEMICOLON) + p.expect(token.SEMICOLON) } } -func (self *_parser) idxOf(offset int) file.Idx { - return file.Idx(self.base + offset) +func (p *_parser) idxOf(offset int) file.Idx { + return file.Idx(p.base + offset) } -func (self *_parser) expect(value token.Token) file.Idx { - idx := self.idx - if self.token != value { - self.errorUnexpectedToken(self.token) +func (p *_parser) expect(value token.Token) file.Idx { + idx := p.idx + if p.token != value { + p.errorUnexpectedToken(p.token) } - self.next() + p.next() return idx } @@ -305,17 +311,17 @@ func lineCount(str string) (int, int) { for index, chr := range str { switch chr { case '\r': - line += 1 + line++ last = index pair = true continue case '\n': if !pair { - line += 1 + line++ } last = index case '\u2028', '\u2029': - line += 1 + line++ last = index + 2 } pair = false @@ -323,11 +329,11 @@ func lineCount(str string) (int, int) { return line, last } -func (self *_parser) position(idx file.Idx) file.Position { +func (p *_parser) position(idx file.Idx) file.Position { position := file.Position{} - offset := int(idx) - self.base - str := self.str[:offset] - position.Filename = self.file.Name() + offset := int(idx) - p.base + str := p.str[:offset] + position.Filename = p.file.Name() line, last := lineCount(str) position.Line = 1 + line if last >= 0 { diff --git a/parser/parser_test.go b/parser/parser_test.go index 94132a7a..1e40c84e 100644 --- a/parser/parser_test.go +++ b/parser/parser_test.go @@ -9,27 +9,27 @@ import ( "github.com/robertkrimen/otto/ast" "github.com/robertkrimen/otto/file" "github.com/robertkrimen/otto/underscore" + "github.com/stretchr/testify/require" ) func firstErr(err error) error { - switch err := err.(type) { - case ErrorList: - return err[0] + var lerr *ErrorList + if errors.As(err, &lerr) { + return (*lerr)[0] } return err } var matchBeforeAfterSeparator = regexp.MustCompile(`(?m)^[ \t]*---$`) -func testParse(src string) (parser *_parser, program *ast.Program, err error) { +func testParse(src string) (*_parser, *ast.Program, error) { return testParseWithMode(src, 0) } -func testParseWithMode(src string, mode Mode) (parser *_parser, program *ast.Program, err error) { +func testParseWithMode(src string, mode Mode) (parser *_parser, program *ast.Program, err error) { //nolint: nonamedreturns defer func() { if tmp := recover(); tmp != nil { - switch tmp := tmp.(type) { - case string: + if tmp, ok := tmp.(string); ok { if strings.HasPrefix(tmp, "SyntaxError:") { parser = nil program = nil @@ -40,10 +40,10 @@ func testParseWithMode(src string, mode Mode) (parser *_parser, program *ast.Pro panic(tmp) } }() - parser = _newParser("", src, 1, nil) + parser = newParser("", src, 1, nil) parser.mode = mode program, err = parser.parse() - return + return parser, program, err } func TestParseFile(t *testing.T) { @@ -92,7 +92,7 @@ func TestParseFunction(t *testing.T) { func TestParserErr(t *testing.T) { tt(t, func() { test := func(input string, expect interface{}) (*ast.Program, *_parser) { - parser := _newParser("", input, 1, nil) + parser := newParser("", input, 1, nil) program, err := parser.parse() is(firstErr(err), expect) return program, parser @@ -162,17 +162,17 @@ func TestParserErr(t *testing.T) { 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("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("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 + 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: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("--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") @@ -192,9 +192,9 @@ func TestParserErr(t *testing.T) { 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 + 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("+abc = 1", "(anonymous): Line 1:1 invalid left-hand side in assignment") test("1 + (", "(anonymous): Line 1:6 Unexpected end of input") @@ -203,19 +203,19 @@ func TestParserErr(t *testing.T) { 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) { } }) + // { 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") @@ -506,7 +506,7 @@ func TestParser(t *testing.T) { abc -- [] - `, "(anonymous): Line 3:13 Invalid left-hand side in assignment") + `, "(anonymous): Line 3:13 invalid left-hand side in assignment") test(` abc-- @@ -779,7 +779,7 @@ func TestParser(t *testing.T) { test("'\\\r\n'", nil) //// 11.13.1-1-1 - test("42 = 42;", "(anonymous): Line 1:1 Invalid left-hand side in assignment") + test("42 = 42;", "(anonymous): Line 1:1 invalid left-hand side in assignment") // S11.13.2_A4.2_T1.3 test(` @@ -968,7 +968,7 @@ func Test_parseNumberLiteral(t *testing.T) { func TestPosition(t *testing.T) { tt(t, func() { - parser := _newParser("", "// Lorem ipsum", 1, nil) + parser := newParser("", "// Lorem ipsum", 1, nil) // Out of range, idx0 (error condition) is(parser.slice(0, 1), "") @@ -986,7 +986,7 @@ func TestPosition(t *testing.T) { is(parser.str[0:14], "// Lorem ipsum") is(parser.slice(1, 15), "// Lorem ipsum") - parser = _newParser("", "(function(){ return 0; })", 1, nil) + parser = newParser("", "(function(){ return 0; })", 1, nil) program, err := parser.parse() is(err, nil) @@ -1004,20 +1004,20 @@ func TestPosition(t *testing.T) { is(node.Idx1(), file.Idx(25)) is(parser.slice(node.Idx0(), node.Idx1()), "function(){ return 0; }") - parser = _newParser("", "(function(){ return abc; })", 1, nil) + parser = newParser("", "(function(){ return abc; })", 1, nil) program, err = parser.parse() is(err, nil) node = program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.FunctionLiteral) is(node.(*ast.FunctionLiteral).Source, "function(){ return abc; }") - parser = _newParser("", "this.style", 1, nil) + parser = newParser("", "this.style", 1, nil) program, err = parser.parse() is(err, nil) node = program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.DotExpression).Left.(*ast.ThisExpression) is(node.Idx0(), file.Idx(1)) is(node.Idx1(), file.Idx(5)) - parser = _newParser("", "(function(){ if (abc) { throw 'failed'; } })", 1, nil) + parser = newParser("", "(function(){ if (abc) { throw 'failed'; } })", 1, nil) program, err = parser.parse() is(err, nil) block := program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.FunctionLiteral).Body.(*ast.BlockStatement) @@ -1033,7 +1033,8 @@ func BenchmarkParser(b *testing.B) { b.ResetTimer() for i := 0; i < b.N; i++ { - parser := _newParser("", src, 1, nil) - parser.parse() + parser := newParser("", src, 1, nil) + _, err := parser.parse() + require.NoError(b, err) } } diff --git a/parser/regexp.go b/parser/regexp.go index e6df9faa..ce1b5bc9 100644 --- a/parser/regexp.go +++ b/parser/regexp.go @@ -6,7 +6,7 @@ import ( "strconv" ) -type _RegExp_parser struct { +type regExpParser struct { //nolint: maligned str string length int @@ -40,7 +40,7 @@ func TransformRegExp(pattern string) (string, error) { // TODO If without \, if without (?=, (?!, then another shortcut - parser := _RegExp_parser{ + parser := regExpParser{ str: pattern, length: len(pattern), goRegexp: bytes.NewBuffer(make([]byte, 0, 3*len(pattern)/2)), @@ -59,109 +59,109 @@ func TransformRegExp(pattern string) (string, error) { return parser.goRegexp.String(), err } -func (self *_RegExp_parser) scan() { - for self.chr != -1 { - switch self.chr { +func (p *regExpParser) scan() { + for p.chr != -1 { + switch p.chr { case '\\': - self.read() - self.scanEscape(false) + p.read() + p.scanEscape(false) case '(': - self.pass() - self.scanGroup() + p.pass() + p.scanGroup() case '[': - self.pass() - self.scanBracket() + p.pass() + p.scanBracket() case ')': - self.error(-1, "Unmatched ')'") - self.invalid = true - self.pass() + p.error(-1, "Unmatched ')'") + p.invalid = true + p.pass() default: - self.pass() + p.pass() } } } // (...) -func (self *_RegExp_parser) scanGroup() { - str := self.str[self.chrOffset:] +func (p *regExpParser) scanGroup() { + str := p.str[p.chrOffset:] if len(str) > 1 { // A possibility of (?= or (?! if str[0] == '?' { if str[1] == '=' || str[1] == '!' { - self.error(-1, "re2: Invalid (%s) ", self.str[self.chrOffset:self.chrOffset+2]) + p.error(-1, "re2: Invalid (%s) ", p.str[p.chrOffset:p.chrOffset+2]) } } } - for self.chr != -1 && self.chr != ')' { - switch self.chr { + for p.chr != -1 && p.chr != ')' { + switch p.chr { case '\\': - self.read() - self.scanEscape(false) + p.read() + p.scanEscape(false) case '(': - self.pass() - self.scanGroup() + p.pass() + p.scanGroup() case '[': - self.pass() - self.scanBracket() + p.pass() + p.scanBracket() default: - self.pass() + p.pass() continue } } - if self.chr != ')' { - self.error(-1, "Unterminated group") - self.invalid = true + if p.chr != ')' { + p.error(-1, "Unterminated group") + p.invalid = true return } - self.pass() + p.pass() } -// [...] -func (self *_RegExp_parser) scanBracket() { - for self.chr != -1 { - if self.chr == ']' { +// [...]. +func (p *regExpParser) scanBracket() { + for p.chr != -1 { + if p.chr == ']' { break - } else if self.chr == '\\' { - self.read() - self.scanEscape(true) + } else if p.chr == '\\' { + p.read() + p.scanEscape(true) continue } - self.pass() + p.pass() } - if self.chr != ']' { - self.error(-1, "Unterminated character class") - self.invalid = true + if p.chr != ']' { + p.error(-1, "Unterminated character class") + p.invalid = true return } - self.pass() + p.pass() } // \... -func (self *_RegExp_parser) scanEscape(inClass bool) { - offset := self.chrOffset +func (p *regExpParser) scanEscape(inClass bool) { + offset := p.chrOffset var length, base uint32 - switch self.chr { + switch p.chr { case '0', '1', '2', '3', '4', '5', '6', '7': var value int64 size := 0 for { - digit := int64(digitValue(self.chr)) + digit := int64(digitValue(p.chr)) if digit >= 8 { // Not a valid digit break } value = value*8 + digit - self.read() - size += 1 + p.read() + size++ } if size == 1 { // The number of characters read - _, err := self.goRegexp.Write([]byte{'\\', byte(value) + '0'}) + _, err := p.goRegexp.Write([]byte{'\\', byte(value) + '0'}) if err != nil { - self.errors = append(self.errors, err) + p.errors = append(p.errors, err) } if value != 0 { // An invalid backreference - self.error(-1, "re2: Invalid \\%d ", value) + p.error(-1, "re2: Invalid \\%d ", value) } return } @@ -172,49 +172,49 @@ func (self *_RegExp_parser) scanEscape(inClass bool) { tmp = tmp[0:3] } tmp = strconv.AppendInt(tmp, value, 16) - _, err := self.goRegexp.Write(tmp) + _, err := p.goRegexp.Write(tmp) if err != nil { - self.errors = append(self.errors, err) + p.errors = append(p.errors, err) } return case '8', '9': size := 0 for { - digit := digitValue(self.chr) + digit := digitValue(p.chr) if digit >= 10 { // Not a valid digit break } - self.read() - size += 1 + p.read() + size++ } - err := self.goRegexp.WriteByte('\\') + err := p.goRegexp.WriteByte('\\') if err != nil { - self.errors = append(self.errors, err) + p.errors = append(p.errors, err) } - _, err = self.goRegexp.WriteString(self.str[offset:self.chrOffset]) + _, err = p.goRegexp.WriteString(p.str[offset:p.chrOffset]) if err != nil { - self.errors = append(self.errors, err) + p.errors = append(p.errors, err) } - self.error(-1, "re2: Invalid \\%s ", self.str[offset:self.chrOffset]) + p.error(-1, "re2: Invalid \\%s ", p.str[offset:p.chrOffset]) return case 'x': - self.read() + p.read() length, base = 2, 16 case 'u': - self.read() + p.read() length, base = 4, 16 case 'b': if inClass { - _, err := self.goRegexp.Write([]byte{'\\', 'x', '0', '8'}) + _, err := p.goRegexp.Write([]byte{'\\', 'x', '0', '8'}) if err != nil { - self.errors = append(self.errors, err) + p.errors = append(p.errors, err) } - self.read() + p.read() return } fallthrough @@ -231,24 +231,25 @@ func (self *_RegExp_parser) scanEscape(inClass bool) { fallthrough case 'f', 'n', 'r', 't', 'v': - err := self.goRegexp.WriteByte('\\') + err := p.goRegexp.WriteByte('\\') if err != nil { - self.errors = append(self.errors, err) + p.errors = append(p.errors, err) } - self.pass() + p.pass() return case 'c': - self.read() + p.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') + switch { + case 'a' <= p.chr && p.chr <= 'z': + value = int64(p.chr) - 'a' + 1 + case 'A' <= p.chr && p.chr <= 'Z': + value = int64(p.chr) - 'A' + 1 + default: + err := p.goRegexp.WriteByte('c') if err != nil { - self.errors = append(self.errors, err) + p.errors = append(p.errors, err) } return } @@ -259,98 +260,93 @@ func (self *_RegExp_parser) scanEscape(inClass bool) { tmp = tmp[0:3] } tmp = strconv.AppendInt(tmp, value, 16) - _, err := self.goRegexp.Write(tmp) + _, err := p.goRegexp.Write(tmp) if err != nil { - self.errors = append(self.errors, err) + p.errors = append(p.errors, err) } - self.read() + p.read() return default: // $ is an identifier character, so we have to have // a special case for it here - if self.chr == '$' || !isIdentifierPart(self.chr) { + if p.chr == '$' || !isIdentifierPart(p.chr) { // A non-identifier character needs escaping - err := self.goRegexp.WriteByte('\\') + err := p.goRegexp.WriteByte('\\') if err != nil { - self.errors = append(self.errors, err) + p.errors = append(p.errors, err) } - } else { + } else { //nolint: staticcheck // Unescape the character for re2 } - self.pass() + p.pass() return } // Otherwise, we're a \u.... or \x... - valueOffset := self.chrOffset + valueOffset := p.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() + for length := length; length > 0; length-- { + digit := uint32(digitValue(p.chr)) + if digit >= base { + // Not a valid digit + goto skip } + value = value*base + digit + p.read() } - if length == 4 { - _, err := self.goRegexp.Write([]byte{ + switch length { + case 4: + if _, err := p.goRegexp.Write([]byte{ '\\', 'x', '{', - self.str[valueOffset+0], - self.str[valueOffset+1], - self.str[valueOffset+2], - self.str[valueOffset+3], + p.str[valueOffset+0], + p.str[valueOffset+1], + p.str[valueOffset+2], + p.str[valueOffset+3], '}', - }) - if err != nil { - self.errors = append(self.errors, err) + }); err != nil { + p.errors = append(p.errors, err) } - } else if length == 2 { - _, err := self.goRegexp.Write([]byte{ + case 2: + if _, err := p.goRegexp.Write([]byte{ '\\', 'x', - self.str[valueOffset+0], - self.str[valueOffset+1], - }) - if err != nil { - self.errors = append(self.errors, err) + p.str[valueOffset+0], + p.str[valueOffset+1], + }); err != nil { + p.errors = append(p.errors, err) } - } else { + default: // Should never, ever get here... - self.error(-1, "re2: Illegal branch in scanEscape") + p.error(-1, "re2: Illegal branch in scanEscape") goto skip } return skip: - _, err := self.goRegexp.WriteString(self.str[offset:self.chrOffset]) + _, err := p.goRegexp.WriteString(p.str[offset:p.chrOffset]) if err != nil { - self.errors = append(self.errors, err) + p.errors = append(p.errors, err) } } -func (self *_RegExp_parser) pass() { - if self.chr != -1 { - _, err := self.goRegexp.WriteRune(self.chr) +func (p *regExpParser) pass() { + if p.chr != -1 { + _, err := p.goRegexp.WriteRune(p.chr) if err != nil { - self.errors = append(self.errors, err) + p.errors = append(p.errors, err) } } - self.read() + p.read() } // TODO Better error reporting, use the offset, etc. -func (self *_RegExp_parser) error(offset int, msg string, msgValues ...interface{}) error { +func (p *regExpParser) error(offset int, msg string, msgValues ...interface{}) { //nolint: unparam err := fmt.Errorf(msg, msgValues...) - self.errors = append(self.errors, err) - return err + p.errors = append(p.errors, err) } diff --git a/parser/scope.go b/parser/scope.go index e1dbdda1..810f4d02 100644 --- a/parser/scope.go +++ b/parser/scope.go @@ -4,8 +4,8 @@ import ( "github.com/robertkrimen/otto/ast" ) -type _scope struct { - outer *_scope +type scope struct { + outer *scope allowIn bool inIteration bool inSwitch bool @@ -15,30 +15,30 @@ type _scope struct { labels []string } -func (self *_parser) openScope() { - self.scope = &_scope{ - outer: self.scope, +func (p *_parser) openScope() { + p.scope = &scope{ + outer: p.scope, allowIn: true, } } -func (self *_parser) closeScope() { - self.scope = self.scope.outer +func (p *_parser) closeScope() { + p.scope = p.scope.outer } -func (self *_scope) declare(declaration ast.Declaration) { - self.declarationList = append(self.declarationList, declaration) +func (p *scope) declare(declaration ast.Declaration) { + p.declarationList = append(p.declarationList, declaration) } -func (self *_scope) hasLabel(name string) bool { - for _, label := range self.labels { +func (p *scope) hasLabel(name string) bool { + for _, label := range p.labels { if label == name { return true } } - if self.outer != nil && !self.inFunction { + if p.outer != nil && !p.inFunction { // Crossing a function boundary to look for a label is verboten - return self.outer.hasLabel(name) + return p.outer.hasLabel(name) } return false } diff --git a/parser/statement.go b/parser/statement.go index 12d27161..21b9e539 100644 --- a/parser/statement.go +++ b/parser/statement.go @@ -5,233 +5,233 @@ import ( "github.com/robertkrimen/otto/token" ) -func (self *_parser) parseBlockStatement() *ast.BlockStatement { +func (p *_parser) parseBlockStatement() *ast.BlockStatement { node := &ast.BlockStatement{} // Find comments before the leading brace - if self.mode&StoreComments != 0 { - self.comments.CommentMap.AddComments(node, self.comments.FetchAll(), ast.LEADING) - self.comments.Unset() + if p.mode&StoreComments != 0 { + p.comments.CommentMap.AddComments(node, p.comments.FetchAll(), ast.LEADING) + p.comments.Unset() } - node.LeftBrace = self.expect(token.LEFT_BRACE) - node.List = self.parseStatementList() + node.LeftBrace = p.expect(token.LEFT_BRACE) + node.List = p.parseStatementList() - if self.mode&StoreComments != 0 { - self.comments.Unset() - self.comments.CommentMap.AddComments(node, self.comments.FetchAll(), ast.FINAL) - self.comments.AfterBlock() + if p.mode&StoreComments != 0 { + p.comments.Unset() + p.comments.CommentMap.AddComments(node, p.comments.FetchAll(), ast.FINAL) + p.comments.AfterBlock() } - node.RightBrace = self.expect(token.RIGHT_BRACE) + node.RightBrace = p.expect(token.RIGHT_BRACE) // Find comments after the trailing brace - if self.mode&StoreComments != 0 { - self.comments.ResetLineBreak() - self.comments.CommentMap.AddComments(node, self.comments.Fetch(), ast.TRAILING) + if p.mode&StoreComments != 0 { + p.comments.ResetLineBreak() + p.comments.CommentMap.AddComments(node, p.comments.Fetch(), ast.TRAILING) } return node } -func (self *_parser) parseEmptyStatement() ast.Statement { - idx := self.expect(token.SEMICOLON) +func (p *_parser) parseEmptyStatement() ast.Statement { + idx := p.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 { - statement := self.parseStatement() +func (p *_parser) parseStatementList() (list []ast.Statement) { //nolint: nonamedreturns + for p.token != token.RIGHT_BRACE && p.token != token.EOF { + statement := p.parseStatement() list = append(list, statement) } - return + return list } -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} +func (p *_parser) parseStatement() ast.Statement { + if p.token == token.EOF { + p.errorUnexpectedToken(p.token) + return &ast.BadStatement{From: p.idx, To: p.idx + 1} } - if self.mode&StoreComments != 0 { - self.comments.ResetLineBreak() + if p.mode&StoreComments != 0 { + p.comments.ResetLineBreak() } - switch self.token { + switch p.token { case token.SEMICOLON: - return self.parseEmptyStatement() + return p.parseEmptyStatement() case token.LEFT_BRACE: - return self.parseBlockStatement() + return p.parseBlockStatement() case token.IF: - return self.parseIfStatement() + return p.parseIfStatement() case token.DO: - statement := self.parseDoWhileStatement() - self.comments.PostProcessNode(statement) + statement := p.parseDoWhileStatement() + p.comments.PostProcessNode(statement) return statement case token.WHILE: - return self.parseWhileStatement() + return p.parseWhileStatement() case token.FOR: - return self.parseForOrForInStatement() + return p.parseForOrForInStatement() case token.BREAK: - return self.parseBreakStatement() + return p.parseBreakStatement() case token.CONTINUE: - return self.parseContinueStatement() + return p.parseContinueStatement() case token.DEBUGGER: - return self.parseDebuggerStatement() + return p.parseDebuggerStatement() case token.WITH: - return self.parseWithStatement() + return p.parseWithStatement() case token.VAR: - return self.parseVariableStatement() + return p.parseVariableStatement() case token.FUNCTION: - return self.parseFunctionStatement() + return p.parseFunctionStatement() case token.SWITCH: - return self.parseSwitchStatement() + return p.parseSwitchStatement() case token.RETURN: - return self.parseReturnStatement() + return p.parseReturnStatement() case token.THROW: - return self.parseThrowStatement() + return p.parseThrowStatement() case token.TRY: - return self.parseTryStatement() + return p.parseTryStatement() } var comments []*ast.Comment - if self.mode&StoreComments != 0 { - comments = self.comments.FetchAll() + if p.mode&StoreComments != 0 { + comments = p.comments.FetchAll() } - expression := self.parseExpression() + expression := p.parseExpression() - if identifier, isIdentifier := expression.(*ast.Identifier); isIdentifier && self.token == token.COLON { + if identifier, isIdentifier := expression.(*ast.Identifier); isIdentifier && p.token == token.COLON { // LabelledStatement - colon := self.idx - if self.mode&StoreComments != 0 { - self.comments.Unset() + colon := p.idx + if p.mode&StoreComments != 0 { + p.comments.Unset() } - self.next() // : + p.next() // : label := identifier.Name - for _, value := range self.scope.labels { + for _, value := range p.scope.labels { if label == value { - self.error(identifier.Idx0(), "Label '%s' already exists", label) + p.error(identifier.Idx0(), "Label '%s' already exists", label) } } var labelComments []*ast.Comment - if self.mode&StoreComments != 0 { - labelComments = self.comments.FetchAll() + if p.mode&StoreComments != 0 { + labelComments = p.comments.FetchAll() } - 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 + p.scope.labels = append(p.scope.labels, label) // Push the label + statement := p.parseStatement() + p.scope.labels = p.scope.labels[:len(p.scope.labels)-1] // Pop the label exp := &ast.LabelledStatement{ Label: identifier, Colon: colon, Statement: statement, } - if self.mode&StoreComments != 0 { - self.comments.CommentMap.AddComments(exp, labelComments, ast.LEADING) + if p.mode&StoreComments != 0 { + p.comments.CommentMap.AddComments(exp, labelComments, ast.LEADING) } return exp } - self.optionalSemicolon() + p.optionalSemicolon() statement := &ast.ExpressionStatement{ Expression: expression, } - if self.mode&StoreComments != 0 { - self.comments.CommentMap.AddComments(statement, comments, ast.LEADING) + if p.mode&StoreComments != 0 { + p.comments.CommentMap.AddComments(statement, comments, ast.LEADING) } return statement } -func (self *_parser) parseTryStatement() ast.Statement { +func (p *_parser) parseTryStatement() ast.Statement { var tryComments []*ast.Comment - if self.mode&StoreComments != 0 { - tryComments = self.comments.FetchAll() + if p.mode&StoreComments != 0 { + tryComments = p.comments.FetchAll() } node := &ast.TryStatement{ - Try: self.expect(token.TRY), - Body: self.parseBlockStatement(), + Try: p.expect(token.TRY), + Body: p.parseBlockStatement(), } - if self.mode&StoreComments != 0 { - self.comments.CommentMap.AddComments(node, tryComments, ast.LEADING) - self.comments.CommentMap.AddComments(node.Body, self.comments.FetchAll(), ast.TRAILING) + if p.mode&StoreComments != 0 { + p.comments.CommentMap.AddComments(node, tryComments, ast.LEADING) + p.comments.CommentMap.AddComments(node.Body, p.comments.FetchAll(), ast.TRAILING) } - if self.token == token.CATCH { - catch := self.idx - if self.mode&StoreComments != 0 { - self.comments.Unset() + if p.token == token.CATCH { + catch := p.idx + if p.mode&StoreComments != 0 { + p.comments.Unset() + } + p.next() + p.expect(token.LEFT_PARENTHESIS) + if p.token != token.IDENTIFIER { + p.expect(token.IDENTIFIER) + p.nextStatement() + return &ast.BadStatement{From: catch, To: p.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.mode&StoreComments != 0 { - self.comments.CommentMap.AddComments(node.Catch.Body, self.comments.FetchAll(), ast.TRAILING) - } + identifier := p.parseIdentifier() + p.expect(token.RIGHT_PARENTHESIS) + node.Catch = &ast.CatchStatement{ + Catch: catch, + Parameter: identifier, + Body: p.parseBlockStatement(), + } + + if p.mode&StoreComments != 0 { + p.comments.CommentMap.AddComments(node.Catch.Body, p.comments.FetchAll(), ast.TRAILING) } } - if self.token == token.FINALLY { - if self.mode&StoreComments != 0 { - self.comments.Unset() + if p.token == token.FINALLY { + if p.mode&StoreComments != 0 { + p.comments.Unset() } - self.next() - if self.mode&StoreComments != 0 { - tryComments = self.comments.FetchAll() + p.next() + if p.mode&StoreComments != 0 { + tryComments = p.comments.FetchAll() } - node.Finally = self.parseBlockStatement() + node.Finally = p.parseBlockStatement() - if self.mode&StoreComments != 0 { - self.comments.CommentMap.AddComments(node.Finally, tryComments, ast.LEADING) + if p.mode&StoreComments != 0 { + p.comments.CommentMap.AddComments(node.Finally, tryComments, ast.LEADING) } } if node.Catch == nil && node.Finally == nil { - self.error(node.Try, "Missing catch or finally after try") + p.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) - if self.mode&StoreComments != 0 { - self.comments.Unset() +func (p *_parser) parseFunctionParameterList() *ast.ParameterList { + opening := p.expect(token.LEFT_PARENTHESIS) + if p.mode&StoreComments != 0 { + p.comments.Unset() } var list []*ast.Identifier - for self.token != token.RIGHT_PARENTHESIS && self.token != token.EOF { - if self.token != token.IDENTIFIER { - self.expect(token.IDENTIFIER) + for p.token != token.RIGHT_PARENTHESIS && p.token != token.EOF { + if p.token != token.IDENTIFIER { + p.expect(token.IDENTIFIER) } else { - identifier := self.parseIdentifier() + identifier := p.parseIdentifier() list = append(list, identifier) } - if self.token != token.RIGHT_PARENTHESIS { - if self.mode&StoreComments != 0 { - self.comments.Unset() + if p.token != token.RIGHT_PARENTHESIS { + if p.mode&StoreComments != 0 { + p.comments.Unset() } - self.expect(token.COMMA) + p.expect(token.COMMA) } } - closing := self.expect(token.RIGHT_PARENTHESIS) + closing := p.expect(token.RIGHT_PARENTHESIS) return &ast.ParameterList{ Opening: opening, @@ -240,285 +240,269 @@ func (self *_parser) parseFunctionParameterList() *ast.ParameterList { } } -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) parseFunctionStatement() *ast.FunctionStatement { +func (p *_parser) parseFunctionStatement() *ast.FunctionStatement { var comments []*ast.Comment - if self.mode&StoreComments != 0 { - comments = self.comments.FetchAll() + if p.mode&StoreComments != 0 { + comments = p.comments.FetchAll() } function := &ast.FunctionStatement{ - Function: self.parseFunction(true), + Function: p.parseFunction(true), } - if self.mode&StoreComments != 0 { - self.comments.CommentMap.AddComments(function, comments, ast.LEADING) + if p.mode&StoreComments != 0 { + p.comments.CommentMap.AddComments(function, comments, ast.LEADING) } return function } -func (self *_parser) parseFunction(declaration bool) *ast.FunctionLiteral { +func (p *_parser) parseFunction(declaration bool) *ast.FunctionLiteral { node := &ast.FunctionLiteral{ - Function: self.expect(token.FUNCTION), + Function: p.expect(token.FUNCTION), } var name *ast.Identifier - if self.token == token.IDENTIFIER { - name = self.parseIdentifier() + if p.token == token.IDENTIFIER { + name = p.parseIdentifier() if declaration { - self.scope.declare(&ast.FunctionDeclaration{ + p.scope.declare(&ast.FunctionDeclaration{ Function: node, }) } } else if declaration { // Use expect error handling - self.expect(token.IDENTIFIER) + p.expect(token.IDENTIFIER) } - if self.mode&StoreComments != 0 { - self.comments.Unset() + if p.mode&StoreComments != 0 { + p.comments.Unset() } node.Name = name - node.ParameterList = self.parseFunctionParameterList() - self.parseFunctionBlock(node) - node.Source = self.slice(node.Idx0(), node.Idx1()) + node.ParameterList = p.parseFunctionParameterList() + p.parseFunctionBlock(node) + node.Source = p.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 (p *_parser) parseFunctionBlock(node *ast.FunctionLiteral) { + p.openScope() + inFunction := p.scope.inFunction + p.scope.inFunction = true + defer func() { + p.scope.inFunction = inFunction + p.closeScope() + }() + node.Body = p.parseBlockStatement() + node.DeclarationList = p.scope.declarationList } -func (self *_parser) parseDebuggerStatement() ast.Statement { - idx := self.expect(token.DEBUGGER) +func (p *_parser) parseDebuggerStatement() ast.Statement { + idx := p.expect(token.DEBUGGER) node := &ast.DebuggerStatement{ Debugger: idx, } - if self.mode&StoreComments != 0 { - self.comments.CommentMap.AddComments(node, self.comments.FetchAll(), ast.TRAILING) + if p.mode&StoreComments != 0 { + p.comments.CommentMap.AddComments(node, p.comments.FetchAll(), ast.TRAILING) } - self.semicolon() + p.semicolon() return node } -func (self *_parser) parseReturnStatement() ast.Statement { - idx := self.expect(token.RETURN) +func (p *_parser) parseReturnStatement() ast.Statement { + idx := p.expect(token.RETURN) var comments []*ast.Comment - if self.mode&StoreComments != 0 { - comments = self.comments.FetchAll() + if p.mode&StoreComments != 0 { + comments = p.comments.FetchAll() } - if !self.scope.inFunction { - self.error(idx, "Illegal return statement") - self.nextStatement() - return &ast.BadStatement{From: idx, To: self.idx} + if !p.scope.inFunction { + p.error(idx, "Illegal return statement") + p.nextStatement() + return &ast.BadStatement{From: idx, To: p.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() + if !p.implicitSemicolon && p.token != token.SEMICOLON && p.token != token.RIGHT_BRACE && p.token != token.EOF { + node.Argument = p.parseExpression() } - if self.mode&StoreComments != 0 { - self.comments.CommentMap.AddComments(node, comments, ast.LEADING) + if p.mode&StoreComments != 0 { + p.comments.CommentMap.AddComments(node, comments, ast.LEADING) } - self.semicolon() + p.semicolon() return node } -func (self *_parser) parseThrowStatement() ast.Statement { +func (p *_parser) parseThrowStatement() ast.Statement { var comments []*ast.Comment - if self.mode&StoreComments != 0 { - comments = self.comments.FetchAll() + if p.mode&StoreComments != 0 { + comments = p.comments.FetchAll() } - idx := self.expect(token.THROW) + idx := p.expect(token.THROW) - if self.implicitSemicolon { - if self.chr == -1 { // Hackish - self.error(idx, "Unexpected end of input") + if p.implicitSemicolon { + if p.chr == -1 { // Hackish + p.error(idx, "Unexpected end of input") } else { - self.error(idx, "Illegal newline after throw") + p.error(idx, "Illegal newline after throw") } - self.nextStatement() - return &ast.BadStatement{From: idx, To: self.idx} + p.nextStatement() + return &ast.BadStatement{From: idx, To: p.idx} } node := &ast.ThrowStatement{ - Throw: self.idx, - Argument: self.parseExpression(), + Throw: p.idx, + Argument: p.parseExpression(), } - if self.mode&StoreComments != 0 { - self.comments.CommentMap.AddComments(node, comments, ast.LEADING) + if p.mode&StoreComments != 0 { + p.comments.CommentMap.AddComments(node, comments, ast.LEADING) } - self.semicolon() + p.semicolon() return node } -func (self *_parser) parseSwitchStatement() ast.Statement { +func (p *_parser) parseSwitchStatement() ast.Statement { var comments []*ast.Comment - if self.mode&StoreComments != 0 { - comments = self.comments.FetchAll() + if p.mode&StoreComments != 0 { + comments = p.comments.FetchAll() } - self.expect(token.SWITCH) - if self.mode&StoreComments != 0 { - comments = append(comments, self.comments.FetchAll()...) + p.expect(token.SWITCH) + if p.mode&StoreComments != 0 { + comments = append(comments, p.comments.FetchAll()...) } - self.expect(token.LEFT_PARENTHESIS) + p.expect(token.LEFT_PARENTHESIS) node := &ast.SwitchStatement{ - Discriminant: self.parseExpression(), + Discriminant: p.parseExpression(), Default: -1, } - self.expect(token.RIGHT_PARENTHESIS) - if self.mode&StoreComments != 0 { - comments = append(comments, self.comments.FetchAll()...) + p.expect(token.RIGHT_PARENTHESIS) + if p.mode&StoreComments != 0 { + comments = append(comments, p.comments.FetchAll()...) } - self.expect(token.LEFT_BRACE) + p.expect(token.LEFT_BRACE) - inSwitch := self.scope.inSwitch - self.scope.inSwitch = true + inSwitch := p.scope.inSwitch + p.scope.inSwitch = true defer func() { - self.scope.inSwitch = inSwitch + p.scope.inSwitch = inSwitch }() - for index := 0; self.token != token.EOF; index++ { - if self.token == token.RIGHT_BRACE { - self.next() + for index := 0; p.token != token.EOF; index++ { + if p.token == token.RIGHT_BRACE { + p.next() break } - clause := self.parseCaseStatement() + clause := p.parseCaseStatement() if clause.Test == nil { if node.Default != -1 { - self.error(clause.Case, "Already saw a default in switch") + p.error(clause.Case, "Already saw a default in switch") } node.Default = index } node.Body = append(node.Body, clause) } - if self.mode&StoreComments != 0 { - self.comments.CommentMap.AddComments(node, comments, ast.LEADING) + if p.mode&StoreComments != 0 { + p.comments.CommentMap.AddComments(node, comments, ast.LEADING) } return node } -func (self *_parser) parseWithStatement() ast.Statement { +func (p *_parser) parseWithStatement() ast.Statement { var comments []*ast.Comment - if self.mode&StoreComments != 0 { - comments = self.comments.FetchAll() + if p.mode&StoreComments != 0 { + comments = p.comments.FetchAll() } - self.expect(token.WITH) + p.expect(token.WITH) var withComments []*ast.Comment - if self.mode&StoreComments != 0 { - withComments = self.comments.FetchAll() + if p.mode&StoreComments != 0 { + withComments = p.comments.FetchAll() } - self.expect(token.LEFT_PARENTHESIS) + p.expect(token.LEFT_PARENTHESIS) node := &ast.WithStatement{ - Object: self.parseExpression(), + Object: p.parseExpression(), } - self.expect(token.RIGHT_PARENTHESIS) + p.expect(token.RIGHT_PARENTHESIS) - if self.mode&StoreComments != 0 { - self.comments.CommentMap.AddComments(node, comments, ast.LEADING) - self.comments.CommentMap.AddComments(node, withComments, ast.WITH) + if p.mode&StoreComments != 0 { + p.comments.CommentMap.AddComments(node, comments, ast.LEADING) + p.comments.CommentMap.AddComments(node, withComments, ast.WITH) } - node.Body = self.parseStatement() + node.Body = p.parseStatement() return node } -func (self *_parser) parseCaseStatement() *ast.CaseStatement { +func (p *_parser) parseCaseStatement() *ast.CaseStatement { node := &ast.CaseStatement{ - Case: self.idx, + Case: p.idx, } var comments []*ast.Comment - if self.mode&StoreComments != 0 { - comments = self.comments.FetchAll() - self.comments.Unset() + if p.mode&StoreComments != 0 { + comments = p.comments.FetchAll() + p.comments.Unset() } - if self.token == token.DEFAULT { - self.next() + if p.token == token.DEFAULT { + p.next() } else { - self.expect(token.CASE) - node.Test = self.parseExpression() + p.expect(token.CASE) + node.Test = p.parseExpression() } - if self.mode&StoreComments != 0 { - self.comments.Unset() + if p.mode&StoreComments != 0 { + p.comments.Unset() } - self.expect(token.COLON) + p.expect(token.COLON) for { - if self.token == token.EOF || - self.token == token.RIGHT_BRACE || - self.token == token.CASE || - self.token == token.DEFAULT { + if p.token == token.EOF || + p.token == token.RIGHT_BRACE || + p.token == token.CASE || + p.token == token.DEFAULT { break } - consequent := self.parseStatement() + consequent := p.parseStatement() node.Consequent = append(node.Consequent, consequent) } // Link the comments to the case statement - if self.mode&StoreComments != 0 { - self.comments.CommentMap.AddComments(node, comments, ast.LEADING) + if p.mode&StoreComments != 0 { + p.comments.CommentMap.AddComments(node, comments, ast.LEADING) } return node } -func (self *_parser) parseIterationStatement() ast.Statement { - inIteration := self.scope.inIteration - self.scope.inIteration = true +func (p *_parser) parseIterationStatement() ast.Statement { + inIteration := p.scope.inIteration + p.scope.inIteration = true defer func() { - self.scope.inIteration = inIteration + p.scope.inIteration = inIteration }() - return self.parseStatement() + return p.parseStatement() } -func (self *_parser) parseForIn(into ast.Expression) *ast.ForInStatement { +func (p *_parser) parseForIn(into ast.Expression) *ast.ForInStatement { // Already have consumed " in" - source := self.parseExpression() - self.expect(token.RIGHT_PARENTHESIS) - body := self.parseIterationStatement() + source := p.parseExpression() + p.expect(token.RIGHT_PARENTHESIS) + body := p.parseIterationStatement() forin := &ast.ForInStatement{ Into: into, @@ -529,24 +513,24 @@ func (self *_parser) parseForIn(into ast.Expression) *ast.ForInStatement { return forin } -func (self *_parser) parseFor(initializer ast.Expression) *ast.ForStatement { +func (p *_parser) parseFor(initializer ast.Expression) *ast.ForStatement { // Already have consumed " ;" var test, update ast.Expression - if self.token != token.SEMICOLON { - test = self.parseExpression() + if p.token != token.SEMICOLON { + test = p.parseExpression() } - if self.mode&StoreComments != 0 { - self.comments.Unset() + if p.mode&StoreComments != 0 { + p.comments.Unset() } - self.expect(token.SEMICOLON) + p.expect(token.SEMICOLON) - if self.token != token.RIGHT_PARENTHESIS { - update = self.parseExpression() + if p.token != token.RIGHT_PARENTHESIS { + update = p.parseExpression() } - self.expect(token.RIGHT_PARENTHESIS) - body := self.parseIterationStatement() + p.expect(token.RIGHT_PARENTHESIS) + body := p.parseIterationStatement() forstatement := &ast.ForStatement{ Initializer: initializer, @@ -558,54 +542,54 @@ func (self *_parser) parseFor(initializer ast.Expression) *ast.ForStatement { return forstatement } -func (self *_parser) parseForOrForInStatement() ast.Statement { +func (p *_parser) parseForOrForInStatement() ast.Statement { var comments []*ast.Comment - if self.mode&StoreComments != 0 { - comments = self.comments.FetchAll() + if p.mode&StoreComments != 0 { + comments = p.comments.FetchAll() } - idx := self.expect(token.FOR) + idx := p.expect(token.FOR) var forComments []*ast.Comment - if self.mode&StoreComments != 0 { - forComments = self.comments.FetchAll() + if p.mode&StoreComments != 0 { + forComments = p.comments.FetchAll() } - self.expect(token.LEFT_PARENTHESIS) + p.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 + if p.token != token.SEMICOLON { + allowIn := p.scope.allowIn + p.scope.allowIn = false + if p.token == token.VAR { + idx := p.idx var varComments []*ast.Comment - if self.mode&StoreComments != 0 { - varComments = self.comments.FetchAll() - self.comments.Unset() + if p.mode&StoreComments != 0 { + varComments = p.comments.FetchAll() + p.comments.Unset() } - self.next() - list := self.parseVariableDeclarationList(var_) - if len(list) == 1 && self.token == token.IN { - if self.mode&StoreComments != 0 { - self.comments.Unset() + p.next() + list := p.parseVariableDeclarationList(idx) + if len(list) == 1 && p.token == token.IN { + if p.mode&StoreComments != 0 { + p.comments.Unset() } - self.next() // in + p.next() // in forIn = true left = []ast.Expression{list[0]} // There is only one declaration } else { left = list } - if self.mode&StoreComments != 0 { - self.comments.CommentMap.AddComments(left[0], varComments, ast.LEADING) + if p.mode&StoreComments != 0 { + p.comments.CommentMap.AddComments(left[0], varComments, ast.LEADING) } } else { - left = append(left, self.parseExpression()) - if self.token == token.IN { - self.next() + left = append(left, p.parseExpression()) + if p.token == token.IN { + p.next() forIn = true } } - self.scope.allowIn = allowIn + p.scope.allowIn = allowIn } if forIn { @@ -613,209 +597,209 @@ func (self *_parser) parseForOrForInStatement() ast.Statement { 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} + p.error(idx, "Invalid left-hand side in for-in") + p.nextStatement() + return &ast.BadStatement{From: idx, To: p.idx} } - forin := self.parseForIn(left[0]) - if self.mode&StoreComments != 0 { - self.comments.CommentMap.AddComments(forin, comments, ast.LEADING) - self.comments.CommentMap.AddComments(forin, forComments, ast.FOR) + forin := p.parseForIn(left[0]) + if p.mode&StoreComments != 0 { + p.comments.CommentMap.AddComments(forin, comments, ast.LEADING) + p.comments.CommentMap.AddComments(forin, forComments, ast.FOR) } return forin } - if self.mode&StoreComments != 0 { - self.comments.Unset() + if p.mode&StoreComments != 0 { + p.comments.Unset() } - self.expect(token.SEMICOLON) + p.expect(token.SEMICOLON) initializer := &ast.SequenceExpression{Sequence: left} - forstatement := self.parseFor(initializer) - if self.mode&StoreComments != 0 { - self.comments.CommentMap.AddComments(forstatement, comments, ast.LEADING) - self.comments.CommentMap.AddComments(forstatement, forComments, ast.FOR) + forstatement := p.parseFor(initializer) + if p.mode&StoreComments != 0 { + p.comments.CommentMap.AddComments(forstatement, comments, ast.LEADING) + p.comments.CommentMap.AddComments(forstatement, forComments, ast.FOR) } return forstatement } -func (self *_parser) parseVariableStatement() *ast.VariableStatement { +func (p *_parser) parseVariableStatement() *ast.VariableStatement { var comments []*ast.Comment - if self.mode&StoreComments != 0 { - comments = self.comments.FetchAll() + if p.mode&StoreComments != 0 { + comments = p.comments.FetchAll() } - idx := self.expect(token.VAR) + idx := p.expect(token.VAR) - list := self.parseVariableDeclarationList(idx) + list := p.parseVariableDeclarationList(idx) statement := &ast.VariableStatement{ Var: idx, List: list, } - if self.mode&StoreComments != 0 { - self.comments.CommentMap.AddComments(statement, comments, ast.LEADING) - self.comments.Unset() + if p.mode&StoreComments != 0 { + p.comments.CommentMap.AddComments(statement, comments, ast.LEADING) + p.comments.Unset() } - self.semicolon() + p.semicolon() return statement } -func (self *_parser) parseDoWhileStatement() ast.Statement { - inIteration := self.scope.inIteration - self.scope.inIteration = true +func (p *_parser) parseDoWhileStatement() ast.Statement { + inIteration := p.scope.inIteration + p.scope.inIteration = true defer func() { - self.scope.inIteration = inIteration + p.scope.inIteration = inIteration }() var comments []*ast.Comment - if self.mode&StoreComments != 0 { - comments = self.comments.FetchAll() + if p.mode&StoreComments != 0 { + comments = p.comments.FetchAll() } - self.expect(token.DO) + p.expect(token.DO) var doComments []*ast.Comment - if self.mode&StoreComments != 0 { - doComments = self.comments.FetchAll() + if p.mode&StoreComments != 0 { + doComments = p.comments.FetchAll() } node := &ast.DoWhileStatement{} - if self.token == token.LEFT_BRACE { - node.Body = self.parseBlockStatement() + if p.token == token.LEFT_BRACE { + node.Body = p.parseBlockStatement() } else { - node.Body = self.parseStatement() + node.Body = p.parseStatement() } - self.expect(token.WHILE) + p.expect(token.WHILE) var whileComments []*ast.Comment - if self.mode&StoreComments != 0 { - whileComments = self.comments.FetchAll() + if p.mode&StoreComments != 0 { + whileComments = p.comments.FetchAll() } - self.expect(token.LEFT_PARENTHESIS) - node.Test = self.parseExpression() - self.expect(token.RIGHT_PARENTHESIS) + p.expect(token.LEFT_PARENTHESIS) + node.Test = p.parseExpression() + p.expect(token.RIGHT_PARENTHESIS) - self.implicitSemicolon = true - self.optionalSemicolon() + p.implicitSemicolon = true + p.optionalSemicolon() - if self.mode&StoreComments != 0 { - self.comments.CommentMap.AddComments(node, comments, ast.LEADING) - self.comments.CommentMap.AddComments(node, doComments, ast.DO) - self.comments.CommentMap.AddComments(node, whileComments, ast.WHILE) + if p.mode&StoreComments != 0 { + p.comments.CommentMap.AddComments(node, comments, ast.LEADING) + p.comments.CommentMap.AddComments(node, doComments, ast.DO) + p.comments.CommentMap.AddComments(node, whileComments, ast.WHILE) } return node } -func (self *_parser) parseWhileStatement() ast.Statement { +func (p *_parser) parseWhileStatement() ast.Statement { var comments []*ast.Comment - if self.mode&StoreComments != 0 { - comments = self.comments.FetchAll() + if p.mode&StoreComments != 0 { + comments = p.comments.FetchAll() } - self.expect(token.WHILE) + p.expect(token.WHILE) var whileComments []*ast.Comment - if self.mode&StoreComments != 0 { - whileComments = self.comments.FetchAll() + if p.mode&StoreComments != 0 { + whileComments = p.comments.FetchAll() } - self.expect(token.LEFT_PARENTHESIS) + p.expect(token.LEFT_PARENTHESIS) node := &ast.WhileStatement{ - Test: self.parseExpression(), + Test: p.parseExpression(), } - self.expect(token.RIGHT_PARENTHESIS) - node.Body = self.parseIterationStatement() + p.expect(token.RIGHT_PARENTHESIS) + node.Body = p.parseIterationStatement() - if self.mode&StoreComments != 0 { - self.comments.CommentMap.AddComments(node, comments, ast.LEADING) - self.comments.CommentMap.AddComments(node, whileComments, ast.WHILE) + if p.mode&StoreComments != 0 { + p.comments.CommentMap.AddComments(node, comments, ast.LEADING) + p.comments.CommentMap.AddComments(node, whileComments, ast.WHILE) } return node } -func (self *_parser) parseIfStatement() ast.Statement { +func (p *_parser) parseIfStatement() ast.Statement { var comments []*ast.Comment - if self.mode&StoreComments != 0 { - comments = self.comments.FetchAll() + if p.mode&StoreComments != 0 { + comments = p.comments.FetchAll() } - self.expect(token.IF) + p.expect(token.IF) var ifComments []*ast.Comment - if self.mode&StoreComments != 0 { - ifComments = self.comments.FetchAll() + if p.mode&StoreComments != 0 { + ifComments = p.comments.FetchAll() } - self.expect(token.LEFT_PARENTHESIS) + p.expect(token.LEFT_PARENTHESIS) node := &ast.IfStatement{ - If: self.idx, - Test: self.parseExpression(), + If: p.idx, + Test: p.parseExpression(), } - self.expect(token.RIGHT_PARENTHESIS) - if self.token == token.LEFT_BRACE { - node.Consequent = self.parseBlockStatement() + p.expect(token.RIGHT_PARENTHESIS) + if p.token == token.LEFT_BRACE { + node.Consequent = p.parseBlockStatement() } else { - node.Consequent = self.parseStatement() + node.Consequent = p.parseStatement() } - if self.token == token.ELSE { - self.next() - node.Alternate = self.parseStatement() + if p.token == token.ELSE { + p.next() + node.Alternate = p.parseStatement() } - if self.mode&StoreComments != 0 { - self.comments.CommentMap.AddComments(node, comments, ast.LEADING) - self.comments.CommentMap.AddComments(node, ifComments, ast.IF) + if p.mode&StoreComments != 0 { + p.comments.CommentMap.AddComments(node, comments, ast.LEADING) + p.comments.CommentMap.AddComments(node, ifComments, ast.IF) } return node } -func (self *_parser) parseSourceElement() ast.Statement { - statement := self.parseStatement() +func (p *_parser) parseSourceElement() ast.Statement { + statement := p.parseStatement() return statement } -func (self *_parser) parseSourceElements() []ast.Statement { +func (p *_parser) parseSourceElements() []ast.Statement { body := []ast.Statement(nil) for { - if self.token != token.STRING { + if p.token != token.STRING { break } - body = append(body, self.parseSourceElement()) + body = append(body, p.parseSourceElement()) } - for self.token != token.EOF { - body = append(body, self.parseSourceElement()) + for p.token != token.EOF { + body = append(body, p.parseSourceElement()) } return body } -func (self *_parser) parseProgram() *ast.Program { - self.openScope() - defer self.closeScope() +func (p *_parser) parseProgram() *ast.Program { + p.openScope() + defer p.closeScope() return &ast.Program{ - Body: self.parseSourceElements(), - DeclarationList: self.scope.declarationList, - File: self.file, + Body: p.parseSourceElements(), + DeclarationList: p.scope.declarationList, + File: p.file, } } -func (self *_parser) parseBreakStatement() ast.Statement { +func (p *_parser) parseBreakStatement() ast.Statement { var comments []*ast.Comment - if self.mode&StoreComments != 0 { - comments = self.comments.FetchAll() + if p.mode&StoreComments != 0 { + comments = p.comments.FetchAll() } - idx := self.expect(token.BREAK) - semicolon := self.implicitSemicolon - if self.token == token.SEMICOLON { + idx := p.expect(token.BREAK) + semicolon := p.implicitSemicolon + if p.token == token.SEMICOLON { semicolon = true - self.next() + p.next() } - if semicolon || self.token == token.RIGHT_BRACE { - self.implicitSemicolon = false - if !self.scope.inIteration && !self.scope.inSwitch { + if semicolon || p.token == token.RIGHT_BRACE { + p.implicitSemicolon = false + if !p.scope.inIteration && !p.scope.inSwitch { goto illegal } breakStatement := &ast.BranchStatement{ @@ -823,52 +807,52 @@ func (self *_parser) parseBreakStatement() ast.Statement { Token: token.BREAK, } - if self.mode&StoreComments != 0 { - self.comments.CommentMap.AddComments(breakStatement, comments, ast.LEADING) - self.comments.CommentMap.AddComments(breakStatement, self.comments.FetchAll(), ast.TRAILING) + if p.mode&StoreComments != 0 { + p.comments.CommentMap.AddComments(breakStatement, comments, ast.LEADING) + p.comments.CommentMap.AddComments(breakStatement, p.comments.FetchAll(), ast.TRAILING) } return breakStatement } - if self.token == token.IDENTIFIER { - identifier := self.parseIdentifier() - if !self.scope.hasLabel(identifier.Name) { - self.error(idx, "Undefined label '%s'", identifier.Name) + if p.token == token.IDENTIFIER { + identifier := p.parseIdentifier() + if !p.scope.hasLabel(identifier.Name) { + p.error(idx, "Undefined label '%s'", identifier.Name) return &ast.BadStatement{From: idx, To: identifier.Idx1()} } - self.semicolon() + p.semicolon() breakStatement := &ast.BranchStatement{ Idx: idx, Token: token.BREAK, Label: identifier, } - if self.mode&StoreComments != 0 { - self.comments.CommentMap.AddComments(breakStatement, comments, ast.LEADING) + if p.mode&StoreComments != 0 { + p.comments.CommentMap.AddComments(breakStatement, comments, ast.LEADING) } return breakStatement } - self.expect(token.IDENTIFIER) + p.expect(token.IDENTIFIER) illegal: - self.error(idx, "Illegal break statement") - self.nextStatement() - return &ast.BadStatement{From: idx, To: self.idx} + p.error(idx, "Illegal break statement") + p.nextStatement() + return &ast.BadStatement{From: idx, To: p.idx} } -func (self *_parser) parseContinueStatement() ast.Statement { - idx := self.expect(token.CONTINUE) - semicolon := self.implicitSemicolon - if self.token == token.SEMICOLON { +func (p *_parser) parseContinueStatement() ast.Statement { + idx := p.expect(token.CONTINUE) + semicolon := p.implicitSemicolon + if p.token == token.SEMICOLON { semicolon = true - self.next() + p.next() } - if semicolon || self.token == token.RIGHT_BRACE { - self.implicitSemicolon = false - if !self.scope.inIteration { + if semicolon || p.token == token.RIGHT_BRACE { + p.implicitSemicolon = false + if !p.scope.inIteration { goto illegal } return &ast.BranchStatement{ @@ -877,16 +861,16 @@ func (self *_parser) parseContinueStatement() ast.Statement { } } - if self.token == token.IDENTIFIER { - identifier := self.parseIdentifier() - if !self.scope.hasLabel(identifier.Name) { - self.error(idx, "Undefined label '%s'", identifier.Name) + if p.token == token.IDENTIFIER { + identifier := p.parseIdentifier() + if !p.scope.hasLabel(identifier.Name) { + p.error(idx, "Undefined label '%s'", identifier.Name) return &ast.BadStatement{From: idx, To: identifier.Idx1()} } - if !self.scope.inIteration { + if !p.scope.inIteration { goto illegal } - self.semicolon() + p.semicolon() return &ast.BranchStatement{ Idx: idx, Token: token.CONTINUE, @@ -894,18 +878,18 @@ func (self *_parser) parseContinueStatement() ast.Statement { } } - self.expect(token.IDENTIFIER) + p.expect(token.IDENTIFIER) illegal: - self.error(idx, "Illegal continue statement") - self.nextStatement() - return &ast.BadStatement{From: idx, To: self.idx} + p.error(idx, "Illegal continue statement") + p.nextStatement() + return &ast.BadStatement{From: idx, To: p.idx} } -// Find the next statement after an error (recover) -func (self *_parser) nextStatement() { +// Find the next statement after an error (recover). +func (p *_parser) nextStatement() { for { - switch self.token { + switch p.token { case token.BREAK, token.CONTINUE, token.FOR, token.IF, token.RETURN, token.SWITCH, token.VAR, token.DO, token.TRY, token.WITH, @@ -914,13 +898,13 @@ func (self *_parser) nextStatement() { // 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++ + if p.idx == p.recover.idx && p.recover.count < 10 { + p.recover.count++ return } - if self.idx > self.recover.idx { - self.recover.idx = self.idx - self.recover.count = 0 + if p.idx > p.recover.idx { + p.recover.idx = p.idx + p.recover.count = 0 return } // Reaching here indicates a parser bug, likely an @@ -931,6 +915,6 @@ func (self *_parser) nextStatement() { case token.EOF: return } - self.next() + p.next() } } diff --git a/property.go b/property.go index 23ea2583..8fa7c1c0 100644 --- a/property.go +++ b/property.go @@ -2,87 +2,87 @@ package otto // property -type _propertyMode int +type propertyMode int const ( - modeWriteMask _propertyMode = 0700 - modeEnumerateMask = 0070 - modeConfigureMask = 0007 - modeOnMask = 0111 - modeSetMask = 0222 // If value is 2, then mode is neither "On" nor "Off" + modeWriteMask propertyMode = 0o700 + modeEnumerateMask propertyMode = 0o070 + modeConfigureMask propertyMode = 0o007 + modeOnMask propertyMode = 0o111 + modeSetMask propertyMode = 0o222 // If value is 2, then mode is neither "On" nor "Off" ) -type _propertyGetSet [2]*_object +type propertyGetSet [2]*object -var _nilGetSetObject _object = _object{} +var nilGetSetObject = object{} -type _property struct { +type property struct { value interface{} - mode _propertyMode + mode propertyMode } -func (self _property) writable() bool { - return self.mode&modeWriteMask == modeWriteMask&modeOnMask +func (p property) writable() bool { + return p.mode&modeWriteMask == modeWriteMask&modeOnMask } -func (self *_property) writeOn() { - self.mode = (self.mode & ^modeWriteMask) | (modeWriteMask & modeOnMask) +func (p *property) writeOn() { + p.mode = (p.mode & ^modeWriteMask) | (modeWriteMask & modeOnMask) } -func (self *_property) writeOff() { - self.mode &= ^modeWriteMask +func (p *property) writeOff() { + p.mode &= ^modeWriteMask } -func (self *_property) writeClear() { - self.mode = (self.mode & ^modeWriteMask) | (modeWriteMask & modeSetMask) +func (p *property) writeClear() { + p.mode = (p.mode & ^modeWriteMask) | (modeWriteMask & modeSetMask) } -func (self _property) writeSet() bool { - return 0 == self.mode&modeWriteMask&modeSetMask +func (p property) writeSet() bool { + return p.mode&modeWriteMask&modeSetMask == 0 } -func (self _property) enumerable() bool { - return self.mode&modeEnumerateMask == modeEnumerateMask&modeOnMask +func (p property) enumerable() bool { + return p.mode&modeEnumerateMask == modeEnumerateMask&modeOnMask } -func (self *_property) enumerateOn() { - self.mode = (self.mode & ^modeEnumerateMask) | (modeEnumerateMask & modeOnMask) +func (p *property) enumerateOn() { + p.mode = (p.mode & ^modeEnumerateMask) | (modeEnumerateMask & modeOnMask) } -func (self *_property) enumerateOff() { - self.mode &= ^modeEnumerateMask +func (p *property) enumerateOff() { + p.mode &= ^modeEnumerateMask } -func (self _property) enumerateSet() bool { - return 0 == self.mode&modeEnumerateMask&modeSetMask +func (p property) enumerateSet() bool { + return p.mode&modeEnumerateMask&modeSetMask == 0 } -func (self _property) configurable() bool { - return self.mode&modeConfigureMask == modeConfigureMask&modeOnMask +func (p property) configurable() bool { + return p.mode&modeConfigureMask == modeConfigureMask&modeOnMask } -func (self *_property) configureOn() { - self.mode = (self.mode & ^modeConfigureMask) | (modeConfigureMask & modeOnMask) +func (p *property) configureOn() { + p.mode = (p.mode & ^modeConfigureMask) | (modeConfigureMask & modeOnMask) } -func (self *_property) configureOff() { - self.mode &= ^modeConfigureMask +func (p *property) configureOff() { + p.mode &= ^modeConfigureMask } -func (self _property) configureSet() bool { - return 0 == self.mode&modeConfigureMask&modeSetMask +func (p property) configureSet() bool { //nolint: unused + return p.mode&modeConfigureMask&modeSetMask == 0 } -func (self _property) copy() *_property { - property := self - return &property +func (p property) copy() *property { //nolint: unused + cpy := p + return &cpy } -func (self _property) get(this *_object) Value { - switch value := self.value.(type) { +func (p property) get(this *object) Value { + switch value := p.value.(type) { case Value: return value - case _propertyGetSet: + case propertyGetSet: if value[0] != nil { return value[0].call(toValue(this), nil, false, nativeFrame) } @@ -90,64 +90,63 @@ func (self _property) get(this *_object) Value { return Value{} } -func (self _property) isAccessorDescriptor() bool { - setGet, test := self.value.(_propertyGetSet) +func (p property) isAccessorDescriptor() bool { + setGet, test := p.value.(propertyGetSet) return test && (setGet[0] != nil || setGet[1] != nil) } -func (self _property) isDataDescriptor() bool { - if self.writeSet() { // Either "On" or "Off" +func (p property) isDataDescriptor() bool { + if p.writeSet() { // Either "On" or "Off" return true } - value, valid := self.value.(Value) + value, valid := p.value.(Value) return valid && !value.isEmpty() } -func (self _property) isGenericDescriptor() bool { - return !(self.isDataDescriptor() || self.isAccessorDescriptor()) +func (p property) isGenericDescriptor() bool { + return !(p.isDataDescriptor() || p.isAccessorDescriptor()) } -func (self _property) isEmpty() bool { - return self.mode == 0222 && self.isGenericDescriptor() +func (p property) isEmpty() bool { + return p.mode == 0o222 && p.isGenericDescriptor() } // _enumerableValue, _enumerableTrue, _enumerableFalse? // .enumerableValue() .enumerableExists() -func toPropertyDescriptor(rt *_runtime, value Value) (descriptor _property) { - objectDescriptor := value._object() +func toPropertyDescriptor(rt *runtime, value Value) property { + objectDescriptor := value.object() if objectDescriptor == nil { panic(rt.panicTypeError()) } - { - descriptor.mode = modeSetMask // Initially nothing is set - if objectDescriptor.hasProperty("enumerable") { - if objectDescriptor.get("enumerable").bool() { - descriptor.enumerateOn() - } else { - descriptor.enumerateOff() - } + var descriptor property + descriptor.mode = modeSetMask // Initially nothing is set + if objectDescriptor.hasProperty("enumerable") { + if objectDescriptor.get("enumerable").bool() { + descriptor.enumerateOn() + } else { + descriptor.enumerateOff() } + } - if objectDescriptor.hasProperty("configurable") { - if objectDescriptor.get("configurable").bool() { - descriptor.configureOn() - } else { - descriptor.configureOff() - } + if objectDescriptor.hasProperty("configurable") { + if objectDescriptor.get("configurable").bool() { + descriptor.configureOn() + } else { + descriptor.configureOff() } + } - if objectDescriptor.hasProperty("writable") { - if objectDescriptor.get("writable").bool() { - descriptor.writeOn() - } else { - descriptor.writeOff() - } + if objectDescriptor.hasProperty("writable") { + if objectDescriptor.get("writable").bool() { + descriptor.writeOn() + } else { + descriptor.writeOff() } } - var getter, setter *_object + var getter, setter *object getterSetter := false if objectDescriptor.hasProperty("get") { @@ -156,10 +155,10 @@ func toPropertyDescriptor(rt *_runtime, value Value) (descriptor _property) { if !value.isCallable() { panic(rt.panicTypeError()) } - getter = value._object() + getter = value.object() getterSetter = true } else { - getter = &_nilGetSetObject + getter = &nilGetSetObject getterSetter = true } } @@ -170,10 +169,10 @@ func toPropertyDescriptor(rt *_runtime, value Value) (descriptor _property) { if !value.isCallable() { panic(rt.panicTypeError()) } - setter = value._object() + setter = value.object() getterSetter = true } else { - setter = &_nilGetSetObject + setter = &nilGetSetObject getterSetter = true } } @@ -182,7 +181,7 @@ func toPropertyDescriptor(rt *_runtime, value Value) (descriptor _property) { if descriptor.writeSet() { panic(rt.panicTypeError()) } - descriptor.value = _propertyGetSet{getter, setter} + descriptor.value = propertyGetSet{getter, setter} } if objectDescriptor.hasProperty("value") { @@ -192,28 +191,28 @@ func toPropertyDescriptor(rt *_runtime, value Value) (descriptor _property) { descriptor.value = objectDescriptor.get("value") } - return + return descriptor } -func (self *_runtime) fromPropertyDescriptor(descriptor _property) *_object { - object := self.newObject() +func (rt *runtime) fromPropertyDescriptor(descriptor property) *object { + obj := rt.newObject() if descriptor.isDataDescriptor() { - object.defineProperty("value", descriptor.value.(Value), 0111, false) - object.defineProperty("writable", toValue_bool(descriptor.writable()), 0111, false) + obj.defineProperty("value", descriptor.value.(Value), 0o111, false) + obj.defineProperty("writable", boolValue(descriptor.writable()), 0o111, false) } else if descriptor.isAccessorDescriptor() { - getSet := descriptor.value.(_propertyGetSet) + getSet := descriptor.value.(propertyGetSet) get := Value{} if getSet[0] != nil { - get = toValue_object(getSet[0]) + get = objectValue(getSet[0]) } set := Value{} if getSet[1] != nil { - set = toValue_object(getSet[1]) + set = objectValue(getSet[1]) } - object.defineProperty("get", get, 0111, false) - object.defineProperty("set", set, 0111, false) + obj.defineProperty("get", get, 0o111, false) + obj.defineProperty("set", set, 0o111, false) } - object.defineProperty("enumerable", toValue_bool(descriptor.enumerable()), 0111, false) - object.defineProperty("configurable", toValue_bool(descriptor.configurable()), 0111, false) - return object + obj.defineProperty("enumerable", boolValue(descriptor.enumerable()), 0o111, false) + obj.defineProperty("configurable", boolValue(descriptor.configurable()), 0o111, false) + return obj } diff --git a/reflect_test.go b/reflect_test.go index ba5efff3..5c3e6935 100644 --- a/reflect_test.go +++ b/reflect_test.go @@ -12,7 +12,7 @@ import ( "github.com/stretchr/testify/require" ) -type _abcStruct struct { +type abcStruct struct { Abc bool Def int Ghi string @@ -21,91 +21,90 @@ type _abcStruct struct { Pqr map[string]int8 } -func (abc _abcStruct) String() string { +func (abc abcStruct) String() string { return abc.Ghi } -func (abc *_abcStruct) FuncPointer() string { +func (abc *abcStruct) FuncPointer() string { return "abc" } -func (abc _abcStruct) Func() { - return +func (abc abcStruct) Func() { } -func (abc _abcStruct) FuncReturn1() string { +func (abc abcStruct) FuncReturn1() string { return "abc" } -func (abc _abcStruct) FuncReturn2() (string, error) { +func (abc abcStruct) FuncReturn2() (string, error) { return "def", nil } -func (abc _abcStruct) Func1Return1(a string) string { +func (abc abcStruct) Func1Return1(a string) string { return a } -func (abc _abcStruct) Func2Return1(x, y string) string { +func (abc abcStruct) Func2Return1(x, y string) string { return x + y } -func (abc _abcStruct) FuncEllipsis(xyz ...string) int { +func (abc abcStruct) FuncEllipsis(xyz ...string) int { return len(xyz) } -func (abc _abcStruct) FuncReturnStruct() _mnoStruct { +func (abc abcStruct) FuncReturnStruct() _mnoStruct { return _mnoStruct{} } -func (abs _abcStruct) Func1Int(i int) int { +func (abc abcStruct) Func1Int(i int) int { return i + 1 } -func (abs _abcStruct) Func1Int8(i int8) int8 { +func (abc abcStruct) Func1Int8(i int8) int8 { return i + 1 } -func (abs _abcStruct) Func1Int16(i int16) int16 { +func (abc abcStruct) Func1Int16(i int16) int16 { return i + 1 } -func (abs _abcStruct) Func1Int32(i int32) int32 { +func (abc abcStruct) Func1Int32(i int32) int32 { return i + 1 } -func (abs _abcStruct) Func1Int64(i int64) int64 { +func (abc abcStruct) Func1Int64(i int64) int64 { return i + 1 } -func (abs _abcStruct) Func1Uint(i uint) uint { +func (abc abcStruct) Func1Uint(i uint) uint { return i + 1 } -func (abs _abcStruct) Func1Uint8(i uint8) uint8 { +func (abc abcStruct) Func1Uint8(i uint8) uint8 { return i + 1 } -func (abs _abcStruct) Func1Uint16(i uint16) uint16 { +func (abc abcStruct) Func1Uint16(i uint16) uint16 { return i + 1 } -func (abs _abcStruct) Func1Uint32(i uint32) uint32 { +func (abc abcStruct) Func1Uint32(i uint32) uint32 { return i + 1 } -func (abs _abcStruct) Func1Uint64(i uint64) uint64 { +func (abc abcStruct) Func1Uint64(i uint64) uint64 { return i + 1 } -func (abs _abcStruct) Func2Int(i, j int) int { +func (abc abcStruct) Func2Int(i, j int) int { return i + j } -func (abs _abcStruct) Func2StringInt(s string, i int) string { +func (abc abcStruct) Func2StringInt(s string, i int) string { return fmt.Sprintf("%v:%v", s, i) } -func (abs _abcStruct) Func1IntVariadic(a ...int) int { +func (abc abcStruct) Func1IntVariadic(a ...int) int { t := 0 for _, i := range a { t += i @@ -113,7 +112,7 @@ func (abs _abcStruct) Func1IntVariadic(a ...int) int { return t } -func (abs _abcStruct) Func2IntVariadic(s string, a ...int) string { +func (abc abcStruct) Func2IntVariadic(s string, a ...int) string { t := 0 for _, i := range a { t += i @@ -121,7 +120,7 @@ func (abs _abcStruct) Func2IntVariadic(s string, a ...int) string { return fmt.Sprintf("%v:%v", s, t) } -func (abs _abcStruct) Func2IntArrayVariadic(s string, a ...[]int) string { +func (abc abcStruct) Func2IntArrayVariadic(s string, a ...[]int) string { t := 0 for _, i := range a { for _, j := range i { @@ -145,10 +144,12 @@ func TestReflect(t *testing.T) { // These should panic str := "test" require.Panics(t, func() { - toValue("Xyzzy").toReflectValue(reflect.ValueOf(&str).Type()) + _, err := toValue("Xyzzy").toReflectValue(reflect.ValueOf(&str).Type()) + require.NoError(t, err) }) require.Panics(t, func() { - stringToReflectValue("Xyzzy", reflect.Ptr) + _, err := stringToReflectValue("Xyzzy", reflect.Ptr) + require.NoError(t, err) }) }) } @@ -159,7 +160,7 @@ func Test_reflectStruct(t *testing.T) { // _abcStruct { - abc := &_abcStruct{} + abc := &abcStruct{} vm.Set("abc", abc) test(` @@ -173,7 +174,7 @@ func Test_reflectStruct(t *testing.T) { [ abc.Abc, abc.Ghi ]; `, "true,Nothing happens.") - *abc = _abcStruct{} + *abc = abcStruct{} test(` [ abc.Abc, abc.Ghi ]; @@ -699,7 +700,7 @@ func Test_reflectMapInterface(t *testing.T) { "jkl": "jkl", } vm.Set("abc", abc) - vm.Set("mno", &_abcStruct{}) + vm.Set("mno", &abcStruct{}) test(` abc.xyz = "pqr"; @@ -714,7 +715,7 @@ func Test_reflectMapInterface(t *testing.T) { is(abc["xyz"], "pqr") is(abc["ghi"], map[string]interface{}{}) is(abc["jkl"], float64(3.14159)) - mno, valid := abc["mno"].(*_abcStruct) + mno, valid := abc["mno"].(*abcStruct) is(valid, true) is(mno.Abc, true) is(mno.Ghi, "Something happens.") @@ -727,7 +728,7 @@ func TestPassthrough(t *testing.T) { test, vm := test() { - abc := &_abcStruct{ + abc := &abcStruct{ Mno: _mnoStruct{ Ghi: "", }, @@ -762,13 +763,13 @@ func TestPassthrough(t *testing.T) { }) } -type TestDynamicFunctionReturningInterface_MyStruct1 struct{} //nolint: errname +type TestDynamicFunctionReturningInterfaceMyStruct1 struct{} //nolint: errname -func (m *TestDynamicFunctionReturningInterface_MyStruct1) Error() string { return "MyStruct1" } +func (m *TestDynamicFunctionReturningInterfaceMyStruct1) Error() string { return "MyStruct1" } -type TestDynamicFunctionReturningInterface_MyStruct2 struct{} //nolint: errname +type TestDynamicFunctionReturningInterfaceMyStruct2 struct{} //nolint: errname -func (m *TestDynamicFunctionReturningInterface_MyStruct2) Error() string { return "MyStruct2" } +func (m *TestDynamicFunctionReturningInterfaceMyStruct2) Error() string { return "MyStruct2" } func TestDynamicFunctionReturningInterface(t *testing.T) { tt(t, func() { @@ -777,8 +778,8 @@ func TestDynamicFunctionReturningInterface(t *testing.T) { var l []func() error vm.Set("r", func(cb func() error) { l = append(l, cb) }) - vm.Set("e1", func() error { return &TestDynamicFunctionReturningInterface_MyStruct1{} }) - vm.Set("e2", func() error { return &TestDynamicFunctionReturningInterface_MyStruct2{} }) + vm.Set("e1", func() error { return &TestDynamicFunctionReturningInterfaceMyStruct1{} }) + vm.Set("e2", func() error { return &TestDynamicFunctionReturningInterfaceMyStruct2{} }) vm.Set("e3", func() error { return nil }) test("r(function() { return e1(); })", UndefinedValue()) @@ -848,9 +849,9 @@ func TestStructCallParameterConversion(t *testing.T) { }) } -type TestTextUnmarshallerCallParameterConversion_MyStruct struct{} +type TestTextUnmarshallerCallParameterConversionMyStruct struct{} -func (m *TestTextUnmarshallerCallParameterConversion_MyStruct) UnmarshalText(b []byte) error { +func (m *TestTextUnmarshallerCallParameterConversionMyStruct) UnmarshalText(b []byte) error { if string(b) == "good" { return nil } @@ -862,7 +863,7 @@ func TestTextUnmarshallerCallParameterConversion(t *testing.T) { tt(t, func() { test, vm := test() - vm.Set("f", func(t TestTextUnmarshallerCallParameterConversion_MyStruct) bool { return true }) + vm.Set("f", func(t TestTextUnmarshallerCallParameterConversionMyStruct) bool { return true }) // success test("f('good')", true) @@ -900,7 +901,8 @@ func TestJSONRawMessageCallParameterConversion(t *testing.T) { } { t.Run(e.c, func(t *testing.T) { vm := New() - vm.Set("f", func(m json.RawMessage) json.RawMessage { return m }) + err := vm.Set("f", func(m json.RawMessage) json.RawMessage { return m }) + require.NoError(t, err) r, err := vm.Run(e.c) if err != nil { if !e.e { diff --git a/regexp_test.go b/regexp_test.go index d98f3ce4..e4f9fbdf 100644 --- a/regexp_test.go +++ b/regexp_test.go @@ -34,15 +34,15 @@ func TestRegExp(t *testing.T) { test(`new RegExp("abc", "mig").toString()`, "/abc/gim") result := test(`/(a)?/.exec('b')`, ",") - is(result._object().get("0"), "") - is(result._object().get("1"), "undefined") - is(result._object().get(propertyLength), 2) + is(result.object().get("0"), "") + is(result.object().get("1"), "undefined") + is(result.object().get(propertyLength), 2) result = test(`/(a)?(b)?/.exec('b')`, "b,,b") - is(result._object().get("0"), "b") - is(result._object().get("1"), "undefined") - is(result._object().get("2"), "b") - is(result._object().get(propertyLength), 3) + is(result.object().get("0"), "b") + is(result.object().get("1"), "undefined") + is(result.object().get("2"), "b") + is(result.object().get(propertyLength), 3) test(`/\u0041/.source`, "\\u0041") test(`/\a/.source`, "\\a") @@ -276,13 +276,13 @@ func TestRegExp_controlCharacter(t *testing.T) { test, _ := test() for code := 0x41; code < 0x5a; code++ { - string_ := string(rune(code - 64)) + val := string(rune(code - 64)) test(fmt.Sprintf(` var code = 0x%x; var string = String.fromCharCode(code %% 32); var result = (new RegExp("\\c" + String.fromCharCode(code))).exec(string); [ code, string, result ]; - `, code), fmt.Sprintf("%d,%s,%s", code, string_, string_)) + `, code), fmt.Sprintf("%d,%s,%s", code, val, val)) } }) } diff --git a/registry/registry.go b/registry/registry.go index 966638ac..e1731332 100644 --- a/registry/registry.go +++ b/registry/registry.go @@ -1,17 +1,17 @@ -/* -Package registry is an expirmental package to facillitate altering the otto runtime via import. - -This interface can change at any time. -*/ +// Package registry is an experimental package to facilitate altering the otto runtime via import. +// +// This interface can change at any time. package registry var registry []*Entry = make([]*Entry, 0) +// Entry represents a registry entry. type Entry struct { active bool source func() string } +// newEntry returns a new Entry for source. func newEntry(source func() string) *Entry { return &Entry{ active: true, @@ -19,18 +19,22 @@ func newEntry(source func() string) *Entry { } } -func (self *Entry) Enable() { - self.active = true +// Enable enables the entry. +func (e *Entry) Enable() { + e.active = true } -func (self *Entry) Disable() { - self.active = false +// Disable disables the entry. +func (e *Entry) Disable() { + e.active = false } -func (self Entry) Source() string { - return self.source() +// Source returns the source of the entry. +func (e Entry) Source() string { + return e.source() } +// Apply applies callback to all registry entries. func Apply(callback func(Entry)) { for _, entry := range registry { if !entry.active { @@ -40,6 +44,7 @@ func Apply(callback func(Entry)) { } } +// Register registers a new Entry for source. func Register(source func() string) *Entry { entry := newEntry(source) registry = append(registry, entry) diff --git a/repl/autocompleter.go b/repl/autocompleter.go index 7e6d4702..cfd2a1cc 100644 --- a/repl/autocompleter.go +++ b/repl/autocompleter.go @@ -18,12 +18,8 @@ func (a *autoCompleter) Do(line []rune, pos int) ([][]rune, int) { bits := strings.Split(lastExpression, ".") - first := bits[:len(bits)-1] - last := bits[len(bits)-1] - var l []string - - if len(first) == 0 { + if first := bits[:len(bits)-1]; len(first) == 0 { c := a.vm.Context() l = make([]string, len(c.Symbols)) @@ -46,6 +42,7 @@ func (a *autoCompleter) Do(line []rune, pos int) ([][]rune, int) { } } + last := bits[len(bits)-1] var r [][]rune for _, s := range l { if strings.HasPrefix(s, last) { diff --git a/repl/repl.go b/repl/repl.go index 268d913f..8764594c 100644 --- a/repl/repl.go +++ b/repl/repl.go @@ -2,6 +2,7 @@ package repl import ( + "errors" "fmt" "io" "strings" @@ -100,7 +101,7 @@ func RunWithOptions(vm *otto.Otto, options Options) error { for { l, err := rl.Readline() if err != nil { - if err == readline.ErrInterrupt { + if errors.Is(err, readline.ErrInterrupt) { if d != nil { d = nil @@ -132,13 +133,20 @@ func RunWithOptions(vm *otto.Otto, options Options) error { v, err := vm.Eval(s) if err != nil { - if oerr, ok := err.(*otto.Error); ok { - io.Copy(rl.Stdout(), strings.NewReader(oerr.String())) + var oerr *otto.Error + if errors.As(err, &oerr) { + if _, err := io.Copy(rl.Stdout(), strings.NewReader(oerr.String())); err != nil { + return fmt.Errorf("write out: %w", err) + } } else { - io.Copy(rl.Stdout(), strings.NewReader(err.Error())) + if _, err := io.Copy(rl.Stdout(), strings.NewReader(err.Error())); err != nil { + return fmt.Errorf("write out: %w", err) + } } } else { - rl.Stdout().Write([]byte(v.String() + "\n")) + if _, err := rl.Stdout().Write([]byte(v.String() + "\n")); err != nil { + return fmt.Errorf("write out: %w", err) + } } } diff --git a/result.go b/result.go index 4daa923f..1896c182 100644 --- a/result.go +++ b/result.go @@ -1,28 +1,28 @@ package otto -type _resultKind int +type resultKind int const ( - _ _resultKind = iota + _ resultKind = iota resultReturn resultBreak resultContinue ) -type _result struct { - kind _resultKind +type result struct { + kind resultKind value Value target string } -func newReturnResult(value Value) _result { - return _result{resultReturn, value, ""} +func newReturnResult(value Value) result { + return result{resultReturn, value, ""} } -func newContinueResult(target string) _result { - return _result{resultContinue, emptyValue, target} +func newContinueResult(target string) result { + return result{resultContinue, emptyValue, target} } -func newBreakResult(target string) _result { - return _result{resultBreak, emptyValue, target} +func newBreakResult(target string) result { + return result{resultBreak, emptyValue, target} } diff --git a/runtime.go b/runtime.go index cfdbb1e4..cbe18571 100644 --- a/runtime.go +++ b/runtime.go @@ -8,7 +8,7 @@ import ( "math" "path" "reflect" - "runtime" + goruntime "runtime" "strconv" "strings" "sync" @@ -17,49 +17,49 @@ import ( "github.com/robertkrimen/otto/parser" ) -type _global struct { - Object *_object // Object( ... ), new Object( ... ) - 1 (length) - Function *_object // Function( ... ), new Function( ... ) - 1 - Array *_object // Array( ... ), new Array( ... ) - 1 - String *_object // String( ... ), new String( ... ) - 1 - Boolean *_object // Boolean( ... ), new Boolean( ... ) - 1 - Number *_object // Number( ... ), new Number( ... ) - 1 - Math *_object - Date *_object // Date( ... ), new Date( ... ) - 7 - RegExp *_object // RegExp( ... ), new RegExp( ... ) - 2 - Error *_object // Error( ... ), new Error( ... ) - 1 - EvalError *_object - TypeError *_object - RangeError *_object - ReferenceError *_object - SyntaxError *_object - URIError *_object - JSON *_object - - ObjectPrototype *_object // Object.prototype - FunctionPrototype *_object // Function.prototype - ArrayPrototype *_object // Array.prototype - StringPrototype *_object // String.prototype - BooleanPrototype *_object // Boolean.prototype - NumberPrototype *_object // Number.prototype - DatePrototype *_object // Date.prototype - RegExpPrototype *_object // RegExp.prototype - ErrorPrototype *_object // Error.prototype - EvalErrorPrototype *_object - TypeErrorPrototype *_object - RangeErrorPrototype *_object - ReferenceErrorPrototype *_object - SyntaxErrorPrototype *_object - URIErrorPrototype *_object +type global struct { + Object *object // Object( ... ), new Object( ... ) - 1 (length) + Function *object // Function( ... ), new Function( ... ) - 1 + Array *object // Array( ... ), new Array( ... ) - 1 + String *object // String( ... ), new String( ... ) - 1 + Boolean *object // Boolean( ... ), new Boolean( ... ) - 1 + Number *object // Number( ... ), new Number( ... ) - 1 + Math *object + Date *object // Date( ... ), new Date( ... ) - 7 + RegExp *object // RegExp( ... ), new RegExp( ... ) - 2 + Error *object // Error( ... ), new Error( ... ) - 1 + EvalError *object + TypeError *object + RangeError *object + ReferenceError *object + SyntaxError *object + URIError *object + JSON *object + + ObjectPrototype *object // Object.prototype + FunctionPrototype *object // Function.prototype + ArrayPrototype *object // Array.prototype + StringPrototype *object // String.prototype + BooleanPrototype *object // Boolean.prototype + NumberPrototype *object // Number.prototype + DatePrototype *object // Date.prototype + RegExpPrototype *object // RegExp.prototype + ErrorPrototype *object // Error.prototype + EvalErrorPrototype *object + TypeErrorPrototype *object + RangeErrorPrototype *object + ReferenceErrorPrototype *object + SyntaxErrorPrototype *object + URIErrorPrototype *object } -type _runtime struct { - global _global - globalObject *_object - globalStash *_objectStash - scope *_scope +type runtime struct { + global global + globalObject *object + globalStash *objectStash + scope *scope otto *Otto - eval *_object // The builtin eval, for determine indirect versus direct invocation + eval *object // The builtin eval, for determine indirect versus direct invocation debugger func(*Otto) random func() float64 stackLimit int @@ -69,54 +69,54 @@ type _runtime struct { lck sync.Mutex } -func (self *_runtime) enterScope(scope *_scope) { - scope.outer = self.scope - if self.scope != nil { - if self.stackLimit != 0 && self.scope.depth+1 >= self.stackLimit { - panic(self.panicRangeError("Maximum call stack size exceeded")) +func (rt *runtime) enterScope(scop *scope) { + scop.outer = rt.scope + if rt.scope != nil { + if rt.stackLimit != 0 && rt.scope.depth+1 >= rt.stackLimit { + panic(rt.panicRangeError("Maximum call stack size exceeded")) } - scope.depth = self.scope.depth + 1 + scop.depth = rt.scope.depth + 1 } - self.scope = scope + rt.scope = scop } -func (self *_runtime) leaveScope() { - self.scope = self.scope.outer +func (rt *runtime) leaveScope() { + rt.scope = rt.scope.outer } -// FIXME This is used in two places (cloning) -func (self *_runtime) enterGlobalScope() { - self.enterScope(newScope(self.globalStash, self.globalStash, self.globalObject)) +// FIXME This is used in two places (cloning). +func (rt *runtime) enterGlobalScope() { + rt.enterScope(newScope(rt.globalStash, rt.globalStash, rt.globalObject)) } -func (self *_runtime) enterFunctionScope(outer _stash, this Value) *_fnStash { +func (rt *runtime) enterFunctionScope(outer stasher, this Value) *fnStash { if outer == nil { - outer = self.globalStash + outer = rt.globalStash } - stash := self.newFunctionStash(outer) - var thisObject *_object + stash := rt.newFunctionStash(outer) + var thisObject *object switch this.kind { case valueUndefined, valueNull: - thisObject = self.globalObject + thisObject = rt.globalObject default: - thisObject = self.toObject(this) + thisObject = rt.toObject(this) } - self.enterScope(newScope(stash, stash, thisObject)) + rt.enterScope(newScope(stash, stash, thisObject)) return stash } -func (self *_runtime) putValue(reference _reference, value Value) { +func (rt *runtime) putValue(reference referencer, value Value) { name := reference.putValue(value) if name != "" { // Why? -- If reference.base == nil // strict = false - self.globalObject.defineProperty(name, value, 0111, false) + rt.globalObject.defineProperty(name, value, 0o111, false) } } -func (self *_runtime) tryCatchEvaluate(inner func() Value) (tryValue Value, exception bool) { +func (rt *runtime) tryCatchEvaluate(inner func() Value) (tryValue Value, isException bool) { //nolint: nonamedreturns // resultValue = The value of the block (e.g. the last statement) // throw = Something was thrown // throwValue = The value of what was thrown @@ -124,18 +124,18 @@ func (self *_runtime) tryCatchEvaluate(inner func() Value) (tryValue Value, exce // Otherwise, some sort of unknown panic happened, we'll just propagate it. defer func() { if caught := recover(); caught != nil { - if exception, ok := caught.(*_exception); ok { - caught = exception.eject() + if excep, ok := caught.(*exception); ok { + caught = excep.eject() } switch caught := caught.(type) { - case _error: - exception = true - tryValue = toValue_object(self.newErrorObjectError(caught)) + case ottoError: + isException = true + tryValue = objectValue(rt.newErrorObjectError(caught)) case Value: - exception = true + isException = true tryValue = caught default: - exception = true + isException = true tryValue = toValue(caught) } } @@ -144,43 +144,43 @@ func (self *_runtime) tryCatchEvaluate(inner func() Value) (tryValue Value, exce return inner(), false } -// toObject - -func (self *_runtime) toObject(value Value) *_object { +func (rt *runtime) toObject(value Value) *object { switch value.kind { case valueEmpty, valueUndefined, valueNull: - panic(self.panicTypeError()) + panic(rt.panicTypeError()) case valueBoolean: - return self.newBoolean(value) + return rt.newBoolean(value) case valueString: - return self.newString(value) + return rt.newString(value) case valueNumber: - return self.newNumber(value) + return rt.newNumber(value) case valueObject: - return value._object() + return value.object() + default: + panic(rt.panicTypeError()) } - panic(self.panicTypeError()) } -func (self *_runtime) objectCoerce(value Value) (*_object, error) { +func (rt *runtime) objectCoerce(value Value) (*object, error) { switch value.kind { case valueUndefined: return nil, errors.New("undefined") case valueNull: return nil, errors.New("null") case valueBoolean: - return self.newBoolean(value), nil + return rt.newBoolean(value), nil case valueString: - return self.newString(value), nil + return rt.newString(value), nil case valueNumber: - return self.newNumber(value), nil + return rt.newNumber(value), nil case valueObject: - return value._object(), nil + return value.object(), nil + default: + panic(rt.panicTypeError()) } - panic(self.panicTypeError()) } -func checkObjectCoercible(rt *_runtime, value Value) { +func checkObjectCoercible(rt *runtime, value Value) { isObject, mustCoerce := testObjectCoercible(value) if !isObject && !mustCoerce { panic(rt.panicTypeError()) @@ -189,7 +189,7 @@ func checkObjectCoercible(rt *_runtime, value Value) { // testObjectCoercible -func testObjectCoercible(value Value) (isObject bool, mustCoerce bool) { +func testObjectCoercible(value Value) (isObject, mustCoerce bool) { //nolint: nonamedreturns switch value.kind { case valueReference, valueEmpty, valueNull, valueUndefined: return false, false @@ -202,17 +202,17 @@ func testObjectCoercible(value Value) (isObject bool, mustCoerce bool) { } } -func (self *_runtime) safeToValue(value interface{}) (Value, error) { +func (rt *runtime) safeToValue(value interface{}) (Value, error) { result := Value{} err := catchPanic(func() { - result = self.toValue(value) + result = rt.toValue(value) }) return result, err } // convertNumeric converts numeric parameter val from js to that of type t if it is safe to do so, otherwise it panics. // This allows literals (int64), bitwise values (int32) and the general form (float64) of javascript numerics to be passed as parameters to go functions easily. -func (self *_runtime) convertNumeric(v Value, t reflect.Type) reflect.Value { +func (rt *runtime) convertNumeric(v Value, t reflect.Type) reflect.Value { val := reflect.ValueOf(v.export()) if val.Kind() == t.Kind() { @@ -231,20 +231,20 @@ func (self *_runtime) convertNumeric(v Value, t reflect.Type) reflect.Value { return reflect.ValueOf(f64) case reflect.Float32: if reflect.Zero(t).OverflowFloat(f64) { - panic(self.panicRangeError("converting float64 to float32 would overflow")) + panic(rt.panicRangeError("converting float64 to float32 would overflow")) } return val.Convert(t) case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: i64 := int64(f64) if float64(i64) != f64 { - panic(self.panicRangeError(fmt.Sprintf("converting %v to %v would cause loss of precision", val.Type(), t))) + panic(rt.panicRangeError(fmt.Sprintf("converting %v to %v would cause loss of precision", val.Type(), t))) } // The float represents an integer val = reflect.ValueOf(i64) default: - panic(self.panicTypeError(fmt.Sprintf("cannot convert %v to %v", val.Type(), t))) + panic(rt.panicTypeError(fmt.Sprintf("cannot convert %v to %v", val.Type(), t))) } } @@ -254,15 +254,15 @@ func (self *_runtime) convertNumeric(v Value, t reflect.Type) reflect.Value { switch t.Kind() { case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: if reflect.Zero(t).OverflowInt(i64) { - panic(self.panicRangeError(fmt.Sprintf("converting %v to %v would overflow", val.Type(), t))) + panic(rt.panicRangeError(fmt.Sprintf("converting %v to %v would overflow", val.Type(), t))) } return val.Convert(t) case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: if i64 < 0 { - panic(self.panicRangeError(fmt.Sprintf("converting %v to %v would underflow", val.Type(), t))) + panic(rt.panicRangeError(fmt.Sprintf("converting %v to %v would underflow", val.Type(), t))) } if reflect.Zero(t).OverflowUint(uint64(i64)) { - panic(self.panicRangeError(fmt.Sprintf("converting %v to %v would overflow", val.Type(), t))) + panic(rt.panicRangeError(fmt.Sprintf("converting %v to %v would overflow", val.Type(), t))) } return val.Convert(t) case reflect.Float32, reflect.Float64: @@ -274,12 +274,12 @@ func (self *_runtime) convertNumeric(v Value, t reflect.Type) reflect.Value { switch t.Kind() { case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: if u64 > math.MaxInt64 || reflect.Zero(t).OverflowInt(int64(u64)) { - panic(self.panicRangeError(fmt.Sprintf("converting %v to %v would overflow", val.Type(), t))) + panic(rt.panicRangeError(fmt.Sprintf("converting %v to %v would overflow", val.Type(), t))) } return val.Convert(t) case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: if reflect.Zero(t).OverflowUint(u64) { - panic(self.panicRangeError(fmt.Sprintf("converting %v to %v would overflow", val.Type(), t))) + panic(rt.panicRangeError(fmt.Sprintf("converting %v to %v would overflow", val.Type(), t))) } return val.Convert(t) case reflect.Float32, reflect.Float64: @@ -287,7 +287,7 @@ func (self *_runtime) convertNumeric(v Value, t reflect.Type) reflect.Value { } } - panic(self.panicTypeError(fmt.Sprintf("unsupported type %v -> %v for numeric conversion", val.Type(), t))) + panic(rt.panicTypeError(fmt.Sprintf("unsupported type %v -> %v for numeric conversion", val.Type(), t))) } func fieldIndexByName(t reflect.Type, name string) []int { @@ -332,13 +332,15 @@ func fieldIndexByName(t reflect.Type, name string) []int { return nil } -var typeOfValue = reflect.TypeOf(Value{}) -var typeOfJSONRawMessage = reflect.TypeOf(json.RawMessage{}) +var ( + typeOfValue = reflect.TypeOf(Value{}) + typeOfJSONRawMessage = reflect.TypeOf(json.RawMessage{}) +) // convertCallParameter converts request val to type t if possible. // If the conversion fails due to overflow or type miss-match then it panics. // If no conversion is known then the original value is returned. -func (self *_runtime) convertCallParameter(v Value, t reflect.Type) (reflect.Value, error) { +func (rt *runtime) convertCallParameter(v Value, t reflect.Type) (reflect.Value, error) { if t == typeOfValue { return reflect.ValueOf(v), nil } @@ -350,25 +352,23 @@ func (self *_runtime) convertCallParameter(v Value, t reflect.Type) (reflect.Val } if v.kind == valueObject { - if gso, ok := v._object().value.(*_goStructObject); ok { + if gso, ok := v.object().value.(*goStructObject); ok { if gso.value.Type().AssignableTo(t) { // please see TestDynamicFunctionReturningInterface for why this exists if t.Kind() == reflect.Interface && gso.value.Type().ConvertibleTo(t) { return gso.value.Convert(t), nil - } else { - return gso.value, nil } + return gso.value, nil } } - if gao, ok := v._object().value.(*_goArrayObject); ok { + if gao, ok := v.object().value.(*goArrayObject); ok { if gao.value.Type().AssignableTo(t) { // please see TestDynamicFunctionReturningInterface for why this exists if t.Kind() == reflect.Interface && gao.value.Type().ConvertibleTo(t) { return gao.value.Convert(t), nil - } else { - return gao.value, nil } + return gao.value, nil } } } @@ -392,9 +392,9 @@ func (self *_runtime) convertCallParameter(v Value, t reflect.Type) (reflect.Val return reflect.Zero(t), nil default: var vv reflect.Value - vv, err := self.convertCallParameter(v, t.Elem()) + vv, err := rt.convertCallParameter(v, t.Elem()) if err != nil { - return reflect.Zero(t), fmt.Errorf("can't convert to %s: %s", t, err.Error()) + return reflect.Zero(t), fmt.Errorf("can't convert to %s: %w", t, err) } if vv.CanAddr() { @@ -418,12 +418,11 @@ func (self *_runtime) convertCallParameter(v Value, t reflect.Type) (reflect.Val return reflect.ValueOf(fmt.Sprintf("%v", v.value)), nil } case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Float32, reflect.Float64: - switch v.kind { - case valueNumber: - return self.convertNumeric(v, t), nil + if v.kind == valueNumber { + return rt.convertNumeric(v, t), nil } case reflect.Slice: - if o := v._object(); o != nil { + if o := v.object(); o != nil { if lv := o.get(propertyLength); lv.IsNumber() { l := lv.number().int64 @@ -432,7 +431,7 @@ func (self *_runtime) convertCallParameter(v Value, t reflect.Type) (reflect.Val tt := t.Elem() switch o.class { - case classArray: + case classArrayName: for i := int64(0); i < l; i++ { p, ok := o.property[strconv.FormatInt(i, 10)] if !ok { @@ -444,24 +443,24 @@ func (self *_runtime) convertCallParameter(v Value, t reflect.Type) (reflect.Val continue } - ev, err := self.convertCallParameter(e, tt) + ev, err := rt.convertCallParameter(e, tt) if err != nil { - return reflect.Zero(t), fmt.Errorf("couldn't convert element %d of %s: %s", i, t, err.Error()) + return reflect.Zero(t), fmt.Errorf("couldn't convert element %d of %s: %w", i, t, err) } s.Index(int(i)).Set(ev) } - case classGoArray, classGoSlice: + case classGoArrayName, classGoSliceName: var gslice bool switch o.value.(type) { - case *_goSliceObject: + case *goSliceObject: gslice = true - case *_goArrayObject: + case *goArrayObject: gslice = false } for i := int64(0); i < l; i++ { - var p *_property + var p *property if gslice { p = goSliceGetOwnProperty(o, strconv.FormatInt(i, 10)) } else { @@ -476,9 +475,9 @@ func (self *_runtime) convertCallParameter(v Value, t reflect.Type) (reflect.Val continue } - ev, err := self.convertCallParameter(e, tt) + ev, err := rt.convertCallParameter(e, tt) if err != nil { - return reflect.Zero(t), fmt.Errorf("couldn't convert element %d of %s: %s", i, t, err.Error()) + return reflect.Zero(t), fmt.Errorf("couldn't convert element %d of %s: %w", i, t, err) } s.Index(int(i)).Set(ev) @@ -489,15 +488,15 @@ func (self *_runtime) convertCallParameter(v Value, t reflect.Type) (reflect.Val } } case reflect.Map: - if o := v._object(); o != nil && t.Key().Kind() == reflect.String { + if o := v.object(); o != nil && t.Key().Kind() == reflect.String { m := reflect.MakeMap(t) var err error o.enumerate(false, func(k string) bool { - v, verr := self.convertCallParameter(o.get(k), t.Elem()) + v, verr := rt.convertCallParameter(o.get(k), t.Elem()) if verr != nil { - err = fmt.Errorf("couldn't convert property %q of %s: %s", k, t, verr.Error()) + err = fmt.Errorf("couldn't convert property %q of %s: %w", k, t, verr) return false } m.SetMapIndex(reflect.ValueOf(k), v) @@ -515,7 +514,7 @@ func (self *_runtime) convertCallParameter(v Value, t reflect.Type) (reflect.Val return reflect.Zero(t), fmt.Errorf("converting JavaScript values to Go functions with more than one return value is currently not supported") } - if o := v._object(); o != nil && o.class == classFunction { + if o := v.object(); o != nil && o.class == classFunctionName { return reflect.MakeFunc(t, func(args []reflect.Value) []reflect.Value { l := make([]interface{}, len(args)) for i, a := range args { @@ -533,16 +532,16 @@ func (self *_runtime) convertCallParameter(v Value, t reflect.Type) (reflect.Val return nil } - r, err := self.convertCallParameter(rv, t.Out(0)) + r, err := rt.convertCallParameter(rv, t.Out(0)) if err != nil { - panic(self.panicTypeError(err.Error())) + panic(rt.panicTypeError(err.Error())) } return []reflect.Value{r} }), nil } case reflect.Struct: - if o := v._object(); o != nil && o.class == classObject { + if o := v.object(); o != nil && o.class == classObjectName { s := reflect.New(t) for _, k := range o.propertyOrder { @@ -570,9 +569,9 @@ func (self *_runtime) convertCallParameter(v Value, t reflect.Type) (reflect.Val ss = ss.Field(i) } - v, err := self.convertCallParameter(o.get(k), ss.Type()) + v, err := rt.convertCallParameter(o.get(k), ss.Type()) if err != nil { - return reflect.Zero(t), fmt.Errorf("couldn't convert property %q of %s: %s", k, t, err.Error()) + return reflect.Zero(t), fmt.Errorf("couldn't convert property %q of %s: %w", k, t, err) } ss.Set(v) @@ -583,16 +582,16 @@ func (self *_runtime) convertCallParameter(v Value, t reflect.Type) (reflect.Val } if tk == reflect.String { - if o := v._object(); o != nil && o.hasProperty("toString") { + if o := v.object(); o != nil && o.hasProperty("toString") { if fn := o.get("toString"); fn.IsFunction() { sv, err := fn.Call(v) if err != nil { - return reflect.Zero(t), fmt.Errorf("couldn't call toString: %s", err.Error()) + return reflect.Zero(t), fmt.Errorf("couldn't call toString: %w", err) } - r, err := self.convertCallParameter(sv, t) + r, err := rt.convertCallParameter(sv, t) if err != nil { - return reflect.Zero(t), fmt.Errorf("couldn't convert toString result: %s", err.Error()) + return reflect.Zero(t), fmt.Errorf("couldn't convert toString result: %w", err) } return r, nil } @@ -608,7 +607,7 @@ func (self *_runtime) convertCallParameter(v Value, t reflect.Type) (reflect.Val r := reflect.New(t) if err := r.Interface().(encoding.TextUnmarshaler).UnmarshalText([]byte(v.string())); err != nil { - return reflect.Zero(t), fmt.Errorf("can't convert to %s as TextUnmarshaller: %s", t.String(), err.Error()) + return reflect.Zero(t), fmt.Errorf("can't convert to %s as TextUnmarshaller: %w", t.String(), err) } return r.Elem(), nil @@ -634,7 +633,7 @@ func (self *_runtime) convertCallParameter(v Value, t reflect.Type) (reflect.Val return reflect.Zero(t), fmt.Errorf("can't convert from %q to %q", s, t) } -func (self *_runtime) toValue(value interface{}) Value { +func (rt *runtime) toValue(value interface{}) Value { rv, ok := value.(reflect.Value) if ok { value = rv.Interface() @@ -647,173 +646,171 @@ func (self *_runtime) toValue(value interface{}) Value { var name, file string var line int pc := reflect.ValueOf(value).Pointer() - fn := runtime.FuncForPC(pc) + fn := goruntime.FuncForPC(pc) if fn != nil { name = fn.Name() file, line = fn.FileLine(pc) file = path.Base(file) } - return toValue_object(self.newNativeFunction(name, file, line, value)) - case _nativeFunction: + return objectValue(rt.newNativeFunction(name, file, line, value)) + case nativeFunction: var name, file string var line int pc := reflect.ValueOf(value).Pointer() - fn := runtime.FuncForPC(pc) + fn := goruntime.FuncForPC(pc) if fn != nil { name = fn.Name() file, line = fn.FileLine(pc) file = path.Base(file) } - return toValue_object(self.newNativeFunction(name, file, line, value)) - case Object, *Object, _object, *_object: + return objectValue(rt.newNativeFunction(name, file, line, value)) + case Object, *Object, object, *object: // Nothing happens. // FIXME We should really figure out what can come here. // This catch-all is ugly. default: - { - value := reflect.ValueOf(value) - if ok && value.Kind() == rv.Kind() { - // Use passed in rv which may be writable. - value = rv - } + val := reflect.ValueOf(value) + if ok && val.Kind() == rv.Kind() { + // Use passed in rv which may be writable. + val = rv + } - switch value.Kind() { - case reflect.Ptr: - switch reflect.Indirect(value).Kind() { - case reflect.Struct: - return toValue_object(self.newGoStructObject(value)) - case reflect.Array: - return toValue_object(self.newGoArray(value)) - } + switch val.Kind() { + case reflect.Ptr: + switch reflect.Indirect(val).Kind() { case reflect.Struct: - return toValue_object(self.newGoStructObject(value)) - case reflect.Map: - return toValue_object(self.newGoMapObject(value)) - case reflect.Slice: - return toValue_object(self.newGoSlice(value)) + return objectValue(rt.newGoStructObject(val)) case reflect.Array: - return toValue_object(self.newGoArray(value)) - case reflect.Func: - var name, file string - var line int - if v := reflect.ValueOf(value); v.Kind() == reflect.Ptr { - pc := v.Pointer() - fn := runtime.FuncForPC(pc) - if fn != nil { - name = fn.Name() - file, line = fn.FileLine(pc) - file = path.Base(file) - } + return objectValue(rt.newGoArray(val)) + } + case reflect.Struct: + return objectValue(rt.newGoStructObject(val)) + case reflect.Map: + return objectValue(rt.newGoMapObject(val)) + case reflect.Slice: + return objectValue(rt.newGoSlice(val)) + case reflect.Array: + return objectValue(rt.newGoArray(val)) + case reflect.Func: + var name, file string + var line int + if v := reflect.ValueOf(val); v.Kind() == reflect.Ptr { + pc := v.Pointer() + fn := goruntime.FuncForPC(pc) + if fn != nil { + name = fn.Name() + file, line = fn.FileLine(pc) + file = path.Base(file) } + } - typ := value.Type() + typ := val.Type() - return toValue_object(self.newNativeFunction(name, file, line, func(c FunctionCall) Value { - nargs := typ.NumIn() + return objectValue(rt.newNativeFunction(name, file, line, func(c FunctionCall) Value { + nargs := typ.NumIn() - if len(c.ArgumentList) != nargs { - if typ.IsVariadic() { - if len(c.ArgumentList) < nargs-1 { - panic(self.panicRangeError(fmt.Sprintf("expected at least %d arguments; got %d", nargs-1, len(c.ArgumentList)))) - } - } else { - panic(self.panicRangeError(fmt.Sprintf("expected %d argument(s); got %d", nargs, len(c.ArgumentList)))) + if len(c.ArgumentList) != nargs { + if typ.IsVariadic() { + if len(c.ArgumentList) < nargs-1 { + panic(rt.panicRangeError(fmt.Sprintf("expected at least %d arguments; got %d", nargs-1, len(c.ArgumentList)))) } + } else { + panic(rt.panicRangeError(fmt.Sprintf("expected %d argument(s); got %d", nargs, len(c.ArgumentList)))) } + } - in := make([]reflect.Value, len(c.ArgumentList)) - - callSlice := false + in := make([]reflect.Value, len(c.ArgumentList)) - for i, a := range c.ArgumentList { - var t reflect.Type + callSlice := false - n := i - if n >= nargs-1 && typ.IsVariadic() { - if n > nargs-1 { - n = nargs - 1 - } + for i, a := range c.ArgumentList { + var t reflect.Type - t = typ.In(n).Elem() - } else { - t = typ.In(n) + n := i + if n >= nargs-1 && typ.IsVariadic() { + if n > nargs-1 { + n = nargs - 1 } - // if this is a variadic Go function, and the caller has supplied - // exactly the number of JavaScript arguments required, and this - // is the last JavaScript argument, try treating the it as the - // actual set of variadic Go arguments. if that succeeds, break - // out of the loop. - if typ.IsVariadic() && len(c.ArgumentList) == nargs && i == nargs-1 { - if v, err := self.convertCallParameter(a, typ.In(n)); err == nil { - in[i] = v - callSlice = true - break - } - } + t = typ.In(n).Elem() + } else { + t = typ.In(n) + } - v, err := self.convertCallParameter(a, t) - if err != nil { - panic(self.panicTypeError(err.Error())) + // if this is a variadic Go function, and the caller has supplied + // exactly the number of JavaScript arguments required, and this + // is the last JavaScript argument, try treating the it as the + // actual set of variadic Go arguments. if that succeeds, break + // out of the loop. + if typ.IsVariadic() && len(c.ArgumentList) == nargs && i == nargs-1 { + if v, err := rt.convertCallParameter(a, typ.In(n)); err == nil { + in[i] = v + callSlice = true + break } - - in[i] = v } - var out []reflect.Value - if callSlice { - out = value.CallSlice(in) - } else { - out = value.Call(in) + v, err := rt.convertCallParameter(a, t) + if err != nil { + panic(rt.panicTypeError(err.Error())) } - switch len(out) { - case 0: - return Value{} - case 1: - return self.toValue(out[0].Interface()) - default: - s := make([]interface{}, len(out)) - for i, v := range out { - s[i] = self.toValue(v.Interface()) - } + in[i] = v + } + + var out []reflect.Value + if callSlice { + out = val.CallSlice(in) + } else { + out = val.Call(in) + } - return self.toValue(s) + switch len(out) { + case 0: + return Value{} + case 1: + return rt.toValue(out[0].Interface()) + default: + s := make([]interface{}, len(out)) + for i, v := range out { + s[i] = rt.toValue(v.Interface()) } - })) - } + + return rt.toValue(s) + } + })) } } return toValue(value) } -func (runtime *_runtime) newGoSlice(value reflect.Value) *_object { - self := runtime.newGoSliceObject(value) - self.prototype = runtime.global.ArrayPrototype - return self +func (rt *runtime) newGoSlice(value reflect.Value) *object { + obj := rt.newGoSliceObject(value) + obj.prototype = rt.global.ArrayPrototype + return obj } -func (runtime *_runtime) newGoArray(value reflect.Value) *_object { - self := runtime.newGoArrayObject(value) - self.prototype = runtime.global.ArrayPrototype - return self +func (rt *runtime) newGoArray(value reflect.Value) *object { + obj := rt.newGoArrayObject(value) + obj.prototype = rt.global.ArrayPrototype + return obj } -func (runtime *_runtime) parse(filename string, src, sm interface{}) (*ast.Program, error) { +func (rt *runtime) parse(filename string, src, sm interface{}) (*ast.Program, error) { return parser.ParseFileWithSourceMap(nil, filename, src, sm, 0) } -func (runtime *_runtime) cmpl_parse(filename string, src, sm interface{}) (*_nodeProgram, error) { +func (rt *runtime) cmplParse(filename string, src, sm interface{}) (*nodeProgram, error) { program, err := parser.ParseFileWithSourceMap(nil, filename, src, sm, 0) if err != nil { return nil, err } - return cmpl_parse(program), nil + return cmplParse(program), nil } -func (self *_runtime) parseSource(src, sm interface{}) (*_nodeProgram, *ast.Program, error) { +func (rt *runtime) parseSource(src, sm interface{}) (*nodeProgram, *ast.Program, error) { switch src := src.(type) { case *ast.Program: return nil, src, nil @@ -821,22 +818,22 @@ func (self *_runtime) parseSource(src, sm interface{}) (*_nodeProgram, *ast.Prog return src.program, nil, nil } - program, err := self.parse("", src, sm) + program, err := rt.parse("", src, sm) return nil, program, err } -func (self *_runtime) cmpl_runOrEval(src, sm interface{}, eval bool) (Value, error) { +func (rt *runtime) cmplRunOrEval(src, sm interface{}, eval bool) (Value, error) { result := Value{} - cmpl_program, program, err := self.parseSource(src, sm) + node, program, err := rt.parseSource(src, sm) if err != nil { return result, err } - if cmpl_program == nil { - cmpl_program = cmpl_parse(program) + if node == nil { + node = cmplParse(program) } err = catchPanic(func() { - result = self.cmpl_evaluate_nodeProgram(cmpl_program, eval) + result = rt.cmplEvaluateNodeProgram(node, eval) }) switch result.kind { case valueEmpty: @@ -847,33 +844,32 @@ func (self *_runtime) cmpl_runOrEval(src, sm interface{}, eval bool) (Value, err return result, err } -func (self *_runtime) cmpl_run(src, sm interface{}) (Value, error) { - return self.cmpl_runOrEval(src, sm, false) +func (rt *runtime) cmplRun(src, sm interface{}) (Value, error) { + return rt.cmplRunOrEval(src, sm, false) } -func (self *_runtime) cmpl_eval(src, sm interface{}) (Value, error) { - return self.cmpl_runOrEval(src, sm, true) +func (rt *runtime) cmplEval(src, sm interface{}) (Value, error) { + return rt.cmplRunOrEval(src, sm, true) } -func (self *_runtime) parseThrow(err error) { +func (rt *runtime) parseThrow(err error) { if err == nil { return } - switch err := err.(type) { - case parser.ErrorList: - { - err := err[0] - if err.Message == "Invalid left-hand side in assignment" { - panic(self.panicReferenceError(err.Message)) - } - panic(self.panicSyntaxError(err.Message)) + + var errl parser.ErrorList + if errors.Is(err, &errl) { + err := errl[0] + if err.Message == "invalid left-hand side in assignment" { + panic(rt.panicReferenceError(err.Message)) } + panic(rt.panicSyntaxError(err.Message)) } - panic(self.panicSyntaxError(err.Error())) + panic(rt.panicSyntaxError(err.Error())) } -func (self *_runtime) cmpl_parseOrThrow(src, sm interface{}) *_nodeProgram { - program, err := self.cmpl_parse("", src, sm) - self.parseThrow(err) // Will panic/throw appropriately +func (rt *runtime) cmplParseOrThrow(src, sm interface{}) *nodeProgram { + program, err := rt.cmplParse("", src, sm) + rt.parseThrow(err) // Will panic/throw appropriately return program } diff --git a/runtime_test.go b/runtime_test.go index de9e8dd9..7036f640 100644 --- a/runtime_test.go +++ b/runtime_test.go @@ -3,6 +3,8 @@ package otto import ( "math" "testing" + + "github.com/stretchr/testify/require" ) // FIXME terst, Review tests @@ -314,12 +316,12 @@ func TestPositiveNegativeZero(t *testing.T) { tt(t, func() { test, _ := test() - test(`1/0`, _Infinity) - test(`1/-0`, -_Infinity) + test(`1/0`, infinity) + test(`1/-0`, -infinity) test(` abc = -0 1/abc - `, -_Infinity) + `, -infinity) }) } @@ -341,10 +343,10 @@ func TestComparison(t *testing.T) { test("0 == 1", false) - is(negativeZero(), -0) - is(positiveZero(), 0) - is(math.Signbit(negativeZero()), true) - is(positiveZero() == negativeZero(), true) + is(negativeZero, -0) + is(positiveZero, 0) + is(math.Signbit(negativeZero), true) + is(positiveZero == negativeZero, true) test("1 == 1", true) @@ -748,17 +750,20 @@ func TestEvaluationOrder(t *testing.T) { func TestClone(t *testing.T) { tt(t, func() { vm1 := New() - vm1.Run(` + _, err := vm1.Run(` var abc = 1; `) + require.NoError(t, err) vm2 := vm1.clone() - vm1.Run(` + _, err = vm1.Run(` abc += 2; `) - vm2.Run(` + require.NoError(t, err) + _, err = vm2.Run(` abc += 4; `) + require.NoError(t, err) is(vm1.getValue("abc"), 3) is(vm2.getValue("abc"), 5) @@ -776,7 +781,7 @@ func Test_debugger(t *testing.T) { }) _, err := vm.Run(`debugger`) - is(err, nil) + require.NoError(t, err) is(called, true) }) @@ -790,7 +795,7 @@ func Test_debugger(t *testing.T) { }) _, err := vm.Run(`null`) - is(err, nil) + require.NoError(t, err) is(called, false) }) @@ -798,7 +803,7 @@ func Test_debugger(t *testing.T) { vm := New() _, err := vm.Run(`debugger`) - is(err, nil) + require.NoError(t, err) }) } @@ -808,9 +813,9 @@ func Test_random(t *testing.T) { vm.SetRandomSource(func() float64 { return 1 }) r, err := vm.Run(`Math.random()`) - is(err, nil) + require.NoError(t, err) f, err := r.ToFloat() - is(err, nil) + require.NoError(t, err) is(f, 1) }) @@ -818,14 +823,14 @@ func Test_random(t *testing.T) { vm := New() r1, err := vm.Run(`Math.random()`) - is(err, nil) + require.NoError(t, err) f1, err := r1.ToFloat() - is(err, nil) + require.NoError(t, err) r2, err := vm.Run(`Math.random()`) - is(err, nil) + require.NoError(t, err) f2, err := r2.ToFloat() - is(err, nil) + require.NoError(t, err) is(f1 == f2, false) }) @@ -848,10 +853,12 @@ func Test_stringArray(t *testing.T) { } tt(t, func() { vm := New() - vm.Set("getStrings", getStrings) - vm.Set("concatStrings", concatStrings) + err := vm.Set("getStrings", getStrings) + require.NoError(t, err) + err = vm.Set("concatStrings", concatStrings) + require.NoError(t, err) r1, err := vm.Run(`var a = getStrings(); concatStrings(a)`) - is(err, nil) + require.NoError(t, err) is(r1, "these are strings") }) } diff --git a/scope.go b/scope.go index 465e6b98..607f7c68 100644 --- a/scope.go +++ b/scope.go @@ -1,33 +1,19 @@ 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 +// An ECMA-262 ExecutionContext. +type scope struct { + lexical stasher + variable stasher + this *object eval bool // Replace this with kind? - outer *_scope + outer *scope depth int - frame _frame + frame frame } -func newScope(lexical _stash, variable _stash, this *_object) *_scope { - return &_scope{ +func newScope(lexical stasher, variable stasher, this *object) *scope { + return &scope{ lexical: lexical, variable: variable, this: this, diff --git a/script.go b/script.go index 8280d41b..ab444294 100644 --- a/script.go +++ b/script.go @@ -6,6 +6,7 @@ import ( "errors" ) +// ErrVersion is an error which represents a version mismatch. var ErrVersion = errors.New("version mismatch") var scriptVersion = "2014-04-13/1" @@ -14,7 +15,7 @@ var scriptVersion = "2014-04-13/1" // Passing a Script value to a run method will evaluate the JavaScript. type Script struct { version string - program *_nodeProgram + program *nodeProgram filename string src string } @@ -24,23 +25,22 @@ type Script struct { // // script, err := vm.Compile("", `var abc; if (!abc) abc = 0; abc += 2; abc;`) // vm.Run(script) -func (self *Otto) Compile(filename string, src interface{}) (*Script, error) { - return self.CompileWithSourceMap(filename, src, nil) +func (o *Otto) Compile(filename string, src interface{}) (*Script, error) { + return o.CompileWithSourceMap(filename, src, nil) } // CompileWithSourceMap does the same thing as Compile, but with the obvious // difference of applying a source map. -func (self *Otto) CompileWithSourceMap(filename string, src, sm interface{}) (*Script, error) { - program, err := self.runtime.parse(filename, src, sm) +func (o *Otto) CompileWithSourceMap(filename string, src, sm interface{}) (*Script, error) { + program, err := o.runtime.parse(filename, src, sm) if err != nil { return nil, err } - cmpl_program := cmpl_parse(program) - + node := cmplParse(program) script := &Script{ version: scriptVersion, - program: cmpl_program, + program: node, filename: filename, src: program.File.Source(), } @@ -48,30 +48,30 @@ func (self *Otto) CompileWithSourceMap(filename string, src, sm interface{}) (*S return script, nil } -func (self *Script) String() string { - return "// " + self.filename + "\n" + self.src +func (s *Script) String() string { + return "// " + s.filename + "\n" + s.src } // MarshalBinary will marshal a script into a binary form. A marshalled script // that is later unmarshalled can be executed on the same version of the otto runtime. // // The binary format can change at any time and should be considered unspecified and opaque. -func (self *Script) marshalBinary() ([]byte, error) { +func (s *Script) marshalBinary() ([]byte, error) { var bfr bytes.Buffer encoder := gob.NewEncoder(&bfr) - err := encoder.Encode(self.version) + err := encoder.Encode(s.version) if err != nil { return nil, err } - err = encoder.Encode(self.program) + err = encoder.Encode(s.program) if err != nil { return nil, err } - err = encoder.Encode(self.filename) + err = encoder.Encode(s.filename) if err != nil { return nil, err } - err = encoder.Encode(self.src) + err = encoder.Encode(s.src) if err != nil { return nil, err } @@ -83,27 +83,27 @@ func (self *Script) marshalBinary() ([]byte, error) { // will return an error. // // The binary format can change at any time and should be considered unspecified and opaque. -func (self *Script) unmarshalBinary(data []byte) (err error) { +func (s *Script) unmarshalBinary(data []byte) (err error) { //nolint: nonamedreturns decoder := gob.NewDecoder(bytes.NewReader(data)) defer func() { if err != nil { - self.version = "" - self.program = nil - self.filename = "" - self.src = "" + s.version = "" + s.program = nil + s.filename = "" + s.src = "" } }() - if err = decoder.Decode(&self.version); err != nil { + if err = decoder.Decode(&s.version); err != nil { return err } - if self.version != scriptVersion { + if s.version != scriptVersion { return ErrVersion } - if err = decoder.Decode(&self.program); err != nil { + if err = decoder.Decode(&s.program); err != nil { return err } - if err = decoder.Decode(&self.filename); err != nil { + if err = decoder.Decode(&s.filename); err != nil { return err } - return decoder.Decode(&self.src) + return decoder.Decode(&s.src) } diff --git a/script_test.go b/script_test.go index 90992374..8b368820 100644 --- a/script_test.go +++ b/script_test.go @@ -2,6 +2,8 @@ package otto import ( "testing" + + "github.com/stretchr/testify/require" ) func TestScript(t *testing.T) { @@ -9,52 +11,53 @@ func TestScript(t *testing.T) { vm := New() script, err := vm.Compile("xyzzy", `var abc; if (!abc) abc = 0; abc += 2; abc;`) - is(err, nil) + require.NoError(t, err) str := script.String() is(str, "// xyzzy\nvar abc; if (!abc) abc = 0; abc += 2; abc;") value, err := vm.Run(script) - is(err, nil) + require.NoError(t, err) is(value, 2) + // TODO(steve): Fix the underlying issues as to why this returns early. if true { return } tmp, err := script.marshalBinary() - is(err, nil) + require.NoError(t, err) is(len(tmp), 1228) { script := &Script{} err = script.unmarshalBinary(tmp) - is(err, nil) + require.NoError(t, err) is(script.String(), str) value, err = vm.Run(script) - is(err, nil) + require.NoError(t, err) is(value, 4) tmp, err = script.marshalBinary() - is(err, nil) + require.NoError(t, err) is(len(tmp), 1228) } { script := &Script{} err = script.unmarshalBinary(tmp) - is(err, nil) + require.NoError(t, err) is(script.String(), str) value, err := vm.Run(script) - is(err, nil) + require.NoError(t, err) is(value, 6) tmp, err = script.marshalBinary() - is(err, nil) + require.NoError(t, err) is(len(tmp), 1228) } @@ -80,15 +83,16 @@ func TestScript(t *testing.T) { func TestFunctionCall_CallerLocation(t *testing.T) { tt(t, func() { vm := New() - vm.Set("loc", func(call FunctionCall) Value { + err := vm.Set("loc", func(call FunctionCall) Value { return toValue(call.CallerLocation()) }) + require.NoError(t, err) script, err := vm.Compile("somefile.js", `var where = loc();`) - is(err, nil) + require.NoError(t, err) _, err = vm.Run(script) - is(err, nil) + require.NoError(t, err) where, err := vm.Get("where") - is(err, nil) + require.NoError(t, err) is(where, "somefile.js:1:13") }) } diff --git a/sourcemap_test.go b/sourcemap_test.go index afb82410..38276c79 100644 --- a/sourcemap_test.go +++ b/sourcemap_test.go @@ -1,7 +1,10 @@ package otto import ( + "errors" "testing" + + "github.com/stretchr/testify/require" ) const ( @@ -19,20 +22,16 @@ func TestSourceMapOriginalWithNoSourcemap(t *testing.T) { vm := New() s, err := vm.Compile("hello.js", testSourcemapCodeOriginal) - if err != nil { - panic(err) - } + require.NoError(t, err) - if _, err := vm.Run(s); err != nil { - panic(err) - } + _, err = vm.Run(s) + require.NoError(t, err) _, err = vm.Run(`functionA()`) - if err == nil { - panic("error should not be nil") - } - - is(err.(*Error).String(), testSourcemapOriginalStack) + require.Error(t, err) + var oerr *Error + require.True(t, errors.As(err, &oerr)) + require.Equal(t, oerr.String(), testSourcemapOriginalStack) }) } @@ -41,20 +40,16 @@ func TestSourceMapMangledWithNoSourcemap(t *testing.T) { vm := New() s, err := vm.Compile("hello.js", testSourcemapCodeMangled) - if err != nil { - panic(err) - } + require.NoError(t, err) - if _, err := vm.Run(s); err != nil { - panic(err) - } + _, err = vm.Run(s) + require.NoError(t, err) _, err = vm.Run(`functionA()`) - if err == nil { - panic("error should not be nil") - } - - is(err.(*Error).String(), testSourcemapMangledStack) + require.Error(t, err) + var oerr *Error + require.True(t, errors.As(err, &oerr)) + require.Equal(t, oerr.String(), testSourcemapMangledStack) }) } @@ -63,20 +58,16 @@ func TestSourceMapMangledWithSourcemap(t *testing.T) { vm := New() s, err := vm.CompileWithSourceMap("hello.js", testSourcemapCodeMangled, testSourcemapContent) - if err != nil { - panic(err) - } + require.NoError(t, err) - if _, err := vm.Run(s); err != nil { - panic(err) - } + _, err = vm.Run(s) + require.NoError(t, err) _, err = vm.Run(`functionA()`) - if err == nil { - panic("error should not be nil") - } - - is(err.(*Error).String(), testSourcemapMappedStack) + require.Error(t, err) + var oerr *Error + require.True(t, errors.As(err, &oerr)) + require.Equal(t, oerr.String(), testSourcemapMappedStack) }) } @@ -85,20 +76,16 @@ func TestSourceMapMangledWithInlineSourcemap(t *testing.T) { vm := New() s, err := vm.CompileWithSourceMap("hello.js", testSourcemapInline, nil) - if err != nil { - panic(err) - } + require.NoError(t, err) - if _, err := vm.Run(s); err != nil { - panic(err) - } + _, err = vm.Run(s) + require.NoError(t, err) _, err = vm.Run(`functionA()`) - if err == nil { - panic("error should not be nil") - } - - is(err.(*Error).String(), testSourcemapMappedStack) + require.Error(t, err) + var oerr *Error + require.True(t, errors.As(err, &oerr)) + require.Equal(t, oerr.String(), testSourcemapMappedStack) }) } @@ -107,15 +94,12 @@ func TestSourceMapContextPosition(t *testing.T) { vm := New() s, err := vm.CompileWithSourceMap("hello.js", testSourcemapCodeMangled, testSourcemapContent) - if err != nil { - panic(err) - } + require.NoError(t, err) - if _, err := vm.Run(s); err != nil { - panic(err) - } + _, err = vm.Run(s) + require.NoError(t, err) - vm.Set("functionExternal", func(c FunctionCall) Value { + err = vm.Set("functionExternal", func(c FunctionCall) Value { ctx := c.Otto.Context() is(ctx.Filename, "hello.js") @@ -124,10 +108,10 @@ func TestSourceMapContextPosition(t *testing.T) { return UndefinedValue() }) + require.NoError(t, err) - if _, err := vm.Run(`functionA()`); err != nil { - panic(err) - } + _, err = vm.Run(`functionA()`) + require.NoError(t, err) }) } @@ -136,15 +120,12 @@ func TestSourceMapContextStacktrace(t *testing.T) { vm := New() s, err := vm.CompileWithSourceMap("hello.js", testSourcemapCodeMangled, testSourcemapContent) - if err != nil { - panic(err) - } + require.NoError(t, err) - if _, err := vm.Run(s); err != nil { - panic(err) - } + _, err = vm.Run(s) + require.NoError(t, err) - vm.Set("functionExternal", func(c FunctionCall) Value { + err = vm.Set("functionExternal", func(c FunctionCall) Value { ctx := c.Otto.Context() is(ctx.Stacktrace, []string{ @@ -155,9 +136,9 @@ func TestSourceMapContextStacktrace(t *testing.T) { return UndefinedValue() }) + require.NoError(t, err) - if _, err := vm.Run(`functionA()`); err != nil { - panic(err) - } + _, err = vm.Run(`functionA()`) + require.NoError(t, err) }) } diff --git a/stash.go b/stash.go index 0d3ffa51..fcbb7173 100644 --- a/stash.go +++ b/stash.go @@ -4,11 +4,8 @@ import ( "fmt" ) -// ====== -// _stash -// ====== - -type _stash interface { +// stasher is implemented by types which can stash data. +type stasher interface { hasBinding(string) bool // createBinding(string, bool, Value) // CreateMutableBinding setBinding(string, Value, bool) // SetMutableBinding @@ -16,160 +13,151 @@ type _stash interface { deleteBinding(string) bool // setValue(string, Value, bool) // createBinding + setBinding - outer() _stash - runtime() *_runtime + outer() stasher + runtime() *runtime - newReference(string, bool, _at) _reference + newReference(string, bool, at) referencer - clone(clone *_clone) _stash + clone(*cloner) stasher } -// ========== -// _objectStash -// ========== - -type _objectStash struct { - _runtime *_runtime - _outer _stash - object *_object +type objectStash struct { + rt *runtime + outr stasher + object *object } -func (self *_objectStash) runtime() *_runtime { - return self._runtime +func (s *objectStash) runtime() *runtime { + return s.rt } -func (runtime *_runtime) newObjectStash(object *_object, outer _stash) *_objectStash { - if object == nil { - object = runtime.newBaseObject() - object.class = "environment" +func (rt *runtime) newObjectStash(obj *object, outer stasher) *objectStash { + if obj == nil { + obj = rt.newBaseObject() + obj.class = "environment" } - return &_objectStash{ - _runtime: runtime, - _outer: outer, - object: object, + return &objectStash{ + rt: rt, + outr: outer, + object: obj, } } -func (in *_objectStash) clone(clone *_clone) _stash { - out, exists := clone.objectStash(in) +func (s *objectStash) clone(c *cloner) stasher { + out, exists := c.objectStash(s) if exists { return out } - *out = _objectStash{ - clone.runtime, - clone.stash(in._outer), - clone.object(in.object), + *out = objectStash{ + c.runtime, + c.stash(s.outr), + c.object(s.object), } return out } -func (self *_objectStash) hasBinding(name string) bool { - return self.object.hasProperty(name) +func (s *objectStash) hasBinding(name string) bool { + return s.object.hasProperty(name) } -func (self *_objectStash) createBinding(name string, deletable bool, value Value) { - if self.object.hasProperty(name) { +func (s *objectStash) createBinding(name string, deletable bool, value Value) { + if s.object.hasProperty(name) { panic(hereBeDragons()) } - mode := _propertyMode(0111) + mode := propertyMode(0o111) if !deletable { - mode = _propertyMode(0110) + mode = propertyMode(0o110) } // TODO False? - self.object.defineProperty(name, value, mode, false) + s.object.defineProperty(name, value, mode, false) } -func (self *_objectStash) setBinding(name string, value Value, strict bool) { - self.object.put(name, value, strict) +func (s *objectStash) setBinding(name string, value Value, strict bool) { + s.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 +func (s *objectStash) setValue(name string, value Value, throw bool) { + if !s.hasBinding(name) { + s.createBinding(name, true, value) // Configurable by default } else { - self.setBinding(name, value, throw) + s.setBinding(name, value, throw) } } -func (self *_objectStash) getBinding(name string, throw bool) Value { - if self.object.hasProperty(name) { - return self.object.get(name) +func (s *objectStash) getBinding(name string, throw bool) Value { + if s.object.hasProperty(name) { + return s.object.get(name) } if throw { // strict? - panic(self._runtime.panicReferenceError("Not Defined", name)) + panic(s.rt.panicReferenceError("Not Defined", name)) } return Value{} } -func (self *_objectStash) deleteBinding(name string) bool { - return self.object.delete(name, false) +func (s *objectStash) deleteBinding(name string) bool { + return s.object.delete(name, false) } -func (self *_objectStash) outer() _stash { - return self._outer +func (s *objectStash) outer() stasher { + return s.outr } -func (self *_objectStash) newReference(name string, strict bool, at _at) _reference { - return newPropertyReference(self._runtime, self.object, name, strict, at) +func (s *objectStash) newReference(name string, strict bool, atv at) referencer { + return newPropertyReference(s.rt, s.object, name, strict, atv) } -// ========= -// _dclStash -// ========= - -type _dclStash struct { - _runtime *_runtime - _outer _stash - property map[string]_dclProperty +type dclStash struct { + rt *runtime + outr stasher + property map[string]dclProperty } -type _dclProperty struct { +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 (rt *runtime) newDeclarationStash(outer stasher) *dclStash { + return &dclStash{ + rt: rt, + outr: outer, + property: map[string]dclProperty{}, } } -func (in *_dclStash) clone(clone *_clone) _stash { - out, exists := clone.dclStash(in) +func (s *dclStash) clone(c *cloner) stasher { + out, exists := c.dclStash(s) if exists { return out } - property := make(map[string]_dclProperty, len(in.property)) - for index, value := range in.property { - property[index] = clone.dclProperty(value) + prop := make(map[string]dclProperty, len(s.property)) + for index, value := range s.property { + prop[index] = c.dclProperty(value) } - *out = _dclStash{ - clone.runtime, - clone.stash(in._outer), - property, + *out = dclStash{ + c.runtime, + c.stash(s.outr), + prop, } return out } -func (self *_dclStash) hasBinding(name string) bool { - _, exists := self.property[name] +func (s *dclStash) hasBinding(name string) bool { + _, exists := s.property[name] return exists } -func (self *_dclStash) runtime() *_runtime { - return self._runtime +func (s *dclStash) runtime() *runtime { + return s.rt } -func (self *_dclStash) createBinding(name string, deletable bool, value Value) { - _, exists := self.property[name] - if exists { +func (s *dclStash) createBinding(name string, deletable bool, value Value) { + if _, exists := s.property[name]; exists { panic(fmt.Errorf("createBinding: %s: already exists", name)) } - self.property[name] = _dclProperty{ + s.property[name] = dclProperty{ value: value, mutable: true, deletable: deletable, @@ -177,62 +165,62 @@ func (self *_dclStash) createBinding(name string, deletable bool, value Value) { } } -func (self *_dclStash) setBinding(name string, value Value, strict bool) { - property, exists := self.property[name] +func (s *dclStash) setBinding(name string, value Value, strict bool) { + prop, exists := s.property[name] if !exists { panic(fmt.Errorf("setBinding: %s: missing", name)) } - if property.mutable { - property.value = value - self.property[name] = property + if prop.mutable { + prop.value = value + s.property[name] = prop } else { - self._runtime.typeErrorResult(strict) + s.rt.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 +func (s *dclStash) setValue(name string, value Value, throw bool) { + if !s.hasBinding(name) { + s.createBinding(name, false, value) // NOT deletable by default } else { - self.setBinding(name, value, throw) + s.setBinding(name, value, throw) } } -// FIXME This is called a __lot__ -func (self *_dclStash) getBinding(name string, throw bool) Value { - property, exists := self.property[name] +// FIXME This is called a __lot__. +func (s *dclStash) getBinding(name string, throw bool) Value { + prop, exists := s.property[name] if !exists { panic(fmt.Errorf("getBinding: %s: missing", name)) } - if !property.mutable && !property.readable { + if !prop.mutable && !prop.readable { if throw { // strict? - panic(self._runtime.panicTypeError()) + panic(s.rt.panicTypeError()) } return Value{} } - return property.value + return prop.value } -func (self *_dclStash) deleteBinding(name string) bool { - property, exists := self.property[name] +func (s *dclStash) deleteBinding(name string) bool { + prop, exists := s.property[name] if !exists { return true } - if !property.deletable { + if !prop.deletable { return false } - delete(self.property, name) + delete(s.property, name) return true } -func (self *_dclStash) outer() _stash { - return self._outer +func (s *dclStash) outer() stasher { + return s.outr } -func (self *_dclStash) newReference(name string, strict bool, _ _at) _reference { - return &_stashReference{ +func (s *dclStash) newReference(name string, strict bool, _ at) referencer { + return &stashReference{ name: name, - base: self, + base: s, } } @@ -240,57 +228,62 @@ func (self *_dclStash) newReference(name string, strict bool, _ _at) _reference // _fnStash // ======== -type _fnStash struct { - _dclStash - arguments *_object +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 (rt *runtime) newFunctionStash(outer stasher) *fnStash { + return &fnStash{ + dclStash: dclStash{ + rt: rt, + outr: outer, + property: map[string]dclProperty{}, }, } } -func (in *_fnStash) clone(clone *_clone) _stash { - out, exists := clone.fnStash(in) +func (s *fnStash) clone(c *cloner) stasher { + out, exists := c.fnStash(s) if exists { return out } - dclStash := in._dclStash.clone(clone).(*_dclStash) - index := make(map[string]string, len(in.indexOfArgumentName)) - for name, value := range in.indexOfArgumentName { + dclStash := s.dclStash.clone(c).(*dclStash) + index := make(map[string]string, len(s.indexOfArgumentName)) + for name, value := range s.indexOfArgumentName { index[name] = value } - *out = _fnStash{ - _dclStash: *dclStash, - arguments: clone.object(in.arguments), + *out = fnStash{ + dclStash: *dclStash, + arguments: c.object(s.arguments), indexOfArgumentName: index, } return out } -func getStashProperties(stash _stash) (keys []string) { +// getStashProperties returns the properties from stash. +func getStashProperties(stash stasher) []string { switch vars := stash.(type) { - case *_dclStash: + case *dclStash: + keys := make([]string, 0, len(vars.property)) for k := range vars.property { keys = append(keys, k) } - case *_fnStash: + return keys + case *fnStash: + keys := make([]string, 0, len(vars.property)) for k := range vars.property { keys = append(keys, k) } - case *_objectStash: + return keys + case *objectStash: + keys := make([]string, 0, len(vars.object.property)) for k := range vars.object.property { keys = append(keys, k) } + return keys default: panic("unknown stash type") } - - return } diff --git a/string_test.go b/string_test.go index c7d31808..0fd94a9b 100644 --- a/string_test.go +++ b/string_test.go @@ -2,6 +2,8 @@ package otto import ( "testing" + + "github.com/stretchr/testify/require" ) func TestString(t *testing.T) { @@ -51,7 +53,7 @@ func TestString_charCodeAt(t *testing.T) { def = "xyzzy".charCodeAt(11) `) test("abc", 120) - test("def", _NaN) + test("def", naN) }) } @@ -275,25 +277,25 @@ func TestString_split(t *testing.T) { func BenchmarkString_splitWithString(b *testing.B) { vm := New() - vm.Set("data", "Lorem ipsum dolor sit amet, blandit nec elit. Ridiculus tortor wisi fusce vivamus") - s, _ := vm.Compile("test.js", `data.split(" ")`) + err := vm.Set("data", "Lorem ipsum dolor sit amet, blandit nec elit. Ridiculous tortor wisi fusce vivamus") + require.NoError(b, err) + s, err := vm.Compile("test.js", `data.split(" ")`) + require.NoError(b, err) for i := 0; i < b.N; i++ { - _, e := vm.Run(s) - if e != nil { - b.Error(e.Error()) - } + _, err = vm.Run(s) + require.NoError(b, err) } } func BenchmarkString_splitWithRegex(b *testing.B) { vm := New() - vm.Set("data", "Lorem ipsum dolor sit amet, blandit nec elit. Ridiculus tortor wisi fusce vivamus") - s, _ := vm.Compile("test.js", `data.split(/ /)`) + err := vm.Set("data", "Lorem ipsum dolor sit amet, blandit nec elit. Ridiculous tortor wisi fusce vivamus") + require.NoError(b, err) + s, err := vm.Compile("test.js", `data.split(/ /)`) + require.NoError(b, err) for i := 0; i < b.N; i++ { - _, e := vm.Run(s) - if e != nil { - b.Error(e.Error()) - } + _, err = vm.Run(s) + require.NoError(b, err) } } diff --git a/terst/terst.go b/terst/terst.go index f026196c..2645e59c 100644 --- a/terst/terst.go +++ b/terst/terst.go @@ -5,27 +5,26 @@ Package terst is a terse (terst = test + terse), easy-to-use testing library for terst is compatible with (and works via) the standard testing package: http://golang.org/pkg/testing - var is = terst.Is + var is = terst.Is - func Test(t *testing.T) { - terst.Terst(t, func() { - is("abc", "abc") + func Test(t *testing.T) { + terst.Terst(t, func() { + is("abc", "abc") - is(1, ">", 0) + is(1, ">", 0) - var abc []int - is(abc, nil) - } - } + var abc []int + is(abc, nil) + } + } Do not import terst directly, instead use `terst-import` to copy it into your testing environment: https://github.com/robertkrimen/terst/tree/master/terst-import - $ go get github.com/robertkrimen/terst/terst-import - - $ terst-import + $ go get github.com/robertkrimen/terst/terst-import + $ terst-import */ package terst @@ -36,7 +35,7 @@ import ( "math/big" "reflect" "regexp" - "runtime" + goruntime "runtime" "strings" "sync" "testing" @@ -49,38 +48,37 @@ import ( // a comparator, that changes how the comparison is made. The following // comparators are available: // -// == # got == expect (default) -// != # got != expect +// == # got == expect (default) +// != # got != expect // -// > # got > expect (float32, uint, uint16, int, int64, ...) -// >= # got >= expect -// < # got < expect -// <= # got <= expect +// > # got > expect (float32, uint, uint16, int, int64, ...) +// >= # got >= expect +// < # got < expect +// <= # got <= expect // -// =~ # regexp.MustCompile(expect).Match{String}(got) -// !~ # !regexp.MustCompile(expect).Match{String}(got) +// =~ # regexp.MustCompile(expect).Match{String}(got) +// !~ # !regexp.MustCompile(expect).Match{String}(got) // // Basic usage with the default comparator (==): // -// Is(, ) +// Is(, ) // // Specifying a different comparator: // -// Is(, , ) +// Is(, , ) // // A simple comparison: // -// Is(2 + 2, 4) +// Is(2 + 2, 4) // // A bit trickier: // -// Is(1, ">", 0) -// Is(2 + 2, "!=", 5) -// Is("Nothing happens.", "=~", `ing(\s+)happens\.$`) +// Is(1, ">", 0) +// Is(2 + 2, "!=", 5) +// Is("Nothing happens.", "=~", `ing(\s+)happens\.$`) // // Is should only be called under a Terst(t, ...) call. For a standalone version, // use IsErr. If no scope is found and the comparison is false, then Is will panic the error. -// func Is(arguments ...interface{}) bool { err := IsErr(arguments...) if err != nil { @@ -117,9 +115,9 @@ func registerScope(pc uintptr, scope *_scope) { registry.table[pc] = scope } -func scope() *_scope { - scope, _ := findScope() - return scope +func getScope() *_scope { + s, _ := findScope() + return s } func floatCompare(a float64, b float64) int { @@ -144,15 +142,11 @@ func bigUint(value uint64) *big.Int { return big.NewInt(0).SetUint64(value) } -type _toString interface { - String() string -} - func toString(value interface{}) (string, error) { switch value := value.(type) { case string: return value, nil - case _toString: + case fmt.Stringer: return value.String(), nil case error: return value.Error(), nil @@ -232,33 +226,31 @@ func bigIntPromote(value reflect.Value) (*big.Int, error) { } func compareOther(got, expect interface{}) (int, error) { - { - switch expect.(type) { - case float32, float64: - return compareNumber(got, expect) - case uint, uint8, uint16, uint32, uint64: - return compareNumber(got, expect) - case int, int8, int16, int32, int64: - return compareNumber(got, expect) - case string: - var err error - got, err = toString(got) - if err != nil { - return 0, err - } - case nil: - got := reflect.ValueOf(got) - switch got.Kind() { - case reflect.Chan, reflect.Func, reflect.Map, reflect.Ptr, reflect.Slice, reflect.Interface: - if got.IsNil() { - return 0, nil - } - return -1, nil - case reflect.Invalid: // reflect.Invalid: var abc interface{} = nil + switch expect.(type) { + case float32, float64: + return compareNumber(got, expect) + case uint, uint8, uint16, uint32, uint64: + return compareNumber(got, expect) + case int, int8, int16, int32, int64: + return compareNumber(got, expect) + case string: + var err error + got, err = toString(got) + if err != nil { + return 0, err + } + case nil: + got := reflect.ValueOf(got) + switch got.Kind() { + case reflect.Chan, reflect.Func, reflect.Map, reflect.Ptr, reflect.Slice, reflect.Interface: + if got.IsNil() { return 0, nil } - return 0, errInvalid + return -1, nil + case reflect.Invalid: // reflect.Invalid: var abc interface{} = nil + return 0, nil } + return 0, errInvalid } if reflect.ValueOf(got).Type() != reflect.ValueOf(expect).Type() { @@ -272,36 +264,32 @@ func compareOther(got, expect interface{}) (int, error) { } func compareNumber(got, expect interface{}) (int, error) { - { - got := reflect.ValueOf(got) - k0 := got.Kind() - expect := reflect.ValueOf(expect) - k1 := expect.Kind() - if reflect.Float32 <= k0 && k0 <= reflect.Float64 || - reflect.Float32 <= k1 && k1 <= reflect.Float64 { - got, err := floatPromote(got) - if err != nil { - return 0, err - } - expect, err := floatPromote(expect) - if err != nil { - return 0, err - } - return floatCompare(got, expect), nil - } else { - got, err := bigIntPromote(got) - if err != nil { - return 0, err - } - expect, err := bigIntPromote(expect) - if err != nil { - return 0, err - } - return got.Cmp(expect), nil + gotRv := reflect.ValueOf(got) + gotKind := gotRv.Kind() + expectRv := reflect.ValueOf(expect) + expectKind := expectRv.Kind() + if reflect.Float32 <= gotKind && gotKind <= reflect.Float64 || + reflect.Float32 <= expectKind && expectKind <= reflect.Float64 { + got, err := floatPromote(gotRv) + if err != nil { + return 0, err } + expect, err := floatPromote(expectRv) + if err != nil { + return 0, err + } + return floatCompare(got, expect), nil } - return 0, errInvalid + goBigInt, err := bigIntPromote(gotRv) + if err != nil { + return 0, err + } + expectBigInt, err := bigIntPromote(expectRv) + if err != nil { + return 0, err + } + return goBigInt.Cmp(expectBigInt), nil } // IsErr compares two values (got & expect) and returns nil if the comparison is true, an ErrFail if @@ -310,9 +298,8 @@ func compareNumber(got, expect interface{}) (int, error) { // // Is & IsErr are similar but different: // -// Is(...) // Should only be called within a Terst(...) call -// IsErr(...) // A standalone comparator, the same as Is, just without the automatic reporting -// +// Is(...) // Should only be called within a Terst(...) call +// IsErr(...) // A standalone comparator, the same as Is, just without the automatic reporting func IsErr(arguments ...interface{}) error { var got, expect interface{} comparator := "==" @@ -417,64 +404,63 @@ func typeKindString(value interface{}) string { return fmt.Sprintf(" (%T=%s)", value, kind) } -func (scope *_scope) reset() { - scope.name = "" - scope.output = scope.output[:0] - scope.start = time.Time{} - scope.duration = 0 +func (s *_scope) reset() { + s.name = "" + s.output = s.output[:0] + s.start = time.Time{} + s.duration = 0 } // Terst creates a testing scope, where Is can be called and errors will be reported // according to the top-level location of the comparison, and not where the Is call // actually takes place. For example: // -// func test(value int) { -// Is(value, 5) // <--- This failure is reported below. -// } -// -// Terst(t, func(){ +// func test(value int) { +// Is(value, 5) // <--- This failure is reported below. +// } // -// Is(2, ">", 3) // <--- An error is reported here. +// Terst(t, func(){ // -// test(5) // <--- An error is reported here. +// Is(2, ">", 3) // <--- An error is reported here. // -// }) +// test(5) // <--- An error is reported here. // +// }) func Terst(t *testing.T, arguments ...func()) { - scope := &_scope{ + curScope := &_scope{ t: t, } - pc, _, _, ok := runtime.Caller(1) // TODO Associate with the Test... func + pc, _, _, ok := goruntime.Caller(1) // TODO Associate with the Test... func if !ok { panic("Here be dragons.") } - _, scope.testFunc = findTestFunc() + _, curScope.testFunc = findTestFunc() - registerScope(pc, scope) + registerScope(pc, curScope) for _, fn := range arguments { func() { - scope.reset() - name := scope.testFunc.Name() - index := strings.LastIndex(scope.testFunc.Name(), ".") + curScope.reset() + name := curScope.testFunc.Name() + index := strings.LastIndex(curScope.testFunc.Name(), ".") if index >= 0 { name = name[index+1:] + "(Terst)" } else { name = "(Terst)" } name = "(Terst)" - scope.name = name - scope.start = time.Now() + curScope.name = name + curScope.start = time.Now() defer func() { - scope.duration = time.Now().Sub(scope.start) + curScope.duration = time.Now().Sub(curScope.start) if err := recover(); err != nil { - scope.t.Fail() - scope.report() + curScope.t.Fail() + curScope.report() panic(err) } - scope.report() + curScope.report() }() fn() }() @@ -482,24 +468,24 @@ func Terst(t *testing.T, arguments ...func()) { } // From "testing" -func (scope *_scope) report() { +func (s *_scope) report() { format := "~~~ %s: (Terst)\n%s" - if scope.t.Failed() { - fmt.Printf(format, "FAIL", scope.output) - } else if testing.Verbose() && len(scope.output) > 0 { - fmt.Printf(format, "PASS", scope.output) + if s.t.Failed() { + fmt.Printf(format, "FAIL", s.output) + } else if testing.Verbose() && len(s.output) > 0 { + fmt.Printf(format, "PASS", s.output) } } -func (scope *_scope) log(call _entry, str string) { - scope.mu.Lock() - defer scope.mu.Unlock() - scope.output = append(scope.output, decorate(call, str)...) +func (s *_scope) log(call entry, str string) { + s.mu.Lock() + defer s.mu.Unlock() + s.output = append(s.output, decorate(call, str)...) } // decorate prefixes the string with the file and line of the call site // and inserts the final newline if needed and indentation tabs for formascing. -func decorate(call _entry, s string) string { +func decorate(call entry, s string) string { file, line := call.File, call.Line if call.PC > 0 { @@ -532,52 +518,52 @@ func decorate(call _entry, s string) string { return buf.String() } -func findScope() (*_scope, _entry) { +func findScope() (*_scope, entry) { registry.lock.RLock() defer registry.lock.RUnlock() table := registry.table depth := 2 // Starting depth - call := _entry{} + call := entry{} for { - pc, _, _, ok := runtime.Caller(depth) + pc, _, _, ok := goruntime.Caller(depth) if !ok { break } - if scope, exists := table[pc]; exists { - pc, file, line, _ := runtime.Caller(depth - 3) // Terst(...) + func(){}() + fn() => ???() + if s, exists := table[pc]; exists { + pc, file, line, _ := goruntime.Caller(depth - 3) // Terst(...) + func(){}() + fn() => ???() call.PC = pc call.File = file call.Line = line - return scope, call + return s, call } depth++ } - return nil, _entry{} + return nil, entry{} } // Call is a reference to a line immediately under a Terst testing scope. type Call struct { scope *_scope - entry _entry + entry entry } // Caller will search the stack, looking for a Terst testing scope. If a scope // is found, then Caller returns a Call for logging errors, accessing testing.T, etc. // If no scope is found, Caller returns nil. func Caller() *Call { - scope, entry := findScope() - if scope == nil { + curScope, entry := findScope() + if curScope == nil { return nil } return &Call{ - scope: scope, + scope: curScope, entry: entry, } } // TestFunc returns the *runtime.Func entry for the top-level Test...(t testing.T) // function. -func (cl *Call) TestFunc() *runtime.Func { +func (cl *Call) TestFunc() *goruntime.Func { return cl.scope.testFunc } @@ -622,7 +608,7 @@ func (cl *Call) Skipf(format string, arguments ...interface{}) { type _scope struct { t *testing.T - testFunc *runtime.Func + testFunc *goruntime.Func name string mu sync.RWMutex output []byte @@ -630,25 +616,25 @@ type _scope struct { duration time.Duration } -type _entry struct { +type entry struct { PC uintptr File string Line int - Func *runtime.Func + Func *goruntime.Func } -func _findFunc(match string) (_entry, *runtime.Func) { +func findFunc(match string) (entry, *goruntime.Func) { depth := 2 // Starting depth for { - pc, file, line, ok := runtime.Caller(depth) + pc, file, line, ok := goruntime.Caller(depth) if !ok { break } - fn := runtime.FuncForPC(pc) + fn := goruntime.FuncForPC(pc) name := fn.Name() if index := strings.LastIndex(name, match); index >= 0 { // Assume we have an instance of TestXyzzy in a _test file - return _entry{ + return entry{ PC: pc, File: file, Line: line, @@ -657,13 +643,13 @@ func _findFunc(match string) (_entry, *runtime.Func) { } depth++ } - return _entry{}, nil + return entry{}, nil } -func findTestFunc() (_entry, *runtime.Func) { - return _findFunc(".Test") +func findTestFunc() (entry, *goruntime.Func) { + return findFunc(".Test") } -func findTerstFunc() (_entry, *runtime.Func) { - return _findFunc(".Terst") +func findTerstFunc() (entry, *goruntime.Func) { + return findFunc(".Terst") } diff --git a/test/tester.go b/test/tester.go index f429760c..4018dbfc 100644 --- a/test/tester.go +++ b/test/tester.go @@ -1,28 +1,34 @@ package main import ( + "context" "encoding/json" "flag" "fmt" - "io/ioutil" + "io" "net/http" "os" "regexp" "strings" "sync" "text/tabwriter" + "time" "github.com/robertkrimen/otto" "github.com/robertkrimen/otto/parser" ) -var flag_test *bool = flag.Bool("test", false, "") -var flag_report *bool = flag.Bool("report", false, "") +var ( + flagTest *bool = flag.Bool("test", false, "") + flagTeport *bool = flag.Bool("report", false, "") +) -var match_ReferenceError_not_defined = regexp.MustCompile(`^ReferenceError: \S+ is not defined$`) -var match_lookahead = regexp.MustCompile(`Invalid regular expression: re2: Invalid \(\?[=!]\) `) -var match_backreference = regexp.MustCompile(`Invalid regular expression: re2: Invalid \\\d `) -var match_TypeError_undefined = regexp.MustCompile(`^TypeError: Cannot access member '[^']+' of undefined$`) +var ( + matchReferenceErrorNotDefined = regexp.MustCompile(`^ReferenceError: \S+ is not defined$`) + matchLookahead = regexp.MustCompile(`Invalid regular expression: re2: Invalid \(\?[=!]\) `) + matchBackreference = regexp.MustCompile(`Invalid regular expression: re2: Invalid \\\d `) + matchTypeErrorUndefined = regexp.MustCompile(`^TypeError: Cannot access member '[^']+' of undefined$`) +) var target = map[string]string{ "test-angular-bindonce.js": "fail", // (anonymous): Line 1:944 Unexpected token ( (and 40 more errors) @@ -41,49 +47,66 @@ var target = map[string]string{ // http://cdnjs.com/ // http://api.cdnjs.com/libraries -func fetch(name, location string) error { - response, err := http.Get(location) //nolint: noctx +type libraries struct { + Results []library `json:"results"` +} + +type library struct { + Name string `json:"name"` + Latest string `json:"latest"` +} + +func (l library) fetch() error { + if !strings.HasSuffix(l.Latest, ".js") { + return nil + } + + ctx, cancel := context.WithTimeout(context.Background(), time.Second*20) + defer cancel() + + req, err := http.NewRequestWithContext(ctx, http.MethodGet, l.Latest, nil) if err != nil { - return err + return fmt.Errorf("request library %q: %w", l.Name, err) } - defer response.Body.Close() - body, err := ioutil.ReadAll(response.Body) + + resp, err := http.DefaultClient.Do(req) if err != nil { - return err + return fmt.Errorf("get library %q: %w", l.Name, err) } + defer resp.Body.Close() //nolint: errcheck - if !strings.HasSuffix(location, ".js") { - return nil + f, err := os.Create("test-" + l.Name + ".js") + if err != nil { + return fmt.Errorf("create library %q: %w", l.Name, err) } - filename := "test-" + name + ".js" - fmt.Println(filename, len(body)) - return ioutil.WriteFile(filename, body, 0644) + if _, err = io.Copy(f, resp.Body); err != nil { + return fmt.Errorf("write library %q: %w", l.Name, err) + } + + return nil } func test(filename string) error { - script, err := ioutil.ReadFile(filename) + script, err := os.ReadFile(filename) //nolint: gosec if err != nil { return err } - if !*flag_report { + if !*flagTeport { fmt.Fprintln(os.Stdout, filename, len(script)) } parse := false - option := target[filename] - - if option != "parse" { + if target[filename] != "parse" { vm := otto.New() - _, err = vm.Run(string(script)) - if err != nil { + if _, err = vm.Run(string(script)); err != nil { value := err.Error() switch { - case match_ReferenceError_not_defined.MatchString(value): - case match_TypeError_undefined.MatchString(value): - case match_lookahead.MatchString(value): - case match_backreference.MatchString(value): + case matchReferenceErrorNotDefined.MatchString(value), + matchTypeErrorUndefined.MatchString(value), + matchLookahead.MatchString(value), + matchBackreference.MatchString(value): default: return err } @@ -102,78 +125,88 @@ func test(filename string) error { return nil } -func main() { - flag.Parse() +func fetchAll() error { + resp, err := http.Get("http://api.cdnjs.com/libraries") //nolint: noctx + if err != nil { + return err + } + defer resp.Body.Close() //nolint: errcheck - filename := "" + var libs libraries + dec := json.NewDecoder(resp.Body) + if err := dec.Decode(&libs); err != nil { + return fmt.Errorf("json decode: %w", err) + } - err := func() error { - if flag.Arg(0) == "fetch" { - response, err := http.Get("http://api.cdnjs.com/libraries") //nolint: noctx - if err != nil { - return err - } - defer response.Body.Close() - body, err := ioutil.ReadAll(response.Body) - if err != nil { - return err - } + var wg sync.WaitGroup + errs := make(chan error, 5) + for _, lib := range libs.Results { + wg.Add(1) + go func(lib library) { + defer wg.Done() + errs <- lib.fetch() + }(lib) + } - var tmp map[string]interface{} + defer func() { + wg.Wait() + close(errs) + }() - err = json.Unmarshal(body, &tmp) - if err != nil { - return err - } + for err := range errs { + if err != nil { + return err + } + } - var wg sync.WaitGroup + return nil +} - for _, value := range tmp["results"].([]interface{}) { - wg.Add(1) - library := value.(map[string]interface{}) - go func() { - defer wg.Done() - fetch(library["name"].(string), library["latest"].(string)) - }() - } +func report() error { + files, err := os.ReadDir(".") + if err != nil { + return fmt.Errorf("read dir: %w", err) + } - wg.Wait() + writer := tabwriter.NewWriter(os.Stdout, 0, 8, 0, '\t', 0) + fmt.Fprintln(writer, "", "\t| Status") + fmt.Fprintln(writer, "---", "\t| ---") + for _, file := range files { + filename := file.Name() + if !strings.HasPrefix(filename, "test-") { + continue + } + err := test(filename) + option := target[filename] + name := strings.TrimPrefix(strings.TrimSuffix(filename, ".js"), "test-") + if err != nil { + fmt.Fprintln(writer, name, "\t| fail") + continue + } - return nil + switch option { + case "": + fmt.Fprintln(writer, name, "\t| pass") + case "parse": + fmt.Fprintln(writer, name, "\t| pass (parse)") + case "re2": + fmt.Fprintln(writer, name, "\t| unknown (re2)") } + } + return writer.Flush() +} - if *flag_report { - files, err := ioutil.ReadDir(".") - if err != nil { - return err - } - writer := tabwriter.NewWriter(os.Stdout, 0, 8, 0, '\t', 0) - fmt.Fprintln(writer, "", "\t| Status") - fmt.Fprintln(writer, "---", "\t| ---") - for _, file := range files { - filename := file.Name() - if !strings.HasPrefix(filename, "test-") { - continue - } - err := test(filename) - option := target[filename] - name := strings.TrimPrefix(strings.TrimSuffix(filename, ".js"), "test-") - if err == nil { - switch option { - case "": - fmt.Fprintln(writer, name, "\t| pass") - case "parse": - fmt.Fprintln(writer, name, "\t| pass (parse)") - case "re2": - fmt.Fprintln(writer, name, "\t| unknown (re2)") - continue - } - } else { - fmt.Fprintln(writer, name, "\t| fail") - } - } - writer.Flush() - return nil +func main() { + flag.Parse() + + var filename string + err := func() error { + if flag.Arg(0) == "fetch" { + return fetchAll() + } + + if *flagTeport { + return report() } filename = flag.Arg(0) @@ -181,7 +214,7 @@ func main() { }() if err != nil { if filename != "" { - if *flag_test && target[filename] == "fail" { + if *flagTest && target[filename] == "fail" { goto exit } fmt.Fprintf(os.Stderr, "%s: %s\n", filename, err.Error()) diff --git a/testing_test.go b/testing_test.go index d4d36d9f..e1f35a2d 100644 --- a/testing_test.go +++ b/testing_test.go @@ -77,29 +77,29 @@ func newTester() *_tester { } } -func (self *_tester) Get(name string) (Value, error) { - return self.vm.Get(name) +func (te *_tester) Get(name string) (Value, error) { + return te.vm.Get(name) } -func (self *_tester) Set(name string, value interface{}) Value { - err := self.vm.Set(name, value) +func (te *_tester) Set(name string, value interface{}) Value { + err := te.vm.Set(name, value) is(err, nil) if err != nil { terst.Caller().T().FailNow() } - return self.vm.getValue(name) + return te.vm.getValue(name) } -func (self *_tester) Run(src interface{}) (Value, error) { - return self.vm.Run(src) +func (te *_tester) Run(src interface{}) (Value, error) { + return te.vm.Run(src) } -func (self *_tester) test(name string, expect ...interface{}) Value { - vm := self.vm +func (te *_tester) test(name string, expect ...interface{}) Value { + vm := te.vm raise := false defer func() { if caught := recover(); caught != nil { - if exception, ok := caught.(*_exception); ok { + if exception, ok := caught.(*exception); ok { caught = exception.eject() } if raise { @@ -124,7 +124,7 @@ func (self *_tester) test(name string, expect ...interface{}) Value { source = source[6:] source = strings.TrimLeft(source, " ") } - value, err = vm.runtime.cmpl_run(source, nil) + value, err = vm.runtime.cmplRun(source, nil) if err != nil { panic(err) } diff --git a/token/token.go b/token/token.go index d57c8c0f..8cb91138 100644 --- a/token/token.go +++ b/token/token.go @@ -14,63 +14,17 @@ type Token int // "+"). 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 { + switch { + case tkn == 0: return "UNKNOWN" - } - if tkn < Token(len(token2string)) { + case tkn < Token(len(token2string)): return token2string[tkn] + default: + return "token(" + strconv.Itoa(int(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 { +type keyword struct { token Token futureKeyword bool strict bool diff --git a/token/token_const.go b/token/token_const.go index 323f4a03..6799cc74 100644 --- a/token/token_const.go +++ b/token/token_const.go @@ -74,7 +74,7 @@ const ( COLON // : QUESTION_MARK // ? - firstKeyword //nolint: deadcode + _ IF IN DO @@ -108,7 +108,6 @@ const ( DEBUGGER INSTANCEOF - lastKeyword //nolint: deadcode ) var token2string = [...]string{ @@ -199,149 +198,149 @@ var token2string = [...]string{ INSTANCEOF: "instanceof", } -var keywordTable = map[string]_keyword{ - "if": _keyword{ +var keywordTable = map[string]keyword{ + "if": { token: IF, }, - "in": _keyword{ + "in": { token: IN, }, - "do": _keyword{ + "do": { token: DO, }, - "var": _keyword{ + "var": { token: VAR, }, - "for": _keyword{ + "for": { token: FOR, }, - "new": _keyword{ + "new": { token: NEW, }, - "try": _keyword{ + "try": { token: TRY, }, - "this": _keyword{ + "this": { token: THIS, }, - "else": _keyword{ + "else": { token: ELSE, }, - "case": _keyword{ + "case": { token: CASE, }, - "void": _keyword{ + "void": { token: VOID, }, - "with": _keyword{ + "with": { token: WITH, }, - "while": _keyword{ + "while": { token: WHILE, }, - "break": _keyword{ + "break": { token: BREAK, }, - "catch": _keyword{ + "catch": { token: CATCH, }, - "throw": _keyword{ + "throw": { token: THROW, }, - "return": _keyword{ + "return": { token: RETURN, }, - "typeof": _keyword{ + "typeof": { token: TYPEOF, }, - "delete": _keyword{ + "delete": { token: DELETE, }, - "switch": _keyword{ + "switch": { token: SWITCH, }, - "default": _keyword{ + "default": { token: DEFAULT, }, - "finally": _keyword{ + "finally": { token: FINALLY, }, - "function": _keyword{ + "function": { token: FUNCTION, }, - "continue": _keyword{ + "continue": { token: CONTINUE, }, - "debugger": _keyword{ + "debugger": { token: DEBUGGER, }, - "instanceof": _keyword{ + "instanceof": { token: INSTANCEOF, }, - "const": _keyword{ + "const": { token: KEYWORD, futureKeyword: true, }, - "class": _keyword{ + "class": { token: KEYWORD, futureKeyword: true, }, - "enum": _keyword{ + "enum": { token: KEYWORD, futureKeyword: true, }, - "export": _keyword{ + "export": { token: KEYWORD, futureKeyword: true, }, - "extends": _keyword{ + "extends": { token: KEYWORD, futureKeyword: true, }, - "import": _keyword{ + "import": { token: KEYWORD, futureKeyword: true, }, - "super": _keyword{ + "super": { token: KEYWORD, futureKeyword: true, }, - "implements": _keyword{ + "implements": { token: KEYWORD, futureKeyword: true, strict: true, }, - "interface": _keyword{ + "interface": { token: KEYWORD, futureKeyword: true, strict: true, }, - "let": _keyword{ + "let": { token: KEYWORD, futureKeyword: true, strict: true, }, - "package": _keyword{ + "package": { token: KEYWORD, futureKeyword: true, strict: true, }, - "private": _keyword{ + "private": { token: KEYWORD, futureKeyword: true, strict: true, }, - "protected": _keyword{ + "protected": { token: KEYWORD, futureKeyword: true, strict: true, }, - "public": _keyword{ + "public": { token: KEYWORD, futureKeyword: true, strict: true, }, - "static": _keyword{ + "static": { token: KEYWORD, futureKeyword: true, strict: true, diff --git a/type_arguments.go b/type_arguments.go index 0a3ddcbf..2e313fb5 100644 --- a/type_arguments.go +++ b/type_arguments.go @@ -4,103 +4,103 @@ import ( "strconv" ) -func (runtime *_runtime) newArgumentsObject(indexOfParameterName []string, stash _stash, length int) *_object { - self := runtime.newClassObject("Arguments") +func (rt *runtime) newArgumentsObject(indexOfParameterName []string, stash stasher, length int) *object { + obj := rt.newClassObject("Arguments") - for index, _ := range indexOfParameterName { + for index := range indexOfParameterName { name := strconv.FormatInt(int64(index), 10) - objectDefineOwnProperty(self, name, _property{Value{}, 0111}, false) + objectDefineOwnProperty(obj, name, property{Value{}, 0o111}, false) } - self.objectClass = _classArguments - self.value = _argumentsObject{ + obj.objectClass = classArguments + obj.value = argumentsObject{ indexOfParameterName: indexOfParameterName, stash: stash, } - self.prototype = runtime.global.ObjectPrototype + obj.prototype = rt.global.ObjectPrototype - self.defineProperty(propertyLength, toValue_int(length), 0101, false) + obj.defineProperty(propertyLength, intValue(length), 0o101, false) - return self + return obj } -type _argumentsObject struct { +type argumentsObject struct { indexOfParameterName []string // function(abc, def, ghi) // indexOfParameterName[0] = "abc" // indexOfParameterName[1] = "def" // indexOfParameterName[2] = "ghi" // ... - stash _stash + stash stasher } -func (in _argumentsObject) clone(clone *_clone) _argumentsObject { - indexOfParameterName := make([]string, len(in.indexOfParameterName)) - copy(indexOfParameterName, in.indexOfParameterName) - return _argumentsObject{ +func (o argumentsObject) clone(c *cloner) argumentsObject { + indexOfParameterName := make([]string, len(o.indexOfParameterName)) + copy(indexOfParameterName, o.indexOfParameterName) + return argumentsObject{ indexOfParameterName, - clone.stash(in.stash), + c.stash(o.stash), } } -func (self _argumentsObject) get(name string) (Value, bool) { +func (o argumentsObject) get(name string) (Value, bool) { index := stringToArrayIndex(name) - if index >= 0 && index < int64(len(self.indexOfParameterName)) { - name := self.indexOfParameterName[index] + if index >= 0 && index < int64(len(o.indexOfParameterName)) { + name := o.indexOfParameterName[index] if name == "" { return Value{}, false } - return self.stash.getBinding(name, false), true + return o.stash.getBinding(name, false), true } return Value{}, false } -func (self _argumentsObject) put(name string, value Value) { +func (o argumentsObject) put(name string, value Value) { index := stringToArrayIndex(name) - name = self.indexOfParameterName[index] - self.stash.setBinding(name, value, false) + name = o.indexOfParameterName[index] + o.stash.setBinding(name, value, false) } -func (self _argumentsObject) delete(name string) { +func (o argumentsObject) delete(name string) { index := stringToArrayIndex(name) - self.indexOfParameterName[index] = "" + o.indexOfParameterName[index] = "" } -func argumentsGet(self *_object, name string) Value { - if value, exists := self.value.(_argumentsObject).get(name); exists { +func argumentsGet(obj *object, name string) Value { + if value, exists := obj.value.(argumentsObject).get(name); exists { return value } - return objectGet(self, name) + return objectGet(obj, name) } -func argumentsGetOwnProperty(self *_object, name string) *_property { - property := objectGetOwnProperty(self, name) - if value, exists := self.value.(_argumentsObject).get(name); exists { - property.value = value +func argumentsGetOwnProperty(obj *object, name string) *property { + prop := objectGetOwnProperty(obj, name) + if value, exists := obj.value.(argumentsObject).get(name); exists { + prop.value = value } - return property + return prop } -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 self.runtime.typeErrorResult(throw) +func argumentsDefineOwnProperty(obj *object, name string, descriptor property, throw bool) bool { + if _, exists := obj.value.(argumentsObject).get(name); exists { + if !objectDefineOwnProperty(obj, name, descriptor, false) { + return obj.runtime.typeErrorResult(throw) } if value, valid := descriptor.value.(Value); valid { - self.value.(_argumentsObject).put(name, value) + obj.value.(argumentsObject).put(name, value) } return true } - return objectDefineOwnProperty(self, name, descriptor, throw) + return objectDefineOwnProperty(obj, name, descriptor, throw) } -func argumentsDelete(self *_object, name string, throw bool) bool { - if !objectDelete(self, name, throw) { +func argumentsDelete(obj *object, name string, throw bool) bool { + if !objectDelete(obj, name, throw) { return false } - if _, exists := self.value.(_argumentsObject).get(name); exists { - self.value.(_argumentsObject).delete(name) + if _, exists := obj.value.(argumentsObject).get(name); exists { + obj.value.(argumentsObject).delete(name) } return true } diff --git a/type_array.go b/type_array.go index 67af78a4..0907d389 100644 --- a/type_array.go +++ b/type_array.go @@ -4,43 +4,43 @@ import ( "strconv" ) -func (runtime *_runtime) newArrayObject(length uint32) *_object { - self := runtime.newObject() - self.class = classArray - self.defineProperty(propertyLength, toValue_uint32(length), 0100, false) - self.objectClass = _classArray - return self +func (rt *runtime) newArrayObject(length uint32) *object { + obj := rt.newObject() + obj.class = classArrayName + obj.defineProperty(propertyLength, uint32Value(length), 0o100, false) + obj.objectClass = classArray + return obj } -func isArray(object *_object) bool { - if object == nil { +func isArray(obj *object) bool { + if obj == nil { return false } - switch object.class { - case classArray, classGoArray, classGoSlice: + switch obj.class { + case classArrayName, classGoArrayName, classGoSliceName: return true default: return false } } -func objectLength(object *_object) uint32 { - if object == nil { +func objectLength(obj *object) uint32 { + if obj == nil { return 0 } - switch object.class { - case classArray: - return object.get(propertyLength).value.(uint32) - case classString: - return uint32(object.get(propertyLength).value.(int)) - case classGoArray, classGoSlice: - return uint32(object.get(propertyLength).value.(int)) + switch obj.class { + case classArrayName: + return obj.get(propertyLength).value.(uint32) + case classStringName: + return uint32(obj.get(propertyLength).value.(int)) + case classGoArrayName, classGoSliceName: + return uint32(obj.get(propertyLength).value.(int)) } return 0 } -func arrayUint32(rt *_runtime, value Value) uint32 { +func arrayUint32(rt *runtime, value Value) uint32 { nm := value.number() if nm.kind != numberInteger || !isUint32(nm.int64) { // FIXME @@ -49,8 +49,8 @@ func arrayUint32(rt *_runtime, value Value) uint32 { return uint32(nm.int64) } -func arrayDefineOwnProperty(self *_object, name string, descriptor _property, throw bool) bool { - lengthProperty := self.getOwnProperty(propertyLength) +func arrayDefineOwnProperty(obj *object, name string, descriptor property, throw bool) bool { + lengthProperty := obj.getOwnProperty(propertyLength) lengthValue, valid := lengthProperty.value.(Value) if !valid { panic("Array.length != Value{}") @@ -58,61 +58,61 @@ func arrayDefineOwnProperty(self *_object, name string, descriptor _property, th length := lengthValue.value.(uint32) if name == propertyLength { if descriptor.value == nil { - return objectDefineOwnProperty(self, name, descriptor, throw) + return objectDefineOwnProperty(obj, name, descriptor, throw) } newLengthValue, isValue := descriptor.value.(Value) if !isValue { - panic(self.runtime.panicTypeError()) + panic(obj.runtime.panicTypeError()) } - newLength := arrayUint32(self.runtime, newLengthValue) - descriptor.value = toValue_uint32(newLength) + newLength := arrayUint32(obj.runtime, newLengthValue) + descriptor.value = uint32Value(newLength) if newLength > length { - return objectDefineOwnProperty(self, name, descriptor, throw) + return objectDefineOwnProperty(obj, name, descriptor, throw) } if !lengthProperty.writable() { goto Reject } newWritable := true - if descriptor.mode&0700 == 0 { + if descriptor.mode&0o700 == 0 { // If writable is off newWritable = false - descriptor.mode |= 0100 + descriptor.mode |= 0o100 } - if !objectDefineOwnProperty(self, name, descriptor, throw) { + if !objectDefineOwnProperty(obj, name, descriptor, throw) { return false } for newLength < length { length-- - if !self.delete(strconv.FormatInt(int64(length), 10), false) { - descriptor.value = toValue_uint32(length + 1) + if !obj.delete(strconv.FormatInt(int64(length), 10), false) { + descriptor.value = uint32Value(length + 1) if !newWritable { - descriptor.mode &= 0077 + descriptor.mode &= 0o077 } - objectDefineOwnProperty(self, name, descriptor, false) + objectDefineOwnProperty(obj, name, descriptor, false) goto Reject } } if !newWritable { - descriptor.mode &= 0077 - objectDefineOwnProperty(self, name, descriptor, false) + descriptor.mode &= 0o077 + objectDefineOwnProperty(obj, name, descriptor, false) } } else if index := stringToArrayIndex(name); index >= 0 { if index >= int64(length) && !lengthProperty.writable() { goto Reject } - if !objectDefineOwnProperty(self, strconv.FormatInt(index, 10), descriptor, false) { + if !objectDefineOwnProperty(obj, strconv.FormatInt(index, 10), descriptor, false) { goto Reject } if index >= int64(length) { - lengthProperty.value = toValue_uint32(uint32(index + 1)) - objectDefineOwnProperty(self, propertyLength, *lengthProperty, false) + lengthProperty.value = uint32Value(uint32(index + 1)) + objectDefineOwnProperty(obj, propertyLength, *lengthProperty, false) return true } } - return objectDefineOwnProperty(self, name, descriptor, throw) + return objectDefineOwnProperty(obj, name, descriptor, throw) Reject: if throw { - panic(self.runtime.panicTypeError()) + panic(obj.runtime.panicTypeError()) } return false } diff --git a/type_boolean.go b/type_boolean.go index 97104366..3620553c 100644 --- a/type_boolean.go +++ b/type_boolean.go @@ -1,5 +1,5 @@ package otto -func (runtime *_runtime) newBooleanObject(value Value) *_object { - return runtime.newPrimitiveObject(classBoolean, toValue_bool(value.bool())) +func (rt *runtime) newBooleanObject(value Value) *object { + return rt.newPrimitiveObject(classBooleanName, boolValue(value.bool())) } diff --git a/type_date.go b/type_date.go index 9b75068b..d5482e26 100644 --- a/type_date.go +++ b/type_date.go @@ -7,23 +7,21 @@ import ( Time "time" ) -type _dateObject struct { +type dateObject struct { time Time.Time // Time from the "time" package, a cached version of time epoch int64 value Value isNaN bool } -var ( - invalidDateObject = _dateObject{ - time: Time.Time{}, - epoch: -1, - value: NaNValue(), - isNaN: true, - } -) +var invalidDateObject = dateObject{ + time: Time.Time{}, + epoch: -1, + value: NaNValue(), + isNaN: true, +} -type _ecmaTime struct { +type ecmaTime struct { year int month int day int @@ -34,8 +32,8 @@ type _ecmaTime struct { location *Time.Location // Basically, either local or UTC } -func ecmaTime(goTime Time.Time) _ecmaTime { - return _ecmaTime{ +func newEcmaTime(goTime Time.Time) ecmaTime { + return ecmaTime{ goTime.Year(), dateFromGoMonth(goTime.Month()), goTime.Day(), @@ -47,58 +45,58 @@ func ecmaTime(goTime Time.Time) _ecmaTime { } } -func (self *_ecmaTime) goTime() Time.Time { +func (t *ecmaTime) goTime() Time.Time { return Time.Date( - self.year, - dateToGoMonth(self.month), - self.day, - self.hour, - self.minute, - self.second, - self.millisecond*(100*100*100), - self.location, + t.year, + dateToGoMonth(t.month), + t.day, + t.hour, + t.minute, + t.second, + t.millisecond*(100*100*100), + t.location, ) } -func (self *_dateObject) Time() Time.Time { - return self.time +func (d *dateObject) Time() Time.Time { + return d.time } -func (self *_dateObject) Epoch() int64 { - return self.epoch +func (d *dateObject) Epoch() int64 { + return d.epoch } -func (self *_dateObject) Value() Value { - return self.value +func (d *dateObject) Value() Value { + return d.value } -// FIXME A date should only be in the range of -100,000,000 to +100,000,000 (1970): 15.9.1.1 -func (self *_dateObject) SetNaN() { - self.time = Time.Time{} - self.epoch = -1 - self.value = NaNValue() - self.isNaN = true +// FIXME A date should only be in the range of -100,000,000 to +100,000,000 (1970): 15.9.1.1. +func (d *dateObject) SetNaN() { + d.time = Time.Time{} + d.epoch = -1 + d.value = NaNValue() + d.isNaN = true } -func (self *_dateObject) SetTime(time Time.Time) { - self.Set(timeToEpoch(time)) +func (d *dateObject) SetTime(time Time.Time) { + d.Set(timeToEpoch(time)) } -func (self *_dateObject) Set(epoch float64) { +func (d *dateObject) Set(epoch float64) { // epoch - self.epoch = epochToInteger(epoch) + d.epoch = epochToInteger(epoch) // time time, err := epochToTime(epoch) - self.time = time // Is either a valid time, or the zero-value for time.Time + d.time = time // Is either a valid time, or the zero-value for time.Time // value & isNaN if err != nil { - self.isNaN = true - self.epoch = -1 - self.value = NaNValue() + d.isNaN = true + d.epoch = -1 + d.value = NaNValue() } else { - self.value = toValue_int64(self.epoch) + d.value = int64Value(d.epoch) } } @@ -109,48 +107,46 @@ func epochToInteger(value float64) int64 { return int64(math.Ceil(value)) } -func epochToTime(value float64) (time Time.Time, err error) { +func epochToTime(value float64) (Time.Time, error) { epochWithMilli := value if math.IsNaN(epochWithMilli) || math.IsInf(epochWithMilli, 0) { - err = fmt.Errorf("Invalid time %v", value) - return + return Time.Time{}, fmt.Errorf("invalid time %v", value) } epoch := int64(epochWithMilli / 1000) milli := int64(epochWithMilli) % 1000 - time = Time.Unix(int64(epoch), milli*1000000).In(utcTimeZone) - return + return Time.Unix(epoch, milli*1000000).In(utcTimeZone), nil } func timeToEpoch(time Time.Time) float64 { return float64(time.UnixMilli()) } -func (runtime *_runtime) newDateObject(epoch float64) *_object { - self := runtime.newObject() - self.class = classDate +func (rt *runtime) newDateObject(epoch float64) *object { + obj := rt.newObject() + obj.class = classDateName // FIXME This is ugly... - date := _dateObject{} + date := dateObject{} date.Set(epoch) - self.value = date - return self + obj.value = date + return obj } -func (self *_object) dateValue() _dateObject { - value, _ := self.value.(_dateObject) +func (o *object) dateValue() dateObject { + value, _ := o.value.(dateObject) return value } -func dateObjectOf(rt *_runtime, _dateObject *_object) _dateObject { - if _dateObject == nil || _dateObject.class != classDate { +func dateObjectOf(rt *runtime, date *object) dateObject { + if date == nil || date.class != classDateName { panic(rt.panicTypeError()) } - return _dateObject.dateValue() + return date.dateValue() } -// JavaScript is 0-based, Go is 1-based (15.9.1.4) +// JavaScript is 0-based, Go is 1-based (15.9.1.4). func dateToGoMonth(month int) Time.Month { return Time.Month(month + 1) } @@ -163,7 +159,8 @@ func dateFromGoDay(day Time.Weekday) int { return int(day) } -func newDateTime(argumentList []Value, location *Time.Location) (epoch float64) { +// newDateTime returns the epoch of date contained in argumentList for location. +func newDateTime(argumentList []Value, location *Time.Location) float64 { pick := func(index int, default_ float64) (float64, bool) { if index >= len(argumentList) { return default_, false @@ -175,29 +172,41 @@ func newDateTime(argumentList []Value, location *Time.Location) (epoch float64) return value, false } - if len(argumentList) >= 2 { // 2-argument, 3-argument, ... + switch len(argumentList) { + case 0: // 0-argument + time := Time.Now().In(utcTimeZone) + return timeToEpoch(time) + case 1: // 1-argument + value := valueOfArrayIndex(argumentList, 0) + value = toPrimitiveValue(value) + if value.IsString() { + return dateParse(value.string()) + } + + return value.float64() + default: // 2-argument, 3-argument, ... var year, month, day, hour, minute, second, millisecond float64 var invalid bool if year, invalid = pick(0, 1900.0); invalid { - goto INVALID + return math.NaN() } if month, invalid = pick(1, 0.0); invalid { - goto INVALID + return math.NaN() } if day, invalid = pick(2, 1.0); invalid { - goto INVALID + return math.NaN() } if hour, invalid = pick(3, 0.0); invalid { - goto INVALID + return math.NaN() } if minute, invalid = pick(4, 0.0); invalid { - goto INVALID + return math.NaN() } if second, invalid = pick(5, 0.0); invalid { - goto INVALID + return math.NaN() } if millisecond, invalid = pick(6, 0.0); invalid { - goto INVALID + return math.NaN() } if year >= 0 && year <= 99 { @@ -206,22 +215,7 @@ func newDateTime(argumentList []Value, location *Time.Location) (epoch float64) time := Time.Date(int(year), dateToGoMonth(int(month)), int(day), int(hour), int(minute), int(second), int(millisecond)*1000*1000, location) return timeToEpoch(time) - } else if len(argumentList) == 0 { // 0-argument - time := Time.Now().In(utcTimeZone) - return timeToEpoch(time) - } else { // 1-argument - value := valueOfArrayIndex(argumentList, 0) - value = toPrimitive(value) - if value.IsString() { - return dateParse(value.string()) - } - - return value.float64() } - -INVALID: - epoch = math.NaN() - return } var ( @@ -259,7 +253,8 @@ var ( matchDateTimeZone = regexp.MustCompile(`^(.*)(?:(Z)|([\+\-]\d{2}):(\d{2}))$`) ) -func dateParse(date string) (epoch float64) { +// dateParse returns the epoch of the parsed date. +func dateParse(date string) float64 { // YYYY-MM-DDTHH:mm:ss.sssZ var time Time.Time var err error diff --git a/type_error.go b/type_error.go index 190b2b48..0b810954 100644 --- a/type_error.go +++ b/type_error.go @@ -1,58 +1,58 @@ package otto -func (rt *_runtime) newErrorObject(name string, message Value, stackFramesToPop int) *_object { - self := rt.newClassObject(classError) +func (rt *runtime) newErrorObject(name string, message Value, stackFramesToPop int) *object { + obj := rt.newClassObject(classErrorName) if message.IsDefined() { msg := message.string() - self.defineProperty("message", toValue_string(msg), 0111, false) - self.value = newError(rt, name, stackFramesToPop, msg) + obj.defineProperty("message", stringValue(msg), 0o111, false) + obj.value = newError(rt, name, stackFramesToPop, msg) } else { - self.value = newError(rt, name, stackFramesToPop) + obj.value = newError(rt, name, stackFramesToPop) } - self.defineOwnProperty("stack", _property{ - value: _propertyGetSet{ + obj.defineOwnProperty("stack", property{ + value: propertyGetSet{ rt.newNativeFunction("get", "internal", 0, func(FunctionCall) Value { - return toValue_string(self.value.(_error).formatWithStack()) + return stringValue(obj.value.(ottoError).formatWithStack()) }), - &_nilGetSetObject, + &nilGetSetObject, }, mode: modeConfigureMask & modeOnMask, }, false) - return self + return obj } -func (rt *_runtime) newErrorObjectError(err _error) *_object { - self := rt.newClassObject(classError) - self.defineProperty("message", err.messageValue(), 0111, false) - self.value = err +func (rt *runtime) newErrorObjectError(err ottoError) *object { + obj := rt.newClassObject(classErrorName) + obj.defineProperty("message", err.messageValue(), 0o111, false) + obj.value = err switch err.name { case "EvalError": - self.prototype = rt.global.EvalErrorPrototype + obj.prototype = rt.global.EvalErrorPrototype case "TypeError": - self.prototype = rt.global.TypeErrorPrototype + obj.prototype = rt.global.TypeErrorPrototype case "RangeError": - self.prototype = rt.global.RangeErrorPrototype + obj.prototype = rt.global.RangeErrorPrototype case "ReferenceError": - self.prototype = rt.global.ReferenceErrorPrototype + obj.prototype = rt.global.ReferenceErrorPrototype case "SyntaxError": - self.prototype = rt.global.SyntaxErrorPrototype + obj.prototype = rt.global.SyntaxErrorPrototype case "URIError": - self.prototype = rt.global.URIErrorPrototype + obj.prototype = rt.global.URIErrorPrototype default: - self.prototype = rt.global.ErrorPrototype + obj.prototype = rt.global.ErrorPrototype } - self.defineOwnProperty("stack", _property{ - value: _propertyGetSet{ + obj.defineOwnProperty("stack", property{ + value: propertyGetSet{ rt.newNativeFunction("get", "internal", 0, func(FunctionCall) Value { - return toValue_string(self.value.(_error).formatWithStack()) + return stringValue(obj.value.(ottoError).formatWithStack()) }), - &_nilGetSetObject, + &nilGetSetObject, }, mode: modeConfigureMask & modeOnMask, }, false) - return self + return obj } diff --git a/type_function.go b/type_function.go index 671269b9..28f6f9b8 100644 --- a/type_function.go +++ b/type_function.go @@ -1,20 +1,20 @@ package otto -// _constructFunction -type _constructFunction func(*_object, []Value) Value +// constructFunction. +type constructFunction func(*object, []Value) Value -// 13.2.2 [[Construct]] -func defaultConstruct(fn *_object, argumentList []Value) Value { - object := fn.runtime.newObject() - object.class = classObject +// 13.2.2 [[Construct]]. +func defaultConstruct(fn *object, argumentList []Value) Value { + obj := fn.runtime.newObject() + obj.class = classObjectName prototype := fn.get("prototype") if prototype.kind != valueObject { - prototype = toValue_object(fn.runtime.global.ObjectPrototype) + prototype = objectValue(fn.runtime.global.ObjectPrototype) } - object.prototype = prototype._object() + obj.prototype = prototype.object() - this := toValue_object(object) + this := objectValue(obj) value := fn.call(this, argumentList, false, nativeFrame) if value.kind == valueObject { return value @@ -22,72 +22,66 @@ func defaultConstruct(fn *_object, argumentList []Value) Value { return this } -// _nativeFunction -type _nativeFunction func(FunctionCall) Value +// nativeFunction. +type nativeFunction func(FunctionCall) Value -// ===================== // -// _nativeFunctionObject // -// ===================== // - -type _nativeFunctionObject struct { +// nativeFunctionObject. +type nativeFunctionObject struct { name string file string line int - call _nativeFunction // [[Call]] - construct _constructFunction // [[Construct]] + call nativeFunction // [[Call]] + construct constructFunction // [[Construct]] } -func (runtime *_runtime) _newNativeFunctionObject(name, file string, line int, native _nativeFunction, length int) *_object { - self := runtime.newClassObject(classFunction) - self.value = _nativeFunctionObject{ +func (rt *runtime) newNativeFunctionProperty(name, file string, line int, native nativeFunction, length int) *object { + o := rt.newClassObject(classFunctionName) + o.value = nativeFunctionObject{ name: name, file: file, line: line, call: native, construct: defaultConstruct, } - self.defineProperty("name", toValue_string(name), 0000, false) - self.defineProperty(propertyLength, toValue_int(length), 0000, false) - return self + o.defineProperty("name", stringValue(name), 0o000, false) + o.defineProperty(propertyLength, intValue(length), 0o000, false) + return o } -func (runtime *_runtime) newNativeFunctionObject(name, file string, line int, native _nativeFunction, length int) *_object { - self := runtime._newNativeFunctionObject(name, file, line, native, length) - self.defineOwnProperty("caller", _property{ - value: _propertyGetSet{ - runtime._newNativeFunctionObject("get", "internal", 0, func(fc FunctionCall) Value { - for sc := runtime.scope; sc != nil; sc = sc.outer { - if sc.frame.fn == self { +func (rt *runtime) newNativeFunctionObject(name, file string, line int, native nativeFunction, length int) *object { + o := rt.newNativeFunctionProperty(name, file, line, native, length) + o.defineOwnProperty("caller", property{ + value: propertyGetSet{ + rt.newNativeFunctionProperty("get", "internal", 0, func(fc FunctionCall) Value { + for sc := rt.scope; sc != nil; sc = sc.outer { + if sc.frame.fn == o { if sc.outer == nil || sc.outer.frame.fn == nil { return nullValue } - return runtime.toValue(sc.outer.frame.fn) + return rt.toValue(sc.outer.frame.fn) } } return nullValue }, 0), - &_nilGetSetObject, + &nilGetSetObject, }, - mode: 0000, + mode: 0o000, }, false) - return self + return o } -// =================== // -// _bindFunctionObject // -// =================== // - -type _bindFunctionObject struct { - target *_object +// bindFunctionObject. +type bindFunctionObject struct { + target *object this Value argumentList []Value } -func (runtime *_runtime) newBoundFunctionObject(target *_object, this Value, argumentList []Value) *_object { - self := runtime.newClassObject(classFunction) - self.value = _bindFunctionObject{ +func (rt *runtime) newBoundFunctionObject(target *object, this Value, argumentList []Value) *object { + o := rt.newClassObject(classFunctionName) + o.value = bindFunctionObject{ target: target, this: this, argumentList: argumentList, @@ -97,100 +91,95 @@ func (runtime *_runtime) newBoundFunctionObject(target *_object, this Value, arg if length < 0 { length = 0 } - self.defineProperty("name", toValue_string("bound "+target.get("name").String()), 0000, false) - self.defineProperty(propertyLength, 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 + o.defineProperty("name", stringValue("bound "+target.get("name").String()), 0o000, false) + o.defineProperty(propertyLength, intValue(length), 0o000, false) + o.defineProperty("caller", Value{}, 0o000, false) // TODO Should throw a TypeError + o.defineProperty("arguments", Value{}, 0o000, false) // TODO Should throw a TypeError + return o } -// [[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: +// [[Construct]]. +func (fn bindFunctionObject) construct(argumentList []Value) Value { + obj := fn.target + switch value := obj.value.(type) { + case nativeFunctionObject: + return value.construct(obj, fn.argumentList) + case nodeFunctionObject: argumentList = append(fn.argumentList, argumentList...) - return object.construct(argumentList) + return obj.construct(argumentList) } panic(fn.target.runtime.panicTypeError()) } -// =================== // -// _nodeFunctionObject // -// =================== // - -type _nodeFunctionObject struct { - node *_nodeFunctionLiteral - stash _stash +// nodeFunctionObject. +type nodeFunctionObject struct { + node *nodeFunctionLiteral + stash stasher } -func (runtime *_runtime) newNodeFunctionObject(node *_nodeFunctionLiteral, stash _stash) *_object { - self := runtime.newClassObject(classFunction) - self.value = _nodeFunctionObject{ +func (rt *runtime) newNodeFunctionObject(node *nodeFunctionLiteral, stash stasher) *object { + o := rt.newClassObject(classFunctionName) + o.value = nodeFunctionObject{ node: node, stash: stash, } - self.defineProperty("name", toValue_string(node.name), 0000, false) - self.defineProperty(propertyLength, toValue_int(len(node.parameterList)), 0000, false) - self.defineOwnProperty("caller", _property{ - value: _propertyGetSet{ - runtime.newNativeFunction("get", "internal", 0, func(fc FunctionCall) Value { - for sc := runtime.scope; sc != nil; sc = sc.outer { - if sc.frame.fn == self { + o.defineProperty("name", stringValue(node.name), 0o000, false) + o.defineProperty(propertyLength, intValue(len(node.parameterList)), 0o000, false) + o.defineOwnProperty("caller", property{ + value: propertyGetSet{ + rt.newNativeFunction("get", "internal", 0, func(fc FunctionCall) Value { + for sc := rt.scope; sc != nil; sc = sc.outer { + if sc.frame.fn == o { if sc.outer == nil || sc.outer.frame.fn == nil { return nullValue } - return runtime.toValue(sc.outer.frame.fn) + return rt.toValue(sc.outer.frame.fn) } } return nullValue }), - &_nilGetSetObject, + &nilGetSetObject, }, - mode: 0000, + mode: 0o000, }, false) - return self + return o } -// ======= // -// _object // -// ======= // - -func (self *_object) isCall() bool { - switch fn := self.value.(type) { - case _nativeFunctionObject: +// _object. +func (o *object) isCall() bool { + switch fn := o.value.(type) { + case nativeFunctionObject: return fn.call != nil - case _bindFunctionObject: + case bindFunctionObject: return true - case _nodeFunctionObject: + case nodeFunctionObject: return true + default: + return false } - return false } -func (self *_object) call(this Value, argumentList []Value, eval bool, frame _frame) Value { - switch fn := self.value.(type) { - case _nativeFunctionObject: +func (o *object) call(this Value, argumentList []Value, eval bool, frm frame) Value { + switch fn := o.value.(type) { + case nativeFunctionObject: // 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 + eval = o == o.runtime.eval // If eval is true, then it IS a direct eval } // Enter a scope, name from the native object... - rt := self.runtime + rt := o.runtime if rt.scope != nil && !eval { rt.enterFunctionScope(rt.scope.lexical, this) - rt.scope.frame = _frame{ + rt.scope.frame = frame{ native: true, nativeFile: fn.file, nativeLine: fn.line, callee: fn.name, file: nil, - fn: self, + fn: o, } defer func() { rt.leaveScope() @@ -198,77 +187,77 @@ func (self *_object) call(this Value, argumentList []Value, eval bool, frame _fr } return fn.call(FunctionCall{ - runtime: self.runtime, + runtime: o.runtime, eval: eval, This: this, ArgumentList: argumentList, - Otto: self.runtime.otto, + Otto: o.runtime.otto, }) - case _bindFunctionObject: + case bindFunctionObject: // TODO Passthrough site, do not enter a scope argumentList = append(fn.argumentList, argumentList...) - return fn.target.call(fn.this, argumentList, false, frame) + return fn.target.call(fn.this, argumentList, false, frm) - case _nodeFunctionObject: - rt := self.runtime + case nodeFunctionObject: + rt := o.runtime stash := rt.enterFunctionScope(fn.stash, this) - rt.scope.frame = _frame{ + rt.scope.frame = frame{ callee: fn.node.name, file: fn.node.file, - fn: self, + fn: o, } defer func() { rt.leaveScope() }() - callValue := rt.cmpl_call_nodeFunction(self, stash, fn.node, this, argumentList) - if value, valid := callValue.value.(_result); valid { + callValue := rt.cmplCallNodeFunction(o, stash, fn.node, 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))) + panic(o.runtime.panicTypeError("%v is not a function", objectValue(o))) } -func (self *_object) construct(argumentList []Value) Value { - switch fn := self.value.(type) { - case _nativeFunctionObject: +func (o *object) construct(argumentList []Value) Value { + switch fn := o.value.(type) { + case nativeFunctionObject: if fn.call == nil { - panic(self.runtime.panicTypeError("%v is not a function", toValue_object(self))) + panic(o.runtime.panicTypeError("%v is not a function", objectValue(o))) } if fn.construct == nil { - panic(self.runtime.panicTypeError("%v is not a constructor", toValue_object(self))) + panic(o.runtime.panicTypeError("%v is not a constructor", objectValue(o))) } - return fn.construct(self, argumentList) + return fn.construct(o, argumentList) - case _bindFunctionObject: + case bindFunctionObject: return fn.construct(argumentList) - case _nodeFunctionObject: - return defaultConstruct(self, argumentList) + case nodeFunctionObject: + return defaultConstruct(o, argumentList) } - panic(self.runtime.panicTypeError("%v is not a function", toValue_object(self))) + panic(o.runtime.panicTypeError("%v is not a function", objectValue(o))) } -// 15.3.5.3 -func (self *_object) hasInstance(of Value) bool { - if !self.isCall() { +// 15.3.5.3. +func (o *object) hasInstance(of Value) bool { + if !o.isCall() { // We should not have a hasInstance method - panic(self.runtime.panicTypeError()) + panic(o.runtime.panicTypeError()) } if !of.IsObject() { return false } - prototype := self.get("prototype") + prototype := o.get("prototype") if !prototype.IsObject() { - panic(self.runtime.panicTypeError()) + panic(o.runtime.panicTypeError()) } - prototypeObject := prototype._object() + prototypeObject := prototype.object() - value := of._object().prototype + value := of.object().prototype for value != nil { if value == prototypeObject { return true @@ -278,15 +267,11 @@ func (self *_object) hasInstance(of Value) bool { 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 + runtime *runtime + thisObj *object + eval bool // This call is a direct call to eval This Value ArgumentList []Value @@ -296,43 +281,42 @@ type FunctionCall struct { // 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 (f FunctionCall) Argument(index int) Value { + return valueOfArrayIndex(f.ArgumentList, index) } -func (self FunctionCall) getArgument(index int) (Value, bool) { - return getValueOfArrayIndex(self.ArgumentList, index) +func (f FunctionCall) getArgument(index int) (Value, bool) { + return getValueOfArrayIndex(f.ArgumentList, index) } -func (self FunctionCall) slice(index int) []Value { - if index < len(self.ArgumentList) { - return self.ArgumentList[index:] +func (f FunctionCall) slice(index int) []Value { + if index < len(f.ArgumentList) { + return f.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) +func (f *FunctionCall) thisObject() *object { + if f.thisObj == nil { + this := f.This.resolve() // FIXME Is this right? + f.thisObj = f.runtime.toObject(this) } - return self._thisObject + return f.thisObj } -func (self *FunctionCall) thisClassObject(class string) *_object { - thisObject := self.thisObject() - if thisObject.class != class { - panic(self.runtime.panicTypeError()) +func (f *FunctionCall) thisClassObject(class string) *object { + if o := f.thisObject(); o.class != class { + panic(f.runtime.panicTypeError()) } - return self._thisObject + return f.thisObj } -func (self FunctionCall) toObject(value Value) *_object { - return self.runtime.toObject(value) +func (f FunctionCall) toObject(value Value) *object { + return f.runtime.toObject(value) } // CallerLocation will return file location information (file:line:pos) where this function is being called. -func (self FunctionCall) CallerLocation() string { +func (f FunctionCall) CallerLocation() string { // see error.go for location() - return self.runtime.scope.outer.frame.location() + return f.runtime.scope.outer.frame.location() } diff --git a/type_go_array.go b/type_go_array.go index b9af7965..ad7b3202 100644 --- a/type_go_array.go +++ b/type_go_array.go @@ -5,51 +5,51 @@ import ( "strconv" ) -func (runtime *_runtime) newGoArrayObject(value reflect.Value) *_object { - self := runtime.newObject() - self.class = classGoArray - self.objectClass = _classGoArray - self.value = _newGoArrayObject(value) - return self +func (rt *runtime) newGoArrayObject(value reflect.Value) *object { + o := rt.newObject() + o.class = classGoArrayName + o.objectClass = classGoArray + o.value = newGoArrayObject(value) + return o } -type _goArrayObject struct { +type goArrayObject struct { value reflect.Value writable bool - propertyMode _propertyMode + propertyMode propertyMode } -func _newGoArrayObject(value reflect.Value) *_goArrayObject { +func newGoArrayObject(value reflect.Value) *goArrayObject { writable := value.Kind() == reflect.Ptr || value.CanSet() // The Array is addressable (like a Slice) - mode := _propertyMode(0010) + mode := propertyMode(0o010) if writable { - mode = 0110 + mode = 0o110 } - self := &_goArrayObject{ + + return &goArrayObject{ value: value, writable: writable, propertyMode: mode, } - return self } -func (self _goArrayObject) getValue(name string) (reflect.Value, bool) { +func (o goArrayObject) getValue(name string) (reflect.Value, bool) { //nolint: unused if index, err := strconv.ParseInt(name, 10, 64); err != nil { - v, ok := self.getValueIndex(index) + v, ok := o.getValueIndex(index) if ok { return v, ok } } - if m := self.value.MethodByName(name); m != (reflect.Value{}) { + if m := o.value.MethodByName(name); m != (reflect.Value{}) { return m, true } return reflect.Value{}, false } -func (self _goArrayObject) getValueIndex(index int64) (reflect.Value, bool) { - value := reflect.Indirect(self.value) +func (o goArrayObject) getValueIndex(index int64) (reflect.Value, bool) { + value := reflect.Indirect(o.value) if index < int64(value.Len()) { return value.Index(int(index)), true } @@ -57,12 +57,12 @@ func (self _goArrayObject) getValueIndex(index int64) (reflect.Value, bool) { return reflect.Value{}, false } -func (self _goArrayObject) setValue(index int64, value Value) bool { - indexValue, exists := self.getValueIndex(index) +func (o goArrayObject) setValue(index int64, value Value) bool { + indexValue, exists := o.getValueIndex(index) if !exists { return false } - reflectValue, err := value.toReflectValue(reflect.Indirect(self.value).Type().Elem()) + reflectValue, err := value.toReflectValue(reflect.Indirect(o.value).Type().Elem()) if err != nil { panic(err) } @@ -70,87 +70,87 @@ func (self _goArrayObject) setValue(index int64, value Value) bool { return true } -func goArrayGetOwnProperty(self *_object, name string) *_property { +func goArrayGetOwnProperty(obj *object, name string) *property { // length if name == propertyLength { - return &_property{ - value: toValue(reflect.Indirect(self.value.(*_goArrayObject).value).Len()), + return &property{ + value: toValue(reflect.Indirect(obj.value.(*goArrayObject).value).Len()), mode: 0, } } // .0, .1, .2, ... if index := stringToArrayIndex(name); index >= 0 { - object := self.value.(*_goArrayObject) + goObj := obj.value.(*goArrayObject) value := Value{} - reflectValue, exists := object.getValueIndex(index) + reflectValue, exists := goObj.getValueIndex(index) if exists { - value = self.runtime.toValue(reflectValue.Interface()) + value = obj.runtime.toValue(reflectValue.Interface()) } - return &_property{ + return &property{ value: value, - mode: object.propertyMode, + mode: goObj.propertyMode, } } - if method := self.value.(*_goArrayObject).value.MethodByName(name); method != (reflect.Value{}) { - return &_property{ - self.runtime.toValue(method.Interface()), - 0110, + if method := obj.value.(*goArrayObject).value.MethodByName(name); method != (reflect.Value{}) { + return &property{ + obj.runtime.toValue(method.Interface()), + 0o110, } } - return objectGetOwnProperty(self, name) + return objectGetOwnProperty(obj, name) } -func goArrayEnumerate(self *_object, all bool, each func(string) bool) { - object := self.value.(*_goArrayObject) +func goArrayEnumerate(obj *object, all bool, each func(string) bool) { + goObj := obj.value.(*goArrayObject) // .0, .1, .2, ... - for index, length := 0, object.value.Len(); index < length; index++ { + for index, length := 0, goObj.value.Len(); index < length; index++ { name := strconv.FormatInt(int64(index), 10) if !each(name) { return } } - objectEnumerate(self, all, each) + objectEnumerate(obj, all, each) } -func goArrayDefineOwnProperty(self *_object, name string, descriptor _property, throw bool) bool { +func goArrayDefineOwnProperty(obj *object, name string, descriptor property, throw bool) bool { if name == propertyLength { - return self.runtime.typeErrorResult(throw) + return obj.runtime.typeErrorResult(throw) } else if index := stringToArrayIndex(name); index >= 0 { - object := self.value.(*_goArrayObject) - if object.writable { - if self.value.(*_goArrayObject).setValue(index, descriptor.value.(Value)) { + goObj := obj.value.(*goArrayObject) + if goObj.writable { + if obj.value.(*goArrayObject).setValue(index, descriptor.value.(Value)) { return true } } - return self.runtime.typeErrorResult(throw) + return obj.runtime.typeErrorResult(throw) } - return objectDefineOwnProperty(self, name, descriptor, throw) + return objectDefineOwnProperty(obj, name, descriptor, throw) } -func goArrayDelete(self *_object, name string, throw bool) bool { +func goArrayDelete(obj *object, name string, throw bool) bool { // length if name == propertyLength { - return self.runtime.typeErrorResult(throw) + return obj.runtime.typeErrorResult(throw) } // .0, .1, .2, ... index := stringToArrayIndex(name) if index >= 0 { - object := self.value.(*_goArrayObject) - if object.writable { - indexValue, exists := object.getValueIndex(index) + goObj := obj.value.(*goArrayObject) + if goObj.writable { + indexValue, exists := goObj.getValueIndex(index) if exists { - indexValue.Set(reflect.Zero(reflect.Indirect(object.value).Type().Elem())) + indexValue.Set(reflect.Zero(reflect.Indirect(goObj.value).Type().Elem())) return true } } - return self.runtime.typeErrorResult(throw) + return obj.runtime.typeErrorResult(throw) } - return self.delete(name, throw) + return obj.delete(name, throw) } diff --git a/type_go_map.go b/type_go_map.go index 88ae40b9..aa7b7801 100644 --- a/type_go_map.go +++ b/type_go_map.go @@ -4,69 +4,68 @@ import ( "reflect" ) -func (runtime *_runtime) newGoMapObject(value reflect.Value) *_object { - self := runtime.newObject() - self.class = classObject // TODO Should this be something else? - self.objectClass = _classGoMap - self.value = _newGoMapObject(value) - return self +func (rt *runtime) newGoMapObject(value reflect.Value) *object { + obj := rt.newObject() + obj.class = classObjectName // TODO Should this be something else? + obj.objectClass = classGoMap + obj.value = newGoMapObject(value) + return obj } -type _goMapObject struct { +type goMapObject struct { value reflect.Value keyType reflect.Type valueType reflect.Type } -func _newGoMapObject(value reflect.Value) *_goMapObject { +func newGoMapObject(value reflect.Value) *goMapObject { if value.Kind() != reflect.Map { dbgf("%/panic//%@: %v != reflect.Map", value.Kind()) } - self := &_goMapObject{ + return &goMapObject{ value: value, keyType: value.Type().Key(), valueType: value.Type().Elem(), } - return self } -func (self _goMapObject) toKey(name string) reflect.Value { - reflectValue, err := stringToReflectValue(name, self.keyType.Kind()) +func (o goMapObject) toKey(name string) reflect.Value { + reflectValue, err := stringToReflectValue(name, o.keyType.Kind()) if err != nil { panic(err) } return reflectValue } -func (self _goMapObject) toValue(value Value) reflect.Value { - reflectValue, err := value.toReflectValue(self.valueType) +func (o goMapObject) toValue(value Value) reflect.Value { + reflectValue, err := value.toReflectValue(o.valueType) if err != nil { panic(err) } return reflectValue } -func goMapGetOwnProperty(self *_object, name string) *_property { - object := self.value.(*_goMapObject) - value := object.value.MapIndex(object.toKey(name)) +func goMapGetOwnProperty(obj *object, name string) *property { + goObj := obj.value.(*goMapObject) + value := goObj.value.MapIndex(goObj.toKey(name)) if value.IsValid() { - return &_property{self.runtime.toValue(value.Interface()), 0111} + return &property{obj.runtime.toValue(value.Interface()), 0o111} } // Other methods - if method := self.value.(*_goMapObject).value.MethodByName(name); method.IsValid() { - return &_property{ - value: self.runtime.toValue(method.Interface()), - mode: 0110, + if method := obj.value.(*goMapObject).value.MethodByName(name); method.IsValid() { + return &property{ + value: obj.runtime.toValue(method.Interface()), + mode: 0o110, } } return nil } -func goMapEnumerate(self *_object, all bool, each func(string) bool) { - object := self.value.(*_goMapObject) - keys := object.value.MapKeys() +func goMapEnumerate(obj *object, all bool, each func(string) bool) { + goObj := obj.value.(*goMapObject) + keys := goObj.value.MapKeys() for _, key := range keys { if !each(toValue(key).String()) { return @@ -74,22 +73,22 @@ func goMapEnumerate(self *_object, all bool, each func(string) bool) { } } -func goMapDefineOwnProperty(self *_object, name string, descriptor _property, throw bool) bool { - object := self.value.(*_goMapObject) +func goMapDefineOwnProperty(obj *object, name string, descriptor property, throw bool) bool { + goObj := obj.value.(*goMapObject) // TODO ...or 0222 - if descriptor.mode != 0111 { - return self.runtime.typeErrorResult(throw) + if descriptor.mode != 0o111 { + return obj.runtime.typeErrorResult(throw) } if !descriptor.isDataDescriptor() { - return self.runtime.typeErrorResult(throw) + return obj.runtime.typeErrorResult(throw) } - object.value.SetMapIndex(object.toKey(name), object.toValue(descriptor.value.(Value))) + goObj.value.SetMapIndex(goObj.toKey(name), goObj.toValue(descriptor.value.(Value))) return true } -func goMapDelete(self *_object, name string, throw bool) bool { - object := self.value.(*_goMapObject) - object.value.SetMapIndex(object.toKey(name), reflect.Value{}) +func goMapDelete(obj *object, name string, throw bool) bool { + goObj := obj.value.(*goMapObject) + goObj.value.SetMapIndex(goObj.toKey(name), reflect.Value{}) // FIXME return true } diff --git a/type_go_map_test.go b/type_go_map_test.go index a89892b6..395393b7 100644 --- a/type_go_map_test.go +++ b/type_go_map_test.go @@ -17,7 +17,7 @@ func (s GoMapTest) Join() string { // All of this is meant to ensure that the test is predictable. keys := make([]string, len(s)) i := 0 - for key, _ := range s { + for key := range s { keys[i] = key i++ } diff --git a/type_go_slice.go b/type_go_slice.go index 6c1253a0..e9acfa33 100644 --- a/type_go_slice.go +++ b/type_go_slice.go @@ -5,33 +5,32 @@ import ( "strconv" ) -func (runtime *_runtime) newGoSliceObject(value reflect.Value) *_object { - self := runtime.newObject() - self.class = classGoSlice - self.objectClass = _classGoSlice - self.value = _newGoSliceObject(value) - return self +func (rt *runtime) newGoSliceObject(value reflect.Value) *object { + o := rt.newObject() + o.class = classGoSliceName + o.objectClass = classGoSlice + o.value = newGoSliceObject(value) + return o } -type _goSliceObject struct { +type goSliceObject struct { value reflect.Value } -func _newGoSliceObject(value reflect.Value) *_goSliceObject { - self := &_goSliceObject{ +func newGoSliceObject(value reflect.Value) *goSliceObject { + return &goSliceObject{ value: value, } - return self } -func (self _goSliceObject) getValue(index int64) (reflect.Value, bool) { - if index < int64(self.value.Len()) { - return self.value.Index(int(index)), true +func (o goSliceObject) getValue(index int64) (reflect.Value, bool) { + if index < int64(o.value.Len()) { + return o.value.Index(int(index)), true } return reflect.Value{}, false } -func (self *_goSliceObject) setLength(value Value) { +func (o *goSliceObject) setLength(value Value) { want, err := value.ToInteger() if err != nil { panic(err) @@ -39,30 +38,30 @@ func (self *_goSliceObject) setLength(value Value) { wantInt := int(want) switch { - case wantInt == self.value.Len(): + case wantInt == o.value.Len(): // No change needed. - case wantInt < self.value.Cap(): + case wantInt < o.value.Cap(): // Fits in current capacity. - self.value.SetLen(wantInt) + o.value.SetLen(wantInt) default: // Needs expanding. - newSlice := reflect.MakeSlice(self.value.Type(), wantInt, wantInt) - reflect.Copy(newSlice, self.value) - self.value = newSlice + newSlice := reflect.MakeSlice(o.value.Type(), wantInt, wantInt) + reflect.Copy(newSlice, o.value) + o.value = newSlice } } -func (self *_goSliceObject) setValue(index int64, value Value) bool { - reflectValue, err := value.toReflectValue(self.value.Type().Elem()) +func (o *goSliceObject) setValue(index int64, value Value) bool { + reflectValue, err := value.toReflectValue(o.value.Type().Elem()) if err != nil { panic(err) } - indexValue, exists := self.getValue(index) + indexValue, exists := o.getValue(index) if !exists { - if int64(self.value.Len()) == index { + if int64(o.value.Len()) == index { // Trying to append e.g. slice.push(...), allow it. - self.value = reflect.Append(self.value, reflectValue) + o.value = reflect.Append(o.value, reflectValue) return true } return false @@ -72,83 +71,83 @@ func (self *_goSliceObject) setValue(index int64, value Value) bool { return true } -func goSliceGetOwnProperty(self *_object, name string) *_property { +func goSliceGetOwnProperty(obj *object, name string) *property { // length if name == propertyLength { - return &_property{ - value: toValue(self.value.(*_goSliceObject).value.Len()), - mode: 0110, + return &property{ + value: toValue(obj.value.(*goSliceObject).value.Len()), + mode: 0o110, } } // .0, .1, .2, ... if index := stringToArrayIndex(name); index >= 0 { value := Value{} - reflectValue, exists := self.value.(*_goSliceObject).getValue(index) + reflectValue, exists := obj.value.(*goSliceObject).getValue(index) if exists { - value = self.runtime.toValue(reflectValue.Interface()) + value = obj.runtime.toValue(reflectValue.Interface()) } - return &_property{ + return &property{ value: value, - mode: 0110, + mode: 0o110, } } // Other methods - if method := self.value.(*_goSliceObject).value.MethodByName(name); method.IsValid() { - return &_property{ - value: self.runtime.toValue(method.Interface()), - mode: 0110, + if method := obj.value.(*goSliceObject).value.MethodByName(name); method.IsValid() { + return &property{ + value: obj.runtime.toValue(method.Interface()), + mode: 0o110, } } - return objectGetOwnProperty(self, name) + return objectGetOwnProperty(obj, name) } -func goSliceEnumerate(self *_object, all bool, each func(string) bool) { - object := self.value.(*_goSliceObject) +func goSliceEnumerate(obj *object, all bool, each func(string) bool) { + goObj := obj.value.(*goSliceObject) // .0, .1, .2, ... - for index, length := 0, object.value.Len(); index < length; index++ { + for index, length := 0, goObj.value.Len(); index < length; index++ { name := strconv.FormatInt(int64(index), 10) if !each(name) { return } } - objectEnumerate(self, all, each) + objectEnumerate(obj, all, each) } -func goSliceDefineOwnProperty(self *_object, name string, descriptor _property, throw bool) bool { +func goSliceDefineOwnProperty(obj *object, name string, descriptor property, throw bool) bool { if name == propertyLength { - self.value.(*_goSliceObject).setLength(descriptor.value.(Value)) + obj.value.(*goSliceObject).setLength(descriptor.value.(Value)) return true } else if index := stringToArrayIndex(name); index >= 0 { - if self.value.(*_goSliceObject).setValue(index, descriptor.value.(Value)) { + if obj.value.(*goSliceObject).setValue(index, descriptor.value.(Value)) { return true } - return self.runtime.typeErrorResult(throw) + return obj.runtime.typeErrorResult(throw) } - return objectDefineOwnProperty(self, name, descriptor, throw) + return objectDefineOwnProperty(obj, name, descriptor, throw) } -func goSliceDelete(self *_object, name string, throw bool) bool { +func goSliceDelete(obj *object, name string, throw bool) bool { // length if name == propertyLength { - return self.runtime.typeErrorResult(throw) + return obj.runtime.typeErrorResult(throw) } // .0, .1, .2, ... index := stringToArrayIndex(name) if index >= 0 { - object := self.value.(*_goSliceObject) - indexValue, exists := object.getValue(index) + goObj := obj.value.(*goSliceObject) + indexValue, exists := goObj.getValue(index) if exists { - indexValue.Set(reflect.Zero(object.value.Type().Elem())) + indexValue.Set(reflect.Zero(goObj.value.Type().Elem())) return true } - return self.runtime.typeErrorResult(throw) + return obj.runtime.typeErrorResult(throw) } - return self.delete(name, throw) + return obj.delete(name, throw) } diff --git a/type_go_struct.go b/type_go_struct.go index 5741b6a0..8cae329a 100644 --- a/type_go_struct.go +++ b/type_go_struct.go @@ -13,40 +13,39 @@ import ( // 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() - self.class = classObject // TODO Should this be something else? - self.objectClass = _classGoStruct - self.value = _newGoStructObject(value) - return self +func (rt *runtime) newGoStructObject(value reflect.Value) *object { + o := rt.newObject() + o.class = classObjectName // TODO Should this be something else? + o.objectClass = classGoStruct + o.value = newGoStructObject(value) + return o } -type _goStructObject struct { +type goStructObject struct { value reflect.Value } -func _newGoStructObject(value reflect.Value) *_goStructObject { +func newGoStructObject(value reflect.Value) *goStructObject { if reflect.Indirect(value).Kind() != reflect.Struct { dbgf("%/panic//%@: %v != reflect.Struct", value.Kind()) } - self := &_goStructObject{ + return &goStructObject{ value: value, } - return self } -func (self _goStructObject) getValue(name string) reflect.Value { - if idx := fieldIndexByName(reflect.Indirect(self.value).Type(), name); len(idx) > 0 { - return reflect.Indirect(self.value).FieldByIndex(idx) +func (o goStructObject) getValue(name string) reflect.Value { + if idx := fieldIndexByName(reflect.Indirect(o.value).Type(), name); len(idx) > 0 { + return reflect.Indirect(o.value).FieldByIndex(idx) } if validGoStructName(name) { // Do not reveal hidden or unexported fields. - if field := reflect.Indirect(self.value).FieldByName(name); field.IsValid() { + if field := reflect.Indirect(o.value).FieldByName(name); field.IsValid() { return field } - if method := self.value.MethodByName(name); method.IsValid() { + if method := o.value.MethodByName(name); method.IsValid() { return method } } @@ -54,20 +53,20 @@ func (self _goStructObject) getValue(name string) reflect.Value { return reflect.Value{} } -func (self _goStructObject) fieldIndex(name string) []int { - return fieldIndexByName(reflect.Indirect(self.value).Type(), name) +func (o goStructObject) fieldIndex(name string) []int { //nolint: unused + return fieldIndexByName(reflect.Indirect(o.value).Type(), name) } -func (self _goStructObject) method(name string) (reflect.Method, bool) { - return reflect.Indirect(self.value).Type().MethodByName(name) +func (o goStructObject) method(name string) (reflect.Method, bool) { //nolint: unused + return reflect.Indirect(o.value).Type().MethodByName(name) } -func (self _goStructObject) setValue(rt *_runtime, name string, value Value) bool { - if idx := fieldIndexByName(reflect.Indirect(self.value).Type(), name); len(idx) == 0 { +func (o goStructObject) setValue(rt *runtime, name string, value Value) bool { + if idx := fieldIndexByName(reflect.Indirect(o.value).Type(), name); len(idx) == 0 { return false } - fieldValue := self.getValue(name) + fieldValue := o.getValue(name) converted, err := rt.convertCallParameter(value, fieldValue.Type()) if err != nil { panic(rt.panicTypeError(err.Error())) @@ -77,14 +76,14 @@ func (self _goStructObject) setValue(rt *_runtime, name string, value Value) boo return true } -func goStructGetOwnProperty(self *_object, name string) *_property { - object := self.value.(*_goStructObject) - value := object.getValue(name) +func goStructGetOwnProperty(obj *object, name string) *property { + goObj := obj.value.(*goStructObject) + value := goObj.getValue(name) if value.IsValid() { - return &_property{self.runtime.toValue(value), 0110} + return &property{obj.runtime.toValue(value), 0o110} } - return objectGetOwnProperty(self, name) + return objectGetOwnProperty(obj, name) } func validGoStructName(name string) bool { @@ -94,12 +93,12 @@ func validGoStructName(name string) bool { return 'A' <= name[0] && name[0] <= 'Z' // TODO What about Unicode? } -func goStructEnumerate(self *_object, all bool, each func(string) bool) { - object := self.value.(*_goStructObject) +func goStructEnumerate(obj *object, all bool, each func(string) bool) { + goObj := obj.value.(*goStructObject) // Enumerate fields - for index := 0; index < reflect.Indirect(object.value).NumField(); index++ { - name := reflect.Indirect(object.value).Type().Field(index).Name + for index := 0; index < reflect.Indirect(goObj.value).NumField(); index++ { + name := reflect.Indirect(goObj.value).Type().Field(index).Name if validGoStructName(name) { if !each(name) { return @@ -108,8 +107,8 @@ func goStructEnumerate(self *_object, all bool, each func(string) bool) { } // Enumerate methods - for index := 0; index < object.value.NumMethod(); index++ { - name := object.value.Type().Method(index).Name + for index := 0; index < goObj.value.NumMethod(); index++ { + name := goObj.value.Type().Method(index).Name if validGoStructName(name) { if !each(name) { return @@ -117,34 +116,31 @@ func goStructEnumerate(self *_object, all bool, each func(string) bool) { } } - objectEnumerate(self, all, each) + objectEnumerate(obj, all, each) } -func goStructCanPut(self *_object, name string) bool { - object := self.value.(*_goStructObject) - value := object.getValue(name) +func goStructCanPut(obj *object, name string) bool { + goObj := obj.value.(*goStructObject) + value := goObj.getValue(name) if value.IsValid() { return true } - return objectCanPut(self, name) + return objectCanPut(obj, name) } -func goStructPut(self *_object, name string, value Value, throw bool) { - object := self.value.(*_goStructObject) - if object.setValue(self.runtime, name, value) { +func goStructPut(obj *object, name string, value Value, throw bool) { + goObj := obj.value.(*goStructObject) + if goObj.setValue(obj.runtime, name, value) { return } - objectPut(self, name, value, throw) + objectPut(obj, name, value, throw) } -func goStructMarshalJSON(self *_object) json.Marshaler { - object := self.value.(*_goStructObject) - goValue := reflect.Indirect(object.value).Interface() - switch marshaler := goValue.(type) { - case json.Marshaler: - return marshaler - } - return nil +func goStructMarshalJSON(obj *object) json.Marshaler { + goObj := obj.value.(*goStructObject) + goValue := reflect.Indirect(goObj.value).Interface() + marshaler, _ := goValue.(json.Marshaler) + return marshaler } diff --git a/type_number.go b/type_number.go index 7992480f..4201c926 100644 --- a/type_number.go +++ b/type_number.go @@ -1,5 +1,5 @@ package otto -func (runtime *_runtime) newNumberObject(value Value) *_object { - return runtime.newPrimitiveObject(classNumber, value.numberValue()) +func (rt *runtime) newNumberObject(value Value) *object { + return rt.newPrimitiveObject(classNumberName, value.numberValue()) } diff --git a/type_reference.go b/type_reference.go index 8fd23c1a..3e45b421 100644 --- a/type_reference.go +++ b/type_reference.go @@ -1,6 +1,6 @@ package otto -type _reference interface { +type referencer interface { invalid() bool // IsUnresolvableReference getValue() Value // getValue putValue(Value) string // PutValue @@ -9,86 +9,85 @@ type _reference interface { // PropertyReference -type _propertyReference struct { +type propertyReference struct { name string strict bool - base *_object - runtime *_runtime - at _at + base *object + runtime *runtime + at at } -func newPropertyReference(rt *_runtime, base *_object, name string, strict bool, at _at) *_propertyReference { - return &_propertyReference{ +func newPropertyReference(rt *runtime, base *object, name string, strict bool, atv at) *propertyReference { + return &propertyReference{ runtime: rt, name: name, strict: strict, base: base, - at: at, + at: atv, } } -func (self *_propertyReference) invalid() bool { - return self.base == nil +func (pr *propertyReference) invalid() bool { + return pr.base == nil } -func (self *_propertyReference) getValue() Value { - if self.base == nil { - panic(self.runtime.panicReferenceError("'%s' is not defined", self.name, self.at)) +func (pr *propertyReference) getValue() Value { + if pr.base == nil { + panic(pr.runtime.panicReferenceError("'%s' is not defined", pr.name, pr.at)) } - return self.base.get(self.name) + return pr.base.get(pr.name) } -func (self *_propertyReference) putValue(value Value) string { - if self.base == nil { - return self.name +func (pr *propertyReference) putValue(value Value) string { + if pr.base == nil { + return pr.name } - self.base.put(self.name, value, self.strict) + pr.base.put(pr.name, value, pr.strict) return "" } -func (self *_propertyReference) delete() bool { - if self.base == nil { +func (pr *propertyReference) delete() bool { + if pr.base == nil { // TODO Throw an error if strict return true } - return self.base.delete(self.name, self.strict) + return pr.base.delete(pr.name, pr.strict) } -type _stashReference struct { +type stashReference struct { name string strict bool - base _stash + base stasher } -func (self *_stashReference) invalid() bool { +func (sr *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 (sr *stashReference) getValue() Value { + return sr.base.getBinding(sr.name, sr.strict) } -func (self *_stashReference) putValue(value Value) string { - self.base.setValue(self.name, value, self.strict) +func (sr *stashReference) putValue(value Value) string { + sr.base.setValue(sr.name, value, sr.strict) return "" } -func (self *_stashReference) delete() bool { - if self.base == nil { +func (sr *stashReference) delete() bool { + if sr.base == nil { // This should never be reached, but just in case return false } - return self.base.deleteBinding(self.name) + return sr.base.deleteBinding(sr.name) } -// getIdentifierReference - -func getIdentifierReference(runtime *_runtime, stash _stash, name string, strict bool, at _at) _reference { +// getIdentifierReference. +func getIdentifierReference(rt *runtime, stash stasher, name string, strict bool, atv at) referencer { if stash == nil { - return newPropertyReference(runtime, nil, name, strict, at) + return newPropertyReference(rt, nil, name, strict, atv) } if stash.hasBinding(name) { - return stash.newReference(name, strict, at) + return stash.newReference(name, strict, atv) } - return getIdentifierReference(runtime, stash.outer(), name, strict, at) + return getIdentifierReference(rt, stash.outer(), name, strict, atv) } diff --git a/type_regexp.go b/type_regexp.go index c66cac4f..19001fe8 100644 --- a/type_regexp.go +++ b/type_regexp.go @@ -7,7 +7,7 @@ import ( "github.com/robertkrimen/otto/parser" ) -type _regExpObject struct { +type regExpObject struct { regularExpression *regexp.Regexp global bool ignoreCase bool @@ -16,9 +16,9 @@ type _regExpObject struct { flags string } -func (runtime *_runtime) newRegExpObject(pattern string, flags string) *_object { - self := runtime.newObject() - self.class = classRegExp +func (rt *runtime) newRegExpObject(pattern string, flags string) *object { + o := rt.newObject() + o.class = classRegExpName global := false ignoreCase := false @@ -31,18 +31,18 @@ func (runtime *_runtime) newRegExpObject(pattern string, flags string) *_object switch chr { case 'g': if global { - panic(runtime.panicSyntaxError("newRegExpObject: %s %s", pattern, flags)) + panic(rt.panicSyntaxError("newRegExpObject: %s %s", pattern, flags)) } global = true case 'm': if multiline { - panic(runtime.panicSyntaxError("newRegExpObject: %s %s", pattern, flags)) + panic(rt.panicSyntaxError("newRegExpObject: %s %s", pattern, flags)) } multiline = true re2flags += "m" case 'i': if ignoreCase { - panic(runtime.panicSyntaxError("newRegExpObject: %s %s", pattern, flags)) + panic(rt.panicSyntaxError("newRegExpObject: %s %s", pattern, flags)) } ignoreCase = true re2flags += "i" @@ -51,7 +51,7 @@ func (runtime *_runtime) newRegExpObject(pattern string, flags string) *_object re2pattern, err := parser.TransformRegExp(pattern) if err != nil { - panic(runtime.panicTypeError("Invalid regular expression: %s", err.Error())) + panic(rt.panicTypeError("Invalid regular expression: %s", err.Error())) } if len(re2flags) > 0 { re2pattern = fmt.Sprintf("(?%s:%s)", re2flags, re2pattern) @@ -59,10 +59,10 @@ func (runtime *_runtime) newRegExpObject(pattern string, flags string) *_object regularExpression, err := regexp.Compile(re2pattern) if err != nil { - panic(runtime.panicSyntaxError("Invalid regular expression: %s", err.Error()[22:])) + panic(rt.panicSyntaxError("Invalid regular expression: %s", err.Error()[22:])) } - self.value = _regExpObject{ + o.value = regExpObject{ regularExpression: regularExpression, global: global, ignoreCase: ignoreCase, @@ -70,21 +70,21 @@ func (runtime *_runtime) newRegExpObject(pattern string, flags string) *_object source: pattern, flags: flags, } - self.defineProperty("global", toValue_bool(global), 0, false) - self.defineProperty("ignoreCase", toValue_bool(ignoreCase), 0, false) - self.defineProperty("multiline", toValue_bool(multiline), 0, false) - self.defineProperty("lastIndex", toValue_int(0), 0100, false) - self.defineProperty("source", toValue_string(pattern), 0, false) - return self + o.defineProperty("global", boolValue(global), 0, false) + o.defineProperty("ignoreCase", boolValue(ignoreCase), 0, false) + o.defineProperty("multiline", boolValue(multiline), 0, false) + o.defineProperty("lastIndex", intValue(0), 0o100, false) + o.defineProperty("source", stringValue(pattern), 0, false) + return o } -func (self *_object) regExpValue() _regExpObject { - value, _ := self.value.(_regExpObject) +func (o *object) regExpValue() regExpObject { + value, _ := o.value.(regExpObject) return value } -func execRegExp(this *_object, target string) (match bool, result []int) { - if this.class != classRegExp { +func execRegExp(this *object, target string) (bool, []int) { + if this.class != classRegExpName { panic(this.runtime.panicTypeError("Calling RegExp.exec on a non-RegExp object")) } lastIndex := this.get("lastIndex").number().int64 @@ -93,15 +93,18 @@ func execRegExp(this *_object, target string) (match bool, result []int) { if !global { index = 0 } + + var result []int if 0 > index || index > int64(len(target)) { } else { result = this.regExpValue().regularExpression.FindStringSubmatchIndex(target[index:]) } + if result == nil { - this.put("lastIndex", toValue_int(0), true) - return // !match + this.put("lastIndex", intValue(0), true) + return false, nil } - match = true + startIndex := index endIndex := int(lastIndex) + result[1] // We do this shift here because the .FindStringSubmatchIndex above @@ -112,18 +115,19 @@ func execRegExp(this *_object, target string) (match bool, result []int) { } } if global { - this.put("lastIndex", toValue_int(endIndex), true) + this.put("lastIndex", intValue(endIndex), true) } - return // match + + return true, result } -func execResultToArray(runtime *_runtime, target string, result []int) *_object { +func execResultToArray(rt *runtime, target string, result []int) *object { captureCount := len(result) / 2 valueArray := make([]Value, captureCount) for index := 0; index < captureCount; index++ { offset := 2 * index if result[offset] != -1 { - valueArray[index] = toValue_string(target[result[offset]:result[offset+1]]) + valueArray[index] = stringValue(target[result[offset]:result[offset+1]]) } else { valueArray[index] = Value{} } @@ -133,8 +137,8 @@ func execResultToArray(runtime *_runtime, target string, result []int) *_object // Find the utf16 index in the string, not the byte index. matchIndex = utf16Length(target[:matchIndex]) } - match := runtime.newArrayOf(valueArray) - match.defineProperty("input", toValue_string(target), 0111, false) - match.defineProperty("index", toValue_int(matchIndex), 0111, false) + match := rt.newArrayOf(valueArray) + match.defineProperty("input", stringValue(target), 0o111, false) + match.defineProperty("index", intValue(matchIndex), 0o111, false) return match } diff --git a/type_string.go b/type_string.go index f08a6183..cea9fc48 100644 --- a/type_string.go +++ b/type_string.go @@ -6,90 +6,90 @@ import ( "unicode/utf8" ) -type _stringObject interface { +type stringObjecter interface { Length() int At(int) rune String() string } -type _stringASCII string +type stringASCII string -func (str _stringASCII) Length() int { +func (str stringASCII) Length() int { return len(str) } -func (str _stringASCII) At(at int) rune { +func (str stringASCII) At(at int) rune { return rune(str[at]) } -func (str _stringASCII) String() string { +func (str stringASCII) String() string { return string(str) } -type _stringWide struct { +type stringWide struct { string string value16 []uint16 } -func (str _stringWide) Length() int { +func (str stringWide) Length() int { if str.value16 == nil { str.value16 = utf16.Encode([]rune(str.string)) } return len(str.value16) } -func (str _stringWide) At(at int) rune { +func (str stringWide) At(at int) rune { if str.value16 == nil { str.value16 = utf16.Encode([]rune(str.string)) } return rune(str.value16[at]) } -func (str _stringWide) String() string { +func (str stringWide) String() string { return str.string } -func _newStringObject(str string) _stringObject { +func newStringObject(str string) stringObjecter { for i := 0; i < len(str); i++ { if str[i] >= utf8.RuneSelf { goto wide } } - return _stringASCII(str) + return stringASCII(str) wide: - return &_stringWide{ + return &stringWide{ string: str, } } -func stringAt(str _stringObject, index int) rune { +func stringAt(str stringObjecter, index int) rune { if 0 <= index && index < str.Length() { return str.At(index) } return utf8.RuneError } -func (runtime *_runtime) newStringObject(value Value) *_object { - str := _newStringObject(value.string()) +func (rt *runtime) newStringObject(value Value) *object { + str := newStringObject(value.string()) - self := runtime.newClassObject(classString) - self.defineProperty(propertyLength, toValue_int(str.Length()), 0, false) - self.objectClass = _classString - self.value = str - return self + obj := rt.newClassObject(classStringName) + obj.defineProperty(propertyLength, intValue(str.Length()), 0, false) + obj.objectClass = classString + obj.value = str + return obj } -func (self *_object) stringValue() _stringObject { - if str, ok := self.value.(_stringObject); ok { +func (o *object) stringValue() stringObjecter { + if str, ok := o.value.(stringObjecter); ok { return str } return nil } -func stringEnumerate(self *_object, all bool, each func(string) bool) { - if str := self.stringValue(); str != nil { +func stringEnumerate(obj *object, all bool, each func(string) bool) { + if str := obj.stringValue(); str != nil { length := str.Length() for index := 0; index < length; index++ { if !each(strconv.FormatInt(int64(index), 10)) { @@ -97,17 +97,17 @@ func stringEnumerate(self *_object, all bool, each func(string) bool) { } } } - objectEnumerate(self, all, each) + objectEnumerate(obj, all, each) } -func stringGetOwnProperty(self *_object, name string) *_property { - if property := objectGetOwnProperty(self, name); property != nil { - return property +func stringGetOwnProperty(obj *object, name string) *property { + if prop := objectGetOwnProperty(obj, name); prop != nil { + return prop } // TODO Test a string of length >= +int32 + 1? if index := stringToArrayIndex(name); index >= 0 { - if chr := stringAt(self.stringValue(), int(index)); chr != utf8.RuneError { - return &_property{toValue_string(string(chr)), 0} + if chr := stringAt(obj.stringValue(), int(index)); chr != utf8.RuneError { + return &property{stringValue(string(chr)), 0} } } return nil diff --git a/underscore/underscore.go b/underscore/underscore.go index f93d9eb7..16b0a3ce 100644 --- a/underscore/underscore.go +++ b/underscore/underscore.go @@ -23,7 +23,7 @@ package underscore import ( - _ "embed" + _ "embed" // Embed underscore. "github.com/robertkrimen/otto/registry" ) diff --git a/underscore_arrays_test.go b/underscore_arrays_test.go index 3a7748c5..28516acc 100644 --- a/underscore_arrays_test.go +++ b/underscore_arrays_test.go @@ -4,10 +4,10 @@ import ( "testing" ) -// first +// first. func Test_underscore_arrays_0(t *testing.T) { tt(t, func() { - test, _ := test_() + test := underscoreTest() test(` test("first", function() { @@ -29,10 +29,10 @@ func Test_underscore_arrays_0(t *testing.T) { }) } -// rest +// rest. func Test_underscore_arrays_1(t *testing.T) { tt(t, func() { - test, _ := test_() + test := underscoreTest() test(` test("rest", function() { @@ -51,10 +51,10 @@ func Test_underscore_arrays_1(t *testing.T) { }) } -// initial +// initial. func Test_underscore_arrays_2(t *testing.T) { tt(t, func() { - test, _ := test_() + test := underscoreTest() test(` test("initial", function() { @@ -69,10 +69,10 @@ func Test_underscore_arrays_2(t *testing.T) { }) } -// last +// last. func Test_underscore_arrays_3(t *testing.T) { tt(t, func() { - test, _ := test_() + test := underscoreTest() test(` test("last", function() { @@ -91,10 +91,10 @@ func Test_underscore_arrays_3(t *testing.T) { }) } -// compact +// compact. func Test_underscore_arrays_4(t *testing.T) { tt(t, func() { - test, _ := test_() + test := underscoreTest() test(` test("compact", function() { @@ -106,10 +106,10 @@ func Test_underscore_arrays_4(t *testing.T) { }) } -// flatten +// flatten. func Test_underscore_arrays_5(t *testing.T) { tt(t, func() { - test, _ := test_() + test := underscoreTest() test(` test("flatten", function() { @@ -123,10 +123,10 @@ func Test_underscore_arrays_5(t *testing.T) { }) } -// without +// without. func Test_underscore_arrays_6(t *testing.T) { tt(t, func() { - test, _ := test_() + test := underscoreTest() test(` test("without", function() { @@ -143,10 +143,10 @@ func Test_underscore_arrays_6(t *testing.T) { }) } -// uniq +// uniq. func Test_underscore_arrays_7(t *testing.T) { tt(t, func() { - test, _ := test_() + test := underscoreTest() test(` test("uniq", function() { @@ -173,10 +173,10 @@ func Test_underscore_arrays_7(t *testing.T) { }) } -// intersection +// intersection. func Test_underscore_arrays_8(t *testing.T) { tt(t, func() { - test, _ := test_() + test := underscoreTest() test(` test("intersection", function() { @@ -190,10 +190,10 @@ func Test_underscore_arrays_8(t *testing.T) { }) } -// union +// union. func Test_underscore_arrays_9(t *testing.T) { tt(t, func() { - test, _ := test_() + test := underscoreTest() test(` test("union", function() { @@ -207,10 +207,10 @@ func Test_underscore_arrays_9(t *testing.T) { }) } -// difference +// difference. func Test_underscore_arrays_10(t *testing.T) { tt(t, func() { - test, _ := test_() + test := underscoreTest() test(` test("difference", function() { @@ -224,10 +224,10 @@ func Test_underscore_arrays_10(t *testing.T) { }) } -// zip +// zip. func Test_underscore_arrays_11(t *testing.T) { tt(t, func() { - test, _ := test_() + test := underscoreTest() test(` test('zip', function() { @@ -239,10 +239,10 @@ func Test_underscore_arrays_11(t *testing.T) { }) } -// object +// object. func Test_underscore_arrays_12(t *testing.T) { tt(t, func() { - test, _ := test_() + test := underscoreTest() test(` test('object', function() { @@ -263,10 +263,10 @@ func Test_underscore_arrays_12(t *testing.T) { }) } -// indexOf +// indexOf. func Test_underscore_arrays_13(t *testing.T) { tt(t, func() { - test, _ := test_() + test := underscoreTest() test(` test("indexOf", function() { @@ -297,10 +297,10 @@ func Test_underscore_arrays_13(t *testing.T) { }) } -// lastIndexOf +// lastIndexOf. func Test_underscore_arrays_14(t *testing.T) { tt(t, func() { - test, _ := test_() + test := underscoreTest() test(` test("lastIndexOf", function() { @@ -323,10 +323,10 @@ func Test_underscore_arrays_14(t *testing.T) { }) } -// range +// range. func Test_underscore_arrays_15(t *testing.T) { tt(t, func() { - test, _ := test_() + test := underscoreTest() test(` test("range", function() { diff --git a/underscore_chaining_test.go b/underscore_chaining_test.go index accf04fd..e064543b 100644 --- a/underscore_chaining_test.go +++ b/underscore_chaining_test.go @@ -4,10 +4,10 @@ import ( "testing" ) -// map/flatten/reduce +// map/flatten/reduce. func Test_underscore_chaining_0(t *testing.T) { tt(t, func() { - test, _ := test_() + test := underscoreTest() test(` test("map/flatten/reduce", function() { @@ -31,10 +31,10 @@ func Test_underscore_chaining_0(t *testing.T) { }) } -// select/reject/sortBy +// select/reject/sortBy. func Test_underscore_chaining_1(t *testing.T) { tt(t, func() { - test, _ := test_() + test := underscoreTest() test(` test("select/reject/sortBy", function() { @@ -52,10 +52,10 @@ func Test_underscore_chaining_1(t *testing.T) { }) } -// select/reject/sortBy in functional style +// select/reject/sortBy in functional style. func Test_underscore_chaining_2(t *testing.T) { tt(t, func() { - test, _ := test_() + test := underscoreTest() test(` test("select/reject/sortBy in functional style", function() { @@ -73,10 +73,10 @@ func Test_underscore_chaining_2(t *testing.T) { }) } -// reverse/concat/unshift/pop/map +// reverse/concat/unshift/pop/map. func Test_underscore_chaining_3(t *testing.T) { tt(t, func() { - test, _ := test_() + test := underscoreTest() test(` test("reverse/concat/unshift/pop/map", function() { diff --git a/underscore_collections_test.go b/underscore_collections_test.go index 4224d4c3..6cbbdaec 100644 --- a/underscore_collections_test.go +++ b/underscore_collections_test.go @@ -4,10 +4,10 @@ import ( "testing" ) -// each +// each. func Test_underscore_collections_0(t *testing.T) { tt(t, func() { - test, _ := test_() + test := underscoreTest() test(` test("each", function() { @@ -42,10 +42,10 @@ func Test_underscore_collections_0(t *testing.T) { }) } -// map +// map. func Test_underscore_collections_1(t *testing.T) { tt(t, func() { - test, _ := test_() + test := underscoreTest() test(` test('map', function() { @@ -82,10 +82,10 @@ func Test_underscore_collections_1(t *testing.T) { }) } -// reduce +// reduce. func Test_underscore_collections_2(t *testing.T) { tt(t, func() { - test, _ := test_() + test := underscoreTest() test(` test('reduce', function() { @@ -111,7 +111,7 @@ func Test_underscore_collections_2(t *testing.T) { } catch (ex) { ifnull = ex; } - ok(ifnull instanceof TypeError, 'handles a null (without inital value) properly'); + ok(ifnull instanceof TypeError, 'handles a null (without initial value) properly'); ok(_.reduce(null, function(){}, 138) === 138, 'handles a null (with initial value) properly'); equal(_.reduce([], function(){}, undefined), undefined, 'undefined can be passed as a special case'); @@ -121,10 +121,10 @@ func Test_underscore_collections_2(t *testing.T) { }) } -// reduceRight +// reduceRight. func Test_underscore_collections_3(t *testing.T) { tt(t, func() { - test, _ := test_() + test := underscoreTest() test(` test('reduceRight', function() { @@ -143,7 +143,7 @@ func Test_underscore_collections_3(t *testing.T) { } catch (ex) { ifnull = ex; } - ok(ifnull instanceof TypeError, 'handles a null (without inital value) properly'); + ok(ifnull instanceof TypeError, 'handles a null (without initial value) properly'); var sum = _.reduceRight({a: 1, b: 2, c: 3}, function(sum, num){ return sum + num; }); equal(sum, 6, 'default initial value on object'); @@ -190,10 +190,10 @@ func Test_underscore_collections_3(t *testing.T) { }) } -// find +// find. func Test_underscore_collections_4(t *testing.T) { tt(t, func() { - test, _ := test_() + test := underscoreTest() test(` test('find', function() { @@ -205,10 +205,10 @@ func Test_underscore_collections_4(t *testing.T) { }) } -// detect +// detect. func Test_underscore_collections_5(t *testing.T) { tt(t, func() { - test, _ := test_() + test := underscoreTest() test(` test('detect', function() { @@ -219,10 +219,10 @@ func Test_underscore_collections_5(t *testing.T) { }) } -// select +// select. func Test_underscore_collections_6(t *testing.T) { tt(t, func() { - test, _ := test_() + test := underscoreTest() test(` test('select', function() { @@ -236,10 +236,10 @@ func Test_underscore_collections_6(t *testing.T) { }) } -// reject +// reject. func Test_underscore_collections_7(t *testing.T) { tt(t, func() { - test, _ := test_() + test := underscoreTest() test(` test('reject', function() { @@ -258,10 +258,10 @@ func Test_underscore_collections_7(t *testing.T) { }) } -// all +// all. func Test_underscore_collections_8(t *testing.T) { tt(t, func() { - test, _ := test_() + test := underscoreTest() test(` test('all', function() { @@ -279,10 +279,10 @@ func Test_underscore_collections_8(t *testing.T) { }) } -// any +// any. func Test_underscore_collections_9(t *testing.T) { tt(t, func() { - test, _ := test_() + test := underscoreTest() test(` test('any', function() { @@ -304,10 +304,10 @@ func Test_underscore_collections_9(t *testing.T) { }) } -// include +// include. func Test_underscore_collections_10(t *testing.T) { tt(t, func() { - test, _ := test_() + test := underscoreTest() test(` test('include', function() { @@ -320,10 +320,10 @@ func Test_underscore_collections_10(t *testing.T) { }) } -// invoke +// invoke. func Test_underscore_collections_11(t *testing.T) { tt(t, func() { - test, _ := test_() + test := underscoreTest() test(` test('invoke', function() { @@ -336,10 +336,10 @@ func Test_underscore_collections_11(t *testing.T) { }) } -// invoke w/ function reference +// invoke w/ function reference. func Test_underscore_collections_12(t *testing.T) { tt(t, func() { - test, _ := test_() + test := underscoreTest() test(` test('invoke w/ function reference', function() { @@ -352,10 +352,10 @@ func Test_underscore_collections_12(t *testing.T) { }) } -// invoke when strings have a call method +// invoke when strings have a call method. func Test_underscore_collections_13(t *testing.T) { tt(t, func() { - test, _ := test_() + test := underscoreTest() test(` test('invoke when strings have a call method', function() { @@ -375,10 +375,10 @@ func Test_underscore_collections_13(t *testing.T) { }) } -// pluck +// pluck. func Test_underscore_collections_14(t *testing.T) { tt(t, func() { - test, _ := test_() + test := underscoreTest() test(` test('pluck', function() { @@ -389,10 +389,10 @@ func Test_underscore_collections_14(t *testing.T) { }) } -// where +// where. func Test_underscore_collections_15(t *testing.T) { tt(t, func() { - test, _ := test_() + test := underscoreTest() test(` test('where', function() { @@ -408,10 +408,10 @@ func Test_underscore_collections_15(t *testing.T) { }) } -// findWhere +// findWhere. func Test_underscore_collections_16(t *testing.T) { tt(t, func() { - test, _ := test_() + test := underscoreTest() test(` test('findWhere', function() { @@ -425,10 +425,10 @@ func Test_underscore_collections_16(t *testing.T) { }) } -// max +// max. func Test_underscore_collections_17(t *testing.T) { tt(t, func() { - test, _ := test_() + test := underscoreTest() test(` test('max', function() { @@ -450,10 +450,10 @@ func Test_underscore_collections_17(t *testing.T) { }) } -// min +// min. func Test_underscore_collections_18(t *testing.T) { tt(t, func() { - test, _ := test_() + test := underscoreTest() test(` test('min', function() { @@ -479,10 +479,10 @@ func Test_underscore_collections_18(t *testing.T) { }) } -// sortBy +// sortBy. func Test_underscore_collections_19(t *testing.T) { tt(t, func() { - test, _ := test_() + test := underscoreTest() test(` test('sortBy', function() { @@ -524,10 +524,10 @@ func Test_underscore_collections_19(t *testing.T) { }) } -// groupBy +// groupBy. func Test_underscore_collections_20(t *testing.T) { tt(t, func() { - test, _ := test_() + test := underscoreTest() test(` test('groupBy', function() { @@ -562,10 +562,10 @@ func Test_underscore_collections_20(t *testing.T) { }) } -// countBy +// countBy. func Test_underscore_collections_21(t *testing.T) { tt(t, func() { - test, _ := test_() + test := underscoreTest() test(` test('countBy', function() { @@ -600,10 +600,10 @@ func Test_underscore_collections_21(t *testing.T) { }) } -// sortedIndex +// sortedIndex. func Test_underscore_collections_22(t *testing.T) { tt(t, func() { - test, _ := test_() + test := underscoreTest() test(` test('sortedIndex', function() { @@ -627,10 +627,10 @@ func Test_underscore_collections_22(t *testing.T) { }) } -// shuffle +// shuffle. func Test_underscore_collections_23(t *testing.T) { tt(t, func() { - test, _ := test_() + test := underscoreTest() test(` test('shuffle', function() { @@ -643,10 +643,10 @@ func Test_underscore_collections_23(t *testing.T) { }) } -// toArray +// toArray. func Test_underscore_collections_24(t *testing.T) { tt(t, func() { - test, _ := test_() + test := underscoreTest() test(` test('toArray', function() { @@ -673,10 +673,10 @@ func Test_underscore_collections_24(t *testing.T) { }) } -// size +// size. func Test_underscore_collections_25(t *testing.T) { tt(t, func() { - test, _ := test_() + test := underscoreTest() test(` test('size', function() { diff --git a/underscore_functions_test.go b/underscore_functions_test.go index 6fea9d60..98a0d326 100644 --- a/underscore_functions_test.go +++ b/underscore_functions_test.go @@ -4,10 +4,10 @@ import ( "testing" ) -// bind +// bind. func Test_underscore_functions_0(t *testing.T) { tt(t, func() { - test, _ := test_() + test := underscoreTest() test(` test("bind", function() { @@ -48,10 +48,10 @@ func Test_underscore_functions_0(t *testing.T) { }) } -// partial +// partial. func Test_underscore_functions_1(t *testing.T) { tt(t, func() { - test, _ := test_() + test := underscoreTest() test(` test("partial", function() { @@ -65,10 +65,10 @@ func Test_underscore_functions_1(t *testing.T) { }) } -// bindAll +// bindAll. func Test_underscore_functions_2(t *testing.T) { tt(t, func() { - test, _ := test_() + test := underscoreTest() test(` test("bindAll", function() { @@ -87,10 +87,10 @@ func Test_underscore_functions_2(t *testing.T) { }) } -// memoize +// memoize. func Test_underscore_functions_3(t *testing.T) { tt(t, func() { - test, _ := test_() + test := underscoreTest() test(` test("memoize", function() { @@ -112,10 +112,10 @@ func Test_underscore_functions_3(t *testing.T) { }) } -// once +// once. func Test_underscore_functions_4(t *testing.T) { tt(t, func() { - test, _ := test_() + test := underscoreTest() test(` test("once", function() { @@ -129,10 +129,10 @@ func Test_underscore_functions_4(t *testing.T) { }) } -// wrap +// wrap. func Test_underscore_functions_5(t *testing.T) { tt(t, func() { - test, _ := test_() + test := underscoreTest() test(` test("wrap", function() { @@ -154,10 +154,10 @@ func Test_underscore_functions_5(t *testing.T) { }) } -// compose +// compose. func Test_underscore_functions_6(t *testing.T) { tt(t, func() { - test, _ := test_() + test := underscoreTest() test(` test("compose", function() { @@ -173,10 +173,10 @@ func Test_underscore_functions_6(t *testing.T) { }) } -// after +// after. func Test_underscore_functions_7(t *testing.T) { tt(t, func() { - test, _ := test_() + test := underscoreTest() test(` test("after", function() { diff --git a/underscore_objects_test.go b/underscore_objects_test.go index e071370a..5601f29b 100644 --- a/underscore_objects_test.go +++ b/underscore_objects_test.go @@ -4,10 +4,10 @@ import ( "testing" ) -// keys +// keys. func Test_underscore_objects_0(t *testing.T) { tt(t, func() { - test, _ := test_() + test := underscoreTest() test(` test("keys", function() { @@ -25,10 +25,10 @@ func Test_underscore_objects_0(t *testing.T) { }) } -// values +// values. func Test_underscore_objects_1(t *testing.T) { tt(t, func() { - test, _ := test_() + test := underscoreTest() test(` test("values", function() { @@ -39,10 +39,10 @@ func Test_underscore_objects_1(t *testing.T) { }) } -// pairs +// pairs. func Test_underscore_objects_2(t *testing.T) { tt(t, func() { - test, _ := test_() + test := underscoreTest() test(` test("pairs", function() { @@ -53,10 +53,10 @@ func Test_underscore_objects_2(t *testing.T) { }) } -// invert +// invert. func Test_underscore_objects_3(t *testing.T) { tt(t, func() { - test, _ := test_() + test := underscoreTest() test(` test("invert", function() { @@ -71,10 +71,10 @@ func Test_underscore_objects_3(t *testing.T) { }) } -// functions +// functions. func Test_underscore_objects_4(t *testing.T) { tt(t, func() { - test, _ := test_() + test := underscoreTest() test(` test("functions", function() { @@ -89,10 +89,10 @@ func Test_underscore_objects_4(t *testing.T) { }) } -// extend +// extend. func Test_underscore_objects_5(t *testing.T) { tt(t, func() { - test, _ := test_() + test := underscoreTest() test(` test("extend", function() { @@ -118,10 +118,10 @@ func Test_underscore_objects_5(t *testing.T) { }) } -// pick +// pick. func Test_underscore_objects_6(t *testing.T) { tt(t, func() { - test, _ := test_() + test := underscoreTest() test(` test("pick", function() { @@ -141,10 +141,10 @@ func Test_underscore_objects_6(t *testing.T) { }) } -// omit +// omit. func Test_underscore_objects_7(t *testing.T) { tt(t, func() { - test, _ := test_() + test := underscoreTest() test(` test("omit", function() { @@ -164,10 +164,10 @@ func Test_underscore_objects_7(t *testing.T) { }) } -// defaults +// defaults. func Test_underscore_objects_8(t *testing.T) { tt(t, func() { - test, _ := test_() + test := underscoreTest() test(` test("defaults", function() { @@ -195,10 +195,10 @@ func Test_underscore_objects_8(t *testing.T) { }) } -// clone +// clone. func Test_underscore_objects_9(t *testing.T) { tt(t, func() { - test, _ := test_() + test := underscoreTest() test(` test("clone", function() { @@ -220,10 +220,10 @@ func Test_underscore_objects_9(t *testing.T) { }) } -// isEqual +// isEqual. func Test_underscore_objects_10(t *testing.T) { tt(t, func() { - test, _ := test_() + test := underscoreTest() test(` test("isEqual", function() { @@ -464,10 +464,10 @@ func Test_underscore_objects_10(t *testing.T) { }) } -// isEmpty +// isEmpty. func Test_underscore_objects_11(t *testing.T) { tt(t, func() { - test, _ := test_() + test := underscoreTest() test(` test("isEmpty", function() { @@ -489,7 +489,7 @@ func Test_underscore_objects_11(t *testing.T) { }) } -// isElement +// isElement. func Test_underscore_objects_12(t *testing.T) { // TEST: ReferenceError: $ is not defined if true { @@ -497,7 +497,7 @@ func Test_underscore_objects_12(t *testing.T) { } tt(t, func() { - test, _ := test_() + test := underscoreTest() test(` test("isElement", function() { @@ -509,10 +509,10 @@ func Test_underscore_objects_12(t *testing.T) { }) } -// isArguments +// isArguments. func Test_underscore_objects_13(t *testing.T) { tt(t, func() { - test, _ := test_() + test := underscoreTest() test(` test("isArguments", function() { @@ -531,10 +531,10 @@ func Test_underscore_objects_13(t *testing.T) { }) } -// isObject +// isObject. func Test_underscore_objects_14(t *testing.T) { tt(t, func() { - test, _ := test_() + test := underscoreTest() test(` test("isObject", function() { @@ -557,10 +557,10 @@ func Test_underscore_objects_14(t *testing.T) { }) } -// isArray +// isArray. func Test_underscore_objects_15(t *testing.T) { tt(t, func() { - test, _ := test_() + test := underscoreTest() test(` test("isArray", function() { @@ -574,7 +574,7 @@ func Test_underscore_objects_15(t *testing.T) { }) } -// isString +// isString. func Test_underscore_objects_16(t *testing.T) { // TEST: ReferenceError: document is not defined if true { @@ -582,7 +582,7 @@ func Test_underscore_objects_16(t *testing.T) { } tt(t, func() { - test, _ := test_() + test := underscoreTest() test(` test("isString", function() { @@ -596,10 +596,10 @@ func Test_underscore_objects_16(t *testing.T) { }) } -// isNumber +// isNumber. func Test_underscore_objects_17(t *testing.T) { tt(t, func() { - test, _ := test_() + test := underscoreTest() test(` test("isNumber", function() { @@ -618,10 +618,10 @@ func Test_underscore_objects_17(t *testing.T) { }) } -// isBoolean +// isBoolean. func Test_underscore_objects_18(t *testing.T) { tt(t, func() { - test, _ := test_() + test := underscoreTest() test(` test("isBoolean", function() { @@ -643,10 +643,10 @@ func Test_underscore_objects_18(t *testing.T) { }) } -// isFunction +// isFunction. func Test_underscore_objects_19(t *testing.T) { tt(t, func() { - test, _ := test_() + test := underscoreTest() test(` test("isFunction", function() { @@ -661,10 +661,10 @@ func Test_underscore_objects_19(t *testing.T) { }) } -// isDate +// isDate. func Test_underscore_objects_20(t *testing.T) { tt(t, func() { - test, _ := test_() + test := underscoreTest() test(` test("isDate", function() { @@ -679,10 +679,10 @@ func Test_underscore_objects_20(t *testing.T) { }) } -// isRegExp +// isRegExp. func Test_underscore_objects_21(t *testing.T) { tt(t, func() { - test, _ := test_() + test := underscoreTest() test(` test("isRegExp", function() { @@ -696,10 +696,10 @@ func Test_underscore_objects_21(t *testing.T) { }) } -// isFinite +// isFinite. func Test_underscore_objects_22(t *testing.T) { tt(t, func() { - test, _ := test_() + test := underscoreTest() test(` test("isFinite", function() { @@ -721,10 +721,10 @@ func Test_underscore_objects_22(t *testing.T) { }) } -// isNaN +// isNaN. func Test_underscore_objects_23(t *testing.T) { tt(t, func() { - test, _ := test_() + test := underscoreTest() test(` test("isNaN", function() { @@ -741,10 +741,10 @@ func Test_underscore_objects_23(t *testing.T) { }) } -// isNull +// isNull. func Test_underscore_objects_24(t *testing.T) { tt(t, func() { - test, _ := test_() + test := underscoreTest() test(` test("isNull", function() { @@ -759,10 +759,10 @@ func Test_underscore_objects_24(t *testing.T) { }) } -// isUndefined +// isUndefined. func Test_underscore_objects_25(t *testing.T) { tt(t, func() { - test, _ := test_() + test := underscoreTest() test(` test("isUndefined", function() { @@ -780,10 +780,10 @@ func Test_underscore_objects_25(t *testing.T) { }) } -// tap +// tap. func Test_underscore_objects_26(t *testing.T) { tt(t, func() { - test, _ := test_() + test := underscoreTest() test(` test("tap", function() { @@ -804,10 +804,10 @@ func Test_underscore_objects_26(t *testing.T) { }) } -// has +// has. func Test_underscore_objects_27(t *testing.T) { tt(t, func() { - test, _ := test_() + test := underscoreTest() test(` test("has", function () { diff --git a/underscore_test.go b/underscore_test.go index a01aa132..8abfb665 100644 --- a/underscore_test.go +++ b/underscore_test.go @@ -1,6 +1,7 @@ package otto import ( + "sync" "testing" "github.com/robertkrimen/otto/terst" @@ -11,31 +12,32 @@ func init() { underscore.Disable() } -// A persistent handle for the underscore tester -// We do not run underscore tests in parallel, so it is okay to stash globally -// (Maybe use sync.Pool in the future...) -var tester_ *_tester +var ( + // A persistent handle for the underscore tester + // We do not run underscore tests in parallel, so it is okay to stash globally. + tester *_tester + once sync.Once +) -// A tester for underscore: test_ => test(underscore) :) -func test_(arguments ...interface{}) (func(string, ...interface{}) Value, *_tester) { - tester := tester_ - if tester == nil { +// A tester for underscore: underscoreTest => test(underscore) :). +func underscoreTest() func(string, ...interface{}) Value { + setTester := func() { tester = newTester() tester.underscore() // Load underscore and testing shim, etc. - tester_ = tester } + once.Do(setTester) - return tester.test, tester + return tester.test } -func (self *_tester) underscore() { - vm := self.vm +func (te *_tester) underscore() { + vm := te.vm _, err := vm.Run(underscore.Source()) if err != nil { panic(err) } - vm.Set("assert", func(call FunctionCall) Value { + err = vm.Set("assert", func(call FunctionCall) Value { if !call.Argument(0).bool() { message := "Assertion failed" if len(call.ArgumentList) > 1 { @@ -48,8 +50,11 @@ func (self *_tester) underscore() { } return trueValue }) + if err != nil { + panic(err) + } - vm.Run(` + _, err = vm.Run(` var templateSettings; function _setup() { @@ -136,11 +141,14 @@ func (self *_tester) underscore() { assert(_.isEqual(a, b), emit) } `) + if err != nil { + panic(err) + } } func Test_underscore(t *testing.T) { tt(t, func() { - test, _ := test_() + test := underscoreTest() test(` _.map([1, 2, 3], function(value){ diff --git a/underscore_utility_test.go b/underscore_utility_test.go index ae9beb6d..1a8886b3 100644 --- a/underscore_utility_test.go +++ b/underscore_utility_test.go @@ -7,7 +7,7 @@ import ( // #750 - Return _ instance. func Test_underscore_utility_0(t *testing.T) { tt(t, func() { - test, _ := test_() + test := underscoreTest() test(` test("#750 - Return _ instance.", 2, function() { @@ -19,10 +19,10 @@ func Test_underscore_utility_0(t *testing.T) { }) } -// identity +// identity. func Test_underscore_utility_1(t *testing.T) { tt(t, func() { - test, _ := test_() + test := underscoreTest() test(` test("identity", function() { @@ -33,10 +33,10 @@ func Test_underscore_utility_1(t *testing.T) { }) } -// random +// random. func Test_underscore_utility_2(t *testing.T) { tt(t, func() { - test, _ := test_() + test := underscoreTest() test(` test("random", function() { @@ -56,10 +56,10 @@ func Test_underscore_utility_2(t *testing.T) { }) } -// uniqueId +// uniqueId. func Test_underscore_utility_3(t *testing.T) { tt(t, func() { - test, _ := test_() + test := underscoreTest() test(` test("uniqueId", function() { @@ -71,10 +71,10 @@ func Test_underscore_utility_3(t *testing.T) { }) } -// times +// times. func Test_underscore_utility_4(t *testing.T) { tt(t, func() { - test, _ := test_() + test := underscoreTest() test(` test("times", function() { @@ -92,10 +92,10 @@ func Test_underscore_utility_4(t *testing.T) { }) } -// mixin +// mixin. func Test_underscore_utility_5(t *testing.T) { tt(t, func() { - test, _ := test_() + test := underscoreTest() test(` test("mixin", function() { @@ -111,10 +111,10 @@ func Test_underscore_utility_5(t *testing.T) { }) } -// _.escape +// _.escape. func Test_underscore_utility_6(t *testing.T) { tt(t, func() { - test, _ := test_() + test := underscoreTest() test(` test("_.escape", function() { @@ -126,10 +126,10 @@ func Test_underscore_utility_6(t *testing.T) { }) } -// _.unescape +// _.unescape. func Test_underscore_utility_7(t *testing.T) { tt(t, func() { - test, _ := test_() + test := underscoreTest() test(` test("_.unescape", function() { @@ -143,10 +143,10 @@ func Test_underscore_utility_7(t *testing.T) { }) } -// template +// template. func Test_underscore_utility_8(t *testing.T) { tt(t, func() { - test, _ := test_() + test := underscoreTest() test(` test("template", function() { @@ -261,10 +261,10 @@ func Test_underscore_utility_8(t *testing.T) { }) } -// _.template provides the generated function source, when a SyntaxError occurs +// _.template provides the generated function source, when a SyntaxError occurs. func Test_underscore_utility_9(t *testing.T) { tt(t, func() { - test, _ := test_() + test := underscoreTest() test(` test('_.template provides the generated function source, when a SyntaxError occurs', function() { @@ -279,10 +279,10 @@ func Test_underscore_utility_9(t *testing.T) { }) } -// _.template handles \\u2028 & \\u2029 +// _.template handles \\u2028 & \\u2029. func Test_underscore_utility_10(t *testing.T) { tt(t, func() { - test, _ := test_() + test := underscoreTest() test(` test('_.template handles \\u2028 & \\u2029', function() { @@ -293,10 +293,10 @@ func Test_underscore_utility_10(t *testing.T) { }) } -// result calls functions and returns primitives +// result calls functions and returns primitives. func Test_underscore_utility_11(t *testing.T) { tt(t, func() { - test, _ := test_() + test := underscoreTest() test(` test('result calls functions and returns primitives', function() { @@ -311,10 +311,10 @@ func Test_underscore_utility_11(t *testing.T) { }) } -// _.templateSettings.variable +// _.templateSettings.variable. func Test_underscore_utility_12(t *testing.T) { tt(t, func() { - test, _ := test_() + test := underscoreTest() test(` test('_.templateSettings.variable', function() { @@ -331,7 +331,7 @@ func Test_underscore_utility_12(t *testing.T) { // #547 - _.templateSettings is unchanged by custom settings. func Test_underscore_utility_13(t *testing.T) { tt(t, func() { - test, _ := test_() + test := underscoreTest() test(` test('#547 - _.templateSettings is unchanged by custom settings.', function() { @@ -346,7 +346,7 @@ func Test_underscore_utility_13(t *testing.T) { // #556 - undefined template variables. func Test_underscore_utility_14(t *testing.T) { tt(t, func() { - test, _ := test_() + test := underscoreTest() test(` test('#556 - undefined template variables.', function() { @@ -373,7 +373,7 @@ func Test_underscore_utility_14(t *testing.T) { // interpolate evaluates code only once. func Test_underscore_utility_15(t *testing.T) { tt(t, func() { - test, _ := test_() + test := underscoreTest() test(` test('interpolate evaluates code only once.', 2, function() { @@ -392,7 +392,7 @@ func Test_underscore_utility_15(t *testing.T) { // #746 - _.template settings are not modified. func Test_underscore_utility_16(t *testing.T) { tt(t, func() { - test, _ := test_() + test := underscoreTest() test(` test('#746 - _.template settings are not modified.', 1, function() { @@ -407,7 +407,7 @@ func Test_underscore_utility_16(t *testing.T) { // #779 - delimeters are applied to unescaped text. func Test_underscore_utility_17(t *testing.T) { tt(t, func() { - test, _ := test_() + test := underscoreTest() test(` test('#779 - delimeters are applied to unescaped text.', 1, function() { diff --git a/value.go b/value.go index c55fc953..521e08a2 100644 --- a/value.go +++ b/value.go @@ -9,17 +9,17 @@ import ( "unicode/utf16" ) -type _valueKind int +type valueKind int const ( - valueUndefined _valueKind = iota + valueUndefined valueKind = iota valueNull valueNumber valueString valueBoolean valueObject - // These are invalid outside of the runtime + // These are invalid outside of the runtime. valueEmpty valueResult valueReference @@ -27,12 +27,12 @@ const ( // Value is the representation of a JavaScript value. type Value struct { - kind _valueKind + kind valueKind value interface{} } -func (value Value) safe() bool { - return value.kind < valueEmpty +func (v Value) safe() bool { + return v.kind < valueEmpty } var ( @@ -54,8 +54,8 @@ func ToValue(value interface{}) (Value, error) { return result, err } -func (value Value) isEmpty() bool { - return value.kind == valueEmpty +func (v Value) isEmpty() bool { + return v.kind == valueEmpty } // Undefined @@ -66,13 +66,13 @@ func UndefinedValue() Value { } // IsDefined will return false if the value is undefined, and true otherwise. -func (value Value) IsDefined() bool { - return value.kind != valueUndefined +func (v Value) IsDefined() bool { + return v.kind != valueUndefined } // IsUndefined will return true if the value is undefined, and false otherwise. -func (value Value) IsUndefined() bool { - return value.kind == valueUndefined +func (v Value) IsUndefined() bool { + return v.kind == valueUndefined } // NullValue will return a Value representing null. @@ -81,15 +81,15 @@ func NullValue() Value { } // IsNull will return true if the value is null, and false otherwise. -func (value Value) IsNull() bool { - return value.kind == valueNull +func (v Value) IsNull() bool { + return v.kind == valueNull } // --- -func (value Value) isCallable() bool { - v, ok := value.value.(*_object) - return ok && v.isCall() +func (v Value) isCallable() bool { + o, ok := v.value.(*object) + return ok && o.isCall() } // Call the value as a function with the given this value and argument list and @@ -102,20 +102,20 @@ func (value Value) isCallable() bool { // 1. There is an error during conversion of the argument list // 2. The value is not actually a function // 3. An (uncaught) exception is thrown -func (value Value) Call(this Value, argumentList ...interface{}) (Value, error) { +func (v Value) Call(this Value, argumentList ...interface{}) (Value, error) { result := Value{} err := catchPanic(func() { // FIXME - result = value.call(nil, this, argumentList...) + result = v.call(nil, this, argumentList...) }) - if !value.safe() { - value = Value{} + if !v.safe() { + v = Value{} } return result, err } -func (value Value) call(rt *_runtime, this Value, argumentList ...interface{}) Value { - if function, ok := value.value.(*_object); ok { +func (v Value) call(rt *runtime, this Value, argumentList ...interface{}) Value { + if function, ok := v.value.(*object); ok { return function.call(this, function.runtime.toValueArray(argumentList...), false, nativeFrame) } if rt == nil { @@ -124,16 +124,16 @@ func (value Value) call(rt *_runtime, this Value, argumentList ...interface{}) V panic(rt.panicTypeError()) } -func (value Value) constructSafe(rt *_runtime, this Value, argumentList ...interface{}) (Value, error) { +func (v Value) constructSafe(rt *runtime, this Value, argumentList ...interface{}) (Value, error) { result := Value{} err := catchPanic(func() { - result = value.construct(rt, this, argumentList...) + result = v.construct(rt, this, argumentList...) }) return result, err } -func (value Value) construct(rt *_runtime, this Value, argumentList ...interface{}) Value { - if fn, ok := value.value.(*_object); ok { +func (v Value) construct(rt *runtime, this Value, argumentList ...interface{}) Value { //nolint: unparam + if fn, ok := v.value.(*object); ok { return fn.construct(fn.runtime.toValueArray(argumentList...)) } if rt == nil { @@ -143,23 +143,23 @@ func (value Value) construct(rt *_runtime, this Value, argumentList ...interface } // IsPrimitive will return true if value is a primitive (any kind of primitive). -func (value Value) IsPrimitive() bool { - return !value.IsObject() +func (v Value) IsPrimitive() bool { + return !v.IsObject() } // IsBoolean will return true if value is a boolean (primitive). -func (value Value) IsBoolean() bool { - return value.kind == valueBoolean +func (v Value) IsBoolean() bool { + return v.kind == valueBoolean } // IsNumber will return true if value is a number (primitive). -func (value Value) IsNumber() bool { - return value.kind == valueNumber +func (v Value) IsNumber() bool { + return v.kind == valueNumber } // IsNaN will return true if value is NaN (or would convert to NaN). -func (value Value) IsNaN() bool { - switch value := value.value.(type) { +func (v Value) IsNaN() bool { + switch value := v.value.(type) { case float64: return math.IsNaN(value) case float32: @@ -170,25 +170,25 @@ func (value Value) IsNaN() bool { return false } - return math.IsNaN(value.float64()) + return math.IsNaN(v.float64()) } // IsString will return true if value is a string (primitive). -func (value Value) IsString() bool { - return value.kind == valueString +func (v Value) IsString() bool { + return v.kind == valueString } // IsObject will return true if value is an object. -func (value Value) IsObject() bool { - return value.kind == valueObject +func (v Value) IsObject() bool { + return v.kind == valueObject } // IsFunction will return true if value is a function. -func (value Value) IsFunction() bool { - if value.kind != valueObject { +func (v Value) IsFunction() bool { + if v.kind != valueObject { return false } - return value.value.(*_object).class == classFunction + return v.value.(*object).class == classFunctionName } // Class will return the class string of the value or the empty string if value is not an object. @@ -203,65 +203,65 @@ func (value Value) IsFunction() bool { // Boolean // Date // RegExp -func (value Value) Class() string { - if value.kind != valueObject { +func (v Value) Class() string { + if v.kind != valueObject { return "" } - return value.value.(*_object).class + return v.value.(*object).class } -func (value Value) isArray() bool { - if value.kind != valueObject { +func (v Value) isArray() bool { //nolint: unused + if v.kind != valueObject { return false } - return isArray(value.value.(*_object)) + return isArray(v.value.(*object)) } -func (value Value) isStringObject() bool { - if value.kind != valueObject { +func (v Value) isStringObject() bool { //nolint: unused + if v.kind != valueObject { return false } - return value.value.(*_object).class == classString + return v.value.(*object).class == classStringName } -func (value Value) isBooleanObject() bool { - if value.kind != valueObject { +func (v Value) isBooleanObject() bool { //nolint: unused + if v.kind != valueObject { return false } - return value.value.(*_object).class == classBoolean + return v.value.(*object).class == classBooleanName } -func (value Value) isNumberObject() bool { - if value.kind != valueObject { +func (v Value) isNumberObject() bool { //nolint: unused + if v.kind != valueObject { return false } - return value.value.(*_object).class == classNumber + return v.value.(*object).class == classNumberName } -func (value Value) isDate() bool { - if value.kind != valueObject { +func (v Value) isDate() bool { //nolint: unused + if v.kind != valueObject { return false } - return value.value.(*_object).class == classDate + return v.value.(*object).class == classDateName } -func (value Value) isRegExp() bool { - if value.kind != valueObject { +func (v Value) isRegExp() bool { + if v.kind != valueObject { return false } - return value.value.(*_object).class == classRegExp + return v.value.(*object).class == classRegExpName } -func (value Value) isError() bool { - if value.kind != valueObject { +func (v Value) isError() bool { //nolint: unused + if v.kind != valueObject { return false } - return value.value.(*_object).class == classError + return v.value.(*object).class == classErrorName } // --- -func toValue_reflectValuePanic(value interface{}, kind reflect.Kind) { +func reflectValuePanic(value interface{}, kind reflect.Kind) { // FIXME? switch kind { case reflect.Struct: @@ -308,15 +308,15 @@ func toValue(value interface{}) Value { case string: return Value{valueString, value} // A rune is actually an int32, which is handled above - case *_object: + case *object: return Value{valueObject, value} case *Object: return Value{valueObject, value.object} case Object: return Value{valueObject, value.object} - case _reference: // reference is an interface (already a pointer) + case referencer: // reference is an interface (already a pointer) return Value{valueReference, value} - case _result: + case result: return Value{valueResult, value} case nil: // TODO Ugh. @@ -335,7 +335,7 @@ func toValue(value interface{}) Value { } switch value.Kind() { case reflect.Bool: - return Value{valueBoolean, bool(value.Bool())} + return Value{valueBoolean, value.Bool()} case reflect.Int: return Value{valueNumber, int(value.Int())} case reflect.Int8: @@ -345,7 +345,7 @@ func toValue(value interface{}) Value { case reflect.Int32: return Value{valueNumber, int32(value.Int())} case reflect.Int64: - return Value{valueNumber, int64(value.Int())} + return Value{valueNumber, value.Int()} case reflect.Uint: return Value{valueNumber, uint(value.Uint())} case reflect.Uint8: @@ -355,15 +355,15 @@ func toValue(value interface{}) Value { case reflect.Uint32: return Value{valueNumber, uint32(value.Uint())} case reflect.Uint64: - return Value{valueNumber, uint64(value.Uint())} + return Value{valueNumber, value.Uint()} case reflect.Float32: return Value{valueNumber, float32(value.Float())} case reflect.Float64: - return Value{valueNumber, float64(value.Float())} + return Value{valueNumber, value.Float()} case reflect.String: - return Value{valueString, string(value.String())} + return Value{valueString, value.String()} default: - toValue_reflectValuePanic(value.Interface(), value.Kind()) + reflectValuePanic(value.Interface(), value.Kind()) } default: return toValue(reflect.ValueOf(value)) @@ -375,10 +375,10 @@ func toValue(value interface{}) Value { // String will return the value as a string. // // This method will make return the empty string if there is an error. -func (value Value) String() string { - result := "" - catchPanic(func() { - result = value.string() +func (v Value) String() string { + var result string + catchPanic(func() { //nolint: errcheck, gosec + result = v.string() }) return result } @@ -392,19 +392,19 @@ func (value Value) String() string { // ToValue("Nothing happens").ToBoolean() => true // // If there is an error during the conversion process (like an uncaught exception), then the result will be false and an error. -func (value Value) ToBoolean() (bool, error) { +func (v Value) ToBoolean() (bool, error) { result := false err := catchPanic(func() { - result = value.bool() + result = v.bool() }) return result, err } -func (value Value) numberValue() Value { - if value.kind == valueNumber { - return value +func (v Value) numberValue() Value { + if v.kind == valueNumber { + return v } - return Value{valueNumber, value.float64()} + return Value{valueNumber, v.float64()} } // ToFloat will convert the value to a number (float64). @@ -414,10 +414,10 @@ func (value Value) numberValue() Value { // ToValue("11").ToFloat() => 11. // // If there is an error during the conversion process (like an uncaught exception), then the result will be 0 and an error. -func (value Value) ToFloat() (float64, error) { +func (v Value) ToFloat() (float64, error) { result := float64(0) err := catchPanic(func() { - result = value.float64() + result = v.float64() }) return result, err } @@ -429,10 +429,10 @@ func (value Value) ToFloat() (float64, error) { // ToValue("11").ToInteger() => 11 // // If there is an error during the conversion process (like an uncaught exception), then the result will be 0 and an error. -func (value Value) ToInteger() (int64, error) { +func (v Value) ToInteger() (int64, error) { result := int64(0) err := catchPanic(func() { - result = value.number().int64 + result = v.number().int64 }) return result, err } @@ -446,16 +446,16 @@ func (value Value) ToInteger() (int64, error) { // ToValue('Nothing happens.').ToString() => "Nothing happens." // // If there is an error during the conversion process (like an uncaught exception), then the result will be the empty string ("") and an error. -func (value Value) ToString() (string, error) { +func (v Value) ToString() (string, error) { result := "" err := catchPanic(func() { - result = value.string() + result = v.string() }) return result, err } -func (value Value) _object() *_object { - if v, ok := value.value.(*_object); ok { +func (v Value) object() *object { + if v, ok := v.value.(*object); ok { return v } return nil @@ -464,66 +464,59 @@ func (value Value) _object() *_object { // Object will return the object of the value, or nil if value is not an object. // // This method will not do any implicit conversion. For example, calling this method on a string primitive value will not return a String object. -func (value Value) Object() *Object { - if object, ok := value.value.(*_object); ok { - return _newObject(object, value) +func (v Value) Object() *Object { + if obj, ok := v.value.(*object); ok { + return &Object{ + object: obj, + value: v, + } } return nil } -func (value Value) reference() _reference { - if value, ok := value.value.(_reference); ok { - return value - } - return nil +func (v Value) reference() referencer { + value, _ := v.value.(referencer) + return value } -func (value Value) resolve() Value { - if value, ok := value.value.(_reference); ok { +func (v Value) resolve() Value { + if value, ok := v.value.(referencer); ok { return value.getValue() } - return value + return v } var ( - __NaN__ float64 = math.NaN() - __PositiveInfinity__ float64 = math.Inf(+1) - __NegativeInfinity__ float64 = math.Inf(-1) - __PositiveZero__ float64 = 0 - __NegativeZero__ float64 = math.Float64frombits(0 | (1 << 63)) + nan float64 = math.NaN() + positiveInfinity float64 = math.Inf(+1) + negativeInfinity float64 = math.Inf(-1) + positiveZero float64 = 0 + negativeZero float64 = math.Float64frombits(0 | (1 << 63)) ) -func positiveZero() float64 { - return __PositiveZero__ -} - -func negativeZero() float64 { - return __NegativeZero__ -} - // NaNValue will return a value representing NaN. // // It is equivalent to: // // ToValue(math.NaN()) func NaNValue() Value { - return Value{valueNumber, __NaN__} + return Value{valueNumber, nan} } func positiveInfinityValue() Value { - return Value{valueNumber, __PositiveInfinity__} + return Value{valueNumber, positiveInfinity} } func negativeInfinityValue() Value { - return Value{valueNumber, __NegativeInfinity__} + return Value{valueNumber, negativeInfinity} } func positiveZeroValue() Value { - return Value{valueNumber, __PositiveZero__} + return Value{valueNumber, positiveZero} } func negativeZeroValue() Value { - return Value{valueNumber, __NegativeZero__} + return Value{valueNumber, negativeZero} } // TrueValue will return a value representing true. @@ -572,7 +565,7 @@ func sameValue(x Value, y Value) bool { case valueBoolean: return x.bool() == y.bool() case valueObject: - return x._object() == y._object() + return x.object() == y.object() default: panic(hereBeDragons()) } @@ -598,7 +591,7 @@ func strictEqualityComparison(x Value, y Value) bool { case valueBoolean: return x.bool() == y.bool() case valueObject: - return x._object() == y._object() + return x.object() == y.object() default: panic(hereBeDragons()) } @@ -620,52 +613,52 @@ func strictEqualityComparison(x Value, y Value) bool { // string -> string // Array -> []interface{} // Object -> map[string]interface{} -func (self Value) Export() (interface{}, error) { - return self.export(), nil +func (v Value) Export() (interface{}, error) { + return v.export(), nil } -func (self Value) export() interface{} { - switch self.kind { +func (v Value) export() interface{} { + switch v.kind { case valueUndefined: return nil case valueNull: return nil case valueNumber, valueBoolean: - return self.value + return v.value case valueString: - switch value := self.value.(type) { + switch value := v.value.(type) { case string: return value case []uint16: return string(utf16.Decode(value)) } case valueObject: - object := self._object() - switch value := object.value.(type) { - case *_goStructObject: + obj := v.object() + switch value := obj.value.(type) { + case *goStructObject: return value.value.Interface() - case *_goMapObject: + case *goMapObject: return value.value.Interface() - case *_goArrayObject: + case *goArrayObject: return value.value.Interface() - case *_goSliceObject: + case *goSliceObject: return value.value.Interface() } - if object.class == classArray { + if obj.class == classArrayName { result := make([]interface{}, 0) - lengthValue := object.get(propertyLength) + lengthValue := obj.get(propertyLength) length := lengthValue.value.(uint32) kind := reflect.Invalid keyKind := reflect.Invalid elemKind := reflect.Invalid state := 0 var t reflect.Type - for index := uint32(0); index < length; index += 1 { + for index := uint32(0); index < length; index++ { name := strconv.FormatInt(int64(index), 10) - if !object.hasProperty(name) { + if !obj.hasProperty(name) { continue } - value := object.get(name).export() + value := obj.get(name).export() t = reflect.TypeOf(value) @@ -704,29 +697,29 @@ func (self Value) export() interface{} { val.Index(i).Set(reflect.ValueOf(v)) } return val.Interface() - } else { - result := make(map[string]interface{}) - // TODO Should we export everything? Or just what is enumerable? - object.enumerate(false, func(name string) bool { - value := object.get(name) - if value.IsDefined() { - result[name] = value.export() - } - return true - }) - return result } + + result := make(map[string]interface{}) + // TODO Should we export everything? Or just what is enumerable? + obj.enumerate(false, func(name string) bool { + value := obj.get(name) + if value.IsDefined() { + result[name] = value.export() + } + return true + }) + return result } - if self.safe() { - return self + if v.safe() { + return v } return Value{} } -func (self Value) evaluateBreakContinue(labels []string) _resultKind { - result := self.value.(_result) +func (v Value) evaluateBreakContinue(labels []string) resultKind { + result := v.value.(result) if result.kind == resultBreak || result.kind == resultContinue { for _, label := range labels { if label == result.target { @@ -737,8 +730,8 @@ func (self Value) evaluateBreakContinue(labels []string) _resultKind { return resultReturn } -func (self Value) evaluateBreak(labels []string) _resultKind { - result := self.value.(_result) +func (v Value) evaluateBreak(labels []string) resultKind { + result := v.value.(result) if result.kind == resultBreak { for _, label := range labels { if label == result.target { @@ -751,12 +744,12 @@ func (self Value) evaluateBreak(labels []string) _resultKind { // 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(typ reflect.Type) (reflect.Value, error) { +func (v Value) toReflectValue(typ reflect.Type) (reflect.Value, error) { kind := typ.Kind() switch kind { case reflect.Float32, reflect.Float64, reflect.Interface: default: - switch value := value.value.(type) { + switch value := v.value.(type) { case float32: _, frac := math.Modf(float64(value)) if frac > 0 { @@ -772,101 +765,90 @@ func (value Value) toReflectValue(typ reflect.Type) (reflect.Value, error) { switch kind { case reflect.Bool: // Bool - return reflect.ValueOf(value.bool()).Convert(typ), nil + return reflect.ValueOf(v.bool()).Convert(typ), 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: %f (%v) to int", tmp, value) - } else { - return reflect.ValueOf(int(tmp)).Convert(typ), nil + tmp := toIntegerFloat(v) + if tmp < floatMinInt || tmp > floatMaxInt { + return reflect.Value{}, fmt.Errorf("RangeError: %f (%v) to int", tmp, v) } + return reflect.ValueOf(int(tmp)).Convert(typ), nil 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)).Convert(typ), nil + tmp := v.number().int64 + if tmp < int64MinInt8 || tmp > int64MaxInt8 { + return reflect.Value{}, fmt.Errorf("RangeError: %d (%v) to int8", tmp, v) } + return reflect.ValueOf(int8(tmp)).Convert(typ), nil 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)).Convert(typ), nil + tmp := v.number().int64 + if tmp < int64MinInt16 || tmp > int64MaxInt16 { + return reflect.Value{}, fmt.Errorf("RangeError: %d (%v) to int16", tmp, v) } + return reflect.ValueOf(int16(tmp)).Convert(typ), nil 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)).Convert(typ), nil + tmp := v.number().int64 + if tmp < int64MinInt32 || tmp > int64MaxInt32 { + return reflect.Value{}, fmt.Errorf("RangeError: %d (%v) to int32", tmp, v) } + return reflect.ValueOf(int32(tmp)).Convert(typ), nil 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: %f (%v) to int", tmp, value) - } else { - return reflect.ValueOf(int64(tmp)).Convert(typ), nil + tmp := toIntegerFloat(v) + if tmp < floatMinInt64 || tmp > floatMaxInt64 { + return reflect.Value{}, fmt.Errorf("RangeError: %f (%v) to int", tmp, v) } + return reflect.ValueOf(int64(tmp)).Convert(typ), nil 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: %f (%v) to uint", tmp, value) - } else { - return reflect.ValueOf(uint(tmp)).Convert(typ), nil + tmp := toIntegerFloat(v) + if tmp < 0 || tmp > floatMaxUint { + return reflect.Value{}, fmt.Errorf("RangeError: %f (%v) to uint", tmp, v) } + return reflect.ValueOf(uint(tmp)).Convert(typ), nil 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)).Convert(typ), nil + tmp := v.number().int64 + if tmp < 0 || tmp > int64MaxUint8 { + return reflect.Value{}, fmt.Errorf("RangeError: %d (%v) to uint8", tmp, v) } + return reflect.ValueOf(uint8(tmp)).Convert(typ), nil 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)).Convert(typ), nil + tmp := v.number().int64 + if tmp < 0 || tmp > int64MaxUint16 { + return reflect.Value{}, fmt.Errorf("RangeError: %d (%v) to uint16", tmp, v) } + return reflect.ValueOf(uint16(tmp)).Convert(typ), nil 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)).Convert(typ), nil + tmp := v.number().int64 + if tmp < 0 || tmp > int64MaxUint32 { + return reflect.Value{}, fmt.Errorf("RangeError: %d (%v) to uint32", tmp, v) } + return reflect.ValueOf(uint32(tmp)).Convert(typ), nil 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) - if tmp < 0 || tmp > float_maxUint64 { - return reflect.Value{}, fmt.Errorf("RangeError: %f (%v) to uint64", tmp, value) - } else { - return reflect.ValueOf(uint64(tmp)).Convert(typ), nil + tmp := toIntegerFloat(v) + if tmp < 0 || tmp > floatMaxUint64 { + return reflect.Value{}, fmt.Errorf("RangeError: %f (%v) to uint64", tmp, v) } + return reflect.ValueOf(uint64(tmp)).Convert(typ), nil case reflect.Float32: // Float32 - tmp := value.float64() + tmp := v.float64() tmp1 := tmp if 0 > tmp1 { tmp1 = -tmp1 } if tmp1 > 0 && (tmp1 < math.SmallestNonzeroFloat32 || tmp1 > math.MaxFloat32) { - return reflect.Value{}, fmt.Errorf("RangeError: %f (%v) to float32", tmp, value) - } else { - return reflect.ValueOf(float32(tmp)).Convert(typ), nil + return reflect.Value{}, fmt.Errorf("RangeError: %f (%v) to float32", tmp, v) } + return reflect.ValueOf(float32(tmp)).Convert(typ), nil case reflect.Float64: // Float64 - value := value.float64() - return reflect.ValueOf(float64(value)).Convert(typ), nil + value := v.float64() + return reflect.ValueOf(value).Convert(typ), nil case reflect.String: // String - return reflect.ValueOf(value.string()).Convert(typ), nil + return reflect.ValueOf(v.string()).Convert(typ), nil case reflect.Invalid: // Invalid case reflect.Complex64: // FIXME? Complex64 case reflect.Complex128: // FIXME? Complex128 @@ -875,20 +857,20 @@ func (value Value) toReflectValue(typ reflect.Type) (reflect.Value, error) { case reflect.Ptr: // FIXME? Ptr case reflect.UnsafePointer: // FIXME? UnsafePointer default: - switch value.kind { + switch v.kind { case valueObject: - object := value._object() - switch vl := object.value.(type) { - case *_goStructObject: // Struct + obj := v.object() + switch vl := obj.value.(type) { + case *goStructObject: // Struct return reflect.ValueOf(vl.value.Interface()), nil - case *_goMapObject: // Map + case *goMapObject: // Map return reflect.ValueOf(vl.value.Interface()), nil - case *_goArrayObject: // Array + case *goArrayObject: // Array return reflect.ValueOf(vl.value.Interface()), nil - case *_goSliceObject: // Slice + case *goSliceObject: // Slice return reflect.ValueOf(vl.value.Interface()), nil } - exported := reflect.ValueOf(value.export()) + exported := reflect.ValueOf(v.export()) if exported.Type().ConvertibleTo(typ) { return exported.Convert(typ), nil } @@ -896,12 +878,12 @@ func (value Value) toReflectValue(typ reflect.Type) (reflect.Value, error) { case valueEmpty, valueResult, valueReference: // These are invalid, and should panic default: - return reflect.ValueOf(value.value), nil + return reflect.ValueOf(v.value), nil } } // FIXME Should this end up as a TypeError? - panic(fmt.Errorf("invalid conversion of %v (%v) to reflect.Type: %v", value.kind, value, typ)) + panic(fmt.Errorf("invalid conversion of %v (%v) to reflect.Type: %v", v.kind, v, typ)) } func stringToReflectValue(value string, kind reflect.Kind) (reflect.Value, error) { @@ -941,7 +923,7 @@ func stringToReflectValue(value string, kind reflect.Kind) (reflect.Value, error if err != nil { return reflect.Value{}, err } - return reflect.ValueOf(int64(value)), nil + return reflect.ValueOf(value), nil case reflect.Uint: value, err := strconv.ParseUint(value, 0, 0) if err != nil { @@ -971,7 +953,7 @@ func stringToReflectValue(value string, kind reflect.Kind) (reflect.Value, error if err != nil { return reflect.Value{}, err } - return reflect.ValueOf(uint64(value)), nil + return reflect.ValueOf(value), nil case reflect.Float32: value, err := strconv.ParseFloat(value, 32) if err != nil { @@ -983,7 +965,7 @@ func stringToReflectValue(value string, kind reflect.Kind) (reflect.Value, error if err != nil { return reflect.Value{}, err } - return reflect.ValueOf(float64(value)), nil + return reflect.ValueOf(value), nil case reflect.String: return reflect.ValueOf(value), nil } @@ -992,16 +974,17 @@ func stringToReflectValue(value string, kind reflect.Kind) (reflect.Value, error panic(fmt.Errorf("invalid conversion of %q to reflect.Kind: %v", value, kind)) } -func (self Value) MarshalJSON() ([]byte, error) { - switch self.kind { +// MarshalJSON implements json.Marshaller. +func (v Value) MarshalJSON() ([]byte, error) { + switch v.kind { case valueUndefined, valueNull: return []byte("null"), nil case valueBoolean, valueNumber: - return json.Marshal(self.value) + return json.Marshal(v.value) case valueString: - return json.Marshal(self.string()) + return json.Marshal(v.string()) case valueObject: - return self.Object().MarshalJSON() + return v.Object().MarshalJSON() } - return nil, fmt.Errorf("invalid type %v", self.kind) + return nil, fmt.Errorf("invalid type %v", v.kind) } diff --git a/value_boolean.go b/value_boolean.go index b631507b..670ecab0 100644 --- a/value_boolean.go +++ b/value_boolean.go @@ -7,37 +7,34 @@ import ( "unicode/utf16" ) -func (value Value) bool() bool { - if value.kind == valueBoolean { - return value.value.(bool) +func (v Value) bool() bool { + if v.kind == valueBoolean { + return v.value.(bool) } - if value.IsUndefined() { + if v.IsUndefined() || v.IsNull() { return false } - if value.IsNull() { - return false - } - switch value := value.value.(type) { + switch value := v.value.(type) { case bool: return value case int, int8, int16, int32, int64: - return 0 != reflect.ValueOf(value).Int() + return reflect.ValueOf(value).Int() != 0 case uint, uint8, uint16, uint32, uint64: - return 0 != reflect.ValueOf(value).Uint() + return reflect.ValueOf(value).Uint() != 0 case float32: - return 0 != value + return value != 0 case float64: if math.IsNaN(value) || value == 0 { return false } return true case string: - return 0 != len(value) + return len(value) != 0 case []uint16: - return 0 != len(utf16.Decode(value)) + return len(utf16.Decode(value)) != 0 } - if value.IsObject() { + if v.IsObject() { return true } - panic(fmt.Errorf("toBoolean(%T)", value.value)) + panic(fmt.Sprintf("unexpected boolean type %T", v.value)) } diff --git a/value_number.go b/value_number.go index e2a169cf..6e8e690e 100644 --- a/value_number.go +++ b/value_number.go @@ -1,6 +1,7 @@ package otto import ( + "errors" "fmt" "math" "regexp" @@ -11,24 +12,25 @@ import ( var stringToNumberParseInteger = regexp.MustCompile(`^(?:0[xX])`) func parseNumber(value string) float64 { - value = strings.Trim(value, builtinString_trim_whitespace) + value = strings.Trim(value, builtinStringTrimWhitespace) if value == "" { return 0 } parseFloat := false - if strings.IndexRune(value, '.') != -1 { + switch { + case strings.IndexRune(value, '.') != -1: //nolint: gosimple parseFloat = true - } else if stringToNumberParseInteger.MatchString(value) { + case stringToNumberParseInteger.MatchString(value): parseFloat = false - } else { + default: parseFloat = true } if parseFloat { number, err := strconv.ParseFloat(value, 64) - if err != nil && err.(*strconv.NumError).Err != strconv.ErrRange { + if err != nil && !errors.Is(err, strconv.ErrRange) { return math.NaN() } return number @@ -41,14 +43,14 @@ func parseNumber(value string) float64 { return float64(number) } -func (value Value) float64() float64 { - switch value.kind { +func (v Value) float64() float64 { + switch v.kind { case valueUndefined: return math.NaN() case valueNull: return 0 } - switch value := value.value.(type) { + switch value := v.value.(type) { case bool: if value { return 1 @@ -78,67 +80,65 @@ func (value Value) float64() float64 { return value case string: return parseNumber(value) - case *_object: + case *object: return value.DefaultValue(defaultValueHintNumber).float64() } - panic(fmt.Errorf("toFloat(%T)", value.value)) + panic(fmt.Errorf("toFloat(%T)", v.value)) } const ( - float_2_32 float64 = 4294967296.0 - float_2_31 float64 = 2147483648.0 - float_2_16 float64 = 65536.0 - sqrt1_2 float64 = math.Sqrt2 / 2 + sqrt1_2 float64 = math.Sqrt2 / 2 ) const ( maxUint32 = math.MaxUint32 maxInt = int(^uint(0) >> 1) - // int64 - int64_maxInt8 int64 = math.MaxInt8 - int64_minInt8 int64 = math.MinInt8 - int64_maxInt16 int64 = math.MaxInt16 - int64_minInt16 int64 = math.MinInt16 - int64_maxInt32 int64 = math.MaxInt32 - int64_minInt32 int64 = math.MinInt32 - int64_maxUint8 int64 = math.MaxUint8 - int64_maxUint16 int64 = math.MaxUint16 - int64_maxUint32 int64 = math.MaxUint32 - - // float64 - float_maxInt float64 = float64(int(^uint(0) >> 1)) - float_minInt float64 = float64(int(-maxInt - 1)) - float_maxUint float64 = float64(uint(^uint(0))) - float_maxUint64 float64 = math.MaxUint64 - float_maxInt64 float64 = math.MaxInt64 - float_minInt64 float64 = math.MinInt64 + // int64. + int64MaxInt8 int64 = math.MaxInt8 + int64MinInt8 int64 = math.MinInt8 + int64MaxInt16 int64 = math.MaxInt16 + int64MinInt16 int64 = math.MinInt16 + int64MaxInt32 int64 = math.MaxInt32 + int64MinInt32 int64 = math.MinInt32 + int64MaxUint8 int64 = math.MaxUint8 + int64MaxUint16 int64 = math.MaxUint16 + int64MaxUint32 int64 = math.MaxUint32 + + // float64. + floatMaxInt float64 = float64(int(^uint(0) >> 1)) + floatMinInt float64 = float64(-maxInt - 1) + floatMaxUint float64 = float64(^uint(0)) + floatMaxUint64 float64 = math.MaxUint64 + floatMaxInt64 float64 = math.MaxInt64 + floatMinInt64 float64 = math.MinInt64 ) func toIntegerFloat(value Value) float64 { float := value.float64() - if math.IsInf(float, 0) { - } else if math.IsNaN(float) { - float = 0 - } else if float > 0 { - float = math.Floor(float) - } else { - float = math.Ceil(float) + switch { + case math.IsInf(float, 0): + return float + case math.IsNaN(float): + return 0 + case float > 0: + return math.Floor(float) + default: + return math.Ceil(float) } - return float } -type _numberKind int +type numberKind int const ( - 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 + 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 _number struct { - kind _numberKind + kind numberKind int64 int64 float64 float64 } @@ -146,56 +146,57 @@ type _number struct { // 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 (value Value) number() (number _number) { - switch value := value.value.(type) { +func (v Value) number() _number { + var num _number + switch value := v.value.(type) { case int8: - number.int64 = int64(value) - return + num.int64 = int64(value) + return num case int16: - number.int64 = int64(value) - return + num.int64 = int64(value) + return num case uint8: - number.int64 = int64(value) - return + num.int64 = int64(value) + return num case uint16: - number.int64 = int64(value) - return + num.int64 = int64(value) + return num case uint32: - number.int64 = int64(value) - return + num.int64 = int64(value) + return num case int: - number.int64 = int64(value) - return + num.int64 = int64(value) + return num case int64: - number.int64 = value - return + num.int64 = value + return num } - float := value.float64() + float := v.float64() if float == 0 { - return + return num } - number.kind = numberFloat - number.float64 = float + num.kind = numberFloat + num.float64 = float if math.IsNaN(float) { - number.kind = numberNaN - return + num.kind = numberNaN + return num } if math.IsInf(float, 0) { - number.kind = numberInfinity + num.kind = numberInfinity } - if float >= float_maxInt64 { - number.int64 = math.MaxInt64 - return + if float >= floatMaxInt64 { + num.int64 = math.MaxInt64 + return num } - if float <= float_minInt64 { - number.int64 = math.MinInt64 - return + if float <= floatMinInt64 { + num.int64 = math.MinInt64 + return num } var integer float64 @@ -206,13 +207,13 @@ func (value Value) number() (number _number) { } if float == integer { - number.kind = numberInteger + num.kind = numberInteger } - number.int64 = int64(float) - return + num.int64 = int64(float) + return num } -// ECMA 262: 9.5 +// ECMA 262: 9.5. func toInt32(value Value) int32 { switch value := value.value.(type) { case int8: @@ -275,47 +276,47 @@ func toUint16(value Value) uint16 { return uint16(int64(floatValue)) } -// toIntSign returns sign of a number converted to -1, 0 ,1 +// toIntSign returns sign of a number converted to -1, 0 ,1. func toIntSign(value Value) int { switch value := value.value.(type) { case int8: - if int8(value) > 0 { + if value > 0 { return 1 - } else if int8(value) < 0 { + } else if value < 0 { return -1 } return 0 case int16: - if int16(value) > 0 { + if value > 0 { return 1 - } else if int16(value) < 0 { + } else if value < 0 { return -1 } return 0 case int32: - if int32(value) > 0 { + if value > 0 { return 1 - } else if int32(value) < 0 { + } else if value < 0 { return -1 } return 0 case uint8: - if uint8(value) > 0 { + if value > 0 { return 1 } return 0 case uint16: - if uint16(value) > 0 { + if value > 0 { return 1 } return 0 case uint32: - if uint32(value) > 0 { + if value > 0 { return 1 } diff --git a/value_primitive.go b/value_primitive.go index e76147ca..23f8e81d 100644 --- a/value_primitive.go +++ b/value_primitive.go @@ -1,19 +1,20 @@ package otto func toNumberPrimitive(value Value) Value { - return _toPrimitive(value, defaultValueHintNumber) + return toPrimitive(value, defaultValueHintNumber) } -func toPrimitive(value Value) Value { - return _toPrimitive(value, defaultValueNoHint) +func toPrimitiveValue(value Value) Value { + return toPrimitive(value, defaultValueNoHint) } -func _toPrimitive(value Value, hint _defaultValueHint) Value { +func toPrimitive(value Value, hint defaultValueHint) Value { switch value.kind { case valueNull, valueUndefined, valueNumber, valueString, valueBoolean: return value case valueObject: - return value._object().DefaultValue(hint) + return value.object().DefaultValue(hint) + default: + panic(hereBeDragons(value.kind, value)) } - panic(hereBeDragons(value.kind, value)) } diff --git a/value_string.go b/value_string.go index 0fbfd6b2..2af5bc3a 100644 --- a/value_string.go +++ b/value_string.go @@ -31,12 +31,15 @@ func floatToString(value float64, bitsize int) string { func numberToStringRadix(value Value, radix int) string { float := value.float64() - if math.IsNaN(float) { + switch { + case math.IsNaN(float): return "NaN" - } else if math.IsInf(float, 1) { + case math.IsInf(float, 1): return "Infinity" - } else if math.IsInf(float, -1) { + case math.IsInf(float, -1): return "-Infinity" + case float == 0: + return "0" } // FIXME This is very broken // Need to do proper radix conversion for floats, ... @@ -44,22 +47,22 @@ func numberToStringRadix(value Value, radix int) string { return strconv.FormatInt(int64(float), radix) } -func (value Value) string() string { - if value.kind == valueString { - switch value := value.value.(type) { +func (v Value) string() string { + if v.kind == valueString { + switch value := v.value.(type) { case string: return value case []uint16: return string(utf16.Decode(value)) } } - if value.IsUndefined() { + if v.IsUndefined() { return "undefined" } - if value.IsNull() { + if v.IsNull() { return "null" } - switch value := value.value.(type) { + switch value := v.value.(type) { case bool: return strconv.FormatBool(value) case int: @@ -96,8 +99,8 @@ func (value Value) string() string { return string(utf16.Decode(value)) case string: return value - case *_object: + case *object: return value.DefaultValue(defaultValueHintString).string() } - panic(fmt.Errorf("%v.string( %T)", value.value, value.value)) + panic(fmt.Errorf("%v.string( %T)", v.value, v.value)) } diff --git a/value_test.go b/value_test.go index 8c877339..a94c01a0 100644 --- a/value_test.go +++ b/value_test.go @@ -23,11 +23,6 @@ func TestValue(t *testing.T) { func TestObject(t *testing.T) { tt(t, func() { is(emptyValue.isEmpty(), true) - //is(newObject().Value(), "[object]") - //is(newBooleanObject(false).Value(), "false") - //is(newFunctionObject(nil).Value(), "[function]") - //is(newNumberObject(1).Value(), "1") - //is(newStringObject("Hello, World.").Value(), "Hello, World.") }) } @@ -95,7 +90,7 @@ func TestToBoolean(t *testing.T) { is("xyzzy", true) is(1, true) is(0, false) - //is(toValue(newObject()), true) + is(UndefinedValue(), false) is(NullValue(), false) is([]uint16{}, false) @@ -115,7 +110,6 @@ func TestToFloat(t *testing.T) { is(1, 1) is(0, 0) is(NullValue(), 0) - //is(newObjectValue(), math.NaN()) } is(math.IsNaN(UndefinedValue().float64()), true) }) @@ -268,14 +262,14 @@ func TestExport(t *testing.T) { 3.1459, []interface{}{true, false, 0, 3.1459, "abc"}, map[string]interface{}{ - classBoolean: true, - classNumber: 3.1459, - classString: "abc", - classArray: []interface{}{false, 0, "", nil}, - classObject: map[string]interface{}{ - classBoolean: false, - classNumber: 0, - classString: "def", + classBooleanName: true, + classNumberName: 3.1459, + classStringName: "abc", + classArrayName: []interface{}{false, 0, "", nil}, + classObjectName: map[string]interface{}{ + classBooleanName: false, + classNumberName: 0, + classStringName: "def", }, }, }