registerFactoryAsConstructor registers the factory function as native JS constructor. If there is missing or nil arguments, their type zero value is used.
(vm *goja.Runtime, constructorName string, factoryFunc any)
| 1096 | // |
| 1097 | // If there is missing or nil arguments, their type zero value is used. |
| 1098 | func registerFactoryAsConstructor(vm *goja.Runtime, constructorName string, factoryFunc any) { |
| 1099 | rv := reflect.ValueOf(factoryFunc) |
| 1100 | rt := cachedFactoryFuncTypes.GetOrSet(constructorName, func() reflect.Type { |
| 1101 | return reflect.TypeOf(factoryFunc) |
| 1102 | }) |
| 1103 | totalArgs := rt.NumIn() |
| 1104 | |
| 1105 | vm.Set(constructorName, func(call goja.ConstructorCall) *goja.Object { |
| 1106 | args := make([]reflect.Value, totalArgs) |
| 1107 | |
| 1108 | for i := 0; i < totalArgs; i++ { |
| 1109 | v := call.Argument(i).Export() |
| 1110 | |
| 1111 | // use the arg type zero value |
| 1112 | if v == nil { |
| 1113 | args[i] = reflect.New(rt.In(i)).Elem() |
| 1114 | } else if number, ok := v.(int64); ok { |
| 1115 | // goja uses int64 for "int"-like numbers but we rarely do that and use int most of the times |
| 1116 | // (at later stage we can use reflection on the arguments to validate the types in case this is not sufficient anymore) |
| 1117 | args[i] = reflect.ValueOf(int(number)) |
| 1118 | } else { |
| 1119 | args[i] = reflect.ValueOf(v) |
| 1120 | } |
| 1121 | } |
| 1122 | |
| 1123 | result := rv.Call(args) |
| 1124 | |
| 1125 | if len(result) != 1 { |
| 1126 | panic("the factory function should return only 1 item") |
| 1127 | } |
| 1128 | |
| 1129 | value := vm.ToValue(result[0].Interface()).(*goja.Object) |
| 1130 | value.SetPrototype(call.This.Prototype()) |
| 1131 | |
| 1132 | return value |
| 1133 | }) |
| 1134 | } |
| 1135 | |
| 1136 | // structConstructor wraps the provided struct with a native JS constructor. |
| 1137 | // |