1# otto 2-- 3```go 4import "github.com/robertkrimen/otto" 5``` 6 7Package otto is a JavaScript parser and interpreter written natively in Go. 8 9http://godoc.org/github.com/robertkrimen/otto 10 11```go 12import ( 13 "github.com/robertkrimen/otto" 14) 15``` 16 17Run something in the VM 18 19```go 20vm := otto.New() 21vm.Run(` 22 abc = 2 + 2; 23 console.log("The value of abc is " + abc); // 4 24`) 25``` 26 27Get a value out of the VM 28 29```go 30if value, err := vm.Get("abc"); err == nil { 31 if value_int, err := value.ToInteger(); err == nil { 32 fmt.Printf("", value_int, err) 33 } 34} 35``` 36 37Set a number 38 39```go 40vm.Set("def", 11) 41vm.Run(` 42 console.log("The value of def is " + def); 43 // The value of def is 11 44`) 45``` 46 47Set a string 48 49```go 50vm.Set("xyzzy", "Nothing happens.") 51vm.Run(` 52 console.log(xyzzy.length); // 16 53`) 54``` 55 56Get the value of an expression 57 58```go 59value, _ = vm.Run("xyzzy.length") 60{ 61 // value is an int64 with a value of 16 62 value, _ := value.ToInteger() 63} 64``` 65 66An error happens 67 68```go 69value, err = vm.Run("abcdefghijlmnopqrstuvwxyz.length") 70if err != nil { 71 // err = ReferenceError: abcdefghijlmnopqrstuvwxyz is not defined 72 // If there is an error, then value.IsUndefined() is true 73 ... 74} 75``` 76 77Set a Go function 78 79```go 80vm.Set("sayHello", func(call otto.FunctionCall) otto.Value { 81 fmt.Printf("Hello, %s.\n", call.Argument(0).String()) 82 return otto.Value{} 83}) 84``` 85 86Set a Go function that returns something useful 87 88```go 89vm.Set("twoPlus", func(call otto.FunctionCall) otto.Value { 90 right, _ := call.Argument(0).ToInteger() 91 result, _ := vm.ToValue(2 + right) 92 return result 93}) 94``` 95 96Use the functions in JavaScript 97 98```go 99result, _ = vm.Run(` 100 sayHello("Xyzzy"); // Hello, Xyzzy. 101 sayHello(); // Hello, undefined 102 103 result = twoPlus(2.0); // 4 104`) 105``` 106 107### Parser 108 109A separate parser is available in the parser package if you're just interested 110in building an AST. 111 112http://godoc.org/github.com/robertkrimen/otto/parser 113 114Parse and return an AST 115 116```go 117filename := "" // A filename is optional 118src := ` 119 // Sample xyzzy example 120 (function(){ 121 if (3.14159 > 0) { 122 console.log("Hello, World."); 123 return; 124 } 125 126 var xyzzy = NaN; 127 console.log("Nothing happens."); 128 return xyzzy; 129 })(); 130` 131 132// Parse some JavaScript, yielding a *ast.Program and/or an ErrorList 133program, err := parser.ParseFile(nil, filename, src, 0) 134``` 135 136### otto 137 138You can run (Go) JavaScript from the commandline with: 139http://github.com/robertkrimen/otto/tree/master/otto 140 141 $ go get -v github.com/robertkrimen/otto/otto 142 143Run JavaScript by entering some source on stdin or by giving otto a filename: 144 145 $ otto example.js 146 147### underscore 148 149Optionally include the JavaScript utility-belt library, underscore, with this 150import: 151 152```go 153import ( 154 "github.com/robertkrimen/otto" 155 _ "github.com/robertkrimen/otto/underscore" 156) 157 158// Now every otto runtime will come loaded with underscore 159``` 160 161For more information: http://github.com/robertkrimen/otto/tree/master/underscore 162 163 164### Caveat Emptor 165 166The following are some limitations with otto: 167 168 * "use strict" will parse, but does nothing. 169 * The regular expression engine (re2/regexp) is not fully compatible with the ECMA5 specification. 170 * Otto targets ES5. ES6 features (eg: Typed Arrays) are not supported. 171 172 173### Regular Expression Incompatibility 174 175Go translates JavaScript-style regular expressions into something that is 176"regexp" compatible via `parser.TransformRegExp`. Unfortunately, RegExp requires 177backtracking for some patterns, and backtracking is not supported by the 178standard Go engine: https://code.google.com/p/re2/wiki/Syntax 179 180Therefore, the following syntax is incompatible: 181 182 (?=) // Lookahead (positive), currently a parsing error 183 (?!) // Lookahead (backhead), currently a parsing error 184 \1 // Backreference (\1, \2, \3, ...), currently a parsing error 185 186A brief discussion of these limitations: "Regexp (?!re)" 187https://groups.google.com/forum/?fromgroups=#%21topic/golang-nuts/7qgSDWPIh_E 188 189More information about re2: https://code.google.com/p/re2/ 190 191In addition to the above, re2 (Go) has a different definition for \s: [\t\n\f\r 192]. The JavaScript definition, on the other hand, also includes \v, Unicode 193"Separator, Space", etc. 194 195 196### Halting Problem 197 198If you want to stop long running executions (like third-party code), you can use 199the interrupt channel to do this: 200 201```go 202package main 203 204import ( 205 "errors" 206 "fmt" 207 "os" 208 "time" 209 210 "github.com/robertkrimen/otto" 211) 212 213var halt = errors.New("Stahp") 214 215func main() { 216 runUnsafe(`var abc = [];`) 217 runUnsafe(` 218 while (true) { 219 // Loop forever 220 }`) 221} 222 223func runUnsafe(unsafe string) { 224 start := time.Now() 225 defer func() { 226 duration := time.Since(start) 227 if caught := recover(); caught != nil { 228 if caught == halt { 229 fmt.Fprintf(os.Stderr, "Some code took to long! Stopping after: %v\n", duration) 230 return 231 } 232 panic(caught) // Something else happened, repanic! 233 } 234 fmt.Fprintf(os.Stderr, "Ran code successfully: %v\n", duration) 235 }() 236 237 vm := otto.New() 238 vm.Interrupt = make(chan func(), 1) // The buffer prevents blocking 239 240 go func() { 241 time.Sleep(2 * time.Second) // Stop after two seconds 242 vm.Interrupt <- func() { 243 panic(halt) 244 } 245 }() 246 247 vm.Run(unsafe) // Here be dragons (risky code) 248} 249``` 250 251Where is setTimeout/setInterval? 252 253These timing functions are not actually part of the ECMA-262 specification. 254Typically, they belong to the `window` object (in the browser). It would not be 255difficult to provide something like these via Go, but you probably want to wrap 256otto in an event loop in that case. 257 258For an example of how this could be done in Go with otto, see natto: 259 260http://github.com/robertkrimen/natto 261 262Here is some more discussion of the issue: 263 264* http://book.mixu.net/node/ch2.html 265 266* http://en.wikipedia.org/wiki/Reentrancy_%28computing%29 267 268* http://aaroncrane.co.uk/2009/02/perl_safe_signals/ 269 270## Usage 271 272```go 273var ErrVersion = errors.New("version mismatch") 274``` 275 276#### type Error 277 278```go 279type Error struct { 280} 281``` 282 283An Error represents a runtime error, e.g. a TypeError, a ReferenceError, etc. 284 285#### func (Error) Error 286 287```go 288func (err Error) Error() string 289``` 290Error returns a description of the error 291 292 TypeError: 'def' is not a function 293 294#### func (Error) String 295 296```go 297func (err Error) String() string 298``` 299String returns a description of the error and a trace of where the error 300occurred. 301 302 TypeError: 'def' is not a function 303 at xyz (<anonymous>:3:9) 304 at <anonymous>:7:1/ 305 306#### type FunctionCall 307 308```go 309type FunctionCall struct { 310 This Value 311 ArgumentList []Value 312 Otto *Otto 313} 314``` 315 316FunctionCall is an encapsulation of a JavaScript function call. 317 318#### func (FunctionCall) Argument 319 320```go 321func (self FunctionCall) Argument(index int) Value 322``` 323Argument will return the value of the argument at the given index. 324 325If no such argument exists, undefined is returned. 326 327#### type Object 328 329```go 330type Object struct { 331} 332``` 333 334Object is the representation of a JavaScript object. 335 336#### func (Object) Call 337 338```go 339func (self Object) Call(name string, argumentList ...interface{}) (Value, error) 340``` 341Call a method on the object. 342 343It is essentially equivalent to: 344 345 var method, _ := object.Get(name) 346 method.Call(object, argumentList...) 347 348An undefined value and an error will result if: 349 350 1. There is an error during conversion of the argument list 351 2. The property is not actually a function 352 3. An (uncaught) exception is thrown 353 354#### func (Object) Class 355 356```go 357func (self Object) Class() string 358``` 359Class will return the class string of the object. 360 361The return value will (generally) be one of: 362 363 Object 364 Function 365 Array 366 String 367 Number 368 Boolean 369 Date 370 RegExp 371 372#### func (Object) Get 373 374```go 375func (self Object) Get(name string) (Value, error) 376``` 377Get the value of the property with the given name. 378 379#### func (Object) Keys 380 381```go 382func (self Object) Keys() []string 383``` 384Get the keys for the object 385 386Equivalent to calling Object.keys on the object 387 388#### func (Object) Set 389 390```go 391func (self Object) Set(name string, value interface{}) error 392``` 393Set the property of the given name to the given value. 394 395An error will result if the setting the property triggers an exception (i.e. 396read-only), or there is an error during conversion of the given value. 397 398#### func (Object) Value 399 400```go 401func (self Object) Value() Value 402``` 403Value will return self as a value. 404 405#### type Otto 406 407```go 408type Otto struct { 409 // Interrupt is a channel for interrupting the runtime. You can use this to halt a long running execution, for example. 410 // See "Halting Problem" for more information. 411 Interrupt chan func() 412} 413``` 414 415Otto is the representation of the JavaScript runtime. Each instance of Otto has 416a self-contained namespace. 417 418#### func New 419 420```go 421func New() *Otto 422``` 423New will allocate a new JavaScript runtime 424 425#### func Run 426 427```go 428func Run(src interface{}) (*Otto, Value, error) 429``` 430Run will allocate a new JavaScript runtime, run the given source on the 431allocated runtime, and return the runtime, resulting value, and error (if any). 432 433src may be a string, a byte slice, a bytes.Buffer, or an io.Reader, but it MUST 434always be in UTF-8. 435 436src may also be a Script. 437 438src may also be a Program, but if the AST has been modified, then runtime 439behavior is undefined. 440 441#### func (Otto) Call 442 443```go 444func (self Otto) Call(source string, this interface{}, argumentList ...interface{}) (Value, error) 445``` 446Call the given JavaScript with a given this and arguments. 447 448If this is nil, then some special handling takes place to determine the proper 449this value, falling back to a "standard" invocation if necessary (where this is 450undefined). 451 452If source begins with "new " (A lowercase new followed by a space), then Call 453will invoke the function constructor rather than performing a function call. In 454this case, the this argument has no effect. 455 456```go 457// value is a String object 458value, _ := vm.Call("Object", nil, "Hello, World.") 459 460// Likewise... 461value, _ := vm.Call("new Object", nil, "Hello, World.") 462 463// This will perform a concat on the given array and return the result 464// value is [ 1, 2, 3, undefined, 4, 5, 6, 7, "abc" ] 465value, _ := vm.Call(`[ 1, 2, 3, undefined, 4 ].concat`, nil, 5, 6, 7, "abc") 466``` 467 468#### func (*Otto) Compile 469 470```go 471func (self *Otto) Compile(filename string, src interface{}) (*Script, error) 472``` 473Compile will parse the given source and return a Script value or nil and an 474error if there was a problem during compilation. 475 476```go 477script, err := vm.Compile("", `var abc; if (!abc) abc = 0; abc += 2; abc;`) 478vm.Run(script) 479``` 480 481#### func (*Otto) Copy 482 483```go 484func (in *Otto) Copy() *Otto 485``` 486Copy will create a copy/clone of the runtime. 487 488Copy is useful for saving some time when creating many similar runtimes. 489 490This method works by walking the original runtime and cloning each object, 491scope, stash, etc. into a new runtime. 492 493Be on the lookout for memory leaks or inadvertent sharing of resources. 494 495#### func (Otto) Get 496 497```go 498func (self Otto) Get(name string) (Value, error) 499``` 500Get the value of the top-level binding of the given name. 501 502If there is an error (like the binding does not exist), then the value will be 503undefined. 504 505#### func (Otto) Object 506 507```go 508func (self Otto) Object(source string) (*Object, error) 509``` 510Object will run the given source and return the result as an object. 511 512For example, accessing an existing object: 513 514```go 515object, _ := vm.Object(`Number`) 516``` 517 518Or, creating a new object: 519 520```go 521object, _ := vm.Object(`({ xyzzy: "Nothing happens." })`) 522``` 523 524Or, creating and assigning an object: 525 526```go 527object, _ := vm.Object(`xyzzy = {}`) 528object.Set("volume", 11) 529``` 530 531If there is an error (like the source does not result in an object), then nil 532and an error is returned. 533 534#### func (Otto) Run 535 536```go 537func (self Otto) Run(src interface{}) (Value, error) 538``` 539Run will run the given source (parsing it first if necessary), returning the 540resulting value and error (if any) 541 542src may be a string, a byte slice, a bytes.Buffer, or an io.Reader, but it MUST 543always be in UTF-8. 544 545If the runtime is unable to parse source, then this function will return 546undefined and the parse error (nothing will be evaluated in this case). 547 548src may also be a Script. 549 550src may also be a Program, but if the AST has been modified, then runtime 551behavior is undefined. 552 553#### func (Otto) Set 554 555```go 556func (self Otto) Set(name string, value interface{}) error 557``` 558Set the top-level binding of the given name to the given value. 559 560Set will automatically apply ToValue to the given value in order to convert it 561to a JavaScript value (type Value). 562 563If there is an error (like the binding is read-only, or the ToValue conversion 564fails), then an error is returned. 565 566If the top-level binding does not exist, it will be created. 567 568#### func (Otto) ToValue 569 570```go 571func (self Otto) ToValue(value interface{}) (Value, error) 572``` 573ToValue will convert an interface{} value to a value digestible by 574otto/JavaScript. 575 576#### type Script 577 578```go 579type Script struct { 580} 581``` 582 583Script is a handle for some (reusable) JavaScript. Passing a Script value to a 584run method will evaluate the JavaScript. 585 586#### func (*Script) String 587 588```go 589func (self *Script) String() string 590``` 591 592#### type Value 593 594```go 595type Value struct { 596} 597``` 598 599Value is the representation of a JavaScript value. 600 601#### func FalseValue 602 603```go 604func FalseValue() Value 605``` 606FalseValue will return a value representing false. 607 608It is equivalent to: 609 610```go 611ToValue(false) 612``` 613 614#### func NaNValue 615 616```go 617func NaNValue() Value 618``` 619NaNValue will return a value representing NaN. 620 621It is equivalent to: 622 623```go 624ToValue(math.NaN()) 625``` 626 627#### func NullValue 628 629```go 630func NullValue() Value 631``` 632NullValue will return a Value representing null. 633 634#### func ToValue 635 636```go 637func ToValue(value interface{}) (Value, error) 638``` 639ToValue will convert an interface{} value to a value digestible by 640otto/JavaScript 641 642This function will not work for advanced types (struct, map, slice/array, etc.) 643and you should use Otto.ToValue instead. 644 645#### func TrueValue 646 647```go 648func TrueValue() Value 649``` 650TrueValue will return a value representing true. 651 652It is equivalent to: 653 654```go 655ToValue(true) 656``` 657 658#### func UndefinedValue 659 660```go 661func UndefinedValue() Value 662``` 663UndefinedValue will return a Value representing undefined. 664 665#### func (Value) Call 666 667```go 668func (value Value) Call(this Value, argumentList ...interface{}) (Value, error) 669``` 670Call the value as a function with the given this value and argument list and 671return the result of invocation. It is essentially equivalent to: 672 673 value.apply(thisValue, argumentList) 674 675An undefined value and an error will result if: 676 677 1. There is an error during conversion of the argument list 678 2. The value is not actually a function 679 3. An (uncaught) exception is thrown 680 681#### func (Value) Class 682 683```go 684func (value Value) Class() string 685``` 686Class will return the class string of the value or the empty string if value is 687not an object. 688 689The return value will (generally) be one of: 690 691 Object 692 Function 693 Array 694 String 695 Number 696 Boolean 697 Date 698 RegExp 699 700#### func (Value) Export 701 702```go 703func (self Value) Export() (interface{}, error) 704``` 705Export will attempt to convert the value to a Go representation and return it 706via an interface{} kind. 707 708Export returns an error, but it will always be nil. It is present for backwards 709compatibility. 710 711If a reasonable conversion is not possible, then the original value is returned. 712 713 undefined -> nil (FIXME?: Should be Value{}) 714 null -> nil 715 boolean -> bool 716 number -> A number type (int, float32, uint64, ...) 717 string -> string 718 Array -> []interface{} 719 Object -> map[string]interface{} 720 721#### func (Value) IsBoolean 722 723```go 724func (value Value) IsBoolean() bool 725``` 726IsBoolean will return true if value is a boolean (primitive). 727 728#### func (Value) IsDefined 729 730```go 731func (value Value) IsDefined() bool 732``` 733IsDefined will return false if the value is undefined, and true otherwise. 734 735#### func (Value) IsFunction 736 737```go 738func (value Value) IsFunction() bool 739``` 740IsFunction will return true if value is a function. 741 742#### func (Value) IsNaN 743 744```go 745func (value Value) IsNaN() bool 746``` 747IsNaN will return true if value is NaN (or would convert to NaN). 748 749#### func (Value) IsNull 750 751```go 752func (value Value) IsNull() bool 753``` 754IsNull will return true if the value is null, and false otherwise. 755 756#### func (Value) IsNumber 757 758```go 759func (value Value) IsNumber() bool 760``` 761IsNumber will return true if value is a number (primitive). 762 763#### func (Value) IsObject 764 765```go 766func (value Value) IsObject() bool 767``` 768IsObject will return true if value is an object. 769 770#### func (Value) IsPrimitive 771 772```go 773func (value Value) IsPrimitive() bool 774``` 775IsPrimitive will return true if value is a primitive (any kind of primitive). 776 777#### func (Value) IsString 778 779```go 780func (value Value) IsString() bool 781``` 782IsString will return true if value is a string (primitive). 783 784#### func (Value) IsUndefined 785 786```go 787func (value Value) IsUndefined() bool 788``` 789IsUndefined will return true if the value is undefined, and false otherwise. 790 791#### func (Value) Object 792 793```go 794func (value Value) Object() *Object 795``` 796Object will return the object of the value, or nil if value is not an object. 797 798This method will not do any implicit conversion. For example, calling this 799method on a string primitive value will not return a String object. 800 801#### func (Value) String 802 803```go 804func (value Value) String() string 805``` 806String will return the value as a string. 807 808This method will make return the empty string if there is an error. 809 810#### func (Value) ToBoolean 811 812```go 813func (value Value) ToBoolean() (bool, error) 814``` 815ToBoolean will convert the value to a boolean (bool). 816 817 ToValue(0).ToBoolean() => false 818 ToValue("").ToBoolean() => false 819 ToValue(true).ToBoolean() => true 820 ToValue(1).ToBoolean() => true 821 ToValue("Nothing happens").ToBoolean() => true 822 823If there is an error during the conversion process (like an uncaught exception), 824then the result will be false and an error. 825 826#### func (Value) ToFloat 827 828```go 829func (value Value) ToFloat() (float64, error) 830``` 831ToFloat will convert the value to a number (float64). 832 833 ToValue(0).ToFloat() => 0. 834 ToValue(1.1).ToFloat() => 1.1 835 ToValue("11").ToFloat() => 11. 836 837If there is an error during the conversion process (like an uncaught exception), 838then the result will be 0 and an error. 839 840#### func (Value) ToInteger 841 842```go 843func (value Value) ToInteger() (int64, error) 844``` 845ToInteger will convert the value to a number (int64). 846 847 ToValue(0).ToInteger() => 0 848 ToValue(1.1).ToInteger() => 1 849 ToValue("11").ToInteger() => 11 850 851If there is an error during the conversion process (like an uncaught exception), 852then the result will be 0 and an error. 853 854#### func (Value) ToString 855 856```go 857func (value Value) ToString() (string, error) 858``` 859ToString will convert the value to a string (string). 860 861 ToValue(0).ToString() => "0" 862 ToValue(false).ToString() => "false" 863 ToValue(1.1).ToString() => "1.1" 864 ToValue("11").ToString() => "11" 865 ToValue('Nothing happens.').ToString() => "Nothing happens." 866 867If there is an error during the conversion process (like an uncaught exception), 868then the result will be the empty string ("") and an error. 869 870-- 871**godocdown** http://github.com/robertkrimen/godocdown 872