Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
projectdiscovery
GitHub Repository: projectdiscovery/nuclei
Path: blob/dev/pkg/js/utils/nucleijs.go
2070 views
1
package utils
2
3
import (
4
"fmt"
5
"reflect"
6
"strings"
7
"sync"
8
9
"github.com/Mzack9999/goja"
10
)
11
12
// temporary on demand runtime to throw errors when vm is not available
13
var (
14
tmpRuntime *goja.Runtime
15
runtimeInit func() = sync.OnceFunc(func() {
16
tmpRuntime = goja.New()
17
})
18
)
19
20
func getRuntime() *goja.Runtime {
21
runtimeInit()
22
return tmpRuntime
23
}
24
25
// NucleiJS is js bindings that handles goja runtime related issue
26
// and allows setting a defer statements to close resources
27
type NucleiJS struct {
28
vm *goja.Runtime
29
ObjectSig string
30
}
31
32
// NewNucleiJS creates a new nucleijs instance
33
func NewNucleiJS(vm *goja.Runtime) *NucleiJS {
34
return &NucleiJS{vm: vm}
35
}
36
37
// internal runtime getter
38
func (j *NucleiJS) runtime() *goja.Runtime {
39
if j == nil {
40
return getRuntime()
41
}
42
return j.vm
43
}
44
45
func (j *NucleiJS) ExecutionId() string {
46
executionId, ok := j.vm.GetContextValue("executionId")
47
if !ok {
48
return ""
49
}
50
return executionId.(string)
51
}
52
53
// see: https://arc.net/l/quote/wpenftpc for throwing docs
54
55
// ThrowError throws an error in goja runtime if is not nil
56
func (j *NucleiJS) ThrowError(err error) {
57
if err == nil {
58
return
59
}
60
panic(j.runtime().ToValue(err.Error()))
61
}
62
63
// HandleError handles error and throws a
64
func (j *NucleiJS) HandleError(err error, msg ...string) {
65
if err == nil {
66
return
67
}
68
if len(msg) == 0 {
69
j.ThrowError(err)
70
}
71
j.Throw("%s: %s", strings.Join(msg, ":"), err.Error())
72
}
73
74
// Throw throws an error in goja runtime
75
func (j *NucleiJS) Throw(format string, args ...interface{}) {
76
if len(args) > 0 {
77
panic(j.runtime().ToValue(fmt.Sprintf(format, args...)))
78
}
79
80
panic(j.runtime().ToValue(format))
81
}
82
83
// GetArg returns argument at index from goja runtime if not found throws error
84
func (j *NucleiJS) GetArg(args []goja.Value, index int) any {
85
if index >= len(args) {
86
j.Throw("Missing argument at index %v: %v", index, j.ObjectSig)
87
}
88
val := args[index]
89
if goja.IsUndefined(val) {
90
j.Throw("Missing argument at index %v: %v", index, j.ObjectSig)
91
}
92
return val.Export()
93
}
94
95
// GetArgSafe returns argument at index from goja runtime if not found returns default value
96
func (j *NucleiJS) GetArgSafe(args []goja.Value, index int, defaultValue any) any {
97
if index >= len(args) {
98
return defaultValue
99
}
100
val := args[index]
101
if goja.IsUndefined(val) {
102
return defaultValue
103
}
104
return val.Export()
105
}
106
107
// Require throws an error if expression is false
108
func (j *NucleiJS) Require(expr bool, msg string) {
109
if !expr {
110
j.Throw("%s", msg)
111
}
112
}
113
114
// LinkConstructor links a type with invocation doing this allows
115
// usage of instance of type in js
116
func LinkConstructor[T any](call goja.ConstructorCall, vm *goja.Runtime, obj T) *goja.Object {
117
instance := vm.ToValue(obj).(*goja.Object)
118
_ = instance.SetPrototype(call.This.Prototype())
119
return instance
120
}
121
122
// GetStructType gets a type defined in go and passed as argument from goja runtime if not found throws error
123
// Donot use this unless you are accepting a struct type from constructor
124
func GetStructType[T any](nj *NucleiJS, args []goja.Value, index int, FuncSig string) T {
125
if nj == nil {
126
nj = &NucleiJS{}
127
}
128
if index >= len(args) {
129
if FuncSig == "" {
130
nj.Throw("Missing argument at index %v", index)
131
}
132
nj.Throw("Missing arguments expected : %v", FuncSig)
133
}
134
value := args[index]
135
// validate type
136
var ptr T
137
expected := reflect.ValueOf(ptr).Type()
138
argType := expected.Name()
139
valueType := value.ExportType().Name()
140
141
if argType != valueType {
142
nj.Throw("Type Mismatch expected %v got %v", argType, valueType)
143
}
144
145
ptrValue := reflect.New(expected).Elem()
146
ptrValue.Set(reflect.ValueOf(value.Export()))
147
148
return ptrValue.Interface().(T)
149
}
150
151
// GetStructTypeSafe gets an type defined in go and passed as argument from goja runtime if not found returns default value
152
// Donot use this unless you are accepting a struct type from constructor
153
func GetStructTypeSafe[T any](nj *NucleiJS, args []goja.Value, index int, defaultValue T) T {
154
if nj == nil {
155
nj = &NucleiJS{}
156
}
157
if index >= len(args) {
158
return defaultValue
159
}
160
value := args[index]
161
// validate type
162
var ptr T
163
argType := reflect.ValueOf(ptr).Type().Name()
164
valueType := value.ExportType().Name()
165
166
if argType != valueType {
167
return defaultValue
168
}
169
return value.ToObject(nj.runtime()).Export().(T)
170
}
171
172