1
0
mirror of https://github.com/robertkrimen/otto synced 2025-10-05 19:19:10 +08:00

fix: linting errors (#441)

Disable new linters which aren't compatible with this code module.

Upgrade github actions to fix caching issues.

Run go mod to bring in new styling.

Remove space on nolint declarations.

Apply all changes to whitespace as required to pass goimports linter.

Only trigger checks on pull_request which works for pulls from other
forks, where as push only works from the same repo.
This commit is contained in:
Steven Hartland 2022-10-08 00:12:19 +01:00 committed by GitHub
parent 201ab5b34f
commit 7009038f79
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 284 additions and 265 deletions

View File

@ -1,24 +1,59 @@
name: Go test and lint
on:
push:
branches: '**'
pull_request:
branches: 'master'
jobs:
go-test-lint:
runs-on: ubuntu-latest
strategy:
matrix:
go: [1.18]
golangcli: [v1.50.0]
os: [ubuntu-latest]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v2
- name: Set up Go
uses: actions/setup-go@v2
uses: actions/setup-go@v3
with:
go-version: 1.17
go-version: ${{ matrix.go }}
- name: Test
run: go test -v ./...
- name: Checkout
uses: actions/checkout@v3
- name: golangci-lint
uses: golangci/golangci-lint-action@v2
- name: Go Cache Paths
id: go-cache-paths
run: |
echo "::set-output name=go-build::$(go env GOCACHE)"
echo "::set-output name=go-mod::$(go env GOMODCACHE)"
- name: Go Build Cache
uses: actions/cache@v3
with:
version: latest
path: ${{ steps.go-cache-paths.outputs.go-build }}
key: ${{ runner.os }}-go-build-${{ hashFiles('**/go.sum') }}
- name: Go Mod Cache
uses: actions/cache@v3
with:
path: ${{ steps.go-cache-paths.outputs.go-mod }}
key: ${{ runner.os }}-go-mod-${{ hashFiles('**/go.sum') }}
- name: Validate go mod
run: |
go mod tidy
git --no-pager diff && [[ 0 -eq $(git status --porcelain | wc -l) ]]
- name: Go Lint
uses: golangci/golangci-lint-action@v3
with:
version: ${{ matrix.golangci }}
args: "--out-${NO_FUTURE}format colored-line-number"
skip-pkg-cache: true
skip-build-cache: true
- name: Go Build
run: go build ./...
- name: Go Test
run: go test -race -v ./...

View File

@ -71,6 +71,15 @@ linters:
- gocyclo
- misspell
- cyclop
- varnamelen
- nonamedreturns
- maintidx
- ireturn
- exhaustruct
- nosnakecase
- deadcode
- dupword
- gci
issues:
exclude:

View File

@ -1,11 +1,10 @@
/*
Package ast declares types representing a JavaScript AST.
Warning
# 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

View File

@ -4,7 +4,7 @@ import (
"fmt"
)
func ExampleSynopsis() { // nolint: govet
func ExampleSynopsis() { //nolint: govet
vm := New()
vm.Run(`
abc = 2 + 2;
@ -69,7 +69,7 @@ func ExampleSynopsis() { // nolint: govet
// 4
}
func ExampleConsole() { // nolint: govet
func ExampleConsole() { //nolint: govet
vm := New()
console := map[string]interface{}{
"log": func(call FunctionCall) Value {

View File

@ -100,8 +100,7 @@ type Error struct {
// Error returns a description of the error
//
// TypeError: 'def' is not a function
//
// TypeError: 'def' is not a function
func (err Error) Error() string {
return err.format()
}
@ -109,10 +108,9 @@ func (err Error) Error() string {
// String returns a description of the error and a trace of where the
// error occurred.
//
// TypeError: 'def' is not a function
// at xyz (<anonymous>:3:9)
// at <anonymous>:7:1/
//
// TypeError: 'def' is not a function
// at xyz (<anonymous>:3:9)
// at <anonymous>:7:1/
func (err Error) String() string {
return err.formatWithStack()
}

View File

@ -1,5 +1,4 @@
// Package file encapsulates the file abstractions used by the ast & parser.
//
package file
import (
@ -36,7 +35,6 @@ 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() {

2
go.mod
View File

@ -5,7 +5,7 @@ go 1.14
require (
github.com/chzyer/logex v1.1.10 // indirect
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1 // indirect
github.com/stretchr/testify v1.7.0 // indirect
github.com/stretchr/testify v1.7.0
gopkg.in/readline.v1 v1.0.0-20160726135117-62c6fe619375
gopkg.in/sourcemap.v1 v1.0.5
)

1
go.sum
View File

@ -9,6 +9,7 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/readline.v1 v1.0.0-20160726135117-62c6fe619375 h1:hPki/oSSWOLiI9Gc9jyIoj33O3j29fUc9PlLha2yDj0=
gopkg.in/readline.v1 v1.0.0-20160726135117-62c6fe619375/go.mod h1:lNEQeAhU009zbRxng+XOj5ITVgY24WcbNnQopyfKoYQ=

272
otto.go
View File

@ -3,81 +3,81 @@ Package otto is a JavaScript parser and interpreter written natively in Go.
http://godoc.org/github.com/robertkrimen/otto
import (
"github.com/robertkrimen/otto"
)
import (
"github.com/robertkrimen/otto"
)
Run something in the VM
vm := otto.New()
vm.Run(`
abc = 2 + 2;
console.log("The value of abc is " + abc); // 4
`)
vm := otto.New()
vm.Run(`
abc = 2 + 2;
console.log("The value of abc is " + abc); // 4
`)
Get a value out of the VM
value, err := vm.Get("abc")
value, _ := value.ToInteger()
}
value, err := vm.Get("abc")
value, _ := value.ToInteger()
}
Set a number
vm.Set("def", 11)
vm.Run(`
console.log("The value of def is " + def);
// The value of def is 11
`)
vm.Set("def", 11)
vm.Run(`
console.log("The value of def is " + def);
// The value of def is 11
`)
Set a string
vm.Set("xyzzy", "Nothing happens.")
vm.Run(`
console.log(xyzzy.length); // 16
`)
vm.Set("xyzzy", "Nothing happens.")
vm.Run(`
console.log(xyzzy.length); // 16
`)
Get the value of an expression
value, _ = vm.Run("xyzzy.length")
{
// value is an int64 with a value of 16
value, _ := value.ToInteger()
}
value, _ = vm.Run("xyzzy.length")
{
// value is an int64 with a value of 16
value, _ := value.ToInteger()
}
An error happens
value, err = vm.Run("abcdefghijlmnopqrstuvwxyz.length")
if err != nil {
// err = ReferenceError: abcdefghijlmnopqrstuvwxyz is not defined
// If there is an error, then value.IsUndefined() is true
...
}
value, err = vm.Run("abcdefghijlmnopqrstuvwxyz.length")
if err != nil {
// err = ReferenceError: abcdefghijlmnopqrstuvwxyz is not defined
// If there is an error, then value.IsUndefined() is true
...
}
Set a Go function
vm.Set("sayHello", func(call otto.FunctionCall) otto.Value {
fmt.Printf("Hello, %s.\n", call.Argument(0).String())
return otto.Value{}
})
vm.Set("sayHello", func(call otto.FunctionCall) otto.Value {
fmt.Printf("Hello, %s.\n", call.Argument(0).String())
return otto.Value{}
})
Set a Go function that returns something useful
vm.Set("twoPlus", func(call otto.FunctionCall) otto.Value {
right, _ := call.Argument(0).ToInteger()
result, _ := vm.ToValue(2 + right)
return result
})
vm.Set("twoPlus", func(call otto.FunctionCall) otto.Value {
right, _ := call.Argument(0).ToInteger()
result, _ := vm.ToValue(2 + right)
return result
})
Use the functions in JavaScript
result, _ = vm.Run(`
sayHello("Xyzzy"); // Hello, Xyzzy.
sayHello(); // Hello, undefined
result, _ = vm.Run(`
sayHello("Xyzzy"); // Hello, Xyzzy.
sayHello(); // Hello, undefined
result = twoPlus(2.0); // 4
`)
result = twoPlus(2.0); // 4
`)
Parser
# Parser
A separate parser is available in the parser package if you're just interested in building an AST.
@ -85,23 +85,23 @@ http://godoc.org/github.com/robertkrimen/otto/parser
Parse and return an AST
filename := "" // A filename is optional
src := `
// Sample xyzzy example
(function(){
if (3.14159 > 0) {
console.log("Hello, World.");
return;
}
filename := "" // A filename is optional
src := `
// Sample xyzzy example
(function(){
if (3.14159 > 0) {
console.log("Hello, World.");
return;
}
var xyzzy = NaN;
console.log("Nothing happens.");
return xyzzy;
})();
`
var xyzzy = NaN;
console.log("Nothing happens.");
return xyzzy;
})();
`
// Parse some JavaScript, yielding a *ast.Program and/or an ErrorList
program, err := parser.ParseFile(nil, filename, src, 0)
// Parse some JavaScript, yielding a *ast.Program and/or an ErrorList
program, err := parser.ParseFile(nil, filename, src, 0)
otto
@ -126,24 +126,24 @@ Optionally include the JavaScript utility-belt library, underscore, with this im
For more information: http://github.com/robertkrimen/otto/tree/master/underscore
Caveat Emptor
# Caveat Emptor
The following are some limitations with otto:
* "use strict" will parse, but does nothing.
* The regular expression engine (re2/regexp) is not fully compatible with the ECMA5 specification.
* Otto targets ES5. ES6 features (eg: Typed Arrays) are not supported.
- "use strict" will parse, but does nothing.
- The regular expression engine (re2/regexp) is not fully compatible with the ECMA5 specification.
- Otto targets ES5. ES6 features (eg: Typed Arrays) are not supported.
Regular Expression Incompatibility
# Regular Expression Incompatibility
Go translates JavaScript-style regular expressions into something that is "regexp" compatible via `parser.TransformRegExp`.
Unfortunately, RegExp requires backtracking for some patterns, and backtracking is not supported by the standard Go engine: https://code.google.com/p/re2/wiki/Syntax
Therefore, the following syntax is incompatible:
(?=) // Lookahead (positive), currently a parsing error
(?!) // Lookahead (backhead), currently a parsing error
\1 // Backreference (\1, \2, \3, ...), currently a parsing error
(?=) // Lookahead (positive), currently a parsing error
(?!) // Lookahead (backhead), currently a parsing error
\1 // Backreference (\1, \2, \3, ...), currently a parsing error
A brief discussion of these limitations: "Regexp (?!re)" https://groups.google.com/forum/?fromgroups=#%21topic/golang-nuts/7qgSDWPIh_E
@ -152,57 +152,57 @@ More information about re2: https://code.google.com/p/re2/
In addition to the above, re2 (Go) has a different definition for \s: [\t\n\f\r ].
The JavaScript definition, on the other hand, also includes \v, Unicode "Separator, Space", etc.
Halting Problem
# Halting Problem
If you want to stop long running executions (like third-party code), you can use the interrupt channel to do this:
package main
package main
import (
"errors"
"fmt"
"os"
"time"
import (
"errors"
"fmt"
"os"
"time"
"github.com/robertkrimen/otto"
)
"github.com/robertkrimen/otto"
)
var halt = errors.New("Stahp")
var halt = errors.New("Stahp")
func main() {
runUnsafe(`var abc = [];`)
runUnsafe(`
while (true) {
// Loop forever
}`)
}
func main() {
runUnsafe(`var abc = [];`)
runUnsafe(`
while (true) {
// Loop forever
}`)
}
func runUnsafe(unsafe string) {
start := time.Now()
defer func() {
duration := time.Since(start)
if caught := recover(); caught != nil {
if caught == halt {
fmt.Fprintf(os.Stderr, "Some code took to long! Stopping after: %v\n", duration)
return
}
panic(caught) // Something else happened, repanic!
}
fmt.Fprintf(os.Stderr, "Ran code successfully: %v\n", duration)
}()
func runUnsafe(unsafe string) {
start := time.Now()
defer func() {
duration := time.Since(start)
if caught := recover(); caught != nil {
if caught == halt {
fmt.Fprintf(os.Stderr, "Some code took to long! Stopping after: %v\n", duration)
return
}
panic(caught) // Something else happened, repanic!
}
fmt.Fprintf(os.Stderr, "Ran code successfully: %v\n", duration)
}()
vm := otto.New()
vm.Interrupt = make(chan func(), 1) // The buffer prevents blocking
vm := otto.New()
vm.Interrupt = make(chan func(), 1) // The buffer prevents blocking
go func() {
time.Sleep(2 * time.Second) // Stop after two seconds
vm.Interrupt <- func() {
panic(halt)
}
}()
go func() {
time.Sleep(2 * time.Second) // Stop after two seconds
vm.Interrupt <- func() {
panic(halt)
}
}()
vm.Run(unsafe) // Here be dragons (risky code)
}
vm.Run(unsafe) // Here be dragons (risky code)
}
Where is setTimeout/setInterval?
@ -220,7 +220,6 @@ Here is some more discussion of the issue:
* http://en.wikipedia.org/wiki/Reentrancy_%28computing%29
* http://aaroncrane.co.uk/2009/02/perl_safe_signals/
*/
package otto
@ -273,7 +272,6 @@ func (otto *Otto) clone() *Otto {
// 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 Run(src interface{}) (*Otto, Value, error) {
otto := New()
value, err := otto.Run(src) // This already does safety checking
@ -290,7 +288,6 @@ 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)
if !value.safe() {
@ -524,16 +521,15 @@ func (self Otto) ContextSkip(limit int, skipNative bool) (ctx Context) {
// Call will invoke the function constructor rather than performing a function call.
// In this case, the this argument has no effect.
//
// // value is a String object
// value, _ := vm.Call("Object", nil, "Hello, World.")
// // value is a String object
// value, _ := vm.Call("Object", nil, "Hello, World.")
//
// // Likewise...
// value, _ := vm.Call("new Object", nil, "Hello, World.")
//
// // 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")
// // Likewise...
// value, _ := vm.Call("new Object", nil, "Hello, World.")
//
// // 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) {
thisValue := Value{}
@ -602,16 +598,16 @@ func (self Otto) Call(source string, this interface{}, argumentList ...interface
//
// For example, accessing an existing object:
//
// object, _ := vm.Object(`Number`)
// object, _ := vm.Object(`Number`)
//
// Or, creating a new object:
//
// object, _ := vm.Object(`({ xyzzy: "Nothing happens." })`)
// object, _ := vm.Object(`({ xyzzy: "Nothing happens." })`)
//
// Or, creating and assigning an object:
//
// object, _ := vm.Object(`xyzzy = {}`)
// object.Set("volume", 11)
// object, _ := vm.Object(`xyzzy = {}`)
// object.Set("volume", 11)
//
// If there is an error (like the source does not result in an object), then
// nil and an error is returned.
@ -667,15 +663,14 @@ func _newObject(object *_object, value Value) *Object {
//
// It is essentially equivalent to:
//
// var method, _ := object.Get(name)
// method.Call(object, argumentList...)
// var method, _ := object.Get(name)
// method.Call(object, argumentList...)
//
// An undefined value and an error will result if:
//
// 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
//
// 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) {
// TODO: Insert an example using JavaScript below...
// e.g., Object("JSON").Call("stringify", ...)
@ -756,15 +751,14 @@ func (self Object) KeysByParent() [][]string {
//
// The return value will (generally) be one of:
//
// Object
// Function
// Array
// String
// Number
// Boolean
// Date
// RegExp
//
// Object
// Function
// Array
// String
// Number
// Boolean
// Date
// RegExp
func (self Object) Class() string {
return self.object.class
}

View File

@ -134,7 +134,7 @@ func rangeStartLength(source []Value, size int64) (start, length int64) {
}
func hereBeDragons(arguments ...interface{}) string {
pc, _, _, _ := runtime_.Caller(1) // nolint: dogsled
pc, _, _, _ := runtime_.Caller(1) //nolint: dogsled
name := runtime_.FuncForPC(pc).Name()
message := fmt.Sprintf("Here be dragons -- %s", name)
if len(arguments) > 0 {

View File

@ -119,7 +119,7 @@ func (self *_parser) errorUnexpectedToken(tkn token.Token) error {
}
// ErrorList is a list of *Errors.
type ErrorList []*Error // nolint: errname
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) {

View File

@ -1,35 +1,34 @@
/*
Package parser implements a parser for JavaScript.
import (
"github.com/robertkrimen/otto/parser"
)
import (
"github.com/robertkrimen/otto/parser"
)
Parse and return an AST
filename := "" // A filename is optional
src := `
// Sample xyzzy example
(function(){
if (3.14159 > 0) {
console.log("Hello, World.");
return;
}
filename := "" // A filename is optional
src := `
// Sample xyzzy example
(function(){
if (3.14159 > 0) {
console.log("Hello, World.");
return;
}
var xyzzy = NaN;
console.log("Nothing happens.");
return xyzzy;
})();
`
var xyzzy = NaN;
console.log("Nothing happens.");
return xyzzy;
})();
`
// Parse some JavaScript, yielding a *ast.Program and/or an ErrorList
program, err := parser.ParseFile(nil, filename, src, 0)
// Parse some JavaScript, yielding a *ast.Program and/or an ErrorList
program, err := parser.ParseFile(nil, filename, src, 0)
Warning
# Warning
The parser and AST interfaces are still works-in-progress (particularly where
node types are concerned) and may change in the future.
*/
package parser
@ -131,7 +130,7 @@ func ReadSource(filename string, src interface{}) ([]byte, error) {
func ReadSourceMap(filename string, src interface{}) (*sourcemap.Consumer, error) {
if src == nil {
return nil, nil
return nil, nil //nolint: nilnil
}
switch src := src.(type) {
@ -203,9 +202,8 @@ func ParseFileWithSourceMap(fileSet *file.FileSet, filename string, javascriptSo
//
// src may be a string, a byte slice, a bytes.Buffer, or an io.Reader, but it MUST always be in UTF-8.
//
// // Parse some JavaScript, yielding a *ast.Program and/or an ErrorList
// program, err := parser.ParseFile(nil, "", `if (abc > 1) {}`, 0)
//
// // Parse some JavaScript, yielding a *ast.Program and/or an ErrorList
// program, err := parser.ParseFile(nil, "", `if (abc > 1) {}`, 0)
func ParseFile(fileSet *file.FileSet, filename string, src interface{}, mode Mode) (*ast.Program, error) {
return ParseFileWithSourceMap(fileSet, filename, src, nil, mode)
}
@ -214,7 +212,6 @@ func ParseFile(fileSet *file.FileSet, filename string, src interface{}, mode Mod
// corresponding ast.FunctionLiteral node.
//
// The parameter list, if any, should be a comma-separated list of identifiers.
//
func ParseFunction(parameterList, body string) (*ast.FunctionLiteral, error) {
src := "(function(" + parameterList + ") {\n" + body + "\n})"

View File

@ -761,11 +761,11 @@ func TestPassthrough(t *testing.T) {
})
}
type TestDynamicFunctionReturningInterface_MyStruct1 struct{} // nolint: errname
type TestDynamicFunctionReturningInterface_MyStruct1 struct{} //nolint: errname
func (m *TestDynamicFunctionReturningInterface_MyStruct1) Error() string { return "MyStruct1" }
type TestDynamicFunctionReturningInterface_MyStruct2 struct{} // nolint: errname
type TestDynamicFunctionReturningInterface_MyStruct2 struct{} //nolint: errname
func (m *TestDynamicFunctionReturningInterface_MyStruct2) Error() string { return "MyStruct2" }

View File

@ -41,7 +41,7 @@ func (a *autoCompleter) Do(line []rune, pos int) ([][]rune, int) {
if o := r.Object(); o != nil {
for _, v := range o.KeysByParent() {
l = append(l, v...) // nolint: makezero
l = append(l, v...) //nolint: makezero
}
}
}

View File

@ -12,7 +12,6 @@ var scriptVersion = "2014-04-13/1"
// Script is a handle for some (reusable) JavaScript.
// Passing a Script value to a run method will evaluate the JavaScript.
//
type Script struct {
version string
program *_nodeProgram
@ -23,9 +22,8 @@ type Script struct {
// Compile will parse the given source and return a Script value or nil and
// an error if there was a problem during compilation.
//
// script, err := vm.Compile("", `var abc; if (!abc) abc = 0; abc += 2; abc;`)
// vm.Run(script)
//
// 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)
}
@ -58,7 +56,6 @@ func (self *Script) String() string {
// 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) {
var bfr bytes.Buffer
encoder := gob.NewEncoder(&bfr)

View File

@ -42,7 +42,7 @@ var target = map[string]string{
// http://api.cdnjs.com/libraries
func fetch(name, location string) error {
response, err := http.Get(location) // nolint: noctx
response, err := http.Get(location) //nolint: noctx
if err != nil {
return err
}
@ -110,7 +110,7 @@ func main() {
err := func() error {
if flag.Arg(0) == "fetch" {
response, err := http.Get("http://api.cdnjs.com/libraries") // nolint: noctx
response, err := http.Get("http://api.cdnjs.com/libraries") //nolint: noctx
if err != nil {
return err
}

View File

@ -13,7 +13,6 @@ type Token int
// token string (e.g., for the token PLUS, the String() is
// "+"). For all other tokens the string corresponds to the token
// name (e.g. for the token IDENTIFIER, the string is "IDENTIFIER").
//
func (tkn Token) String() string {
if 0 == tkn {
return "UNKNOWN"
@ -86,25 +85,24 @@ type _keyword struct {
//
// 7.6.1.2 Future Reserved Words:
//
// const
// class
// enum
// export
// extends
// import
// super
// const
// class
// enum
// export
// extends
// import
// super
//
// 7.6.1.2 Future Reserved Words (strict):
//
// implements
// interface
// let
// package
// private
// protected
// public
// static
//
// implements
// interface
// let
// package
// private
// protected
// public
// static
func IsKeyword(literal string) (Token, bool) {
if keyword, exists := keywordTable[literal]; exists {
if keyword.futureKeyword {

View File

@ -74,7 +74,7 @@ const (
COLON // :
QUESTION_MARK // ?
firstKeyword // nolint: deadcode
firstKeyword //nolint: deadcode
IF
IN
DO
@ -108,7 +108,7 @@ const (
DEBUGGER
INSTANCEOF
lastKeyword // nolint: deadcode
lastKeyword //nolint: deadcode
)
var token2string = [...]string{

View File

@ -21,7 +21,6 @@ To prevent this behavior, you can do the following:
func init() {
underscore.Disable()
}
*/
package underscore

View File

@ -94,14 +94,13 @@ func (value Value) isCallable() bool {
// Call the value as a function with the given this value and argument list and
// return the result of invocation. It is essentially equivalent to:
//
// value.apply(thisValue, argumentList)
// value.apply(thisValue, argumentList)
//
// An undefined value and an error will result if:
//
// 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
//
// 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) {
result := Value{}
err := catchPanic(func() {
@ -195,15 +194,14 @@ func (value Value) IsFunction() bool {
//
// The return value will (generally) be one of:
//
// Object
// Function
// Array
// String
// Number
// Boolean
// Date
// RegExp
//
// Object
// Function
// Array
// String
// Number
// Boolean
// Date
// RegExp
func (value Value) Class() string {
if value.kind != valueObject {
return ""
@ -386,11 +384,11 @@ func (value Value) String() string {
// ToBoolean will convert the value to a boolean (bool).
//
// ToValue(0).ToBoolean() => false
// ToValue("").ToBoolean() => false
// ToValue(true).ToBoolean() => true
// ToValue(1).ToBoolean() => true
// ToValue("Nothing happens").ToBoolean() => true
// ToValue(0).ToBoolean() => false
// ToValue("").ToBoolean() => false
// ToValue(true).ToBoolean() => true
// ToValue(1).ToBoolean() => true
// 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) {
@ -410,9 +408,9 @@ func (value Value) numberValue() Value {
// ToFloat will convert the value to a number (float64).
//
// ToValue(0).ToFloat() => 0.
// ToValue(1.1).ToFloat() => 1.1
// ToValue("11").ToFloat() => 11.
// ToValue(0).ToFloat() => 0.
// ToValue(1.1).ToFloat() => 1.1
// 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) {
@ -425,9 +423,9 @@ func (value Value) ToFloat() (float64, error) {
// ToInteger will convert the value to a number (int64).
//
// ToValue(0).ToInteger() => 0
// ToValue(1.1).ToInteger() => 1
// ToValue("11").ToInteger() => 11
// ToValue(0).ToInteger() => 0
// ToValue(1.1).ToInteger() => 1
// 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) {
@ -440,11 +438,11 @@ func (value Value) ToInteger() (int64, error) {
// ToString will convert the value to a string (string).
//
// ToValue(0).ToString() => "0"
// ToValue(false).ToString() => "false"
// ToValue(1.1).ToString() => "1.1"
// ToValue("11").ToString() => "11"
// ToValue('Nothing happens.').ToString() => "Nothing happens."
// ToValue(0).ToString() => "0"
// ToValue(false).ToString() => "false"
// ToValue(1.1).ToString() => "1.1"
// ToValue("11").ToString() => "11"
// 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) {
@ -506,8 +504,7 @@ func negativeZero() float64 {
//
// It is equivalent to:
//
// ToValue(math.NaN())
//
// ToValue(math.NaN())
func NaNValue() Value {
return Value{valueNumber, __NaN__}
}
@ -532,8 +529,7 @@ func negativeZeroValue() Value {
//
// It is equivalent to:
//
// ToValue(true)
//
// ToValue(true)
func TrueValue() Value {
return Value{valueBoolean, true}
}
@ -542,8 +538,7 @@ func TrueValue() Value {
//
// It is equivalent to:
//
// ToValue(false)
//
// ToValue(false)
func FalseValue() Value {
return Value{valueBoolean, false}
}
@ -617,14 +612,13 @@ func strictEqualityComparison(x Value, y Value) bool {
// If a reasonable conversion is not possible, then the original
// value is returned.
//
// undefined -> nil (FIXME?: Should be Value{})
// null -> nil
// boolean -> bool
// number -> A number type (int, float32, uint64, ...)
// string -> string
// Array -> []interface{}
// Object -> map[string]interface{}
//
// undefined -> nil (FIXME?: Should be Value{})
// null -> nil
// boolean -> bool
// number -> A number type (int, float32, uint64, ...)
// string -> string
// Array -> []interface{}
// Object -> map[string]interface{}
func (self Value) Export() (interface{}, error) {
return self.export(), nil
}