Skip to content

Commit

Permalink
Destructuring assignments, rest and spread properties, default functi…
Browse files Browse the repository at this point in the history
…on parameters (#303)

Closes #280, #301, #302
  • Loading branch information
dop251 authored Jul 20, 2021
1 parent 241fc7c commit a7a3a13
Show file tree
Hide file tree
Showing 19 changed files with 2,780 additions and 518 deletions.
2 changes: 1 addition & 1 deletion array.go
Original file line number Diff line number Diff line change
Expand Up @@ -426,7 +426,7 @@ func (a *arrayObject) _defineIdxProperty(idx uint32, desc PropertyDescriptor, th
a.propValueCount++
}
} else {
a.val.self.(*sparseArrayObject).add(uint32(idx), prop)
a.val.self.(*sparseArrayObject).add(idx, prop)
}
}
return ok
Expand Down
164 changes: 121 additions & 43 deletions ast/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,15 @@ import (
"github.com/dop251/goja/unistring"
)

type PropertyKind string

const (
PropertyKindValue PropertyKind = "value"
PropertyKindGet PropertyKind = "get"
PropertyKindSet PropertyKind = "set"
PropertyKindMethod PropertyKind = "method"
)

// All nodes implement the Node interface.
type Node interface {
Idx0() file.Idx // The index of the first character belonging to the node
Expand All @@ -32,12 +41,34 @@ type (
_expressionNode()
}

BindingTarget interface {
Expression
_bindingTarget()
}

Binding struct {
Target BindingTarget
Initializer Expression
}

Pattern interface {
BindingTarget
_pattern()
}

ArrayLiteral struct {
LeftBracket file.Idx
RightBracket file.Idx
Value []Expression
}

ArrayPattern struct {
LeftBracket file.Idx
RightBracket file.Idx
Elements []Expression
Rest Expression
}

AssignExpression struct {
Operator token.Token
Left Expression
Expand Down Expand Up @@ -127,18 +158,40 @@ type (
Value []Property
}

ObjectPattern struct {
LeftBrace file.Idx
RightBrace file.Idx
Properties []Property
Rest Expression
}

ParameterList struct {
Opening file.Idx
List []*Identifier
List []*Binding
Rest Expression
Closing file.Idx
}

Property struct {
Property interface {
Expression
_property()
}

PropertyShort struct {
Name Identifier
Initializer Expression
}

PropertyKeyed struct {
Key Expression
Kind string
Kind PropertyKind
Value Expression
}

SpreadElement struct {
Expression
}

RegExpLiteral struct {
Idx file.Idx
Literal string
Expand Down Expand Up @@ -167,12 +220,6 @@ type (
Postfix bool
}

VariableExpression struct {
Name unistring.String
Idx file.Idx
Initializer Expression
}

MetaProperty struct {
Meta, Property *Identifier
Idx file.Idx
Expand Down Expand Up @@ -201,8 +248,13 @@ func (*SequenceExpression) _expressionNode() {}
func (*StringLiteral) _expressionNode() {}
func (*ThisExpression) _expressionNode() {}
func (*UnaryExpression) _expressionNode() {}
func (*VariableExpression) _expressionNode() {}
func (*MetaProperty) _expressionNode() {}
func (*ObjectPattern) _expressionNode() {}
func (*ArrayPattern) _expressionNode() {}
func (*Binding) _expressionNode() {}

func (*PropertyShort) _expressionNode() {}
func (*PropertyKeyed) _expressionNode() {}

// ========= //
// Statement //
Expand Down Expand Up @@ -323,13 +375,13 @@ type (

VariableStatement struct {
Var file.Idx
List []*VariableExpression
List []*Binding
}

LexicalDeclaration struct {
Idx file.Idx
Token token.Token
List []*VariableExpression
List []*Binding
}

WhileStatement struct {
Expand Down Expand Up @@ -382,7 +434,7 @@ func (*FunctionDeclaration) _statementNode() {}
type (
VariableDeclaration struct {
Var file.Idx
List []*VariableExpression
List []*Binding
}
)

Expand All @@ -397,7 +449,7 @@ type (

ForLoopInitializerVarDeclList struct {
Var file.Idx
List []*VariableExpression
List []*Binding
}

ForLoopInitializerLexicalDecl struct {
Expand All @@ -409,22 +461,13 @@ type (
}

ForIntoVar struct {
Binding *VariableExpression
}

ForBinding interface {
_forBinding()
}

BindingIdentifier struct {
Idx file.Idx
Name unistring.String
Binding *Binding
}

ForDeclaration struct {
Idx file.Idx
IsConst bool
Binding ForBinding
Target BindingTarget
}

ForIntoExpression struct {
Expand All @@ -440,7 +483,19 @@ func (*ForIntoVar) _forInto() {}
func (*ForDeclaration) _forInto() {}
func (*ForIntoExpression) _forInto() {}

func (*BindingIdentifier) _forBinding() {}
func (*ArrayPattern) _pattern() {}
func (*ArrayPattern) _bindingTarget() {}

func (*ObjectPattern) _pattern() {}
func (*ObjectPattern) _bindingTarget() {}

func (*BadExpression) _bindingTarget() {}

func (*PropertyShort) _property() {}
func (*PropertyKeyed) _property() {}
func (*SpreadElement) _property() {}

func (*Identifier) _bindingTarget() {}

// ==== //
// Node //
Expand All @@ -459,6 +514,8 @@ type Program struct {
// ==== //

func (self *ArrayLiteral) Idx0() file.Idx { return self.LeftBracket }
func (self *ArrayPattern) Idx0() file.Idx { return self.LeftBracket }
func (self *ObjectPattern) Idx0() file.Idx { return self.LeftBrace }
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() }
Expand All @@ -478,7 +535,6 @@ func (self *SequenceExpression) Idx0() file.Idx { return self.Sequence[0].Idx
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 *MetaProperty) Idx0() file.Idx { return self.Idx }

func (self *BadStatement) Idx0() file.Idx { return self.From }
Expand All @@ -505,14 +561,18 @@ func (self *WhileStatement) Idx0() file.Idx { return self.While }
func (self *WithStatement) Idx0() file.Idx { return self.With }
func (self *LexicalDeclaration) Idx0() file.Idx { return self.Idx }
func (self *FunctionDeclaration) Idx0() file.Idx { return self.Function.Idx0() }
func (self *Binding) Idx0() file.Idx { return self.Target.Idx0() }

func (self *ForLoopInitializerVarDeclList) Idx0() file.Idx { return self.List[0].Idx0() }
func (self *PropertyShort) Idx0() file.Idx { return self.Name.Idx }
func (self *PropertyKeyed) Idx0() file.Idx { return self.Key.Idx0() }

// ==== //
// Idx1 //
// ==== //

func (self *ArrayLiteral) Idx1() file.Idx { return self.RightBracket }
func (self *ArrayLiteral) Idx1() file.Idx { return self.RightBracket + 1 }
func (self *ArrayPattern) Idx1() file.Idx { return self.RightBracket + 1 }
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() }
Expand All @@ -526,23 +586,18 @@ func (self *Identifier) Idx1() file.Idx { return file.Idx(int(self.Id
func (self *NewExpression) Idx1() file.Idx { return self.RightParenthesis + 1 }
func (self *NullLiteral) Idx1() file.Idx { return file.Idx(int(self.Idx) + 4) } // "null"
func (self *NumberLiteral) Idx1() file.Idx { return file.Idx(int(self.Idx) + len(self.Literal)) }
func (self *ObjectLiteral) Idx1() file.Idx { return self.RightBrace }
func (self *ObjectLiteral) Idx1() file.Idx { return self.RightBrace + 1 }
func (self *ObjectPattern) Idx1() file.Idx { return self.RightBrace + 1 }
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 *SequenceExpression) Idx1() file.Idx { return self.Sequence[len(self.Sequence)-1].Idx1() }
func (self *StringLiteral) Idx1() file.Idx { return file.Idx(int(self.Idx) + len(self.Literal)) }
func (self *ThisExpression) Idx1() file.Idx { return self.Idx }
func (self *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()
}
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 *MetaProperty) Idx1() file.Idx {
return self.Property.Idx1()
}
Expand All @@ -565,16 +620,39 @@ func (self *IfStatement) Idx1() file.Idx {
}
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 *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 + 6 }
func (self *SwitchStatement) Idx1() file.Idx { return self.Body[len(self.Body)-1].Idx1() }
func (self *ThrowStatement) Idx1() file.Idx { return self.Argument.Idx1() }
func (self *TryStatement) Idx1() file.Idx {
if self.Finally != nil {
return self.Finally.Idx1()
}
if self.Catch != nil {
return self.Catch.Idx1()
}
return self.Body.Idx1()
}
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() }
func (self *LexicalDeclaration) Idx1() file.Idx { return self.List[len(self.List)-1].Idx1() }
func (self *FunctionDeclaration) Idx1() file.Idx { return self.Function.Idx1() }
func (self *Binding) Idx1() file.Idx {
if self.Initializer != nil {
return self.Initializer.Idx1()
}
return self.Target.Idx1()
}

func (self *ForLoopInitializerVarDeclList) Idx1() file.Idx { return self.List[len(self.List)-1].Idx1() }

func (self *PropertyShort) Idx1() file.Idx {
if self.Initializer != nil {
return self.Initializer.Idx1()
}
return self.Name.Idx1()
}

func (self *PropertyKeyed) Idx1() file.Idx { return self.Value.Idx1() }
1 change: 1 addition & 0 deletions builtin_array.go
Original file line number Diff line number Diff line change
Expand Up @@ -380,6 +380,7 @@ func (r *Runtime) arrayproto_splice(call FunctionCall) Value {
for k := int64(0); k < actualDeleteCount; k++ {
createDataPropertyOrThrow(a, intToValue(k), src.values[k+actualStart])
}
a.self.setOwnStr("length", intToValue(actualDeleteCount), true)
}
var values []Value
if itemCount < actualDeleteCount {
Expand Down
11 changes: 5 additions & 6 deletions builtin_function.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,9 @@ repeat:
case *funcObject:
return newStringValue(f.src)
case *nativeFuncObject:
return newStringValue(fmt.Sprintf("function %s() { [native code] }", f.nameProp.get(call.This).toString()))
return newStringValue(fmt.Sprintf("function %s() { [native code] }", nilSafe(f.getStr("name", nil)).toString()))
case *boundFuncObject:
return newStringValue(fmt.Sprintf("function %s() { [native code] }", f.nameProp.get(call.This).toString()))
return newStringValue(fmt.Sprintf("function %s() { [native code] }", nilSafe(f.getStr("name", nil)).toString()))
case *lazyObject:
obj.self = f.create(obj)
goto repeat
Expand All @@ -47,9 +47,9 @@ repeat:
case *funcObject:
name = c.src
case *nativeFuncObject:
name = nilSafe(c.nameProp.get(call.This)).toString().String()
name = nilSafe(f.getStr("name", nil)).toString().String()
case *boundFuncObject:
name = nilSafe(c.nameProp.get(call.This)).toString().String()
name = nilSafe(f.getStr("name", nil)).toString().String()
case *lazyObject:
f.target.self = c.create(obj)
goto repeat2
Expand Down Expand Up @@ -183,8 +183,7 @@ func (r *Runtime) functionproto_bind(call FunctionCall) Value {
func (r *Runtime) initFunction() {
o := r.global.FunctionPrototype.self.(*nativeFuncObject)
o.prototype = r.global.ObjectPrototype
o.nameProp.value = stringEmpty

o._putProp("name", stringEmpty, false, false, true)
o._putProp("apply", r.newNativeFunc(r.functionproto_apply, nil, "apply", nil, 2), true, false, true)
o._putProp("bind", r.newNativeFunc(r.functionproto_bind, nil, "bind", nil, 1), true, false, true)
o._putProp("call", r.newNativeFunc(r.functionproto_call, nil, "call", nil, 1), true, false, true)
Expand Down
Loading

0 comments on commit a7a3a13

Please sign in to comment.