• Home
  • History
  • Annotate
Name Date Size #Lines LOC

..03-May-2022-

ast/H19-Jul-2018-

file/H19-Jul-2018-

goja/H19-Jul-2018-

parser/H19-Jul-2018-

testdata/H03-May-2022-

token/H19-Jul-2018-

.gitignoreH A D19-Jul-201829

LICENSEH A D19-Jul-20181.1 KiB

README.mdH A D19-Jul-20185.7 KiB

array.goH A D19-Jul-201810.3 KiB

array_sparse.goH A D19-Jul-20189.9 KiB

array_sparse_test.goH A D19-Jul-20182.3 KiB

builtin_array.goH A D19-Jul-201822 KiB

builtin_boolean.goH A D19-Jul-20181.4 KiB

builtin_date.goH A D19-Jul-201828.9 KiB

builtin_error.goH A D19-Jul-20182.9 KiB

builtin_function.goH A D19-Jul-20184.3 KiB

builtin_global.goH A D19-Jul-20188.7 KiB

builtin_global_test.goH A D19-Jul-2018409

builtin_json.goH A D19-Jul-201811.2 KiB

builtin_json_test.goH A D19-Jul-20181.4 KiB

builtin_math.goH A D19-Jul-20185.5 KiB

builtin_number.goH A D19-Jul-20184.3 KiB

builtin_object.goH A D19-Jul-201811.8 KiB

builtin_regexp.goH A D19-Jul-20187.1 KiB

builtin_string.goH A D19-Jul-201816.3 KiB

builtin_string_test.goH A D19-Jul-20183.5 KiB

builtin_typedarrays.goH A D19-Jul-20182.4 KiB

builtin_typedarrays_test.goH A D19-Jul-2018169

compiler.goH A D19-Jul-20189.5 KiB

compiler_expr.goH A D19-Jul-201831.9 KiB

compiler_stmt.goH A D19-Jul-201818.4 KiB

compiler_test.goH A D19-Jul-201828.5 KiB

date.goH A D19-Jul-20182 KiB

date_test.goH A D19-Jul-20185.4 KiB

dtoa.goH A D19-Jul-20185.6 KiB

func.goH A D19-Jul-20184.9 KiB

ipow.goH A D19-Jul-20182.1 KiB

object.goH A D19-Jul-201813 KiB

object_args.goH A D19-Jul-20183.3 KiB

object_gomap.goH A D19-Jul-20184.7 KiB

object_gomap_reflect.goH A D19-Jul-20184.6 KiB

object_gomap_reflect_test.goH A D19-Jul-20182.7 KiB

object_gomap_test.goH A D19-Jul-20182.9 KiB

object_goreflect.goH A D19-Jul-201812.3 KiB

object_goreflect_test.goH A D19-Jul-201810.3 KiB

object_goslice.goH A D19-Jul-20186.2 KiB

object_goslice_reflect.goH A D19-Jul-20185.7 KiB

object_goslice_reflect_test.goH A D19-Jul-20181.9 KiB

object_goslice_test.goH A D19-Jul-20181.4 KiB

object_lazy.goH A D19-Jul-20184.1 KiB

object_test.goH A D19-Jul-20184.5 KiB

regexp.goH A D19-Jul-20188.2 KiB

regexp_test.goH A D19-Jul-20184 KiB

runtime.goH A D19-Jul-201833.1 KiB

runtime_test.goH A D19-Jul-201818.7 KiB

srcfile.goH A D19-Jul-20181.4 KiB

srcfile_test.goH A D19-Jul-2018520

string.goH A D19-Jul-20186 KiB

string_ascii.goH A D19-Jul-20185.7 KiB

string_unicode.goH A D19-Jul-20185.9 KiB

tc39_test.goH A D19-Jul-20187.3 KiB

value.goH A D19-Jul-201816.6 KiB

vm.goH A D19-Jul-201842.5 KiB

vm_test.goH A D19-Jul-20186 KiB

README.md

