summaryrefslogtreecommitdiffstats
path: root/vendor/github.com/d5
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/d5')
-rw-r--r--vendor/github.com/d5/tengo/v2/Makefile1
-rw-r--r--vendor/github.com/d5/tengo/v2/README.md35
-rw-r--r--vendor/github.com/d5/tengo/v2/bytecode.go12
-rw-r--r--vendor/github.com/d5/tengo/v2/compiler.go42
-rw-r--r--vendor/github.com/d5/tengo/v2/script.go13
-rw-r--r--vendor/github.com/d5/tengo/v2/stdlib/json/encode.go195
6 files changed, 264 insertions, 34 deletions
diff --git a/vendor/github.com/d5/tengo/v2/Makefile b/vendor/github.com/d5/tengo/v2/Makefile
index 793bc129..d461b661 100644
--- a/vendor/github.com/d5/tengo/v2/Makefile
+++ b/vendor/github.com/d5/tengo/v2/Makefile
@@ -6,6 +6,7 @@ lint:
test: generate lint
go test -race -cover ./...
+ go run ./cmd/tengo -resolve ./testdata/cli/test.tengo
fmt:
go fmt ./...
diff --git a/vendor/github.com/d5/tengo/v2/README.md b/vendor/github.com/d5/tengo/v2/README.md
index f170be24..bee19599 100644
--- a/vendor/github.com/d5/tengo/v2/README.md
+++ b/vendor/github.com/d5/tengo/v2/README.md
@@ -5,8 +5,8 @@
# The Tengo Language
[![GoDoc](https://godoc.org/github.com/d5/tengo?status.svg)](https://godoc.org/github.com/d5/tengo)
+![test](https://github.com/d5/tengo/workflows/test/badge.svg)
[![Go Report Card](https://goreportcard.com/badge/github.com/d5/tengo)](https://goreportcard.com/report/github.com/d5/tengo)
-[![CircleCI](https://circleci.com/gh/d5/tengo.svg?style=svg)](https://circleci.com/gh/d5/tengo)
**Tengo is a small, dynamic, fast, secure script language for Go.**
@@ -51,19 +51,21 @@ fmt.println(sum("", [1, 2, 3])) // "123"
## Benchmark
-| | fib(35) | fibt(35) | Type |
+| | fib(35) | fibt(35) | Language (Type) |
| :--- | ---: | ---: | :---: |
-| Go | `48ms` | `3ms` | Go (native) |
-| [**Tengo**](https://github.com/d5/tengo) | `2,349ms` | `5ms` | VM on Go |
-| Lua | `1,416ms` | `3ms` | Lua (native) |
-| [go-lua](https://github.com/Shopify/go-lua) | `4,402ms` | `5ms` | Lua VM on Go |
-| [GopherLua](https://github.com/yuin/gopher-lua) | `4,023ms` | `5ms` | Lua VM on Go |
-| Python | `2,588ms` | `26ms` | Python (native) |
-| [starlark-go](https://github.com/google/starlark-go) | `11,126ms` | `6ms` | Python-like Interpreter on Go |
-| [gpython](https://github.com/go-python/gpython) | `15,035ms` | `4ms` | Python Interpreter on Go |
-| [goja](https://github.com/dop251/goja) | `5,089ms` | `5ms` | JS VM on Go |
-| [otto](https://github.com/robertkrimen/otto) | `68,377ms` | `11ms` | JS Interpreter on Go |
-| [Anko](https://github.com/mattn/anko) | `92,579ms` | `18ms` | Interpreter on Go |
+| [**Tengo**](https://github.com/d5/tengo) | `2,931ms` | `4ms` | Tengo (VM) |
+| [go-lua](https://github.com/Shopify/go-lua) | `4,824ms` | `4ms` | Lua (VM) |
+| [GopherLua](https://github.com/yuin/gopher-lua) | `5,365ms` | `4ms` | Lua (VM) |
+| [goja](https://github.com/dop251/goja) | `5,533ms` | `5ms` | JavaScript (VM) |
+| [starlark-go](https://github.com/google/starlark-go) | `11,495ms` | `5ms` | Starlark (Interpreter) |
+| [Yaegi](https://github.com/containous/yaegi) | `15,645ms` | `12ms` | Yaegi (Interpreter) |
+| [gpython](https://github.com/go-python/gpython) | `16,322ms` | `5ms` | Python (Interpreter) |
+| [otto](https://github.com/robertkrimen/otto) | `73,093ms` | `10ms` | JavaScript (Interpreter) |
+| [Anko](https://github.com/mattn/anko) | `79,809ms` | `8ms` | Anko (Interpreter) |
+| - | - | - | - |
+| Go | `53ms` | `3ms` | Go (Native) |
+| Lua | `1,612ms` | `3ms` | Lua (Native) |
+| Python | `2,632ms` | `23ms` | Python 2 (Native) |
_* [fib(35)](https://github.com/d5/tengobench/blob/master/code/fib.tengo):
Fibonacci(35)_
@@ -136,3 +138,10 @@ each([a, b, c, d], func(x) {
- [Interoperability](https://github.com/d5/tengo/blob/master/docs/interoperability.md)
- [Tengo CLI](https://github.com/d5/tengo/blob/master/docs/tengo-cli.md)
- [Standard Library](https://github.com/d5/tengo/blob/master/docs/stdlib.md)
+- Syntax Highlighters: [VSCode](https://github.com/lissein/vscode-tengo), [Atom](https://github.com/d5/tengo-atom)
+- **Why the name Tengo?** It's from [1Q84](https://en.wikipedia.org/wiki/1Q84).
+
+##
+
+:hearts: Like writing Go code? Come work at Skool. [We're hiring!](https://jobs.lever.co/skool)
+
diff --git a/vendor/github.com/d5/tengo/v2/bytecode.go b/vendor/github.com/d5/tengo/v2/bytecode.go
index cfd0d0b5..f3049cee 100644
--- a/vendor/github.com/d5/tengo/v2/bytecode.go
+++ b/vendor/github.com/d5/tengo/v2/bytecode.go
@@ -97,6 +97,7 @@ func (b *Bytecode) RemoveDuplicates() {
var deduped []Object
indexMap := make(map[int]int) // mapping from old constant index to new index
+ fns := make(map[*CompiledFunction]int)
ints := make(map[int64]int)
strings := make(map[string]int)
floats := make(map[float64]int)
@@ -106,9 +107,14 @@ func (b *Bytecode) RemoveDuplicates() {
for curIdx, c := range b.Constants {
switch c := c.(type) {
case *CompiledFunction:
- // add to deduped list
- indexMap[curIdx] = len(deduped)
- deduped = append(deduped, c)
+ if newIdx, ok := fns[c]; ok {
+ indexMap[curIdx] = newIdx
+ } else {
+ newIdx = len(deduped)
+ fns[c] = newIdx
+ indexMap[curIdx] = newIdx
+ deduped = append(deduped, c)
+ }
case *ImmutableMap:
modName := inferModuleName(c)
newIdx, ok := immutableMaps[modName]
diff --git a/vendor/github.com/d5/tengo/v2/compiler.go b/vendor/github.com/d5/tengo/v2/compiler.go
index eb686ed6..cb1c8f30 100644
--- a/vendor/github.com/d5/tengo/v2/compiler.go
+++ b/vendor/github.com/d5/tengo/v2/compiler.go
@@ -44,6 +44,7 @@ type Compiler struct {
file *parser.SourceFile
parent *Compiler
modulePath string
+ importDir string
constants []Object
symbolTable *SymbolTable
scopes []compilationScope
@@ -520,7 +521,7 @@ func (c *Compiler) Compile(node parser.Node) error {
switch v := v.(type) {
case []byte: // module written in Tengo
compiled, err := c.compileModule(node,
- node.ModuleName, node.ModuleName, v)
+ node.ModuleName, v, false)
if err != nil {
return err
}
@@ -537,24 +538,20 @@ func (c *Compiler) Compile(node parser.Node) error {
moduleName += ".tengo"
}
- modulePath, err := filepath.Abs(moduleName)
+ modulePath, err := filepath.Abs(
+ filepath.Join(c.importDir, moduleName))
if err != nil {
return c.errorf(node, "module file path error: %s",
err.Error())
}
- if err := c.checkCyclicImports(node, modulePath); err != nil {
- return err
- }
-
- moduleSrc, err := ioutil.ReadFile(moduleName)
+ moduleSrc, err := ioutil.ReadFile(modulePath)
if err != nil {
return c.errorf(node, "module file read error: %s",
err.Error())
}
- compiled, err := c.compileModule(node,
- moduleName, modulePath, moduleSrc)
+ compiled, err := c.compileModule(node, modulePath, moduleSrc, true)
if err != nil {
return err
}
@@ -634,6 +631,11 @@ func (c *Compiler) EnableFileImport(enable bool) {
c.allowFileImport = enable
}
+// SetImportDir sets the initial import directory path for file imports.
+func (c *Compiler) SetImportDir(dir string) {
+ c.importDir = dir
+}
+
func (c *Compiler) compileAssign(
node parser.Node,
lhs, rhs []parser.Expr,
@@ -847,8 +849,8 @@ func (c *Compiler) compileForInStmt(stmt *parser.ForInStmt) error {
// ... body ...
// }
//
- // ":it" is a local variable but will be conflict with other user variables
- // because character ":" is not allowed.
+ // ":it" is a local variable but it will not conflict with other user variables
+ // because character ":" is not allowed in the variable names.
// init
// :it = iterator(iterable)
@@ -893,6 +895,7 @@ func (c *Compiler) compileForInStmt(stmt *parser.ForInStmt) error {
if keySymbol.Scope == ScopeGlobal {
c.emit(stmt, parser.OpSetGlobal, keySymbol.Index)
} else {
+ keySymbol.LocalAssigned = true
c.emit(stmt, parser.OpDefineLocal, keySymbol.Index)
}
}
@@ -909,6 +912,7 @@ func (c *Compiler) compileForInStmt(stmt *parser.ForInStmt) error {
if valueSymbol.Scope == ScopeGlobal {
c.emit(stmt, parser.OpSetGlobal, valueSymbol.Index)
} else {
+ valueSymbol.LocalAssigned = true
c.emit(stmt, parser.OpDefineLocal, valueSymbol.Index)
}
}
@@ -955,8 +959,9 @@ func (c *Compiler) checkCyclicImports(
func (c *Compiler) compileModule(
node parser.Node,
- moduleName, modulePath string,
+ modulePath string,
src []byte,
+ isFile bool,
) (*CompiledFunction, error) {
if err := c.checkCyclicImports(node, modulePath); err != nil {
return nil, err
@@ -967,7 +972,7 @@ func (c *Compiler) compileModule(
return compiledModule, nil
}
- modFile := c.file.Set().AddFile(moduleName, -1, len(src))
+ modFile := c.file.Set().AddFile(modulePath, -1, len(src))
p := parser.NewParser(modFile, src, nil)
file, err := p.ParseFile()
if err != nil {
@@ -984,7 +989,7 @@ func (c *Compiler) compileModule(
symbolTable = symbolTable.Fork(false)
// compile module
- moduleCompiler := c.fork(modFile, modulePath, symbolTable)
+ moduleCompiler := c.fork(modFile, modulePath, symbolTable, isFile)
if err := moduleCompiler.Compile(file); err != nil {
return nil, err
}
@@ -1082,10 +1087,16 @@ func (c *Compiler) fork(
file *parser.SourceFile,
modulePath string,
symbolTable *SymbolTable,
+ isFile bool,
) *Compiler {
child := NewCompiler(file, symbolTable, nil, c.modules, c.trace)
child.modulePath = modulePath // module file path
child.parent = c // parent to set to current compiler
+ child.allowFileImport = c.allowFileImport
+ child.importDir = c.importDir
+ if isFile && c.importDir != "" {
+ child.importDir = filepath.Dir(modulePath)
+ }
return child
}
@@ -1192,6 +1203,7 @@ func (c *Compiler) optimizeFunc(node parser.Node) {
var lastOp parser.Opcode
var appendReturn bool
endPos := len(c.scopes[c.scopeIndex].Instructions)
+ newEndPost := len(newInsts)
iterateInstructions(newInsts,
func(pos int, opcode parser.Opcode, operands []int) bool {
switch opcode {
@@ -1204,6 +1216,8 @@ func (c *Compiler) optimizeFunc(node parser.Node) {
} else if endPos == operands[0] {
// there's a jump instruction that jumps to the end of
// function compiler should append "return".
+ copy(newInsts[pos:],
+ MakeInstruction(opcode, newEndPost))
appendReturn = true
} else {
panic(fmt.Errorf("invalid jump position: %d", newDst))
diff --git a/vendor/github.com/d5/tengo/v2/script.go b/vendor/github.com/d5/tengo/v2/script.go
index 906771d9..4f9608c1 100644
--- a/vendor/github.com/d5/tengo/v2/script.go
+++ b/vendor/github.com/d5/tengo/v2/script.go
@@ -3,6 +3,7 @@ package tengo
import (
"context"
"fmt"
+ "path/filepath"
"sync"
"github.com/d5/tengo/v2/parser"
@@ -16,6 +17,7 @@ type Script struct {
maxAllocs int64
maxConstObjects int
enableFileImport bool
+ importDir string
}
// NewScript creates a Script instance with an input script.
@@ -56,6 +58,16 @@ func (s *Script) SetImports(modules *ModuleMap) {
s.modules = modules
}
+// SetImportDir sets the initial import directory for script files.
+func (s *Script) SetImportDir(dir string) error {
+ dir, err := filepath.Abs(dir)
+ if err != nil {
+ return err
+ }
+ s.importDir = dir
+ return nil
+}
+
// SetMaxAllocs sets the maximum number of objects allocations during the run
// time. Compiled script will return ErrObjectAllocLimit error if it
// exceeds this limit.
@@ -93,6 +105,7 @@ func (s *Script) Compile() (*Compiled, error) {
c := NewCompiler(srcFile, symbolTable, nil, s.modules, nil)
c.EnableFileImport(s.enableFileImport)
+ c.SetImportDir(s.importDir)
if err := c.Compile(file); err != nil {
return nil, err
}
diff --git a/vendor/github.com/d5/tengo/v2/stdlib/json/encode.go b/vendor/github.com/d5/tengo/v2/stdlib/json/encode.go
index ab7ca6ff..10805b01 100644
--- a/vendor/github.com/d5/tengo/v2/stdlib/json/encode.go
+++ b/vendor/github.com/d5/tengo/v2/stdlib/json/encode.go
@@ -1,20 +1,129 @@
// A modified version of Go's JSON implementation.
-// Copyright 2010 The Go Authors. All rights reserved.
+// Copyright 2010, 2020 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package json
import (
+ "bytes"
"encoding/base64"
"errors"
"math"
"strconv"
+ "unicode/utf8"
"github.com/d5/tengo/v2"
)
+// safeSet holds the value true if the ASCII character with the given array
+// position can be represented inside a JSON string without any further
+// escaping.
+//
+// All values are true except for the ASCII control characters (0-31), the
+// double quote ("), and the backslash character ("\").
+var safeSet = [utf8.RuneSelf]bool{
+ ' ': true,
+ '!': true,
+ '"': false,
+ '#': true,
+ '$': true,
+ '%': true,
+ '&': true,
+ '\'': true,
+ '(': true,
+ ')': true,
+ '*': true,
+ '+': true,
+ ',': true,
+ '-': true,
+ '.': true,
+ '/': true,
+ '0': true,
+ '1': true,
+ '2': true,
+ '3': true,
+ '4': true,
+ '5': true,
+ '6': true,
+ '7': true,
+ '8': true,
+ '9': true,
+ ':': true,
+ ';': true,
+ '<': true,
+ '=': true,
+ '>': true,
+ '?': true,
+ '@': true,
+ 'A': true,
+ 'B': true,
+ 'C': true,
+ 'D': true,
+ 'E': true,
+ 'F': true,
+ 'G': true,
+ 'H': true,
+ 'I': true,
+ 'J': true,
+ 'K': true,
+ 'L': true,
+ 'M': true,
+ 'N': true,
+ 'O': true,
+ 'P': true,
+ 'Q': true,
+ 'R': true,
+ 'S': true,
+ 'T': true,
+ 'U': true,
+ 'V': true,
+ 'W': true,
+ 'X': true,
+ 'Y': true,
+ 'Z': true,
+ '[': true,
+ '\\': false,
+ ']': true,
+ '^': true,
+ '_': true,
+ '`': true,
+ 'a': true,
+ 'b': true,
+ 'c': true,
+ 'd': true,
+ 'e': true,
+ 'f': true,
+ 'g': true,
+ 'h': true,
+ 'i': true,
+ 'j': true,
+ 'k': true,
+ 'l': true,
+ 'm': true,
+ 'n': true,
+ 'o': true,
+ 'p': true,
+ 'q': true,
+ 'r': true,
+ 's': true,
+ 't': true,
+ 'u': true,
+ 'v': true,
+ 'w': true,
+ 'x': true,
+ 'y': true,
+ 'z': true,
+ '{': true,
+ '|': true,
+ '}': true,
+ '~': true,
+ '\u007f': true,
+}
+
+var hex = "0123456789abcdef"
+
// Encode returns the JSON encoding of the object.
func Encode(o tengo.Object) ([]byte, error) {
var b []byte
@@ -53,7 +162,7 @@ func Encode(o tengo.Object) ([]byte, error) {
len1 := len(o.Value) - 1
idx := 0
for key, value := range o.Value {
- b = strconv.AppendQuote(b, key)
+ b = encodeString(b, key)
b = append(b, ':')
eb, err := Encode(value)
if err != nil {
@@ -71,7 +180,7 @@ func Encode(o tengo.Object) ([]byte, error) {
len1 := len(o.Value) - 1
idx := 0
for key, value := range o.Value {
- b = strconv.AppendQuote(b, key)
+ b = encodeString(b, key)
b = append(b, ':')
eb, err := Encode(value)
if err != nil {
@@ -130,7 +239,9 @@ func Encode(o tengo.Object) ([]byte, error) {
case *tengo.Int:
b = strconv.AppendInt(b, o.Value, 10)
case *tengo.String:
- b = strconv.AppendQuote(b, o.Value)
+ // string encoding bug is fixed with newly introduced function
+ // encodeString(). See: https://github.com/d5/tengo/issues/268
+ b = encodeString(b, o.Value)
case *tengo.Time:
y, err := o.Value.MarshalJSON()
if err != nil {
@@ -144,3 +255,79 @@ func Encode(o tengo.Object) ([]byte, error) {
}
return b, nil
}
+
+// encodeString encodes given string as JSON string according to
+// https://www.json.org/img/string.png
+// Implementation is inspired by https://github.com/json-iterator/go
+// See encodeStringSlowPath() for more information.
+func encodeString(b []byte, val string) []byte {
+ valLen := len(val)
+ buf := bytes.NewBuffer(b)
+ buf.WriteByte('"')
+
+ // write string, the fast path, without utf8 and escape support
+ i := 0
+ for ; i < valLen; i++ {
+ c := val[i]
+ if c > 31 && c != '"' && c != '\\' {
+ buf.WriteByte(c)
+ } else {
+ break
+ }
+ }
+ if i == valLen {
+ buf.WriteByte('"')
+ return buf.Bytes()
+ }
+ encodeStringSlowPath(buf, i, val, valLen)
+ buf.WriteByte('"')
+ return buf.Bytes()
+}
+
+// encodeStringSlowPath is ported from Go 1.14.2 encoding/json package.
+// U+2028 U+2029 JSONP security holes can be fixed with addition call to
+// json.html_escape() thus it is removed from the implementation below.
+// Note: Invalid runes are not checked as they are checked in original
+// implementation.
+func encodeStringSlowPath(buf *bytes.Buffer, i int, val string, valLen int) {
+ start := i
+ for i < valLen {
+ if b := val[i]; b < utf8.RuneSelf {
+ if safeSet[b] {
+ i++
+ continue
+ }
+ if start < i {
+ buf.WriteString(val[start:i])
+ }
+ buf.WriteByte('\\')
+ switch b {
+ case '\\', '"':
+ buf.WriteByte(b)
+ case '\n':
+ buf.WriteByte('n')
+ case '\r':
+ buf.WriteByte('r')
+ case '\t':
+ buf.WriteByte('t')
+ default:
+ // This encodes bytes < 0x20 except for \t, \n and \r.
+ // If escapeHTML is set, it also escapes <, >, and &
+ // because they can lead to security holes when
+ // user-controlled strings are rendered into JSON
+ // and served to some browsers.
+ buf.WriteString(`u00`)
+ buf.WriteByte(hex[b>>4])
+ buf.WriteByte(hex[b&0xF])
+ }
+ i++
+ start = i
+ continue
+ }
+ i++
+ continue
+ }
+ if start < valLen {
+ buf.WriteString(val[start:])
+ }
+}