mirror of
https://github.com/robertkrimen/otto.git
synced 2025-12-24 12:58:05 +08:00
Add compilation (Script, vm.Compile, etc.)
This commit is contained in:
@@ -392,6 +392,17 @@ this case, the this argument has no effect.
|
||||
// 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 (*Otto) Compile
|
||||
|
||||
```go
|
||||
func (self *Otto) Compile(filename string, src interface{}) (*Script, error)
|
||||
```
|
||||
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)
|
||||
|
||||
#### func (*Otto) Copy
|
||||
|
||||
```go
|
||||
@@ -479,6 +490,22 @@ func (self Otto) ToValue(value interface{}) (Value, error)
|
||||
ToValue will convert an interface{} value to a value digestible by
|
||||
otto/JavaScript.
|
||||
|
||||
#### type Script
|
||||
|
||||
```go
|
||||
type Script struct {
|
||||
}
|
||||
```
|
||||
|
||||
Script is a handle for some (reusable) JavaScript. Passing a Script value to a
|
||||
run method will evaluate the JavaScript.
|
||||
|
||||
#### func (*Script) String
|
||||
|
||||
```go
|
||||
func (self *Script) String() string
|
||||
```
|
||||
|
||||
#### type Value
|
||||
|
||||
```go
|
||||
|
||||
2
otto.go
2
otto.go
@@ -357,7 +357,7 @@ func (self Otto) Call(source string, this interface{}, argumentList ...interface
|
||||
}
|
||||
|
||||
if !construct && this == nil {
|
||||
program, err := self.runtime.parse(source + "()")
|
||||
program, err := self.runtime.parse("", source+"()")
|
||||
if err == nil {
|
||||
if node, ok := program.Body[0].(*ast.ExpressionStatement); ok {
|
||||
if node, ok := node.Expression.(*ast.CallExpression); ok {
|
||||
|
||||
15
otto_test.go
15
otto_test.go
@@ -1381,6 +1381,21 @@ func TestOttoRun(t *testing.T) {
|
||||
Is(err, nil)
|
||||
is(value, 12)
|
||||
}
|
||||
|
||||
{
|
||||
script, err := vm.Compile("", `var abc; if (!abc) abc = 0; abc += 2; abc;`)
|
||||
Is(err, nil)
|
||||
|
||||
value, err = vm.Run(script)
|
||||
Is(err, nil)
|
||||
is(value, 14)
|
||||
|
||||
value, err = vm.Run(script)
|
||||
Is(err, nil)
|
||||
is(value, 16)
|
||||
|
||||
Is(script.String(), "// \nvar abc; if (!abc) abc = 0; abc += 2; abc;")
|
||||
}
|
||||
}
|
||||
|
||||
func Test_objectLength(t *testing.T) {
|
||||
|
||||
@@ -65,6 +65,12 @@ the corresponding ast.FunctionExpression node.
|
||||
|
||||
The parameter list, if any, should be a comma-separated list of identifiers.
|
||||
|
||||
#### func ReadSource
|
||||
|
||||
```go
|
||||
func ReadSource(filename string, src interface{}) ([]byte, error)
|
||||
```
|
||||
|
||||
#### func TransformRegExp
|
||||
|
||||
```go
|
||||
|
||||
@@ -93,7 +93,7 @@ func newParser(filename, src string) *_parser {
|
||||
return _newParser(filename, src, 1)
|
||||
}
|
||||
|
||||
func readSource(filename string, src interface{}) ([]byte, error) {
|
||||
func ReadSource(filename string, src interface{}) ([]byte, error) {
|
||||
if src != nil {
|
||||
switch src := src.(type) {
|
||||
case string:
|
||||
@@ -130,7 +130,7 @@ func readSource(filename string, src interface{}) ([]byte, error) {
|
||||
// program, err := parser.ParseFile(nil, "", `if (abc > 1) {}`, 0)
|
||||
//
|
||||
func ParseFile(fileSet *file.FileSet, filename string, src interface{}, mode Mode) (*ast.Program, error) {
|
||||
str, err := readSource(filename, src)
|
||||
str, err := ReadSource(filename, src)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
10
runtime.go
10
runtime.go
@@ -398,16 +398,18 @@ func (runtime *_runtime) newGoArray(value reflect.Value) *_object {
|
||||
return self
|
||||
}
|
||||
|
||||
func (runtime *_runtime) parse(src interface{}) (*ast.Program, error) {
|
||||
return parser.ParseFile(nil, "", src, 0)
|
||||
func (runtime *_runtime) parse(filename string, src interface{}) (*ast.Program, error) {
|
||||
return parser.ParseFile(nil, filename, src, 0)
|
||||
}
|
||||
|
||||
func (self *_runtime) parseSource(src interface{}) (ast.Node, error) {
|
||||
switch src := src.(type) {
|
||||
case ast.Node:
|
||||
return src, nil
|
||||
case *Script:
|
||||
return src.program, nil
|
||||
}
|
||||
return self.parse(src)
|
||||
return self.parse("", src)
|
||||
}
|
||||
|
||||
func (self *_runtime) run(src interface{}) (Value, error) {
|
||||
@@ -446,7 +448,7 @@ func (self *_runtime) parseThrow(err error) {
|
||||
}
|
||||
|
||||
func (self *_runtime) parseOrThrow(source string) *ast.Program {
|
||||
program, err := self.parse(source)
|
||||
program, err := self.parse("", source)
|
||||
self.parseThrow(err) // Will panic/throw appropriately
|
||||
return program
|
||||
}
|
||||
|
||||
47
script.go
Normal file
47
script.go
Normal file
@@ -0,0 +1,47 @@
|
||||
package otto
|
||||
|
||||
import (
|
||||
"github.com/robertkrimen/otto/ast"
|
||||
"github.com/robertkrimen/otto/parser"
|
||||
)
|
||||
|
||||
// Script is a handle for some (reusable) JavaScript.
|
||||
// Passing a Script value to a run method will evaluate the JavaScript.
|
||||
//
|
||||
type Script struct {
|
||||
program *ast.Program
|
||||
filename string
|
||||
src string
|
||||
}
|
||||
|
||||
// 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)
|
||||
//
|
||||
func (self *Otto) Compile(filename string, src interface{}) (*Script, error) {
|
||||
{
|
||||
src, err := parser.ReadSource(filename, src)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
program, err := self.runtime.parse(filename, src)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
script := &Script{
|
||||
program: program,
|
||||
filename: filename,
|
||||
src: string(src),
|
||||
}
|
||||
|
||||
return script, nil
|
||||
}
|
||||
}
|
||||
|
||||
func (self *Script) String() string {
|
||||
return "// " + self.filename + "\n" + self.src
|
||||
}
|
||||
Reference in New Issue
Block a user