1goja
2====
3
4ECMAScript 5.1(+) implementation in Go.
5
6[![GoDoc](https://godoc.org/github.com/dop251/goja?status.svg)](https://godoc.org/github.com/dop251/goja)
7
8It is not a replacement for V8 or SpiderMonkey or any other general-purpose JavaScript engine as it is much slower.
9It can be used as an embedded scripting language where the cost of making a lot of cgo calls may
10outweight the benefits of a faster JavaScript engine or as a way to avoid having non-Go dependencies.
11
12This project was largely inspired by [otto](https://github.com/robertkrimen/otto).
13
14Features
15--------
16
17 * Full ECMAScript 5.1 support (yes, including regex and strict mode).
18 * Passes nearly all [tc39 tests](https://github.com/tc39/test262) tagged with es5id. The goal is to pass all of them. Note, the last working commit is https://github.com/tc39/test262/commit/1ba3a7c4a93fc93b3d0d7e4146f59934a896837d. The next commit made use of template strings which goja does not support.
19 * On average 6-7 times faster than otto. Also uses considerably less memory.
20
21Current Status
22--------------
23
24 * API is still work in progress and is subject to change.
25 * Some of the AnnexB functionality is missing.
26 * No typed arrays yet.
27
28Basic Example
29-------------
30
31```go
32vm := goja.New()
33v, err := vm.RunString("2 + 2")
34if err != nil {
35    panic(err)
36}
37if num := v.Export().(int64); num != 4 {
38    panic(num)
39}
40```
41
42Passing Values to JS
43--------------------
44
45Any Go value can be passed to JS using Runtime.ToValue() method. Primitive types (ints and uints, floats, string, bool)
46are converted to the corresponding JavaScript primitives.
47
48*func(FunctionCall) Value* is treated as a native JavaScript function.
49
50*func(ConstructorCall) \*Object* is treated as a JavaScript constructor (see Native Constructors).
51
52*map[string]interface{}* is converted into a host object that largely behaves like a JavaScript Object.
53
54*[]interface{}* is converted into a host object that behaves largely like a JavaScript Array, however it's not extensible
55because extending it can change the pointer so it becomes detached from the original.
56
57**[]interface{}* is same as above, but the array becomes extensible.
58
59A function is wrapped within a native JavaScript function. When called the arguments are automatically converted to
60the appropriate Go types. If conversion is not possible, a TypeError is thrown.
61
62A slice type is converted into a generic reflect based host object that behaves similar to an unexpandable Array.
63
64A map type with numeric or string keys and no methods is converted into a host object where properties are map keys.
65
66A map type with methods is converted into a host object where properties are method names,
67the map values are not accessible. This is to avoid ambiguity between m\["Property"\] and m.Property.
68
69Any other type is converted to a generic reflect based host object. Depending on the underlying type it behaves similar
70to a Number, String, Boolean or Object.
71
72Note that these conversions wrap the original value which means any changes made inside JS
73are reflected on the value and calling Export() returns the original value. This applies to all
74reflect based types.
75
76Exporting Values from JS
77------------------------
78
79A JS value can be exported into its default Go representation using Value.Export() method.
80
81Alternatively it can be exported into a specific Go variable using Runtime.ExportTo() method.
82
83Native Constructors
84-------------------
85
86In order to implement a constructor function in Go:
87```go
88func MyObject(call goja.ConstructorCall) *Object {
89    // call.This contains the newly created object as per http://www.ecma-international.org/ecma-262/5.1/index.html#sec-13.2.2
90    // call.Arguments contain arguments passed to the function
91
92    call.This.Set("method", method)
93
94    //...
95
96    // If return value is a non-nil *Object, it will be used instead of call.This
97    // This way it is possible to return a Go struct or a map converted
98    // into goja.Value using runtime.ToValue(), however in this case
99    // instanceof will not work as expected.
100    return nil
101}
102
103runtime.Set("MyObject", MyObject)
104
105```
106
107Then it can be used in JS as follows:
108
109```js
110var o = new MyObject(arg);
111var o1 = MyObject(arg); // same thing
112o instanceof MyObject && o1 instanceof MyObject; // true
113```
114
115Regular Expressions
116-------------------
117
118Goja uses the embedded Go regexp library where possible, otherwise it falls back to [regexp2](https://github.com/dlclark/regexp2).
119
120Exceptions
121----------
122
123Any exception thrown in JavaScript is returned as an error of type *Exception. It is possible to extract the value thrown
124by using the Value() method:
125
126```go
127vm := New()
128_, err := vm.RunString(`
129
130throw("Test");
131
132`)
133
134if jserr, ok := err.(*Exception); ok {
135    if jserr.Value().Export() != "Test" {
136        panic("wrong value")
137    }
138} else {
139    panic("wrong type")
140}
141```
142
143If a native Go function panics with a Value, it is thrown as a Javascript exception (and therefore can be caught):
144
145```go
146var vm *Runtime
147
148func Test() {
149    panic(vm.ToValue("Error"))
150}
151
152vm = New()
153vm.Set("Test", Test)
154_, err := vm.RunString(`
155
156try {
157    Test();
158} catch(e) {
159    if (e !== "Error") {
160        throw e;
161    }
162}
163
164`)
165
166if err != nil {
167    panic(err)
168}
169```
170
171Interrupting
172------------
173
174```go
175func TestInterrupt(t *testing.T) {
176    const SCRIPT = `
177    var i = 0;
178    for (;;) {
179        i++;
180    }
181    `
182
183    vm := New()
184    time.AfterFunc(200 * time.Millisecond, func() {
185        vm.Interrupt("halt")
186    })
187
188    _, err := vm.RunString(SCRIPT)
189    if err == nil {
190        t.Fatal("Err is nil")
191    }
192    // err is of type *InterruptError and its Value() method returns whatever has been passed to vm.Interrupt()
193}
194```
195
196NodeJS Compatibility
197--------------------
198
199There is a [separate project](https://github.com/dop251/goja_nodejs) aimed at providing some of the NodeJS functionality.
200