Browse Source

Make Export() for classes return func(ConstructorCall) *Object. Closes #671

Dmitry Panov 3 months ago
parent
commit
c0d5092cad
3 changed files with 27 additions and 1 deletions
  1. 9 1
      func.go
  2. 15 0
      runtime_test.go
  3. 3 0
      value.go

+ 9 - 1
func.go

@@ -293,8 +293,16 @@ func (f *classFuncObject) vmCall(vm *vm, n int) {
 	f.Call(FunctionCall{})
 }
 
+func (f *classFuncObject) exportType() reflect.Type {
+	return reflectTypeCtor
+}
+
+func (f *classFuncObject) Construct(ccall ConstructorCall) *Object {
+	return f.construct(ccall.Arguments, ccall.NewTarget)
+}
+
 func (f *classFuncObject) export(*objectExportCtx) interface{} {
-	return f.Call
+	return f.Construct
 }
 
 func (f *classFuncObject) createInstance(args []Value, newTarget *Object) (instance *Object) {

+ 15 - 0
runtime_test.go

@@ -3117,6 +3117,21 @@ func TestToValueNilBigInt(t *testing.T) {
 	vm.testScript(`n === 0n`, valueTrue, t)
 }
 
+func TestClassReexport(t *testing.T) {
+	vm := New()
+	vm.Set("m", map[string]any{})
+	vm.testScript(`
+	class C {
+		constructor() {
+			this.test = true;
+		}
+	}
+	m.C = C; // this does Export()
+	const c = new m.C() // 'm.C' does ToValue()
+	c instanceof C && c.test;
+	`, valueTrue, t)
+}
+
 /*
 func TestArrayConcatSparse(t *testing.T) {
 function foo(a,b,c)

+ 3 - 0
value.go

@@ -53,6 +53,7 @@ var (
 	reflectTypeArrayPtr = reflect.TypeOf((*[]interface{})(nil))
 	reflectTypeString   = reflect.TypeOf("")
 	reflectTypeFunc     = reflect.TypeOf((func(FunctionCall) Value)(nil))
+	reflectTypeCtor     = reflect.TypeOf((func(ConstructorCall) *Object)(nil))
 	reflectTypeError    = reflect.TypeOf((*error)(nil)).Elem()
 )
 
@@ -764,6 +765,8 @@ func (o *Object) baseObject(*Runtime) *Object {
 // Export the Object to a plain Go type.
 // If the Object is a wrapped Go value (created using ToValue()) returns the original value.
 //
+// If the Object is a class function, returns func(ConstructorCall) *Object. See the note about exceptions below.
+//
 // If the Object is a function, returns func(FunctionCall) Value. Note that exceptions thrown inside the function
 // result in panics, which can also leave the Runtime in an unusable state. Therefore, these values should only
 // be used inside another ES function implemented in Go. For calling a function from Go, use AssertFunction() or