|
@@ -33,6 +33,12 @@ type compiledCallExpr struct {
|
|
baseCompiledExpr
|
|
baseCompiledExpr
|
|
args []compiledExpr
|
|
args []compiledExpr
|
|
callee compiledExpr
|
|
callee compiledExpr
|
|
|
|
+
|
|
|
|
+ isVariadic bool
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+type compiledNewExpr struct {
|
|
|
|
+ compiledCallExpr
|
|
}
|
|
}
|
|
|
|
|
|
type compiledObjectLiteral struct {
|
|
type compiledObjectLiteral struct {
|
|
@@ -124,12 +130,6 @@ type compiledThisExpr struct {
|
|
baseCompiledExpr
|
|
baseCompiledExpr
|
|
}
|
|
}
|
|
|
|
|
|
-type compiledNewExpr struct {
|
|
|
|
- baseCompiledExpr
|
|
|
|
- callee compiledExpr
|
|
|
|
- args []compiledExpr
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
type compiledNewTarget struct {
|
|
type compiledNewTarget struct {
|
|
baseCompiledExpr
|
|
baseCompiledExpr
|
|
}
|
|
}
|
|
@@ -176,6 +176,11 @@ type defaultDeleteExpr struct {
|
|
expr compiledExpr
|
|
expr compiledExpr
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+type compiledSpreadCallArgument struct {
|
|
|
|
+ baseCompiledExpr
|
|
|
|
+ expr compiledExpr
|
|
|
|
+}
|
|
|
|
+
|
|
func (e *defaultDeleteExpr) emitGetter(putOnStack bool) {
|
|
func (e *defaultDeleteExpr) emitGetter(putOnStack bool) {
|
|
e.expr.emitGetter(false)
|
|
e.expr.emitGetter(false)
|
|
if putOnStack {
|
|
if putOnStack {
|
|
@@ -935,18 +940,20 @@ func (e *compiledFunctionLiteral) emitGetter(putOnStack bool) {
|
|
funcs := e.c.extractFunctions(body)
|
|
funcs := e.c.extractFunctions(body)
|
|
s := e.c.scope
|
|
s := e.c.scope
|
|
var calleeBinding *binding
|
|
var calleeBinding *binding
|
|
- if e.isExpr && e.expr.Name != nil {
|
|
|
|
- if b, created := s.bindNameLexical(e.expr.Name.Name, false, 0); created {
|
|
|
|
- b.isConst = true
|
|
|
|
- calleeBinding = b
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
preambleLen := 4 // enter, boxThis, createArgs, set
|
|
preambleLen := 4 // enter, boxThis, createArgs, set
|
|
e.c.p.code = make([]instruction, preambleLen, 8)
|
|
e.c.p.code = make([]instruction, preambleLen, 8)
|
|
|
|
|
|
- if calleeBinding != nil {
|
|
|
|
- e.c.emit(loadCallee)
|
|
|
|
- calleeBinding.emitInit()
|
|
|
|
|
|
+ if hasPatterns || hasInits {
|
|
|
|
+ if e.isExpr && e.expr.Name != nil {
|
|
|
|
+ if b, created := s.bindNameLexical(e.expr.Name.Name, false, 0); created {
|
|
|
|
+ b.isConst = true
|
|
|
|
+ calleeBinding = b
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ if calleeBinding != nil {
|
|
|
|
+ e.c.emit(loadCallee)
|
|
|
|
+ calleeBinding.emitInit()
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
emitArgsRestMark := -1
|
|
emitArgsRestMark := -1
|
|
@@ -1031,6 +1038,16 @@ func (e *compiledFunctionLiteral) emitGetter(putOnStack bool) {
|
|
e.c.compileDeclList(e.expr.DeclarationList, true)
|
|
e.c.compileDeclList(e.expr.DeclarationList, true)
|
|
e.c.createFunctionBindings(funcs)
|
|
e.c.createFunctionBindings(funcs)
|
|
e.c.compileLexicalDeclarations(body, true)
|
|
e.c.compileLexicalDeclarations(body, true)
|
|
|
|
+ if e.isExpr && e.expr.Name != nil {
|
|
|
|
+ if b, created := s.bindNameLexical(e.expr.Name.Name, false, 0); created {
|
|
|
|
+ b.isConst = true
|
|
|
|
+ calleeBinding = b
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ if calleeBinding != nil {
|
|
|
|
+ e.c.emit(loadCallee)
|
|
|
|
+ calleeBinding.emitInit()
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
e.c.compileFunctions(funcs)
|
|
e.c.compileFunctions(funcs)
|
|
@@ -1194,25 +1211,45 @@ func (e *compiledThisExpr) emitGetter(putOnStack bool) {
|
|
}
|
|
}
|
|
|
|
|
|
func (e *compiledNewExpr) emitGetter(putOnStack bool) {
|
|
func (e *compiledNewExpr) emitGetter(putOnStack bool) {
|
|
|
|
+ if e.isVariadic {
|
|
|
|
+ e.c.emit(startVariadic)
|
|
|
|
+ }
|
|
e.callee.emitGetter(true)
|
|
e.callee.emitGetter(true)
|
|
for _, expr := range e.args {
|
|
for _, expr := range e.args {
|
|
expr.emitGetter(true)
|
|
expr.emitGetter(true)
|
|
}
|
|
}
|
|
e.addSrcMap()
|
|
e.addSrcMap()
|
|
- e.c.emit(_new(len(e.args)))
|
|
|
|
|
|
+ if e.isVariadic {
|
|
|
|
+ e.c.emit(newVariadic, endVariadic)
|
|
|
|
+ } else {
|
|
|
|
+ e.c.emit(_new(len(e.args)))
|
|
|
|
+ }
|
|
if !putOnStack {
|
|
if !putOnStack {
|
|
e.c.emit(pop)
|
|
e.c.emit(pop)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
-func (c *compiler) compileNewExpression(v *ast.NewExpression) compiledExpr {
|
|
|
|
- args := make([]compiledExpr, len(v.ArgumentList))
|
|
|
|
- for i, expr := range v.ArgumentList {
|
|
|
|
- args[i] = c.compileExpression(expr)
|
|
|
|
|
|
+func (c *compiler) compileCallArgs(list []ast.Expression) (args []compiledExpr, isVariadic bool) {
|
|
|
|
+ args = make([]compiledExpr, len(list))
|
|
|
|
+ for i, argExpr := range list {
|
|
|
|
+ if spread, ok := argExpr.(*ast.SpreadElement); ok {
|
|
|
|
+ args[i] = c.compileSpreadCallArgument(spread)
|
|
|
|
+ isVariadic = true
|
|
|
|
+ } else {
|
|
|
|
+ args[i] = c.compileExpression(argExpr)
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
+ return
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (c *compiler) compileNewExpression(v *ast.NewExpression) compiledExpr {
|
|
|
|
+ args, isVariadic := c.compileCallArgs(v.ArgumentList)
|
|
r := &compiledNewExpr{
|
|
r := &compiledNewExpr{
|
|
- callee: c.compileExpression(v.Callee),
|
|
|
|
- args: args,
|
|
|
|
|
|
+ compiledCallExpr: compiledCallExpr{
|
|
|
|
+ callee: c.compileExpression(v.Callee),
|
|
|
|
+ args: args,
|
|
|
|
+ isVariadic: isVariadic,
|
|
|
|
+ },
|
|
}
|
|
}
|
|
r.init(c, v.Idx0())
|
|
r.init(c, v.Idx0())
|
|
return r
|
|
return r
|
|
@@ -1765,6 +1802,9 @@ func (c *compiler) compileRegexpLiteral(v *ast.RegExpLiteral) compiledExpr {
|
|
|
|
|
|
func (e *compiledCallExpr) emitGetter(putOnStack bool) {
|
|
func (e *compiledCallExpr) emitGetter(putOnStack bool) {
|
|
var calleeName unistring.String
|
|
var calleeName unistring.String
|
|
|
|
+ if e.isVariadic {
|
|
|
|
+ e.c.emit(startVariadic)
|
|
|
|
+ }
|
|
switch callee := e.callee.(type) {
|
|
switch callee := e.callee.(type) {
|
|
case *compiledDotExpr:
|
|
case *compiledDotExpr:
|
|
callee.left.emitGetter(true)
|
|
callee.left.emitGetter(true)
|
|
@@ -1805,14 +1845,28 @@ func (e *compiledCallExpr) emitGetter(putOnStack bool) {
|
|
}
|
|
}
|
|
|
|
|
|
if e.c.scope.strict {
|
|
if e.c.scope.strict {
|
|
- e.c.emit(callEvalStrict(len(e.args)))
|
|
|
|
|
|
+ if e.isVariadic {
|
|
|
|
+ e.c.emit(callEvalVariadicStrict)
|
|
|
|
+ } else {
|
|
|
|
+ e.c.emit(callEvalStrict(len(e.args)))
|
|
|
|
+ }
|
|
} else {
|
|
} else {
|
|
- e.c.emit(callEval(len(e.args)))
|
|
|
|
|
|
+ if e.isVariadic {
|
|
|
|
+ e.c.emit(callEvalVariadic)
|
|
|
|
+ } else {
|
|
|
|
+ e.c.emit(callEval(len(e.args)))
|
|
|
|
+ }
|
|
}
|
|
}
|
|
} else {
|
|
} else {
|
|
- e.c.emit(call(len(e.args)))
|
|
|
|
|
|
+ if e.isVariadic {
|
|
|
|
+ e.c.emit(callVariadic)
|
|
|
|
+ } else {
|
|
|
|
+ e.c.emit(call(len(e.args)))
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ if e.isVariadic {
|
|
|
|
+ e.c.emit(endVariadic)
|
|
}
|
|
}
|
|
-
|
|
|
|
if !putOnStack {
|
|
if !putOnStack {
|
|
e.c.emit(pop)
|
|
e.c.emit(pop)
|
|
}
|
|
}
|
|
@@ -1826,16 +1880,31 @@ func (e *compiledCallExpr) deleteExpr() compiledExpr {
|
|
return r
|
|
return r
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+func (c *compiler) compileSpreadCallArgument(spread *ast.SpreadElement) compiledExpr {
|
|
|
|
+ r := &compiledSpreadCallArgument{
|
|
|
|
+ expr: c.compileExpression(spread.Expression),
|
|
|
|
+ }
|
|
|
|
+ r.init(c, spread.Idx0())
|
|
|
|
+ return r
|
|
|
|
+}
|
|
|
|
+
|
|
func (c *compiler) compileCallExpression(v *ast.CallExpression) compiledExpr {
|
|
func (c *compiler) compileCallExpression(v *ast.CallExpression) compiledExpr {
|
|
|
|
|
|
args := make([]compiledExpr, len(v.ArgumentList))
|
|
args := make([]compiledExpr, len(v.ArgumentList))
|
|
|
|
+ isVariadic := false
|
|
for i, argExpr := range v.ArgumentList {
|
|
for i, argExpr := range v.ArgumentList {
|
|
- args[i] = c.compileExpression(argExpr)
|
|
|
|
|
|
+ if spread, ok := argExpr.(*ast.SpreadElement); ok {
|
|
|
|
+ args[i] = c.compileSpreadCallArgument(spread)
|
|
|
|
+ isVariadic = true
|
|
|
|
+ } else {
|
|
|
|
+ args[i] = c.compileExpression(argExpr)
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
r := &compiledCallExpr{
|
|
r := &compiledCallExpr{
|
|
- args: args,
|
|
|
|
- callee: c.compileExpression(v.Callee),
|
|
|
|
|
|
+ args: args,
|
|
|
|
+ callee: c.compileExpression(v.Callee),
|
|
|
|
+ isVariadic: isVariadic,
|
|
}
|
|
}
|
|
r.init(c, v.LeftParenthesis)
|
|
r.init(c, v.LeftParenthesis)
|
|
return r
|
|
return r
|
|
@@ -2178,3 +2247,10 @@ func (c *compiler) compileNamedEmitterExpr(namedEmitter func(unistring.String),
|
|
r.init(c, idx)
|
|
r.init(c, idx)
|
|
return r
|
|
return r
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+func (e *compiledSpreadCallArgument) emitGetter(putOnStack bool) {
|
|
|
|
+ e.expr.emitGetter(putOnStack)
|
|
|
|
+ if putOnStack {
|
|
|
|
+ e.c.emit(pushSpread)
|
|
|
|
+ }
|
|
|
|
+}
|