-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathmain.go
116 lines (100 loc) · 3.1 KB
/
main.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
package main
import (
"text/template"
"github.com/drakedevel/go-text-template-napi/internal/napi"
)
type moduleData struct {
templateConstructor napi.Ref
envStack envStack
}
func getInstanceData(env napi.Env) (*moduleData, error) {
raw, err := napi.GetInstanceData(env)
if err != nil {
return nil, err
}
return raw.(*moduleData), nil
}
func moduleTeardown(env napi.Env, data interface{}) error {
modData := data.(*moduleData)
if err := env.DeleteReference(modData.templateConstructor); err != nil {
return err
}
return nil
}
type propBuilder func(napi.Env, string) (napi.Value, error)
func makeHelperBuilder(impl staticMethodFunc, minArgs int) propBuilder {
return func(env napi.Env, name string) (napi.Value, error) {
// TODO: Don't leak cbData
cb, cbData, _ := makeStaticMethodCallback(impl, minArgs)
return env.CreateFunction(name, cbData, cb)
}
}
func makeEscapeStringBuilder(fn func(string) string) propBuilder {
return makeHelperBuilder(func(env napi.Env, args []napi.Value) (napi.Value, error) {
str, err := jsStringToGo(env, args[0])
if err != nil {
return nil, err
}
return env.CreateString(fn(str))
}, 1)
}
func makeEscaperBuilder(fn func(...any) string) propBuilder {
return makeHelperBuilder(func(env napi.Env, args []napi.Value) (napi.Value, error) {
goArgs, err := jsValuesToGo(env, args, jsValueToGo)
if err != nil {
return nil, err
}
return env.CreateString(fn(goArgs...))
}, 0)
}
func moduleInit(env napi.Env, exports napi.Value) (napi.Value, error) {
// Build module properties values
propBuilders := map[string]propBuilder{
"Template": buildTemplateClass,
"htmlEscapeString": makeEscapeStringBuilder(template.HTMLEscapeString),
"htmlEscaper": makeEscaperBuilder(template.HTMLEscaper),
"jsEscapeString": makeEscapeStringBuilder(template.JSEscapeString),
"jsEscaper": makeEscaperBuilder(template.JSEscaper),
"urlQueryEscaper": makeEscaperBuilder(template.URLQueryEscaper),
}
propValues := make(map[string]napi.Value)
for name, builder := range propBuilders {
propValue, err := builder(env, name)
if err != nil {
return nil, err
}
propValues[name] = propValue
}
// Build property descriptors and create properties
var propDescs []napi.PropertyDescriptor
for name, propValue := range propValues {
nameValue, err := env.CreateString(name)
if err != nil {
return nil, err
}
propDescs = append(propDescs, napi.PropertyDescriptor{
Name: nameValue,
Value: propValue,
Attributes: napi.Enumerable,
})
}
if err := env.DefineProperties(exports, propDescs); err != nil {
return nil, err
}
// Attach an object for "global" state to this instance of the module
modData := moduleData{nil, newEnvStack()}
if err := napi.SetInstanceData(env, &modData, moduleTeardown); err != nil {
return nil, err
}
// Create a reference to the Template class and save it in the module data
clsRef, err := env.CreateReference(propValues["Template"], 1)
if err != nil {
return nil, err
}
modData.templateConstructor = clsRef
return exports, nil
}
func init() {
napi.SetModuleInit(moduleInit)
}
func main() {}