forked from rogchap/v8go
-
Notifications
You must be signed in to change notification settings - Fork 1
/
arraybuffer_test.go
152 lines (132 loc) · 4.17 KB
/
arraybuffer_test.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
package v8go_test
import (
"errors"
"fmt"
"testing"
v8 "rogchap.com/v8go"
)
func reverseArrayBufferFunctionCallback(info *v8.FunctionCallbackInfo) *v8.Value {
iso := info.Context().Isolate()
args := info.Args()
if len(args) != 1 {
e, _ := v8.NewValue(iso, "Function ReverseArrayBuffer expects 1 parameter")
return iso.ThrowException(e)
}
if !args[0].IsArrayBuffer() {
e, _ := v8.NewValue(iso, "Function ReverseArrayBuffer expects ArrayBuffer parameter")
return iso.ThrowException(e)
}
ab := args[0].ArrayBuffer() // "cast" to ArrayBuffer
length := int(ab.ByteLength())
bytes := ab.GetBytes() // get a copy of the bytes from the ArrayBuffer
reversed := make([]uint8, length)
for i := 0; i < length; i++ {
reversed[i] = bytes[length-i-1]
}
ab.PutBytes(reversed) // update the bytes in the ArrayBuffer (length must match!)
return nil
}
func createArrayBufferFunctionCallback(info *v8.FunctionCallbackInfo) *v8.Value {
iso := info.Context().Isolate()
args := info.Args()
if len(args) != 1 {
e, _ := v8.NewValue(iso, "Function CreateArrayBuffer expects 1 parameter")
return iso.ThrowException(e)
}
if !args[0].IsInt32() {
e, _ := v8.NewValue(iso, "Function CreateArrayBuffer expects Int32 parameter")
return iso.ThrowException(e)
}
length := args[0].Int32()
ab := v8.NewArrayBuffer(info.Context(), int64(length)) // create ArrayBuffer object of given length
bytes := make([]uint8, length)
for i := uint8(0); i < uint8(length); i++ {
bytes[i] = i
}
ab.PutBytes(bytes) // copy these bytes into it. Caller is responsible for avoiding overruns!
return ab.Value // return the ArrayBuffer to javascript
}
func injectArrayBufferTester(ctx *v8.Context, funcName string, funcCb v8.FunctionCallback) error {
if ctx == nil {
return errors.New("injectArrayBufferTester: ctx is required")
}
iso := ctx.Isolate()
con := v8.NewObjectTemplate(iso)
funcTempl := v8.NewFunctionTemplate(iso, funcCb)
if err := con.Set(funcName, funcTempl, v8.ReadOnly); err != nil {
return fmt.Errorf("injectArrayBufferTester: %v", err)
}
nativeObj, err := con.NewInstance(ctx)
if err != nil {
return fmt.Errorf("injectArrayBufferTester: %v", err)
}
global := ctx.Global()
if err := global.Set("native", nativeObj); err != nil {
return fmt.Errorf("injectArrayBufferTester: %v", err)
}
return nil
}
// Test that a script can call a go function to reverse an ArrayBuffer.
// The function reverses the ArrayBuffer in-place, i.e. this is a call-by-reference.
func TestModifyArrayBuffer(t *testing.T) {
t.Parallel()
iso := v8.NewIsolate()
ctx := v8.NewContext(iso)
if err := injectArrayBufferTester(ctx, "reverseArrayBuffer", reverseArrayBufferFunctionCallback); err != nil {
t.Error(err)
}
js := `
let ab = new ArrayBuffer(10);
let view = new Uint8Array(ab);
for (let i = 0; i < 10; i++) view[i] = i;
native.reverseArrayBuffer(ab);
ab;
`
if val, err := ctx.RunScript(js, ""); err != nil {
t.Error(err)
} else {
if !val.IsArrayBuffer() {
t.Errorf("Expected ArrayBuffer return value")
}
ab := val.ArrayBuffer()
if ab.ByteLength() != 10 {
t.Errorf("Got wrong ArrayBuffer length %d, expected 10", ab.ByteLength())
}
bytes := ab.GetBytes()
fmt.Printf("Got reversed ArrayBuffer from script: %v\n", bytes)
for i := int64(0); i < ab.ByteLength(); i++ {
if bytes[i] != uint8(10-i-1) {
t.Errorf("Incorrect byte at index %d (whole array: %v)", i, ab)
}
}
}
}
func TestCreateArrayBuffer(t *testing.T) {
t.Parallel()
iso := v8.NewIsolate()
ctx := v8.NewContext(iso)
if err := injectArrayBufferTester(ctx, "createArrayBuffer", createArrayBufferFunctionCallback); err != nil {
t.Error(err)
}
js := `
native.createArrayBuffer(16);
`
if val, err := ctx.RunScript(js, ""); err != nil {
t.Error(err)
} else {
if !val.IsArrayBuffer() {
t.Errorf("Expected ArrayBuffer return value")
}
ab := val.ArrayBuffer()
if ab.ByteLength() != 16 {
t.Errorf("Got wrong ArrayBuffer length %d, expected 16", ab.ByteLength())
}
bytes := ab.GetBytes()
fmt.Printf("Got ArrayBuffer from script: %v\n", bytes)
for i := int64(0); i < ab.ByteLength(); i++ {
if bytes[i] != uint8(i) {
t.Errorf("Incorrect byte at index %d (whole array: %v)", i, bytes)
}
}
}
}