|
15 | 15 | package server
|
16 | 16 |
|
17 | 17 | import (
|
18 |
| - "strings" |
19 |
| - "testing" |
20 |
| - |
| 18 | + "encoding/json" |
21 | 19 | "github.com/dop251/goja"
|
22 | 20 | "go.uber.org/zap"
|
23 | 21 | "go.uber.org/zap/zaptest/observer"
|
| 22 | + "strings" |
| 23 | + "testing" |
24 | 24 | )
|
25 | 25 |
|
26 | 26 | func TestJsObjectFreeze(t *testing.T) {
|
@@ -112,3 +112,61 @@ m.get('a');
|
112 | 112 | }
|
113 | 113 | })
|
114 | 114 | }
|
| 115 | + |
| 116 | +const data = `{"title_data":{"ads_config": [1,2,3]}}` |
| 117 | + |
| 118 | +// go test -run=XXX -bench=BenchmarkParse ./... |
| 119 | +// go test -run=XXX -bench=BenchmarkParse ./... -benchmem |
| 120 | +func BenchmarkParseJsonGo(b *testing.B) { |
| 121 | + vm := goja.New() |
| 122 | + b.ResetTimer() |
| 123 | + for i := 0; i < b.N; i++ { |
| 124 | + v, err := jsJsonParse(vm, data) |
| 125 | + if err != nil { |
| 126 | + b.Fatal(err) |
| 127 | + } |
| 128 | + vm.Set("data", v) |
| 129 | + vm.RunString(`data.foo = []; data.foo.push(3)`) |
| 130 | + } |
| 131 | +} |
| 132 | +func BenchmarkParseJsonGoja(b *testing.B) { |
| 133 | + vm := goja.New() |
| 134 | + b.ResetTimer() |
| 135 | + for i := 0; i < b.N; i++ { |
| 136 | + var out map[string]any |
| 137 | + if err := json.Unmarshal([]byte(data), &out); err != nil { |
| 138 | + b.Fatal(err) |
| 139 | + } |
| 140 | + pointerizeSlices(out) |
| 141 | + vm.Set("data", out) |
| 142 | + vm.RunString(`data.foo = []; data.foo.push(3)`) |
| 143 | + } |
| 144 | +} |
| 145 | + |
| 146 | +// pointerizeSlices recursively walks a map[string]interface{} and replaces any []interface{} references for *[]interface{}. |
| 147 | +// This is needed to allow goja operations that resize a JS wrapped Go slice to work as expected, otherwise |
| 148 | +// such operations won't reflect on the original slice as it would be passed by value and not by reference. |
| 149 | +func pointerizeSlices(m interface{}) { |
| 150 | + switch i := m.(type) { |
| 151 | + case map[string]interface{}: |
| 152 | + for k, v := range i { |
| 153 | + if s, ok := v.([]interface{}); ok { |
| 154 | + i[k] = &s |
| 155 | + pointerizeSlices(&s) |
| 156 | + } |
| 157 | + if mi, ok := v.(map[string]interface{}); ok { |
| 158 | + pointerizeSlices(mi) |
| 159 | + } |
| 160 | + } |
| 161 | + case *[]interface{}: |
| 162 | + for idx, v := range *i { |
| 163 | + if s, ok := v.([]interface{}); ok { |
| 164 | + (*i)[idx] = &s |
| 165 | + pointerizeSlices(&s) |
| 166 | + } |
| 167 | + if mi, ok := v.(map[string]interface{}); ok { |
| 168 | + pointerizeSlices(mi) |
| 169 | + } |
| 170 | + } |
| 171 | + } |
| 172 | +} |
0 commit comments