diff --git a/.github/workflows/emscripten.yml b/.github/workflows/emscripten.yml index 796d6dd..7bc1df8 100644 --- a/.github/workflows/emscripten.yml +++ b/.github/workflows/emscripten.yml @@ -15,7 +15,7 @@ jobs: strategy: fail-fast: false matrix: - emscripten: [ "3.1.44", "3.1.45", "3.1.46", "3.1.47" ] + emscripten: [ "3.1.44", "3.1.45", "3.1.46", "3.1.47", "3.1.48", "3.1.49", "3.1.50" ] runs-on: "ubuntu-latest" steps: - uses: actions/checkout@v3 diff --git a/examples/classes/wasm/classes.wasm b/examples/classes/wasm/classes.wasm index 7484182..ef78452 100755 Binary files a/examples/classes/wasm/classes.wasm and b/examples/classes/wasm/classes.wasm differ diff --git a/examples/enums-and-constants/wasm/enums_and_constants.wasm b/examples/enums-and-constants/wasm/enums_and_constants.wasm index 438e316..f08e38f 100755 Binary files a/examples/enums-and-constants/wasm/enums_and_constants.wasm and b/examples/enums-and-constants/wasm/enums_and_constants.wasm differ diff --git a/examples/hello-world/wasm/hello_world.wasm b/examples/hello-world/wasm/hello_world.wasm index 1f185fb..9c3ccbd 100755 Binary files a/examples/hello-world/wasm/hello_world.wasm and b/examples/hello-world/wasm/hello_world.wasm differ diff --git a/internal/array.go b/internal/array.go index 25c6cd4..db88af4 100644 --- a/internal/array.go +++ b/internal/array.go @@ -209,7 +209,7 @@ var FinalizeValueArray = api.GoModuleFunc(func(ctx context.Context, mod api.Modu baseType: baseType{ rawType: rawTupleType, name: reg.name, - argPackAdvance: 8, + argPackAdvance: GenericWireTypeSize, }, reg: reg, elementsLength: elementsLength, diff --git a/internal/bigint.go b/internal/bigint.go index de8d589..8b86253 100644 --- a/internal/bigint.go +++ b/internal/bigint.go @@ -97,7 +97,7 @@ var RegisterBigInt = api.GoModuleFunc(func(ctx context.Context, mod api.Module, baseType: baseType{ rawType: rawType, name: name, - argPackAdvance: 8, + argPackAdvance: GenericWireTypeSize, }, size: api.DecodeI32(stack[2]), signed: !strings.HasPrefix(name, "u"), diff --git a/internal/bool.go b/internal/bool.go index dd8cbc2..308f234 100644 --- a/internal/bool.go +++ b/internal/bool.go @@ -150,7 +150,7 @@ var RegisterBool = func(hasSize bool) api.GoModuleFunc { baseType: baseType{ rawType: rawType, name: name, - argPackAdvance: 8, + argPackAdvance: GenericWireTypeSize, }, size: size, trueVal: trueVal, diff --git a/internal/class.go b/internal/class.go index f01e207..c60f9b7 100644 --- a/internal/class.go +++ b/internal/class.go @@ -646,7 +646,7 @@ var RegisterClass = api.GoModuleFunc(func(ctx context.Context, mod api.Module, s referenceConverter := ®isteredPointerType{ baseType: baseType{ - argPackAdvance: 8, + argPackAdvance: GenericWireTypeSize, name: name, }, registeredClass: engine.registeredClasses[name], @@ -657,7 +657,7 @@ var RegisterClass = api.GoModuleFunc(func(ctx context.Context, mod api.Module, s pointerConverter := ®isteredPointerType{ baseType: baseType{ - argPackAdvance: 8, + argPackAdvance: GenericWireTypeSize, name: name + "*", }, registeredClass: engine.registeredClasses[name], @@ -668,7 +668,7 @@ var RegisterClass = api.GoModuleFunc(func(ctx context.Context, mod api.Module, s constPointerConverter := ®isteredPointerType{ baseType: baseType{ - argPackAdvance: 8, + argPackAdvance: GenericWireTypeSize, name: name + " const*", }, registeredClass: engine.registeredClasses[name], @@ -805,6 +805,11 @@ var RegisterClassFunction = api.GoModuleFunc(func(ctx context.Context, mod api.M panic(fmt.Errorf("could not read method name: %w", err)) } + methodName, err = getFunctionName(methodName) + if err != nil { + panic(fmt.Errorf("could not read method name: %w", err)) + } + err = engine.whenDependentTypesAreResolved([]int32{}, []int32{rawClassType}, func(classTypes []registeredType) ([]registeredType, error) { classType := classTypes[0].(*registeredPointerType) humanName := classType.Name() + "." + methodName @@ -937,6 +942,11 @@ var RegisterClassClassFunction = api.GoModuleFunc(func(ctx context.Context, mod panic(fmt.Errorf("could not read method name: %w", err)) } + methodName, err = getFunctionName(methodName) + if err != nil { + panic(fmt.Errorf("could not read method name: %w", err)) + } + err = engine.whenDependentTypesAreResolved([]int32{}, []int32{rawClassType}, func(classTypes []registeredType) ([]registeredType, error) { classType := classTypes[0].(*registeredPointerType) humanName := classType.Name() + "." + methodName @@ -1356,7 +1366,7 @@ var RegisterSmartPtr = api.GoModuleFunc(func(ctx context.Context, mod api.Module smartPointerType := ®isteredPointerType{ baseType: baseType{ - argPackAdvance: 8, + argPackAdvance: GenericWireTypeSize, name: name, }, registeredClass: pointeeType.(*registeredPointerType).registeredClass, diff --git a/internal/embind.go b/internal/embind.go index 599b62a..0278598 100644 --- a/internal/embind.go +++ b/internal/embind.go @@ -5,6 +5,7 @@ import ( "errors" "fmt" "reflect" + "strings" "github.com/tetratelabs/wazero/api" ) @@ -105,3 +106,15 @@ func CreateEngine(config IEngineConfig) IEngine { emvalEngine: createEmvalEngine(), } } + +const GenericWireTypeSize = 8 + +func getFunctionName(signature string) (string, error) { + signature = strings.TrimSpace(signature) + argsIndex := strings.Index(signature, "(") + if argsIndex != -1 { + return signature[0:argsIndex], nil + } + + return signature, nil +} diff --git a/internal/emval.go b/internal/emval.go index 91ec174..ce4dd5b 100644 --- a/internal/emval.go +++ b/internal/emval.go @@ -161,6 +161,7 @@ type emvalRegisteredMethod struct { id int32 argTypes []registeredType name string + kind *int32 // FUNCTION == 0, CONSTRUCTOR == 1 } type emvalEngine struct { @@ -283,82 +284,98 @@ func (e *emvalEngine) getElemField(symbol any, field string) (*reflect.Value, er return nil, fmt.Errorf("could not find field \"%s\" by embind_property tag, name or by %s", field, upperFirst) } -func (e *emvalEngine) callMethod(ctx context.Context, mod api.Module, registeredMethod *emvalRegisteredMethod, handle any, methodName string, destructorsRef, argsBase uint32) (uint64, error) { - var matchedMethod *reflect.Method - st := reflect.TypeOf(handle) - - c, ok := handle.(IEmvalFunctionMapper) - if ok { - argCount := len(registeredMethod.argTypes) - argTypeNames := make([]string, argCount-1) - for i := 1; i < argCount; i++ { - argTypeNames[i-1] = registeredMethod.argTypes[i].Name() - } - mappedFunction, err := c.MapFunction(methodName, registeredMethod.argTypes[0].Name(), argTypeNames) +func (e *emvalEngine) callMethod(ctx context.Context, mod api.Module, registeredMethod *emvalRegisteredMethod, obj any, methodToCall *reflect.Value, destructorsRef, argsBase uint32, injectCtx bool) (uint64, error) { + var err error + argCount := len(registeredMethod.argTypes) + args := make([]any, argCount) + argTypeNames := make([]string, argCount) + for i := 1; i < argCount; i++ { + args[i], err = registeredMethod.argTypes[i].ReadValueFromPointer(ctx, mod, argsBase) if err != nil { - return 0, fmt.Errorf("mapper function of type %T returned error: %w", handle, err) + return 0, fmt.Errorf("could not read arg value from pointer for arg %d, %w", i-1, err) } - if mappedFunction != "" { - m, ok := st.MethodByName(mappedFunction) - if ok { - matchedMethod = &m - } else { - return 0, fmt.Errorf("mapper function of type %T returned method %s, but method could not be found", handle, mappedFunction) - } - } + argsBase += uint32(registeredMethod.argTypes[i].ArgPackAdvance()) + argTypeNames[i] = registeredMethod.argTypes[i].Name() } - actualMethodName := methodName - if matchedMethod == nil { - manualMap := map[string]string{ - "__destruct": "deleteInheritedInstance", + if methodToCall == nil && registeredMethod.kind != nil { + if *registeredMethod.kind == 0 { + objMethod := reflect.ValueOf(obj) + methodToCall = &objMethod } + if *registeredMethod.kind == 1 { + var res any + c, ok := obj.(IEmvalConstructor) + if ok { + res, err = c.New(argTypeNames[1:], args...) + if err != nil { + panic(fmt.Errorf("could not instaniate new value on %T with New(): %w", obj, err)) + } + } else { + typeElem := reflect.TypeOf(obj) - _, ok := manualMap[methodName] - if ok { - methodName = manualMap[methodName] - } + // If we received a pointer, resolve the struct behind it. + if typeElem.Kind() == reflect.Pointer { + typeElem = typeElem.Elem() + } - m, ok := st.MethodByName(methodName) - if ok { - matchedMethod = &m - } else { - actualMethodName = string(unicode.ToUpper(rune(methodName[0]))) + methodName[1:] - m, ok = st.MethodByName(actualMethodName) - if ok { - matchedMethod = &m - } - } - } + // Make new instance of struct. + newElem := reflect.New(typeElem) - if matchedMethod == nil { - return 0, fmt.Errorf("type %T does not have method name %s or %s and was also not mapped by the EmvalFunctionMapper interface", handle, methodName, actualMethodName) - } + // Set the values on the struct if we need to/can. + if argCount > 1 { + if typeElem.Kind() != reflect.Struct { + panic(fmt.Errorf("could not instaniate new value of %T: arguments required but can only be set on a struct", obj)) + } - if !matchedMethod.IsExported() { - return 0, fmt.Errorf("the method name %s on type %T is not exported", methodName, handle) - } + for i := 1; i < argCount; i++ { + argSet := false + for fieldI := 0; fieldI < typeElem.NumField(); fieldI++ { + var err error + func() { + defer func() { + if recoverErr := recover(); recoverErr != nil { + realError, ok := recoverErr.(error) + if ok { + err = fmt.Errorf("could not set arg %d with embind_arg tag on emval %T: %w", i-1, obj, realError) + } + err = fmt.Errorf("could not set arg %d with embind_arg tag on emval %T: %v", i-1, obj, recoverErr) + } + }() + + val := typeElem.Field(fieldI) + if val.Tag.Get("embind_arg") == strconv.Itoa(i-1) { + f := newElem.Elem().FieldByName(val.Name) + if f.IsValid() && f.CanSet() { + f.Set(reflect.ValueOf(args[i])) + argSet = true + } + } + }() + if err != nil { + panic(fmt.Errorf("could not instaniate new value of %T: %w", obj, err)) + } + } + if !argSet { + panic(fmt.Errorf("could not instaniate new value of %T: could not bind arg %d", obj, i-1)) + } + } + } - var err error - argCount := len(registeredMethod.argTypes) - args := make([]any, argCount) - for i := 1; i < argCount; i++ { - args[i], err = registeredMethod.argTypes[i].ReadValueFromPointer(ctx, mod, argsBase) - if err != nil { - return 0, fmt.Errorf("could not read arg value from pointer for arg %d, %w", i-1, err) - } + if reflect.TypeOf(obj).Kind() == reflect.Pointer { + res = newElem.Interface() + } else { + res = newElem.Elem().Interface() + } + } - argsBase += uint32(registeredMethod.argTypes[i].ArgPackAdvance()) - } + newRes, err := EmvalReturnValue(ctx, mod, registeredMethod.argTypes[0], destructorsRef, res) + if err != nil { + return 0, fmt.Errorf("could not call EmvalReturnValue on response") + } - var destructors *[]*destructorFunc - if destructorsRef != 0 { - var destructors = &[]*destructorFunc{} - rd := e.toHandle(destructors) - ok = mod.Memory().WriteUint32Le(destructorsRef, uint32(rd)) - if !ok { - return 0, fmt.Errorf("could not write destructor ref to memory") + return newRes, nil } } @@ -378,14 +395,12 @@ func (e *emvalEngine) callMethod(ctx context.Context, mod api.Module, registered callArgs[i-1] = reflect.ValueOf(args[i]) } - // Workaround to pass a context on to DeleteInheritedInstance. - if matchedMethod.Name == "DeleteInheritedInstance" { + if injectCtx { callArgs = make([]reflect.Value, 1) callArgs[0] = reflect.ValueOf(ctx) } - resultData := reflect.ValueOf(handle).MethodByName(matchedMethod.Name).Call(callArgs) - + resultData := methodToCall.Call(callArgs) for i := 1; i < argCount; i++ { if registeredMethod.argTypes[i].HasDeleteObject() { err = registeredMethod.argTypes[i].DeleteObject(ctx, mod, args[i]) @@ -395,7 +410,7 @@ func (e *emvalEngine) callMethod(ctx context.Context, mod api.Module, registered } } - _, ok = registeredMethod.argTypes[0].(*voidType) + _, ok := registeredMethod.argTypes[0].(*voidType) if ok { if len(resultData) > 1 { return 0, fmt.Errorf("wrong result type count, got %d, need at most 1 (error)", len(resultData)) @@ -415,8 +430,8 @@ func (e *emvalEngine) callMethod(ctx context.Context, mod api.Module, registered return 0, nil } - if len(resultData) < 1 { - return 0, fmt.Errorf("wrong result type count, got %d, need at least 1 and at most 2 (value and error)", len(resultData)) + if len(resultData) == 0 { + return 0, nil } if len(resultData) == 2 { @@ -431,9 +446,9 @@ func (e *emvalEngine) callMethod(ctx context.Context, mod api.Module, registered } rv := resultData[0].Interface() - res, err := registeredMethod.argTypes[0].ToWireType(ctx, mod, destructors, rv) + res, err := EmvalReturnValue(ctx, mod, registeredMethod.argTypes[0], destructorsRef, rv) if err != nil { - return 0, fmt.Errorf("could not call ToWireType on response") + return 0, fmt.Errorf("could not call EmvalReturnValue on response") } return res, nil @@ -452,7 +467,7 @@ var RegisterEmval = api.GoModuleFunc(func(ctx context.Context, mod api.Module, s baseType: baseType{ rawType: rawType, name: name, - argPackAdvance: 8, + argPackAdvance: GenericWireTypeSize, }, }, ®isterTypeOptions{ ignoreDuplicateRegistrations: true, @@ -528,34 +543,56 @@ var EmvalGetGlobal = api.GoModuleFunc(func(ctx context.Context, mod api.Module, } }) -var EmvalAs = api.GoModuleFunc(func(ctx context.Context, mod api.Module, stack []uint64) { +func EmvalReturnValue(ctx context.Context, mod api.Module, returnType registeredType, destructorsRef uint32, handle any) (uint64, error) { engine := MustGetEngineFromContext(ctx, mod).(*engine) - id := api.DecodeI32(stack[0]) - handle, err := engine.emvalEngine.toValue(id) + + var destructors = &[]*destructorFunc{} + returnVal, err := returnType.ToWireType(ctx, mod, destructors, handle) if err != nil { - panic(fmt.Errorf("could not find handle: %w", err)) + return 0, fmt.Errorf("could not call toWireType on _emval_as: %w", err) + } + + // Default of 0 to reset value at memory address. + rd := int32(0) + + // Only create destructor ref when needed. + if destructors != nil && len(*destructors) > 0 { + rd = engine.emvalEngine.toHandle(destructors) + } + + ok := mod.Memory().WriteUint32Le(destructorsRef, uint32(rd)) + if !ok { + return 0, fmt.Errorf("could not write destructor ref to memory") } + return returnVal, nil +} + +var EmvalAs = api.GoModuleFunc(func(ctx context.Context, mod api.Module, stack []uint64) { + engine := MustGetEngineFromContext(ctx, mod).(*engine) + id := api.DecodeI32(stack[0]) + destructorsRef := uint32(api.DecodeI32(stack[2])) + returnType, err := engine.requireRegisteredType(ctx, api.DecodeI32(stack[1]), "emval::as") if err != nil { panic(fmt.Errorf("could not require registered type: %w", err)) } - var destructors = &[]*destructorFunc{} - rd := engine.emvalEngine.toHandle(destructors) - ok := mod.Memory().WriteUint32Le(uint32(api.DecodeI32(stack[2])), uint32(rd)) - if !ok { - panic(fmt.Errorf("could not write destructor ref to memory")) + handle, err := engine.emvalEngine.toValue(id) + if err != nil { + panic(fmt.Errorf("could not get value of handle: %w", err)) } - returnVal, err := returnType.ToWireType(ctx, mod, destructors, handle) + returnVal, err := EmvalReturnValue(ctx, mod, returnType, destructorsRef, handle) if err != nil { - panic(fmt.Errorf("could not call toWireType on _emval_as: %w", err)) + panic(fmt.Errorf("could not get emval return value: %w", err)) } stack[0] = api.EncodeF64(returnType.ToF64(returnVal)) }) +// This function is not used anymore since 3.1.48, it has been integrated into +// emval_call and emval_get_method_caller. var EmvalNew = api.GoModuleFunc(func(ctx context.Context, mod api.Module, stack []uint64) { engine := MustGetEngineFromContext(ctx, mod).(*engine) id := api.DecodeI32(stack[0]) @@ -797,6 +834,12 @@ var EmvalNewCString = api.GoModuleFunc(func(ctx context.Context, mod api.Module, var EmvalRunDestructors = api.GoModuleFunc(func(ctx context.Context, mod api.Module, stack []uint64) { engine := MustGetEngineFromContext(ctx, mod).(*engine) id := api.DecodeI32(stack[0]) + + // Fix emval_run_destructors for <= 3.1.46 when id is 0 (no destructors). + if id == 0 { + return + } + destructorsVal, err := engine.emvalEngine.toValue(id) if err != nil { panic(fmt.Errorf("could not find handle: %w", err)) @@ -815,95 +858,195 @@ var EmvalRunDestructors = api.GoModuleFunc(func(ctx context.Context, mod api.Mod } }) -var EmvalGetMethodCaller = api.GoModuleFunc(func(ctx context.Context, mod api.Module, stack []uint64) { - engine := MustGetEngineFromContext(ctx, mod).(*engine) +var EmvalGetMethodCaller = func(hasKind bool) api.GoModuleFunc { + return api.GoModuleFunc(func(ctx context.Context, mod api.Module, stack []uint64) { + engine := MustGetEngineFromContext(ctx, mod).(*engine) - argCount := int(api.DecodeI32(stack[0])) - argsTypeBase := uint32(api.DecodeI32(stack[1])) + argCount := int(api.DecodeI32(stack[0])) + argsTypeBase := uint32(api.DecodeI32(stack[1])) - typeNames := make([]string, argCount) - argTypes := make([]registeredType, argCount) - for i := 0; i < argCount; i++ { - argType, ok := mod.Memory().ReadUint32Le(argsTypeBase + (4 * uint32(i))) - if !ok { - panic(fmt.Errorf("could not read arg type for arg %d from memory", i)) + typeNames := make([]string, argCount) + argTypes := make([]registeredType, argCount) + for i := 0; i < argCount; i++ { + argType, ok := mod.Memory().ReadUint32Le(argsTypeBase + (4 * uint32(i))) + if !ok { + panic(fmt.Errorf("could not read arg type for arg %d from memory", i)) + } + + registeredType, err := engine.requireRegisteredType(ctx, int32(argType), fmt.Sprintf("argument %d", i)) + if err != nil { + panic(fmt.Errorf("could not require registered type: %w", err)) + } + + typeNames[i] = registeredType.Name() + argTypes[i] = registeredType } - registeredType, err := engine.requireRegisteredType(ctx, int32(argType), fmt.Sprintf("argument %d", i)) - if err != nil { - panic(fmt.Errorf("could not require registered type: %w", err)) + signatureName := typeNames[0] + "_$" + strings.Join(typeNames[1:], "_") + "$" + + id, ok := engine.emvalEngine.registeredMethodIds[signatureName] + if ok { + stack[0] = api.EncodeI32(id) + return } - typeNames[i] = registeredType.Name() - argTypes[i] = registeredType - } + newID := engine.emvalEngine.registeredMethodCount + newRegisteredMethod := &emvalRegisteredMethod{ + id: newID, + argTypes: argTypes, + name: signatureName, + } - signatureName := typeNames[0] + "_$" + strings.Join(typeNames[1:], "_") + "$" + if hasKind { + kind := api.DecodeI32(stack[2]) + newRegisteredMethod.kind = &kind + } - id, ok := engine.emvalEngine.registeredMethodIds[signatureName] - if ok { - stack[0] = api.EncodeI32(id) + engine.emvalEngine.registeredMethodIds[signatureName] = newID + engine.emvalEngine.registeredMethods[newID] = newRegisteredMethod + engine.emvalEngine.registeredMethodCount++ + + stack[0] = api.EncodeI32(newID) return - } + }) +} - newID := engine.emvalEngine.registeredMethodCount - newRegisteredMethod := &emvalRegisteredMethod{ - id: newID, - argTypes: argTypes, - name: signatureName, - } - engine.emvalEngine.registeredMethodIds[signatureName] = newID - engine.emvalEngine.registeredMethods[newID] = newRegisteredMethod - engine.emvalEngine.registeredMethodCount++ +var EmvalCall = func(hasF64Return bool) api.GoModuleFunc { + return api.GoModuleFunc(func(ctx context.Context, mod api.Module, stack []uint64) { + engine := MustGetEngineFromContext(ctx, mod).(*engine) + if hasF64Return { + caller := api.DecodeI32(stack[0]) + id := api.DecodeI32(stack[1]) + destructorsRef := uint32(api.DecodeI32(stack[2])) + argsBase := uint32(api.DecodeI32(stack[3])) - stack[0] = api.EncodeI32(newID) - return -}) + handle, err := engine.emvalEngine.toValue(id) + if err != nil { + panic(fmt.Errorf("could not find handle: %w", err)) + } -var EmvalCall = api.GoModuleFunc(func(ctx context.Context, mod api.Module, stack []uint64) { - engine := MustGetEngineFromContext(ctx, mod).(*engine) - id := api.DecodeI32(stack[0]) - argCount := api.DecodeI32(stack[1]) - argTypes := api.DecodeI32(stack[2]) - argv := api.DecodeI32(stack[3]) + registeredMethod, ok := engine.emvalEngine.registeredMethods[caller] + if !ok { + panic(fmt.Errorf("could not call method with ID %d", caller)) + } - handle, err := engine.emvalEngine.toValue(id) - if err != nil { - panic(fmt.Errorf("could not find handle: %w", err)) - } + res, err := engine.emvalEngine.callMethod(ctx, mod, registeredMethod, handle, nil, destructorsRef, argsBase, false) + if err != nil { + panic(fmt.Errorf("could not call %s on %T: %w", registeredMethod.name, handle, err)) + } + stack[0] = api.EncodeF64(float64(res)) + } else { + id := api.DecodeI32(stack[0]) + argCount := api.DecodeI32(stack[1]) + argTypes := api.DecodeI32(stack[2]) + argv := api.DecodeI32(stack[3]) - registeredArgTypes, err := engine.lookupTypes(ctx, argCount, argTypes) - if err != nil { - panic(fmt.Errorf("could not load required types: %w", err)) - } + handle, err := engine.emvalEngine.toValue(id) + if err != nil { + panic(fmt.Errorf("could not find handle: %w", err)) + } - args := make([]any, argCount) - for i := 0; i < int(argCount); i++ { - requiredType := registeredArgTypes[i] - args[i], err = requiredType.ReadValueFromPointer(ctx, mod, uint32(argv)) + registeredArgTypes, err := engine.lookupTypes(ctx, argCount, argTypes) + if err != nil { + panic(fmt.Errorf("could not load required types: %w", err)) + } + + args := make([]any, argCount) + for i := 0; i < int(argCount); i++ { + requiredType := registeredArgTypes[i] + args[i], err = requiredType.ReadValueFromPointer(ctx, mod, uint32(argv)) + if err != nil { + panic(fmt.Errorf("could not load argument value: %w", err)) + } + + argv += requiredType.ArgPackAdvance() + } + + reflectValues := make([]reflect.Value, argCount) + for i := range args { + reflectValues[i] = reflect.ValueOf(args[i]) + } + + value := reflect.ValueOf(handle) + result := value.Call(reflectValues) + + var resultVal any = types.Undefined + if len(result) > 0 { + resultVal = result[0].Interface() + } + + newHandle := engine.emvalEngine.toHandle(resultVal) + stack[0] = api.EncodeI32(newHandle) + } + }) +} + +func EmvalGetMethodOnObject(obj any, registeredMethod *emvalRegisteredMethod, methodName string) (*reflect.Value, bool, error) { + var matchedMethod *reflect.Method + st := reflect.TypeOf(obj) + + c, ok := obj.(IEmvalFunctionMapper) + if ok { + argCount := len(registeredMethod.argTypes) + argTypeNames := make([]string, argCount-1) + for i := 1; i < argCount; i++ { + argTypeNames[i-1] = registeredMethod.argTypes[i].Name() + } + mappedFunction, err := c.MapFunction(methodName, registeredMethod.argTypes[0].Name(), argTypeNames) if err != nil { - panic(fmt.Errorf("could not load argument value: %w", err)) + return nil, false, fmt.Errorf("mapper function of type %T returned error: %w", obj, err) } - argv += requiredType.ArgPackAdvance() + if mappedFunction != "" { + m, ok := st.MethodByName(mappedFunction) + if ok { + matchedMethod = &m + } else { + return nil, false, fmt.Errorf("mapper function of type %T returned method %s, but method could not be found", obj, mappedFunction) + } + } } - reflectValues := make([]reflect.Value, argCount) - for i := range args { - reflectValues[i] = reflect.ValueOf(args[i]) + actualMethodName := methodName + if matchedMethod == nil { + manualMap := map[string]string{ + "__destruct": "deleteInheritedInstance", + } + + _, ok := manualMap[methodName] + if ok { + methodName = manualMap[methodName] + } + + m, ok := st.MethodByName(methodName) + if ok { + matchedMethod = &m + } else { + actualMethodName = string(unicode.ToUpper(rune(methodName[0]))) + methodName[1:] + m, ok = st.MethodByName(actualMethodName) + if ok { + matchedMethod = &m + } + } } - value := reflect.ValueOf(handle) - result := value.Call(reflectValues) + if matchedMethod == nil { + return nil, false, fmt.Errorf("type %T does not have method name %s or %s and was also not mapped by the EmvalFunctionMapper interface", obj, methodName, actualMethodName) + } - var resultVal any = types.Undefined - if len(result) > 0 { - resultVal = result[0].Interface() + if !matchedMethod.IsExported() { + return nil, false, fmt.Errorf("the method name %s on type %T is not exported", methodName, obj) } - newHandle := engine.emvalEngine.toHandle(resultVal) - stack[0] = api.EncodeI32(newHandle) -}) + resolvedMethod := reflect.ValueOf(obj).MethodByName(matchedMethod.Name) + + // Workaround to pass a context on to DeleteInheritedInstance. + if matchedMethod.Name == "DeleteInheritedInstance" { + return &resolvedMethod, true, nil + } + + return &resolvedMethod, false, nil +} var EmvalCallMethod = api.GoModuleFunc(func(ctx context.Context, mod api.Module, stack []uint64) { engine := MustGetEngineFromContext(ctx, mod).(*engine) @@ -928,13 +1071,20 @@ var EmvalCallMethod = api.GoModuleFunc(func(ctx context.Context, mod api.Module, argsBase := uint32(api.DecodeI32(stack[4])) destructorsRef := uint32(api.DecodeI32(stack[3])) - res, err := engine.emvalEngine.callMethod(ctx, mod, registeredMethod, handle, methodName, destructorsRef, argsBase) + method, injectCtx, err := EmvalGetMethodOnObject(handle, registeredMethod, methodName) + if err != nil { + panic(fmt.Errorf("could not call %s on %T: %w", methodName, handle, err)) + } + + res, err := engine.emvalEngine.callMethod(ctx, mod, registeredMethod, handle, method, destructorsRef, argsBase, injectCtx) if err != nil { panic(fmt.Errorf("could not call %s on %T: %w", methodName, handle, err)) } stack[0] = api.EncodeF64(float64(res)) }) +// This function is not used anymore since 3.1.48, it has been integrated into +// emval_call. var EmvalCallVoidMethod = api.GoModuleFunc(func(ctx context.Context, mod api.Module, stack []uint64) { engine := MustGetEngineFromContext(ctx, mod).(*engine) caller := api.DecodeI32(stack[0]) @@ -957,7 +1107,12 @@ var EmvalCallVoidMethod = api.GoModuleFunc(func(ctx context.Context, mod api.Mod argsBase := uint32(api.DecodeI32(stack[3])) - _, err = engine.emvalEngine.callMethod(ctx, mod, registeredMethod, handle, methodName, 0, argsBase) + method, injectCtx, err := EmvalGetMethodOnObject(handle, registeredMethod, methodName) + if err != nil { + panic(fmt.Errorf("could not call %s on %T: %w", methodName, handle, err)) + } + + _, err = engine.emvalEngine.callMethod(ctx, mod, registeredMethod, handle, method, 0, argsBase, injectCtx) if err != nil { panic(fmt.Errorf("could not call %s on %T: %w", methodName, handle, err)) } diff --git a/internal/enum.go b/internal/enum.go index eb77243..75157f5 100644 --- a/internal/enum.go +++ b/internal/enum.go @@ -150,7 +150,7 @@ var RegisterEnum = api.GoModuleFunc(func(ctx context.Context, mod api.Module, st engine.registeredEnums[name].baseType = baseType{ rawType: rawType, name: name, - argPackAdvance: 8, + argPackAdvance: GenericWireTypeSize, } engine.registeredEnums[name].intHelper = intType{ diff --git a/internal/float.go b/internal/float.go index 35bb18e..2663c4f 100644 --- a/internal/float.go +++ b/internal/float.go @@ -53,7 +53,7 @@ func (ft *floatType) ReadValueFromPointer(ctx context.Context, mod api.Module, p return val, nil } - return nil, fmt.Errorf("unknown float type: %s", ft.name) + return nil, fmt.Errorf("invalid float width (%d): %s", ft.size, ft.name) } func (ft *floatType) NativeType() api.ValueType { @@ -103,7 +103,7 @@ var RegisterFloat = api.GoModuleFunc(func(ctx context.Context, mod api.Module, s baseType: baseType{ rawType: rawType, name: name, - argPackAdvance: 8, + argPackAdvance: GenericWireTypeSize, }, size: api.DecodeI32(stack[2]), }, nil) diff --git a/internal/int.go b/internal/int.go index 4cbfa9a..733c21e 100644 --- a/internal/int.go +++ b/internal/int.go @@ -115,7 +115,7 @@ func (it *intType) ReadValueFromPointer(ctx context.Context, mod api.Module, poi return int32(val), nil } - return nil, fmt.Errorf("unknown integer type: %s", it.name) + return nil, fmt.Errorf("invalid integer width (%d): %s", it.size, it.name) } func (it *intType) GoType() string { @@ -173,7 +173,7 @@ var RegisterInteger = api.GoModuleFunc(func(ctx context.Context, mod api.Module, baseType: baseType{ rawType: rawType, name: name, - argPackAdvance: 8, + argPackAdvance: GenericWireTypeSize, }, size: api.DecodeI32(stack[2]), signed: !strings.Contains(name, "unsigned"), diff --git a/internal/memory_view.go b/internal/memory_view.go index 44a91eb..dc705da 100644 --- a/internal/memory_view.go +++ b/internal/memory_view.go @@ -150,7 +150,7 @@ var RegisterMemoryView = api.GoModuleFunc(func(ctx context.Context, mod api.Modu baseType: baseType{ rawType: rawType, name: name, - argPackAdvance: 8, + argPackAdvance: GenericWireTypeSize, }, dataTypeIndex: dataTypeIndex, nativeSize: sizeMapping[dataTypeIndex], diff --git a/internal/object.go b/internal/object.go index f7864dc..8ab9f87 100644 --- a/internal/object.go +++ b/internal/object.go @@ -219,7 +219,7 @@ var FinalizeValueObject = api.GoModuleFunc(func(ctx context.Context, mod api.Mod baseType: baseType{ rawType: structType, name: reg.name, - argPackAdvance: 8, + argPackAdvance: GenericWireTypeSize, }, reg: reg, }, diff --git a/internal/std_string.go b/internal/std_string.go index 3a63a8f..43f9613 100644 --- a/internal/std_string.go +++ b/internal/std_string.go @@ -120,7 +120,7 @@ var RegisterStdString = api.GoModuleFunc(func(ctx context.Context, mod api.Modul baseType: baseType{ rawType: rawType, name: name, - argPackAdvance: 8, + argPackAdvance: GenericWireTypeSize, }, stdStringIsUTF8: name == "std::string", }, nil) diff --git a/internal/std_wstring.go b/internal/std_wstring.go index 200c829..f20e931 100644 --- a/internal/std_wstring.go +++ b/internal/std_wstring.go @@ -151,7 +151,7 @@ var RegisterStdWString = api.GoModuleFunc(func(ctx context.Context, mod api.Modu baseType: baseType{ rawType: rawType, name: name, - argPackAdvance: 8, + argPackAdvance: GenericWireTypeSize, }, charSize: api.DecodeI32(stack[1]), }, nil) diff --git a/internal/symbol.go b/internal/symbol.go index 17c322f..304d2de 100644 --- a/internal/symbol.go +++ b/internal/symbol.go @@ -110,6 +110,11 @@ var RegisterFunction = api.GoModuleFunc(func(ctx context.Context, mod api.Module panic(fmt.Errorf("could not read name: %w", err)) } + name, err = getFunctionName(name) + if err != nil { + panic(fmt.Errorf("could not read function name: %w", err)) + } + publicSymbolArgs := argCount - 1 // Set a default callback that errors out when not all types are resolved. diff --git a/testdata/wasm/tests.html b/testdata/wasm/tests.html index cf05aac..b2483f6 100644 --- a/testdata/wasm/tests.html +++ b/testdata/wasm/tests.html @@ -4,1213 +4,122 @@ Emscripten-Generated Code - + - - image/svg+xml - +
Downloading...
- - Resize canvas - Lock/hide mouse pointer     - - - + + Resize canvas + Lock/hide mouse pointer     + + +
-
@@ -1222,8 +131,6 @@ var spinnerElement = document.getElementById('spinner'); var Module = { - preRun: [], - postRun: [], print: (function() { var element = document.getElementById('output'); if (element) element.value = ''; // clear browser cache diff --git a/testdata/wasm/tests.js b/testdata/wasm/tests.js index 4dd429d..0244d30 100644 --- a/testdata/wasm/tests.js +++ b/testdata/wasm/tests.js @@ -58,8 +58,7 @@ function locateFile(path) { // Hooks that are implemented differently in different runtime environments. var read_, readAsync, - readBinary, - setWindowTitle; + readBinary; if (ENVIRONMENT_IS_NODE) { if (typeof process == 'undefined' || !process.release || process.release.name !== 'node') throw new Error('not compiled for this environment (did you build to HTML and try to run it not on the web, or set ENVIRONMENT to something - like node - and run it someplace else - like on the web?)'); @@ -269,8 +268,6 @@ read_ = (url) => { // end include: web_or_worker_shell_read.js } - - setWindowTitle = (title) => document.title = title; } else { throw new Error('environment detection error'); @@ -306,7 +303,7 @@ assert(typeof Module['filePackagePrefixURL'] == 'undefined', 'Module.filePackage assert(typeof Module['read'] == 'undefined', 'Module.read option was removed (modify read_ in JS)'); assert(typeof Module['readAsync'] == 'undefined', 'Module.readAsync option was removed (modify readAsync in JS)'); assert(typeof Module['readBinary'] == 'undefined', 'Module.readBinary option was removed (modify readBinary in JS)'); -assert(typeof Module['setWindowTitle'] == 'undefined', 'Module.setWindowTitle option was removed (modify setWindowTitle in JS)'); +assert(typeof Module['setWindowTitle'] == 'undefined', 'Module.setWindowTitle option was removed (modify emscripten_set_window_title in JS)'); assert(typeof Module['TOTAL_MEMORY'] == 'undefined', 'Module.TOTAL_MEMORY has been renamed Module.INITIAL_MEMORY'); legacyModuleProp('asm', 'wasmExports'); legacyModuleProp('read', 'read_'); @@ -316,6 +313,11 @@ legacyModuleProp('setWindowTitle', 'setWindowTitle'); var IDBFS = 'IDBFS is no longer included by default; build with -lidbfs.js'; var PROXYFS = 'PROXYFS is no longer included by default; build with -lproxyfs.js'; var WORKERFS = 'WORKERFS is no longer included by default; build with -lworkerfs.js'; +var FETCHFS = 'FETCHFS is no longer included by default; build with -lfetchfs.js'; +var ICASEFS = 'ICASEFS is no longer included by default; build with -licasefs.js'; +var JSFILEFS = 'JSFILEFS is no longer included by default; build with -ljsfilefs.js'; +var OPFS = 'OPFS is no longer included by default; build with -lopfs.js'; + var NODEFS = 'NODEFS is no longer included by default; build with -lnodefs.js'; assert(!ENVIRONMENT_IS_SHELL, "shell environment detected but not enabled at build time. Add 'shell' to `-sENVIRONMENT` to enable."); @@ -333,9 +335,8 @@ assert(!ENVIRONMENT_IS_SHELL, "shell environment detected but not enabled at bui // An online HTML version (which may be of a different version of Emscripten) // is up at http://kripken.github.io/emscripten-site/docs/api_reference/preamble.js.html -var wasmBinary; +var wasmBinary; if (Module['wasmBinary']) wasmBinary = Module['wasmBinary'];legacyModuleProp('wasmBinary', 'wasmBinary'); -var noExitRuntime = Module['noExitRuntime'] || true;legacyModuleProp('noExitRuntime', 'noExitRuntime'); if (typeof WebAssembly != 'object') { abort('no native wasm support detected'); @@ -344,7 +345,6 @@ if (typeof WebAssembly != 'object') { // Wasm globals var wasmMemory; -var wasmExports; //======================================== // Runtime essentials @@ -359,6 +359,10 @@ var ABORT = false; // but only when noExitRuntime is false. var EXITSTATUS; +// In STRICT mode, we only define assert() when ASSERTIONS is set. i.e. we +// don't define it at all in release modes. This matches the behaviour of +// MINIMAL_RUNTIME. +// TODO(sbc): Make this the default even without STRICT enabled. /** @type {function(*, string=)} */ function assert(condition, text) { if (!condition) { @@ -393,9 +397,9 @@ function updateMemoryViews() { var b = wasmMemory.buffer; Module['HEAP8'] = HEAP8 = new Int8Array(b); Module['HEAP16'] = HEAP16 = new Int16Array(b); - Module['HEAP32'] = HEAP32 = new Int32Array(b); Module['HEAPU8'] = HEAPU8 = new Uint8Array(b); Module['HEAPU16'] = HEAPU16 = new Uint16Array(b); + Module['HEAP32'] = HEAP32 = new Int32Array(b); Module['HEAPU32'] = HEAPU32 = new Uint32Array(b); Module['HEAPF32'] = HEAPF32 = new Float32Array(b); Module['HEAPF64'] = HEAPF64 = new Float64Array(b); @@ -410,12 +414,6 @@ assert(typeof Int32Array != 'undefined' && typeof Float64Array !== 'undefined' & assert(!Module['wasmMemory'], 'Use of `wasmMemory` detected. Use -sIMPORTED_MEMORY to define wasmMemory externally'); assert(!Module['INITIAL_MEMORY'], 'Detected runtime INITIAL_MEMORY setting. Use -sIMPORTED_MEMORY to define wasmMemory dynamically'); -// include: runtime_init_table.js -// In regular non-RELOCATABLE mode the table is exported -// from the wasm module and this will be assigned once -// the exports are available. -var wasmTable; -// end include: runtime_init_table.js // include: runtime_stack_check.js // Initializes the stack cookie. Called at the startup of main and at the startup of each thread in pthreads mode. function writeStackCookie() { @@ -471,12 +469,6 @@ var __ATPOSTRUN__ = []; // functions called after the main() is called var runtimeInitialized = false; -var runtimeKeepaliveCounter = 0; - -function keepRuntimeAlive() { - return noExitRuntime || runtimeKeepaliveCounter > 0; -} - function preRun() { if (Module['preRun']) { if (typeof Module['preRun'] == 'function') Module['preRun'] = [Module['preRun']]; @@ -588,7 +580,7 @@ function addRunDependency(id) { shown = true; err('still waiting on run dependencies:'); } - err('dependency: ' + dep); + err(`dependency: ${dep}`); } if (shown) { err('(end of list)'); @@ -668,16 +660,17 @@ function abort(what) { // Prefix of data URIs emitted by SINGLE_FILE and related options. var dataURIPrefix = 'data:application/octet-stream;base64,'; -// Indicates whether filename is a base64 data URI. -function isDataURI(filename) { - // Prefix of data URIs emitted by SINGLE_FILE and related options. - return filename.startsWith(dataURIPrefix); -} - -// Indicates whether filename is delivered via file protocol (as opposed to http/https) -function isFileURI(filename) { - return filename.startsWith('file://'); -} +/** + * Indicates whether filename is a base64 data URI. + * @noinline + */ +var isDataURI = (filename) => filename.startsWith(dataURIPrefix); + +/** + * Indicates whether filename is delivered via file protocol (as opposed to http/https) + * @noinline + */ +var isFileURI = (filename) => filename.startsWith('file://'); // end include: URIUtils.js function createExportWrapper(name) { return function() { @@ -742,11 +735,11 @@ function instantiateArrayBuffer(binaryFile, imports, receiver) { }).then((instance) => { return instance; }).then(receiver, (reason) => { - err('failed to asynchronously prepare wasm: ' + reason); + err(`failed to asynchronously prepare wasm: ${reason}`); // Warn on some common problems. if (isFileURI(wasmBinaryFile)) { - err('warning: Loading from a file URI (' + wasmBinaryFile + ') is not supported in most browsers. See https://emscripten.org/docs/getting_started/FAQ.html#how-do-i-run-a-local-webserver-for-testing-why-does-my-program-stall-in-downloading-or-preparing'); + err(`warning: Loading from a file URI (${wasmBinaryFile}) is not supported in most browsers. See https://emscripten.org/docs/getting_started/FAQ.html#how-do-i-run-a-local-webserver-for-testing-why-does-my-program-stall-in-downloading-or-preparing`); } abort(reason); }); @@ -779,7 +772,7 @@ function instantiateAsync(binary, binaryFile, imports, callback) { function(reason) { // We expect the most common failure cause to be a bad MIME type for the binary, // in which case falling back to ArrayBuffer instantiation should work. - err('wasm streaming compile failed: ' + reason); + err(`wasm streaming compile failed: ${reason}`); err('falling back to ArrayBuffer instantiation'); return instantiateArrayBuffer(binaryFile, imports, callback); }); @@ -801,9 +794,8 @@ function createWasm() { // performing other necessary setup /** @param {WebAssembly.Module=} module*/ function receiveInstance(instance, module) { - var exports = instance.exports; + wasmExports = instance.exports; - wasmExports = exports; wasmMemory = wasmExports['memory']; @@ -822,7 +814,7 @@ function createWasm() { addOnInit(wasmExports['__wasm_call_ctors']); removeRunDependency('wasm-instantiate'); - return exports; + return wasmExports; } // wait for the pthread pool (if any) addRunDependency('wasm-instantiate'); @@ -853,7 +845,7 @@ function createWasm() { try { return Module['instantiateWasm'](info, receiveInstance); } catch(e) { - err('Module.instantiateWasm callback failed with error: ' + e); + err(`Module.instantiateWasm callback failed with error: ${e}`); return false; } } @@ -904,7 +896,7 @@ function missingGlobal(sym, msg) { Object.defineProperty(globalThis, sym, { configurable: true, get() { - warnOnce('`' + sym + '` is not longer defined by emscripten. ' + msg); + warnOnce(`\`${sym}\` is not longer defined by emscripten. ${msg}`); return undefined; } }); @@ -912,6 +904,7 @@ function missingGlobal(sym, msg) { } missingGlobal('buffer', 'Please use HEAP8.buffer or wasmMemory.buffer'); +missingGlobal('asm', 'Please use wasmExports instead'); function missingLibrarySymbol(sym) { if (typeof globalThis !== 'undefined' && !Object.getOwnPropertyDescriptor(globalThis, sym)) { @@ -920,7 +913,7 @@ function missingLibrarySymbol(sym) { get() { // Can't `abort()` here because it would break code that does runtime // checks. e.g. `if (typeof SDL === 'undefined')`. - var msg = '`' + sym + '` is a library symbol and not included by default; add it to your library.js __deps or to DEFAULT_LIBRARY_FUNCS_TO_INCLUDE on the command line'; + var msg = `\`${sym}\` is a library symbol and not included by default; add it to your library.js __deps or to DEFAULT_LIBRARY_FUNCS_TO_INCLUDE on the command line`; // DEFAULT_LIBRARY_FUNCS_TO_INCLUDE requires the name as it appears in // library.js, which means $name for a JS name with no prefix, or name // for a JS name like _name. @@ -928,7 +921,7 @@ function missingLibrarySymbol(sym) { if (!librarySymbol.startsWith('_')) { librarySymbol = '$' + sym; } - msg += " (e.g. -sDEFAULT_LIBRARY_FUNCS_TO_INCLUDE='" + librarySymbol + "')"; + msg += ` (e.g. -sDEFAULT_LIBRARY_FUNCS_TO_INCLUDE='${librarySymbol}')`; if (isExportedByForceFilesystem(sym)) { msg += '. Alternatively, forcing filesystem support (-sFORCE_FILESYSTEM) can export this for you'; } @@ -947,7 +940,7 @@ function unexportedRuntimeSymbol(sym) { Object.defineProperty(Module, sym, { configurable: true, get() { - var msg = "'" + sym + "' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the Emscripten FAQ)"; + var msg = `'${sym}' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the Emscripten FAQ)`; if (isExportedByForceFilesystem(sym)) { msg += '. Alternatively, forcing filesystem support (-sFORCE_FILESYSTEM) can export this for you'; } @@ -1002,6 +995,8 @@ function dbg(text) { } } + var noExitRuntime = Module['noExitRuntime'] || true; + var ptrToString = (ptr) => { assert(typeof ptr === 'number'); // With CAN_ADDRESS_2GB or MEMORY64, pointers are already unsigned. @@ -1109,7 +1104,7 @@ function dbg(text) { * @return {string} */ var UTF8ToString = (ptr, maxBytesToRead) => { - assert(typeof ptr == 'number'); + assert(typeof ptr == 'number', `UTF8ToString expects a number (got ${typeof ptr})`); return ptr ? UTF8ArrayToString(HEAPU8, ptr, maxBytesToRead) : ''; }; var ___assert_fail = (condition, filename, line, func) => { @@ -1137,21 +1132,21 @@ function dbg(text) { return HEAPU32[(((this.ptr)+(8))>>2)]; }; - this.set_caught = function (caught) { + this.set_caught = function(caught) { caught = caught ? 1 : 0; HEAP8[(((this.ptr)+(12))>>0)] = caught; }; - this.get_caught = function () { + this.get_caught = function() { return HEAP8[(((this.ptr)+(12))>>0)] != 0; }; - this.set_rethrown = function (rethrown) { + this.set_rethrown = function(rethrown) { rethrown = rethrown ? 1 : 0; HEAP8[(((this.ptr)+(13))>>0)] = rethrown; }; - this.get_rethrown = function () { + this.get_rethrown = function() { return HEAP8[(((this.ptr)+(13))>>0)] != 0; }; @@ -1190,39 +1185,18 @@ function dbg(text) { var exceptionLast = 0; var uncaughtExceptionCount = 0; - function ___cxa_throw(ptr, type, destructor) { + var ___cxa_throw = (ptr, type, destructor) => { var info = new ExceptionInfo(ptr); // Initialize ExceptionInfo content after it was allocated in __cxa_allocate_exception. info.init(type, destructor); exceptionLast = ptr; uncaughtExceptionCount++; assert(false, 'Exception thrown, but exception catching is not enabled. Compile with -sNO_DISABLE_EXCEPTION_CATCHING or -sEXCEPTION_CATCHING_ALLOWED=[..] to catch.'); - } + }; - var char_0 = 48; - - var char_9 = 57; - function makeLegalFunctionName(name) { - if (undefined === name) { - return '_unknown'; - } - name = name.replace(/[^a-zA-Z0-9_]/g, '$'); - var f = name.charCodeAt(0); - if (f >= char_0 && f <= char_9) { - return `_${name}`; - } - return name; - } - function createNamedFunction(name, body) { - name = makeLegalFunctionName(name); - // Use an abject with a computed property name to create a new function with - // a name specified at runtime, but without using `new Function` or `eval`. - return { - [name]: function() { - return body.apply(this, arguments); - } - }[name]; - } + var createNamedFunction = (name, body) => Object.defineProperty(body, 'name', { + value: name + }); function handleAllocatorInit() { Object.assign(HandleAllocator.prototype, /** @lends {HandleAllocator.prototype} */ { @@ -1255,12 +1229,10 @@ function dbg(text) { } var emval_handles = new HandleAllocator();; - var BindingError = undefined; - function throwBindingError(message) { - throw new BindingError(message); - } + var BindingError; + var throwBindingError = (message) => { throw new BindingError(message); }; - function count_emval_handles() { + var count_emval_handles = () => { var count = 0; for (var i = emval_handles.reserved; i < emval_handles.allocated.length; ++i) { if (emval_handles.allocated[i] !== undefined) { @@ -1268,9 +1240,9 @@ function dbg(text) { } } return count; - } + }; - function init_emval() { + var init_emval = () => { // reserve some special values. These never get de-allocated. // The HandleAllocator takes care of reserving zero. emval_handles.allocated.push( @@ -1281,7 +1253,7 @@ function dbg(text) { ); emval_handles.reserved = emval_handles.allocated.length Module['count_emval_handles'] = count_emval_handles; - } + }; var Emval = { toValue:(handle) => { if (!handle) { @@ -1302,7 +1274,7 @@ function dbg(text) { }, }; - function extendError(baseErrorType, errorName) { + var extendError = (baseErrorType, errorName) => { var errorClass = createNamedFunction(errorName, function(message) { this.name = errorName; this.message = message; @@ -1324,31 +1296,29 @@ function dbg(text) { }; return errorClass; - } - var PureVirtualError = undefined; + }; + var PureVirtualError; - function embind_init_charCodes() { + var embind_init_charCodes = () => { var codes = new Array(256); for (var i = 0; i < 256; ++i) { codes[i] = String.fromCharCode(i); } embind_charCodes = codes; - } - var embind_charCodes = undefined; - function readLatin1String(ptr) { + }; + var embind_charCodes; + var readLatin1String = (ptr) => { var ret = ""; var c = ptr; while (HEAPU8[c]) { ret += embind_charCodes[HEAPU8[c++]]; } return ret; - } + }; - function getInheritedInstanceCount() { - return Object.keys(registeredInstances).length; - } + var getInheritedInstanceCount = () => Object.keys(registeredInstances).length; - function getLiveInheritedInstances() { + var getLiveInheritedInstances = () => { var rv = []; for (var k in registeredInstances) { if (registeredInstances.hasOwnProperty(k)) { @@ -1356,36 +1326,36 @@ function dbg(text) { } } return rv; - } + }; var deletionQueue = []; - function flushPendingDeletes() { + var flushPendingDeletes = () => { while (deletionQueue.length) { var obj = deletionQueue.pop(); obj.$$.deleteScheduled = false; obj['delete'](); } - } + }; - var delayFunction = undefined; + var delayFunction; - function setDelayFunction(fn) { + var setDelayFunction = (fn) => { delayFunction = fn; if (deletionQueue.length && delayFunction) { delayFunction(flushPendingDeletes); } - } - function init_embind() { + }; + var init_embind = () => { Module['getInheritedInstanceCount'] = getInheritedInstanceCount; Module['getLiveInheritedInstances'] = getLiveInheritedInstances; Module['flushPendingDeletes'] = flushPendingDeletes; Module['setDelayFunction'] = setDelayFunction; - } + }; var registeredInstances = { }; - function getBasestPointer(class_, ptr) { + var getBasestPointer = (class_, ptr) => { if (ptr === undefined) { throwBindingError('ptr should not be undefined'); } @@ -1394,70 +1364,70 @@ function dbg(text) { class_ = class_.baseClass; } return ptr; - } + }; - function registerInheritedInstance(class_, ptr, instance) { + var registerInheritedInstance = (class_, ptr, instance) => { ptr = getBasestPointer(class_, ptr); if (registeredInstances.hasOwnProperty(ptr)) { throwBindingError(`Tried to register registered instance: ${ptr}`); } else { registeredInstances[ptr] = instance; } - } + }; var registeredTypes = { }; - function getTypeName(type) { + var getTypeName = (type) => { var ptr = ___getTypeName(type); var rv = readLatin1String(ptr); _free(ptr); return rv; - } + }; - function requireRegisteredType(rawType, humanName) { + var requireRegisteredType = (rawType, humanName) => { var impl = registeredTypes[rawType]; if (undefined === impl) { throwBindingError(humanName + " has unknown type " + getTypeName(rawType)); } return impl; - } + }; - function unregisterInheritedInstance(class_, ptr) { + var unregisterInheritedInstance = (class_, ptr) => { ptr = getBasestPointer(class_, ptr); if (registeredInstances.hasOwnProperty(ptr)) { delete registeredInstances[ptr]; } else { throwBindingError(`Tried to unregister unregistered instance: ${ptr}`); } - } + }; - function detachFinalizer(handle) {} + var detachFinalizer = (handle) => {}; var finalizationRegistry = false; - function runDestructor($$) { + var runDestructor = ($$) => { if ($$.smartPtr) { $$.smartPtrType.rawDestructor($$.smartPtr); } else { $$.ptrType.registeredClass.rawDestructor($$.ptr); } - } - function releaseClassHandle($$) { + }; + var releaseClassHandle = ($$) => { $$.count.value -= 1; var toDelete = 0 === $$.count.value; if (toDelete) { runDestructor($$); } - } + }; - function downcastPointer(ptr, ptrClass, desiredClass) { + var downcastPointer = (ptr, ptrClass, desiredClass) => { if (ptrClass === desiredClass) { return ptr; } @@ -1470,23 +1440,21 @@ function dbg(text) { return null; } return desiredClass.downcast(rv); - } + }; var registeredPointers = { }; - function getInheritedInstance(class_, ptr) { + var getInheritedInstance = (class_, ptr) => { ptr = getBasestPointer(class_, ptr); return registeredInstances[ptr]; - } + }; - var InternalError = undefined; - function throwInternalError(message) { - throw new InternalError(message); - } + var InternalError; + var throwInternalError = (message) => { throw new InternalError(message); }; - function makeClassHandle(prototype, record) { + var makeClassHandle = (prototype, record) => { if (!record.ptrType || !record.ptr) { throwInternalError('makeClassHandle requires ptr and ptrType'); } @@ -1501,7 +1469,8 @@ function dbg(text) { value: record, }, })); - } + }; + /** @suppress {globalThis} */ function RegisteredPointer_fromWireType(ptr) { // ptr is a raw pointer (or a raw smartpointer) @@ -1577,7 +1546,7 @@ function dbg(text) { }); } } - var attachFinalizer = function(handle) { + var attachFinalizer = (handle) => { if ('undefined' === typeof FinalizationRegistry) { attachFinalizer = (handle) => handle; return handle; @@ -1615,7 +1584,7 @@ function dbg(text) { detachFinalizer = (handle) => finalizationRegistry.unregister(handle); return attachFinalizer(handle); }; - function __embind_create_inheriting_constructor(constructorName, wrapperType, properties) { + var __embind_create_inheriting_constructor = (constructorName, wrapperType, properties) => { constructorName = readLatin1String(constructorName); wrapperType = requireRegisteredType(wrapperType, 'wrapper'); properties = Emval.toValue(properties); @@ -1629,13 +1598,13 @@ function dbg(text) { var baseConstructor = registeredClass.baseClass.constructor; var ctor = createNamedFunction(constructorName, function() { registeredClass.baseClass.pureVirtualFunctions.forEach(function(name) { - if (this[name] === baseClassPrototype[name]) { - throw new PureVirtualError(`Pure virtual function ${name} must be implemented in JavaScript`); - } + if (this[name] === baseClassPrototype[name]) { + throw new PureVirtualError(`Pure virtual function ${name} must be implemented in JavaScript`); + } }.bind(this)); Object.defineProperty(this, '__parent', { - value: wrapperPrototype + value: wrapperPrototype }); this["__construct"].apply(this, arraySlice.call(arguments)); }); @@ -1671,23 +1640,22 @@ function dbg(text) { }; ctor.prototype = Object.create(wrapperPrototype); - for (var p in properties) { - ctor.prototype[p] = properties[p]; - } + Object.assign(ctor.prototype, properties); return Emval.toHandle(ctor); - } + }; var tupleRegistrations = { }; - function runDestructors(destructors) { + var runDestructors = (destructors) => { while (destructors.length) { var ptr = destructors.pop(); var del = destructors.pop(); del(ptr); } - } + }; + /** @suppress {globalThis} */ function simpleReadValueFromPointer(pointer) { return this['fromWireType'](HEAP32[((pointer)>>2)]); } @@ -1699,7 +1667,7 @@ function dbg(text) { var typeDependencies = { }; - function whenDependentTypesAreResolved(myTypes, dependentTypes, getTypeConverters) { + var whenDependentTypesAreResolved = (myTypes, dependentTypes, getTypeConverters) => { myTypes.forEach(function(type) { typeDependencies[type] = dependentTypes; }); @@ -1737,14 +1705,14 @@ function dbg(text) { if (0 === unregisteredTypes.length) { onComplete(typeConverters); } - } - function __embind_finalize_value_array(rawTupleType) { + }; + var __embind_finalize_value_array = (rawTupleType) => { var reg = tupleRegistrations[rawTupleType]; delete tupleRegistrations[rawTupleType]; var elements = reg.elements; var elementsLength = elements.length; - var elementTypes = elements.map(function(elt) { return elt.getterReturnType; }). - concat(elements.map(function(elt) { return elt.setterArgumentType; })); + var elementTypes = elements.map((elt) => elt.getterReturnType). + concat(elements.map((elt) => elt.setterArgumentType)); var rawConstructor = reg.rawConstructor; var rawDestructor = reg.rawDestructor; @@ -1757,9 +1725,7 @@ function dbg(text) { var setterArgumentType = elementTypes[i + elementsLength]; var setter = elt.setter; var setterContext = elt.setterContext; - elt.read = (ptr) => { - return getterReturnType['fromWireType'](getter(getterContext, ptr)); - }; + elt.read = (ptr) => getterReturnType['fromWireType'](getter(getterContext, ptr)); elt.write = (ptr, o) => { var destructors = []; setter(setterContext, ptr, setterArgumentType['toWireType'](destructors, o)); @@ -1769,7 +1735,7 @@ function dbg(text) { return [{ name: reg.name, - 'fromWireType': function(ptr) { + 'fromWireType': (ptr) => { var rv = new Array(elementsLength); for (var i = 0; i < elementsLength; ++i) { rv[i] = elements[i].read(ptr); @@ -1777,7 +1743,7 @@ function dbg(text) { rawDestructor(ptr); return rv; }, - 'toWireType': function(destructors, o) { + 'toWireType': (destructors, o) => { if (elementsLength !== o.length) { throw new TypeError(`Incorrect number of tuple elements for ${reg.name}: expected=${elementsLength}, actual=${o.length}`); } @@ -1790,19 +1756,19 @@ function dbg(text) { } return ptr; }, - 'argPackAdvance': 8, + 'argPackAdvance': GenericWireTypeSize, 'readValueFromPointer': simpleReadValueFromPointer, destructorFunction: rawDestructor, }]; }); - } + }; var structRegistrations = { }; - var __embind_finalize_value_object = function(structType) { + var __embind_finalize_value_object = (structType) => { var reg = structRegistrations[structType]; delete structRegistrations[structType]; @@ -1822,10 +1788,7 @@ function dbg(text) { var setter = field.setter; var setterContext = field.setterContext; fields[fieldName] = { - read: (ptr) => { - return getterReturnType['fromWireType']( - getter(getterContext, ptr)); - }, + read: (ptr) => getterReturnType['fromWireType'](getter(getterContext, ptr)), write: (ptr, o) => { var destructors = []; setter(setterContext, ptr, setterArgumentType['toWireType'](destructors, o)); @@ -1836,7 +1799,7 @@ function dbg(text) { return [{ name: reg.name, - 'fromWireType': function(ptr) { + 'fromWireType': (ptr) => { var rv = {}; for (var i in fields) { rv[i] = fields[i].read(ptr); @@ -1844,7 +1807,7 @@ function dbg(text) { rawDestructor(ptr); return rv; }, - 'toWireType': function(destructors, o) { + 'toWireType': (destructors, o) => { // todo: Here we have an opportunity for -O3 level "unsafe" optimizations: // assume all fields are present without checking. for (var fieldName in fields) { @@ -1861,26 +1824,15 @@ function dbg(text) { } return ptr; }, - 'argPackAdvance': 8, + 'argPackAdvance': GenericWireTypeSize, 'readValueFromPointer': simpleReadValueFromPointer, destructorFunction: rawDestructor, }]; }); }; - function __embind_register_bigint(primitiveType, name, size, minRange, maxRange) {} + var __embind_register_bigint = (primitiveType, name, size, minRange, maxRange) => {}; - function getShiftFromSize(size) { - switch (size) { - case 1: return 0; - case 2: return 1; - case 4: return 2; - case 8: return 3; - default: - throw new TypeError(`Unknown type size: ${size}`); - } - } - @@ -1916,9 +1868,10 @@ function dbg(text) { } return sharedRegisterType(rawType, registeredInstance, options); } - function __embind_register_bool(rawType, name, size, trueValue, falseValue) { - var shift = getShiftFromSize(size); + var GenericWireTypeSize = 8; + /** @suppress {globalThis} */ + var __embind_register_bool = (rawType, name, trueValue, falseValue) => { name = readLatin1String(name); registerType(rawType, { name, @@ -1930,53 +1883,17 @@ function dbg(text) { 'toWireType': function(destructors, o) { return o ? trueValue : falseValue; }, - 'argPackAdvance': 8, + 'argPackAdvance': GenericWireTypeSize, 'readValueFromPointer': function(pointer) { - // TODO: if heap is fixed (like in asm.js) this could be executed outside - var heap; - if (size === 1) { - heap = HEAP8; - } else if (size === 2) { - heap = HEAP16; - } else if (size === 4) { - heap = HEAP32; - } else { - throw new TypeError("Unknown boolean type size: " + name); - } - return this['fromWireType'](heap[pointer >> shift]); + return this['fromWireType'](HEAPU8[pointer]); }, destructorFunction: null, // This type does not need a destructor }); - } + }; - function ClassHandle_isAliasOf(other) { - if (!(this instanceof ClassHandle)) { - return false; - } - if (!(other instanceof ClassHandle)) { - return false; - } - - var leftClass = this.$$.ptrType.registeredClass; - var left = this.$$.ptr; - var rightClass = other.$$.ptrType.registeredClass; - var right = other.$$.ptr; - - while (leftClass.baseClass) { - left = leftClass.upcast(left); - leftClass = leftClass.baseClass; - } - - while (rightClass.baseClass) { - right = rightClass.upcast(right); - rightClass = rightClass.baseClass; - } - - return leftClass === rightClass && left === right; - } - function shallowCopyInternalPointer(o) { + var shallowCopyInternalPointer = (o) => { return { count: o.count, deleteScheduled: o.deleteScheduled, @@ -1986,90 +1903,113 @@ function dbg(text) { smartPtr: o.smartPtr, smartPtrType: o.smartPtrType, }; - } + }; - function throwInstanceAlreadyDeleted(obj) { + var throwInstanceAlreadyDeleted = (obj) => { function getInstanceTypeName(handle) { return handle.$$.ptrType.registeredClass.name; } throwBindingError(getInstanceTypeName(obj) + ' instance already deleted'); - } + }; - function ClassHandle_clone() { - if (!this.$$.ptr) { - throwInstanceAlreadyDeleted(this); - } - if (this.$$.preservePointerOnDelete) { - this.$$.count.value += 1; - return this; - } else { - var clone = attachFinalizer(Object.create(Object.getPrototypeOf(this), { - $$: { - value: shallowCopyInternalPointer(this.$$), + + + var init_ClassHandle = () => { + Object.assign(ClassHandle.prototype, { + "isAliasOf"(other) { + if (!(this instanceof ClassHandle)) { + return false; + } + if (!(other instanceof ClassHandle)) { + return false; } - })); - clone.$$.count.value += 1; - clone.$$.deleteScheduled = false; - return clone; - } - } + var leftClass = this.$$.ptrType.registeredClass; + var left = this.$$.ptr; + other.$$ = /** @type {Object} */ (other.$$); + var rightClass = other.$$.ptrType.registeredClass; + var right = other.$$.ptr; + while (leftClass.baseClass) { + left = leftClass.upcast(left); + leftClass = leftClass.baseClass; + } + while (rightClass.baseClass) { + right = rightClass.upcast(right); + rightClass = rightClass.baseClass; + } + return leftClass === rightClass && left === right; + }, - function ClassHandle_delete() { - if (!this.$$.ptr) { - throwInstanceAlreadyDeleted(this); - } + "clone"() { + if (!this.$$.ptr) { + throwInstanceAlreadyDeleted(this); + } - if (this.$$.deleteScheduled && !this.$$.preservePointerOnDelete) { - throwBindingError('Object already scheduled for deletion'); - } + if (this.$$.preservePointerOnDelete) { + this.$$.count.value += 1; + return this; + } else { + var clone = attachFinalizer(Object.create(Object.getPrototypeOf(this), { + $$: { + value: shallowCopyInternalPointer(this.$$), + } + })); - detachFinalizer(this); - releaseClassHandle(this.$$); + clone.$$.count.value += 1; + clone.$$.deleteScheduled = false; + return clone; + } + }, - if (!this.$$.preservePointerOnDelete) { - this.$$.smartPtr = undefined; - this.$$.ptr = undefined; - } - } + "delete"() { + if (!this.$$.ptr) { + throwInstanceAlreadyDeleted(this); + } - function ClassHandle_isDeleted() { - return !this.$$.ptr; - } + if (this.$$.deleteScheduled && !this.$$.preservePointerOnDelete) { + throwBindingError('Object already scheduled for deletion'); + } + detachFinalizer(this); + releaseClassHandle(this.$$); + if (!this.$$.preservePointerOnDelete) { + this.$$.smartPtr = undefined; + this.$$.ptr = undefined; + } + }, - function ClassHandle_deleteLater() { - if (!this.$$.ptr) { - throwInstanceAlreadyDeleted(this); - } - if (this.$$.deleteScheduled && !this.$$.preservePointerOnDelete) { - throwBindingError('Object already scheduled for deletion'); - } - deletionQueue.push(this); - if (deletionQueue.length === 1 && delayFunction) { - delayFunction(flushPendingDeletes); - } - this.$$.deleteScheduled = true; - return this; - } - function init_ClassHandle() { - ClassHandle.prototype['isAliasOf'] = ClassHandle_isAliasOf; - ClassHandle.prototype['clone'] = ClassHandle_clone; - ClassHandle.prototype['delete'] = ClassHandle_delete; - ClassHandle.prototype['isDeleted'] = ClassHandle_isDeleted; - ClassHandle.prototype['deleteLater'] = ClassHandle_deleteLater; - } + "isDeleted"() { + return !this.$$.ptr; + }, + + "deleteLater"() { + if (!this.$$.ptr) { + throwInstanceAlreadyDeleted(this); + } + if (this.$$.deleteScheduled && !this.$$.preservePointerOnDelete) { + throwBindingError('Object already scheduled for deletion'); + } + deletionQueue.push(this); + if (deletionQueue.length === 1 && delayFunction) { + delayFunction(flushPendingDeletes); + } + this.$$.deleteScheduled = true; + return this; + }, + }); + }; + /** @constructor */ function ClassHandle() { } - function ensureOverloadTable(proto, methodName, humanName) { + var ensureOverloadTable = (proto, methodName, humanName) => { if (undefined === proto[methodName].overloadTable) { var prevFunc = proto[methodName]; // Inject an overload resolver function that routes to the appropriate overload based on the number of arguments. @@ -2084,10 +2024,10 @@ function dbg(text) { proto[methodName].overloadTable = []; proto[methodName].overloadTable[prevFunc.argCount] = prevFunc; } - } + }; /** @param {number=} numArguments */ - function exposePublicSymbol(name, value, numArguments) { + var exposePublicSymbol = (name, value, numArguments) => { if (Module.hasOwnProperty(name)) { if (undefined === numArguments || (undefined !== Module[name].overloadTable && undefined !== Module[name].overloadTable[numArguments])) { throwBindingError(`Cannot register public name '${name}' twice`); @@ -2108,8 +2048,22 @@ function dbg(text) { Module[name].numArguments = numArguments; } } - } + }; + var char_0 = 48; + + var char_9 = 57; + var makeLegalFunctionName = (name) => { + if (undefined === name) { + return '_unknown'; + } + name = name.replace(/[^a-zA-Z0-9_]/g, '$'); + var f = name.charCodeAt(0); + if (f >= char_0 && f <= char_9) { + return `_${name}`; + } + return name; + }; /** @constructor */ @@ -2133,7 +2087,7 @@ function dbg(text) { } - function upcastPointer(ptr, ptrClass, desiredClass) { + var upcastPointer = (ptr, ptrClass, desiredClass) => { while (ptrClass !== desiredClass) { if (!ptrClass.upcast) { throwBindingError(`Expected null or instance of ${desiredClass.name}, got an instance of ${ptrClass.name}`); @@ -2142,7 +2096,8 @@ function dbg(text) { ptrClass = ptrClass.baseClass; } return ptr; - } + }; + /** @suppress {globalThis} */ function constNoSmartPtrRawPointerToWireType(destructors, handle) { if (handle === null) { if (this.isReference) { @@ -2163,6 +2118,7 @@ function dbg(text) { } + /** @suppress {globalThis} */ function genericPointerToWireType(destructors, handle) { var ptr; if (handle === null) { @@ -2222,9 +2178,7 @@ function dbg(text) { var clonedHandle = handle['clone'](); ptr = this.rawShare( ptr, - Emval.toHandle(function() { - clonedHandle['delete'](); - }) + Emval.toHandle(() => clonedHandle['delete']()) ); if (destructors !== null) { destructors.push(this.rawDestructor, ptr); @@ -2240,6 +2194,7 @@ function dbg(text) { } + /** @suppress {globalThis} */ function nonConstNoSmartPtrRawPointerToWireType(destructors, handle) { if (handle === null) { if (this.isReference) { @@ -2263,33 +2218,35 @@ function dbg(text) { } - function RegisteredPointer_getPointee(ptr) { - if (this.rawGetPointee) { - ptr = this.rawGetPointee(ptr); - } - return ptr; - } - - function RegisteredPointer_destructor(ptr) { - if (this.rawDestructor) { - this.rawDestructor(ptr); - } + /** @suppress {globalThis} */ + function readPointer(pointer) { + return this['fromWireType'](HEAPU32[((pointer)>>2)]); } - function RegisteredPointer_deleteObject(handle) { - if (handle !== null) { - handle['delete'](); - } - } - function init_RegisteredPointer() { - RegisteredPointer.prototype.getPointee = RegisteredPointer_getPointee; - RegisteredPointer.prototype.destructor = RegisteredPointer_destructor; - RegisteredPointer.prototype['argPackAdvance'] = 8; - RegisteredPointer.prototype['readValueFromPointer'] = simpleReadValueFromPointer; - RegisteredPointer.prototype['deleteObject'] = RegisteredPointer_deleteObject; - RegisteredPointer.prototype['fromWireType'] = RegisteredPointer_fromWireType; - } + var init_RegisteredPointer = () => { + Object.assign(RegisteredPointer.prototype, { + getPointee(ptr) { + if (this.rawGetPointee) { + ptr = this.rawGetPointee(ptr); + } + return ptr; + }, + destructor(ptr) { + if (this.rawDestructor) { + this.rawDestructor(ptr); + } + }, + 'argPackAdvance': GenericWireTypeSize, + 'readValueFromPointer': readPointer, + 'deleteObject'(handle) { + if (handle !== null) { + handle['delete'](); + } + }, + 'fromWireType': RegisteredPointer_fromWireType, + }); + }; /** @constructor @param {*=} pointeeType, @param {*=} sharingPolicy, @@ -2345,7 +2302,7 @@ function dbg(text) { } /** @param {number=} numArguments */ - function replacePublicSymbol(name, value, numArguments) { + var replacePublicSymbol = (name, value, numArguments) => { if (!Module.hasOwnProperty(name)) { throwInternalError('Replacing nonexistant public symbol'); } @@ -2357,7 +2314,7 @@ function dbg(text) { Module[name] = value; Module[name].argCount = numArguments; } - } + }; @@ -2374,6 +2331,8 @@ function dbg(text) { }; var wasmTableMirror = []; + + var wasmTable; var getWasmTableEntry = (funcPtr) => { var func = wasmTableMirror[funcPtr]; if (!func) { @@ -2395,7 +2354,6 @@ function dbg(text) { assert(getWasmTableEntry(ptr), `missing table entry in dynCall: ${ptr}`); var rtn = getWasmTableEntry(ptr).apply(null, args); return rtn; - }; var getDynCaller = (sig, ptr) => { assert(sig.includes('j') || sig.includes('p'), 'getDynCaller should only be called with i64 sigs') @@ -2408,7 +2366,7 @@ function dbg(text) { }; - function embind__requireFunction(signature, rawFunction) { + var embind__requireFunction = (signature, rawFunction) => { signature = readLatin1String(signature); function makeDynCaller() { @@ -2423,13 +2381,13 @@ function dbg(text) { throwBindingError(`unknown function pointer with signature ${signature}: ${rawFunction}`); } return fp; - } + }; - var UnboundTypeError = undefined; + var UnboundTypeError; - function throwUnboundTypeError(message, types) { + var throwUnboundTypeError = (message, types) => { var unboundTypes = []; var seen = {}; function visit(type) { @@ -2449,21 +2407,21 @@ function dbg(text) { types.forEach(visit); throw new UnboundTypeError(`${message}: ` + unboundTypes.map(getTypeName).join([', '])); - } + }; - function __embind_register_class(rawType, - rawPointerType, - rawConstPointerType, - baseClassRawType, - getActualTypeSignature, - getActualType, - upcastSignature, - upcast, - downcastSignature, - downcast, - name, - destructorSignature, - rawDestructor) { + var __embind_register_class = (rawType, + rawPointerType, + rawConstPointerType, + baseClassRawType, + getActualTypeSignature, + getActualType, + upcastSignature, + upcast, + downcastSignature, + downcast, + name, + destructorSignature, + rawDestructor) => { name = readLatin1String(name); getActualType = embind__requireFunction(getActualTypeSignature, getActualType); if (upcast) { @@ -2495,7 +2453,7 @@ function dbg(text) { basePrototype = ClassHandle.prototype; } - var constructor = createNamedFunction(legalFunctionName, function() { + var constructor = createNamedFunction(name, function() { if (Object.getPrototypeOf(this) !== instancePrototype) { throw new BindingError("Use 'new' to construct " + name); } @@ -2561,7 +2519,7 @@ function dbg(text) { return [referenceConverter, pointerConverter, constPointerConverter]; } ); - } + }; @@ -2634,9 +2592,9 @@ function dbg(text) { } var invokerFnBody = ` - return function ${makeLegalFunctionName(humanName)}(${argsList}) { + return function (${argsList}) { if (arguments.length !== ${argCount - 2}) { - throwBindingError('function ${humanName} called with ${arguments.length} arguments, expected ${argCount - 2} args!'); + throwBindingError('function ${humanName} called with ' + arguments.length + ' arguments, expected ${argCount - 2}'); }`; if (needsDestructorStack) { @@ -2687,11 +2645,12 @@ function dbg(text) { args1.push(invokerFnBody); - return newFunc(Function, args1).apply(null, args2); + var invokerFn = newFunc(Function, args1).apply(null, args2); + return createNamedFunction(humanName, invokerFn); } - function heap32VectorToArray(count, firstElement) { + var heap32VectorToArray = (count, firstElement) => { var array = []; for (var i = 0; i < count; i++) { // TODO(https://github.com/emscripten-core/emscripten/issues/17310): @@ -2699,21 +2658,33 @@ function dbg(text) { array.push(HEAPU32[(((firstElement)+(i * 4))>>2)]); } return array; - } + }; - function __embind_register_class_class_function(rawClassType, - methodName, - argCount, - rawArgTypesAddr, - invokerSignature, - rawInvoker, - fn, - isAsync) { + + var getFunctionName = (signature) => { + signature = signature.trim(); + const argsIndex = signature.indexOf("("); + if (argsIndex !== -1) { + assert(signature[signature.length - 1] == ")", "Parentheses for argument names should match."); + return signature.substr(0, argsIndex); + } else { + return signature; + } + }; + var __embind_register_class_class_function = (rawClassType, + methodName, + argCount, + rawArgTypesAddr, + invokerSignature, + rawInvoker, + fn, + isAsync) => { var rawArgTypes = heap32VectorToArray(argCount, rawArgTypesAddr); methodName = readLatin1String(methodName); + methodName = getFunctionName(methodName); rawInvoker = embind__requireFunction(invokerSignature, rawInvoker); whenDependentTypesAreResolved([], [rawClassType], function(classType) { classType = classType[0]; @@ -2765,7 +2736,7 @@ function dbg(text) { }); return []; }); - } + }; @@ -2774,7 +2745,7 @@ function dbg(text) { - function validateThis(this_, classType, humanName) { + var validateThis = (this_, classType, humanName) => { if (!(this_ instanceof Object)) { throwBindingError(`${humanName} with invalid "this": ${this_}`); } @@ -2789,15 +2760,15 @@ function dbg(text) { return upcastPointer(this_.$$.ptr, this_.$$.ptrType.registeredClass, classType.registeredClass); - } - function __embind_register_class_class_property(rawClassType, - fieldName, - rawFieldType, - rawFieldPtr, - getterSignature, - getter, - setterSignature, - setter) { + }; + var __embind_register_class_class_property = (rawClassType, + fieldName, + rawFieldType, + rawFieldPtr, + getterSignature, + getter, + setterSignature, + setter) => { fieldName = readLatin1String(fieldName); getter = embind__requireFunction(getterSignature, getter); @@ -2847,7 +2818,7 @@ function dbg(text) { return []; }); - } + }; @@ -2855,14 +2826,14 @@ function dbg(text) { - function __embind_register_class_constructor( + var __embind_register_class_constructor = ( rawClassType, argCount, rawArgTypesAddr, invokerSignature, invoker, rawConstructor - ) { + ) => { assert(argCount > 0); var rawArgTypes = heap32VectorToArray(argCount, rawArgTypesAddr); invoker = embind__requireFunction(invokerSignature, invoker); @@ -2883,7 +2854,7 @@ function dbg(text) { throwUnboundTypeError(`Cannot construct ${classType.name} due to unbound types`, rawArgTypes); }; - whenDependentTypesAreResolved([], rawArgTypes, function(argTypes) { + whenDependentTypesAreResolved([], rawArgTypes, (argTypes) => { // Insert empty slot for context type (argTypes[1]). argTypes.splice(1, 0, null); classType.registeredClass.constructor_body[argCount - 1] = craftInvokerFunction(humanName, argTypes, null, invoker, rawConstructor); @@ -2891,24 +2862,26 @@ function dbg(text) { }); return []; }); - } + }; - function __embind_register_class_function(rawClassType, - methodName, - argCount, - rawArgTypesAddr, // [ReturnType, ThisType, Args...] - invokerSignature, - rawInvoker, - context, - isPureVirtual, - isAsync) { + + var __embind_register_class_function = (rawClassType, + methodName, + argCount, + rawArgTypesAddr, // [ReturnType, ThisType, Args...] + invokerSignature, + rawInvoker, + context, + isPureVirtual, + isAsync) => { var rawArgTypes = heap32VectorToArray(argCount, rawArgTypesAddr); methodName = readLatin1String(methodName); + methodName = getFunctionName(methodName); rawInvoker = embind__requireFunction(invokerSignature, rawInvoker); whenDependentTypesAreResolved([], [rawClassType], function(classType) { @@ -2959,7 +2932,7 @@ function dbg(text) { }); return []; }); - } + }; @@ -2967,16 +2940,16 @@ function dbg(text) { - function __embind_register_class_property(classType, - fieldName, - getterReturnType, - getterSignature, - getter, - getterContext, - setterArgumentType, - setterSignature, - setter, - setterContext) { + var __embind_register_class_property = (classType, + fieldName, + getterReturnType, + getterSignature, + getter, + getterContext, + setterArgumentType, + setterSignature, + setter, + setterContext) => { fieldName = readLatin1String(fieldName); getter = embind__requireFunction(getterSignature, getter); @@ -2991,13 +2964,9 @@ function dbg(text) { configurable: true }; if (setter) { - desc.set = () => { - throwUnboundTypeError(`Cannot access ${humanName} due to unbound types`, [getterReturnType, setterArgumentType]); - }; + desc.set = () => throwUnboundTypeError(`Cannot access ${humanName} due to unbound types`, [getterReturnType, setterArgumentType]); } else { - desc.set = (v) => { - throwBindingError(humanName + ' is a read-only property'); - }; + desc.set = (v) => throwBindingError(humanName + ' is a read-only property'); } Object.defineProperty(classType.registeredClass.instancePrototype, fieldName, desc); @@ -3032,72 +3001,66 @@ function dbg(text) { return []; }); - } + }; - function __embind_register_constant(name, type, value) { + var __embind_register_constant = (name, type, value) => { name = readLatin1String(name); whenDependentTypesAreResolved([], [type], function(type) { type = type[0]; Module[name] = type['fromWireType'](value); return []; }); - } + }; - function __emval_decref(handle) { + var __emval_decref = (handle) => { if (handle >= emval_handles.reserved && 0 === --emval_handles.get(handle).refcount) { emval_handles.free(handle); } - } + }; - function __embind_register_emval(rawType, name) { + var __embind_register_emval = (rawType, name) => { name = readLatin1String(name); registerType(rawType, { name, - 'fromWireType': function(handle) { + 'fromWireType': (handle) => { var rv = Emval.toValue(handle); __emval_decref(handle); return rv; }, - 'toWireType': function(destructors, value) { - return Emval.toHandle(value); - }, - 'argPackAdvance': 8, + 'toWireType': (destructors, value) => Emval.toHandle(value), + 'argPackAdvance': GenericWireTypeSize, 'readValueFromPointer': simpleReadValueFromPointer, destructorFunction: null, // This type does not need a destructor // TODO: do we need a deleteObject here? write a test where // emval is passed into JS via an interface }); - } + }; - - function enumReadValueFromPointer(name, shift, signed) { - switch (shift) { - case 0: return function(pointer) { - var heap = signed ? HEAP8 : HEAPU8; - return this['fromWireType'](heap[pointer]); - }; - case 1: return function(pointer) { - var heap = signed ? HEAP16 : HEAPU16; - return this['fromWireType'](heap[pointer >> 1]); - }; - case 2: return function(pointer) { - var heap = signed ? HEAP32 : HEAPU32; - return this['fromWireType'](heap[pointer >> 2]); - }; + var enumReadValueFromPointer = (name, width, signed) => { + switch (width) { + case 1: return signed ? + function(pointer) { return this['fromWireType'](HEAP8[((pointer)>>0)]) } : + function(pointer) { return this['fromWireType'](HEAPU8[((pointer)>>0)]) }; + case 2: return signed ? + function(pointer) { return this['fromWireType'](HEAP16[((pointer)>>1)]) } : + function(pointer) { return this['fromWireType'](HEAPU16[((pointer)>>1)]) }; + case 4: return signed ? + function(pointer) { return this['fromWireType'](HEAP32[((pointer)>>2)]) } : + function(pointer) { return this['fromWireType'](HEAPU32[((pointer)>>2)]) }; default: - throw new TypeError("Unknown integer type: " + name); + throw new TypeError(`invalid integer width (${width}): ${name}`); } - } + }; - function __embind_register_enum(rawType, name, size, isSigned) { - var shift = getShiftFromSize(size); + /** @suppress {globalThis} */ + var __embind_register_enum = (rawType, name, size, isSigned) => { name = readLatin1String(name); function ctor() {} @@ -3109,19 +3072,17 @@ function dbg(text) { 'fromWireType': function(c) { return this.constructor.values[c]; }, - 'toWireType': function(destructors, c) { - return c.value; - }, - 'argPackAdvance': 8, - 'readValueFromPointer': enumReadValueFromPointer(name, shift, isSigned), + 'toWireType': (destructors, c) => c.value, + 'argPackAdvance': GenericWireTypeSize, + 'readValueFromPointer': enumReadValueFromPointer(name, size, isSigned), destructorFunction: null, }); exposePublicSymbol(name, ctor); - } + }; - function __embind_register_enum_value(rawEnumType, name, enumValue) { + var __embind_register_enum_value = (rawEnumType, name, enumValue) => { var enumType = requireRegisteredType(rawEnumType, 'enum'); name = readLatin1String(name); @@ -3133,9 +3094,9 @@ function dbg(text) { }); Enum.values[enumValue] = Value; Enum[name] = Value; - } + }; - function embindRepr(v) { + var embindRepr = (v) => { if (v === null) { return 'null'; } @@ -3145,32 +3106,28 @@ function dbg(text) { } else { return '' + v; } - } + }; - function floatReadValueFromPointer(name, shift) { - switch (shift) { - case 2: return function(pointer) { - return this['fromWireType'](HEAPF32[pointer >> 2]); + var floatReadValueFromPointer = (name, width) => { + switch (width) { + case 4: return function(pointer) { + return this['fromWireType'](HEAPF32[((pointer)>>2)]); }; - case 3: return function(pointer) { - return this['fromWireType'](HEAPF64[pointer >> 3]); + case 8: return function(pointer) { + return this['fromWireType'](HEAPF64[((pointer)>>3)]); }; default: - throw new TypeError("Unknown float type: " + name); + throw new TypeError(`invalid float width (${width}): ${name}`); } - } - + }; - function __embind_register_float(rawType, name, size) { - var shift = getShiftFromSize(size); + var __embind_register_float = (rawType, name, size) => { name = readLatin1String(name); registerType(rawType, { name, - 'fromWireType': function(value) { - return value; - }, - 'toWireType': function(destructors, value) { + 'fromWireType': (value) => value, + 'toWireType': (destructors, value) => { if (typeof value != "number" && typeof value != "boolean") { throw new TypeError(`Cannot convert ${embindRepr(value)} to ${this.name}`); } @@ -3178,11 +3135,11 @@ function dbg(text) { // https://www.w3.org/TR/wasm-js-api-1/#towebassemblyvalue return value; }, - 'argPackAdvance': 8, - 'readValueFromPointer': floatReadValueFromPointer(name, shift), + 'argPackAdvance': GenericWireTypeSize, + 'readValueFromPointer': floatReadValueFromPointer(name, size), destructorFunction: null, // This type does not need a destructor }); - } + }; @@ -3191,9 +3148,11 @@ function dbg(text) { - function __embind_register_function(name, argCount, rawArgTypesAddr, signature, rawInvoker, fn, isAsync) { + + var __embind_register_function = (name, argCount, rawArgTypesAddr, signature, rawInvoker, fn, isAsync) => { var argTypes = heap32VectorToArray(argCount, rawArgTypesAddr); name = readLatin1String(name); + name = getFunctionName(name); rawInvoker = embind__requireFunction(signature, rawInvoker); @@ -3206,43 +3165,41 @@ function dbg(text) { replacePublicSymbol(name, craftInvokerFunction(name, invokerArgsArray, null /* no class 'this'*/, rawInvoker, fn, isAsync), argCount - 1); return []; }); - } + }; - - function integerReadValueFromPointer(name, shift, signed) { + var integerReadValueFromPointer = (name, width, signed) => { // integers are quite common, so generate very specialized functions - switch (shift) { - case 0: return signed ? - function readS8FromPointer(pointer) { return HEAP8[pointer]; } : - function readU8FromPointer(pointer) { return HEAPU8[pointer]; }; + switch (width) { case 1: return signed ? - function readS16FromPointer(pointer) { return HEAP16[pointer >> 1]; } : - function readU16FromPointer(pointer) { return HEAPU16[pointer >> 1]; }; + (pointer) => HEAP8[((pointer)>>0)] : + (pointer) => HEAPU8[((pointer)>>0)]; case 2: return signed ? - function readS32FromPointer(pointer) { return HEAP32[pointer >> 2]; } : - function readU32FromPointer(pointer) { return HEAPU32[pointer >> 2]; }; + (pointer) => HEAP16[((pointer)>>1)] : + (pointer) => HEAPU16[((pointer)>>1)] + case 4: return signed ? + (pointer) => HEAP32[((pointer)>>2)] : + (pointer) => HEAPU32[((pointer)>>2)] default: - throw new TypeError("Unknown integer type: " + name); + throw new TypeError(`invalid integer width (${width}): ${name}`); } - } + }; - function __embind_register_integer(primitiveType, name, size, minRange, maxRange) { + /** @suppress {globalThis} */ + var __embind_register_integer = (primitiveType, name, size, minRange, maxRange) => { name = readLatin1String(name); // LLVM doesn't have signed and unsigned 32-bit types, so u32 literals come // out as 'i32 -1'. Always treat those as max u32. if (maxRange === -1) { - maxRange = 4294967295; + maxRange = 4294967295; } - var shift = getShiftFromSize(size); - var fromWireType = (value) => value; if (minRange === 0) { - var bitshift = 32 - 8*size; - fromWireType = (value) => (value << bitshift) >>> bitshift; + var bitshift = 32 - 8*size; + fromWireType = (value) => (value << bitshift) >>> bitshift; } var isUnsignedType = (name.includes('unsigned')); @@ -3272,14 +3229,14 @@ function dbg(text) { name, 'fromWireType': fromWireType, 'toWireType': toWireType, - 'argPackAdvance': 8, - 'readValueFromPointer': integerReadValueFromPointer(name, shift, minRange !== 0), + 'argPackAdvance': GenericWireTypeSize, + 'readValueFromPointer': integerReadValueFromPointer(name, size, minRange !== 0), destructorFunction: null, // This type does not need a destructor }); - } + }; - function __embind_register_memory_view(rawType, dataTypeIndex, name) { + var __embind_register_memory_view = (rawType, dataTypeIndex, name) => { var typeMapping = [ Int8Array, Uint8Array, @@ -3294,38 +3251,36 @@ function dbg(text) { var TA = typeMapping[dataTypeIndex]; function decodeMemoryView(handle) { - handle = handle >> 2; - var heap = HEAPU32; - var size = heap[handle]; // in elements - var data = heap[handle + 1]; // byte offset into emscripten heap - return new TA(heap.buffer, data, size); + var size = HEAPU32[((handle)>>2)]; + var data = HEAPU32[(((handle)+(4))>>2)]; + return new TA(HEAP8.buffer, data, size); } name = readLatin1String(name); registerType(rawType, { name, 'fromWireType': decodeMemoryView, - 'argPackAdvance': 8, + 'argPackAdvance': GenericWireTypeSize, 'readValueFromPointer': decodeMemoryView, }, { ignoreDuplicateRegistrations: true, }); - } + }; - function __embind_register_smart_ptr(rawType, - rawPointeeType, - name, - sharingPolicy, - getPointeeSignature, - rawGetPointee, - constructorSignature, - rawConstructor, - shareSignature, - rawShare, - destructorSignature, - rawDestructor) { + var __embind_register_smart_ptr = (rawType, + rawPointeeType, + name, + sharingPolicy, + getPointeeSignature, + rawGetPointee, + constructorSignature, + rawConstructor, + shareSignature, + rawShare, + destructorSignature, + rawDestructor) => { name = readLatin1String(name); rawGetPointee = embind__requireFunction(getPointeeSignature, rawGetPointee); rawConstructor = embind__requireFunction(constructorSignature, rawConstructor); @@ -3349,14 +3304,14 @@ function dbg(text) { rawDestructor); return [registeredPointer]; }); - } + }; var stringToUTF8Array = (str, heap, outIdx, maxBytesToWrite) => { - assert(typeof str === 'string'); + assert(typeof str === 'string', `stringToUTF8Array expects a string (got ${typeof str})`); // Parameter maxBytesToWrite is not optional. Negative values, 0, null, // undefined and false each don't write out any bytes. if (!(maxBytesToWrite > 0)) @@ -3404,7 +3359,7 @@ function dbg(text) { }; var stringToUTF8 = (str, outPtr, maxBytesToWrite) => { assert(typeof maxBytesToWrite == 'number', 'stringToUTF8(str, outPtr, maxBytesToWrite) is missing the third parameter that specifies the length of the output buffer!'); - return stringToUTF8Array(str, HEAPU8,outPtr, maxBytesToWrite); + return stringToUTF8Array(str, HEAPU8, outPtr, maxBytesToWrite); }; var lengthBytesUTF8 = (str) => { @@ -3430,7 +3385,7 @@ function dbg(text) { - function __embind_register_std_string(rawType, name) { + var __embind_register_std_string = (rawType, name) => { name = readLatin1String(name); var stdStringIsUTF8 //process only std::string bindings with UTF8 support, in contrast to e.g. std::basic_string @@ -3438,7 +3393,9 @@ function dbg(text) { registerType(rawType, { name, - 'fromWireType': function(value) { + // For some method names we use string keys here since they are part of + // the public/external API and/or used by the runtime-generated code. + 'fromWireType'(value) { var length = HEAPU32[((value)>>2)]; var payload = value + 4; @@ -3472,7 +3429,7 @@ function dbg(text) { return str; }, - 'toWireType': function(destructors, value) { + 'toWireType'(destructors, value) { if (value instanceof ArrayBuffer) { value = new Uint8Array(value); } @@ -3517,11 +3474,13 @@ function dbg(text) { } return base; }, - 'argPackAdvance': 8, - 'readValueFromPointer': simpleReadValueFromPointer, - destructorFunction: function(ptr) { _free(ptr); }, + 'argPackAdvance': GenericWireTypeSize, + 'readValueFromPointer': readPointer, + destructorFunction(ptr) { + _free(ptr); + }, }); - } + }; @@ -3649,7 +3608,7 @@ function dbg(text) { return len; }; - var __embind_register_std_wstring = function(rawType, charSize, name) { + var __embind_register_std_wstring = (rawType, charSize, name) => { name = readLatin1String(name); var decodeString, encodeString, getHeap, lengthBytesUTF, shift; if (charSize === 2) { @@ -3667,9 +3626,9 @@ function dbg(text) { } registerType(rawType, { name, - 'fromWireType': function(value) { + 'fromWireType': (value) => { // Code mostly taken from _embind_register_std_string fromWireType - var length = HEAPU32[value >> 2]; + var length = HEAPU32[((value)>>2)]; var HEAP = getHeap(); var str; @@ -3694,7 +3653,7 @@ function dbg(text) { return str; }, - 'toWireType': function(destructors, value) { + 'toWireType': (destructors, value) => { if (!(typeof value == 'string')) { throwBindingError(`Cannot pass non-string to C++ string type ${name}`); } @@ -3711,32 +3670,34 @@ function dbg(text) { } return ptr; }, - 'argPackAdvance': 8, + 'argPackAdvance': GenericWireTypeSize, 'readValueFromPointer': simpleReadValueFromPointer, - destructorFunction: function(ptr) { _free(ptr); }, + destructorFunction(ptr) { + _free(ptr); + } }); }; - function __embind_register_value_array( + var __embind_register_value_array = ( rawType, name, constructorSignature, rawConstructor, destructorSignature, rawDestructor - ) { + ) => { tupleRegistrations[rawType] = { name: readLatin1String(name), rawConstructor: embind__requireFunction(constructorSignature, rawConstructor), rawDestructor: embind__requireFunction(destructorSignature, rawDestructor), elements: [], }; - } + }; - function __embind_register_value_array_element( + var __embind_register_value_array_element = ( rawTupleType, getterReturnType, getterSignature, @@ -3746,7 +3707,7 @@ function dbg(text) { setterSignature, setter, setterContext - ) { + ) => { tupleRegistrations[rawTupleType].elements.push({ getterReturnType, getter: embind__requireFunction(getterSignature, getter), @@ -3755,29 +3716,29 @@ function dbg(text) { setter: embind__requireFunction(setterSignature, setter), setterContext, }); - } + }; - function __embind_register_value_object( + var __embind_register_value_object = ( rawType, name, constructorSignature, rawConstructor, destructorSignature, rawDestructor - ) { + ) => { structRegistrations[rawType] = { name: readLatin1String(name), rawConstructor: embind__requireFunction(constructorSignature, rawConstructor), rawDestructor: embind__requireFunction(destructorSignature, rawDestructor), fields: [], }; - } + }; - function __embind_register_value_object_field( + var __embind_register_value_object_field = ( structType, fieldName, getterReturnType, @@ -3788,7 +3749,7 @@ function dbg(text) { setterSignature, setter, setterContext - ) { + ) => { structRegistrations[structType].fields.push({ fieldName: readLatin1String(fieldName), getterReturnType, @@ -3798,388 +3759,305 @@ function dbg(text) { setter: embind__requireFunction(setterSignature, setter), setterContext, }); - } + }; - function __embind_register_void(rawType, name) { + var __embind_register_void = (rawType, name) => { name = readLatin1String(name); registerType(rawType, { - isVoid: true, // void return values can be optimized out sometimes - name, - 'argPackAdvance': 0, - 'fromWireType': function() { - return undefined; - }, - 'toWireType': function(destructors, o) { - // TODO: assert if anything else is given? - return undefined; - }, + isVoid: true, // void return values can be optimized out sometimes + name, + 'argPackAdvance': 0, + 'fromWireType': () => undefined, + // TODO: assert if anything else is given? + 'toWireType': (destructors, o) => undefined, }); - } + }; - function __emval_as(handle, returnType, destructorsRef) { + + var emval_returnValue = (returnType, destructorsRef, handle) => { + var destructors = []; + var result = returnType['toWireType'](destructors, handle); + if (destructors.length) { + // void, primitives and any other types w/o destructors don't need to allocate a handle + HEAPU32[((destructorsRef)>>2)] = Emval.toHandle(destructors); + } + return result; + }; + var __emval_as = (handle, returnType, destructorsRef) => { handle = Emval.toValue(handle); returnType = requireRegisteredType(returnType, 'emval::as'); - var destructors = []; - var rd = Emval.toHandle(destructors); - HEAPU32[((destructorsRef)>>2)] = rd; - return returnType['toWireType'](destructors, handle); - } + return emval_returnValue(returnType, destructorsRef, handle); + }; - function __emval_as_int64(handle, returnType) { + var __emval_as_int64 = (handle, returnType) => { handle = Emval.toValue(handle); returnType = requireRegisteredType(returnType, 'emval::as'); return returnType['toWireType'](null, handle); - } + }; - function __emval_as_uint64(handle, returnType) { + var __emval_as_uint64 = (handle, returnType) => { handle = Emval.toValue(handle); returnType = requireRegisteredType(returnType, 'emval::as'); return returnType['toWireType'](null, handle); - } + }; /** @type {function(...*):?} */ function __emval_await( ) { - err('missing function: _emval_await'); abort(-1); + abort('missing function: _emval_await'); } + __emval_await.stub = true; - function emval_lookupTypes(argCount, argTypes) { - var a = new Array(argCount); - for (var i = 0; i < argCount; ++i) { - a[i] = requireRegisteredType(HEAPU32[(((argTypes)+(i * 4))>>2)], - "parameter " + i); - } - return a; - } + var emval_methodCallers = []; - function __emval_call(handle, argCount, argTypes, argv) { + var __emval_call = (caller, handle, destructorsRef, args) => { + caller = emval_methodCallers[caller]; handle = Emval.toValue(handle); - var types = emval_lookupTypes(argCount, argTypes); - - var args = new Array(argCount); - for (var i = 0; i < argCount; ++i) { - var type = types[i]; - args[i] = type['readValueFromPointer'](argv); - argv += type['argPackAdvance']; - } - - var rv = handle.apply(undefined, args); - return Emval.toHandle(rv); - } + return caller(null, handle, destructorsRef, args); + }; - function emval_allocateDestructors(destructorsRef) { - var destructors = []; - HEAPU32[((destructorsRef)>>2)] = Emval.toHandle(destructors); - return destructors; - } - var emval_symbols = { }; - function getStringOrSymbol(address) { + var getStringOrSymbol = (address) => { var symbol = emval_symbols[address]; if (symbol === undefined) { return readLatin1String(address); } return symbol; - } - - var emval_methodCallers = []; - - function __emval_call_method(caller, handle, methodName, destructorsRef, args) { - caller = emval_methodCallers[caller]; - handle = Emval.toValue(handle); - methodName = getStringOrSymbol(methodName); - return caller(handle, methodName, emval_allocateDestructors(destructorsRef), args); - } - - + }; - function __emval_call_void_method(caller, handle, methodName, args) { + var __emval_call_method = (caller, objHandle, methodName, destructorsRef, args) => { caller = emval_methodCallers[caller]; - handle = Emval.toValue(handle); + objHandle = Emval.toValue(objHandle); methodName = getStringOrSymbol(methodName); - caller(handle, methodName, null, args); - } + return caller(objHandle, objHandle[methodName], destructorsRef, args); + }; - function __emval_delete(object, property) { + var __emval_delete = (object, property) => { object = Emval.toValue(object); property = Emval.toValue(property); return delete object[property]; - } + }; - function __emval_equals(first, second) { + var __emval_equals = (first, second) => { first = Emval.toValue(first); second = Emval.toValue(second); return first == second; - } + }; - function emval_get_global() { + var emval_get_global = () => { if (typeof globalThis == 'object') { return globalThis; } return (function(){ return Function; })()('return this')(); - } - function __emval_get_global(name) { + }; + var __emval_get_global = (name) => { if (name===0) { return Emval.toHandle(emval_get_global()); } else { name = getStringOrSymbol(name); return Emval.toHandle(emval_get_global()[name]); } - } + }; - function emval_addMethodCaller(caller) { + var emval_addMethodCaller = (caller) => { var id = emval_methodCallers.length; emval_methodCallers.push(caller); return id; - } - + }; + var emval_lookupTypes = (argCount, argTypes) => { + var a = new Array(argCount); + for (var i = 0; i < argCount; ++i) { + a[i] = requireRegisteredType(HEAPU32[(((argTypes)+(i * 4))>>2)], + "parameter " + i); + } + return a; + }; - var emval_registeredMethods = []; - function __emval_get_method_caller(argCount, argTypes) { - var types = emval_lookupTypes(argCount, argTypes); - var retType = types[0]; - var signatureName = retType.name + "_$" + types.slice(1).map(function (t) { return t.name; }).join("_") + "$"; - var returnId = emval_registeredMethods[signatureName]; - if (returnId !== undefined) { - return returnId; - } + var reflectConstruct = Reflect.construct; - var params = ["retType"]; - var args = [retType]; - var argsList = ""; // 'arg0, arg1, arg2, ... , argN' - for (var i = 0; i < argCount - 1; ++i) { - argsList += (i !== 0 ? ", " : "") + "arg" + i; - params.push("argType" + i); - args.push(types[1 + i]); - } + var __emval_get_method_caller = (argCount, argTypes, kind) => { + var types = emval_lookupTypes(argCount, argTypes); + var retType = types.shift(); + argCount--; // remove the shifted off return type - var functionName = makeLegalFunctionName("methodCaller_" + signatureName); var functionBody = - "return function " + functionName + "(handle, name, destructors, args) {\n"; + `return function (obj, func, destructorsRef, args) {\n`; var offset = 0; - for (var i = 0; i < argCount - 1; ++i) { - functionBody += - " var arg" + i + " = argType" + i + ".readValueFromPointer(args" + (offset ? ("+"+offset) : "") + ");\n"; - offset += types[i + 1]['argPackAdvance']; + var argsList = []; // 'obj?, arg0, arg1, arg2, ... , argN' + if (kind === /* FUNCTION */ 0) { + argsList.push("obj"); } + var params = ["retType"]; + var args = [retType]; + for (var i = 0; i < argCount; ++i) { + argsList.push("arg" + i); + params.push("argType" + i); + args.push(types[i]); + functionBody += + ` var arg${i} = argType${i}.readValueFromPointer(args${offset ? "+" + offset : ""});\n`; + offset += types[i]['argPackAdvance']; + } + var invoker = kind === /* CONSTRUCTOR */ 1 ? 'new func' : 'func.call'; functionBody += - " var rv = handle[name](" + argsList + ");\n"; - for (var i = 0; i < argCount - 1; ++i) { - if (types[i + 1]['deleteObject']) { - functionBody += - " argType" + i + ".deleteObject(arg" + i + ");\n"; - } + ` var rv = ${invoker}(${argsList.join(", ")});\n`; + for (var i = 0; i < argCount; ++i) { + if (types[i]['deleteObject']) { + functionBody += + ` argType${i}.deleteObject(arg${i});\n`; + } } if (!retType.isVoid) { - functionBody += - " return retType.toWireType(destructors, rv);\n"; + params.push("emval_returnValue"); + args.push(emval_returnValue); + functionBody += + " return emval_returnValue(retType, destructorsRef, rv);\n"; } functionBody += - "};\n"; + "};\n"; params.push(functionBody); var invokerFunction = newFunc(Function, params).apply(null, args); - returnId = emval_addMethodCaller(invokerFunction); - emval_registeredMethods[signatureName] = returnId; - return returnId; - } + var functionName = `methodCaller<(${types.map(t => t.name).join(', ')}) => ${retType.name}>`; + return emval_addMethodCaller(createNamedFunction(functionName, invokerFunction)); + }; - function __emval_get_module_property(name) { + var __emval_get_module_property = (name) => { name = getStringOrSymbol(name); return Emval.toHandle(Module[name]); - } + }; - function __emval_get_property(handle, key) { + var __emval_get_property = (handle, key) => { handle = Emval.toValue(handle); key = Emval.toValue(key); return Emval.toHandle(handle[key]); - } + }; - function __emval_in(item, object) { + var __emval_in = (item, object) => { item = Emval.toValue(item); object = Emval.toValue(object); return item in object; - } + }; - function __emval_incref(handle) { + var __emval_incref = (handle) => { if (handle > 4) { emval_handles.get(handle).refcount += 1; } - } + }; - function __emval_instanceof(object, constructor) { + var __emval_instanceof = (object, constructor) => { object = Emval.toValue(object); constructor = Emval.toValue(constructor); return object instanceof constructor; - } + }; - function __emval_is_number(handle) { + var __emval_is_number = (handle) => { handle = Emval.toValue(handle); return typeof handle == 'number'; - } + }; - function __emval_is_string(handle) { + var __emval_is_string = (handle) => { handle = Emval.toValue(handle); return typeof handle == 'string'; - } + }; - - function craftEmvalAllocator(argCount) { - /*This function returns a new function that looks like this: - function emval_allocator_3(constructor, argTypes, args) { - var argType0 = requireRegisteredType(HEAP32[(argTypes >> 2)], "parameter 0"); - var arg0 = argType0['readValueFromPointer'](args); - var argType1 = requireRegisteredType(HEAP32[(argTypes >> 2) + 1], "parameter 1"); - var arg1 = argType1['readValueFromPointer'](args + 8); - var argType2 = requireRegisteredType(HEAP32[(argTypes >> 2) + 2], "parameter 2"); - var arg2 = argType2['readValueFromPointer'](args + 16); - var obj = new constructor(arg0, arg1, arg2); - return Emval.toHandle(obj); - } */ - var argsList = ""; - for (var i = 0; i < argCount; ++i) { - argsList += (i!==0?", ":"")+"arg"+i; // 'arg0, arg1, ..., argn' - } - - // The body of the generated function does not have access to enclosing - // scope where HEAPU64/HEAPU32/etc are defined, and we cannot pass them - // directly as arguments (like we do the Module object) since memory - // growth can cause them to be re-bound. - var getMemory = () => HEAPU32; - - var functionBody = - "return function emval_allocator_"+argCount+"(constructor, argTypes, args) {\n" + - " var HEAPU32 = getMemory();\n"; - - for (var i = 0; i < argCount; ++i) { - functionBody += - "var argType"+i+" = requireRegisteredType(HEAPU32[((argTypes)>>2)], 'parameter "+i+"');\n" + - "var arg"+i+" = argType"+i+".readValueFromPointer(args);\n" + - "args += argType"+i+"['argPackAdvance'];\n" + - "argTypes += 4;\n"; - } - functionBody += - "var obj = new constructor("+argsList+");\n" + - "return valueToHandle(obj);\n" + - "}\n"; - - /*jshint evil:true*/ - return (new Function("requireRegisteredType", "Module", "valueToHandle", "getMemory" , functionBody))( - requireRegisteredType, Module, Emval.toHandle, getMemory); - } - - var emval_newers = { - }; - - function __emval_new(handle, argCount, argTypes, args) { - handle = Emval.toValue(handle); - - var newer = emval_newers[argCount]; - if (!newer) { - newer = craftEmvalAllocator(argCount); - emval_newers[argCount] = newer; - } - - return newer(handle, argTypes, args); - } + var __emval_iter_begin = (iterable) => { + iterable = Emval.toValue(iterable); + return Emval.toHandle(iterable[Symbol.iterator]()); + }; - function __emval_new_array() { - return Emval.toHandle([]); - } + var __emval_iter_next = (iterator) => { + iterator = Emval.toValue(iterator); + var result = iterator.next(); + return result.done ? 0 : Emval.toHandle(result.value); + }; + + var __emval_new_array = () => Emval.toHandle([]); - function __emval_new_array_from_memory_view(view) { + var __emval_new_array_from_memory_view = (view) => { view = Emval.toValue(view); // using for..loop is faster than Array.from var a = new Array(view.length); for (var i = 0; i < view.length; i++) a[i] = view[i]; return Emval.toHandle(a); - } + }; - function __emval_new_cstring(v) { - return Emval.toHandle(getStringOrSymbol(v)); - } + var __emval_new_cstring = (v) => Emval.toHandle(getStringOrSymbol(v)); - function __emval_new_object() { - return Emval.toHandle({}); - } + var __emval_new_object = () => Emval.toHandle({}); - function __emval_new_u16string(v) { - return Emval.toHandle(UTF16ToString(v)); - } + var __emval_new_u16string = (v) => Emval.toHandle(UTF16ToString(v)); - function __emval_new_u8string(v) { - return Emval.toHandle(UTF8ToString(v)); - } + var __emval_new_u8string = (v) => Emval.toHandle(UTF8ToString(v)); - function __emval_register_symbol(address) { + var __emval_register_symbol = (address) => { emval_symbols[address] = readLatin1String(address); - } + }; - function __emval_run_destructors(handle) { + var __emval_run_destructors = (handle) => { var destructors = Emval.toValue(handle); runDestructors(destructors); __emval_decref(handle); - } + }; - function __emval_set_property(handle, key, value) { + var __emval_set_property = (handle, key, value) => { handle = Emval.toValue(handle); key = Emval.toValue(key); value = Emval.toValue(value); handle[key] = value; - } + }; - function __emval_strictly_equals(first, second) { + var __emval_strictly_equals = (first, second) => { first = Emval.toValue(first); second = Emval.toValue(second); return first === second; - } + }; - function __emval_take_value(type, arg) { + var __emval_take_value = (type, arg) => { type = requireRegisteredType(type, '_emval_take_value'); var v = type['readValueFromPointer'](arg); return Emval.toHandle(v); - } + }; - function __emval_throw(object) { + var __emval_throw = (object) => { object = Emval.toValue(object); throw object; - } + }; - function __emval_typeof(handle) { + var __emval_typeof = (handle) => { handle = Emval.toValue(handle); return Emval.toHandle(typeof handle); - } + }; var _abort = () => { abort('native code called abort()'); }; - var _emscripten_memcpy_big = (dest, src, num) => HEAPU8.copyWithin(dest, src, src + num); + var _emscripten_memcpy_js = (dest, src, num) => HEAPU8.copyWithin(dest, src, src + num); var getHeapMax = () => HEAPU8.length; @@ -4309,9 +4187,7 @@ function dbg(text) { var paths = Array.prototype.slice.call(arguments); return PATH.normalize(paths.join('/')); }, - join2:(l, r) => { - return PATH.normalize(l + '/' + r); - }, + join2:(l, r) => PATH.normalize(l + '/' + r), }; var initRandomFill = () => { @@ -4435,7 +4311,7 @@ function dbg(text) { var fd = process.stdin.fd; try { - bytesRead = fs.readSync(fd, buf, 0, BUFSIZE, -1); + bytesRead = fs.readSync(fd, buf); } catch(e) { // Cross-platform differences: on Windows, reading EOF throws an exception, but on other OSes, // reading EOF returns 0. Uniformize behavior by treating the EOF exception to return 0. @@ -4472,7 +4348,7 @@ function dbg(text) { }; var TTY = { ttys:[], - init:function () { + init() { // https://github.com/emscripten-core/emscripten/pull/1555 // if (ENVIRONMENT_IS_NODE) { // // currently, FS.init does not distinguish if process.stdin is a file or TTY @@ -4482,7 +4358,7 @@ function dbg(text) { // process.stdin.setEncoding('utf8'); // } }, - shutdown:function() { + shutdown() { // https://github.com/emscripten-core/emscripten/pull/1555 // if (ENVIRONMENT_IS_NODE) { // // inolen: any idea as to why node -e 'process.stdin.read()' wouldn't exit immediately (with process.stdin being a tty)? @@ -4493,12 +4369,12 @@ function dbg(text) { // process.stdin.pause(); // } }, - register:function(dev, ops) { + register(dev, ops) { TTY.ttys[dev] = { input: [], output: [], ops: ops }; FS.registerDevice(dev, TTY.stream_ops); }, stream_ops:{ - open:function(stream) { + open(stream) { var tty = TTY.ttys[stream.node.rdev]; if (!tty) { throw new FS.ErrnoError(43); @@ -4506,14 +4382,14 @@ function dbg(text) { stream.tty = tty; stream.seekable = false; }, - close:function(stream) { + close(stream) { // flush any pending line data stream.tty.ops.fsync(stream.tty); }, - fsync:function(stream) { + fsync(stream) { stream.tty.ops.fsync(stream.tty); }, - read:function(stream, buffer, offset, length, pos /* ignored */) { + read(stream, buffer, offset, length, pos /* ignored */) { if (!stream.tty || !stream.tty.ops.get_char) { throw new FS.ErrnoError(60); } @@ -4537,7 +4413,7 @@ function dbg(text) { } return bytesRead; }, - write:function(stream, buffer, offset, length, pos) { + write(stream, buffer, offset, length, pos) { if (!stream.tty || !stream.tty.ops.put_char) { throw new FS.ErrnoError(60); } @@ -4555,10 +4431,10 @@ function dbg(text) { }, }, default_tty_ops:{ - get_char:function(tty) { + get_char(tty) { return FS_stdin_getChar(); }, - put_char:function(tty, val) { + put_char(tty, val) { if (val === null || val === 10) { out(UTF8ArrayToString(tty.output, 0)); tty.output = []; @@ -4566,13 +4442,13 @@ function dbg(text) { if (val != 0) tty.output.push(val); // val == 0 would cut text output off in the middle. } }, - fsync:function(tty) { + fsync(tty) { if (tty.output && tty.output.length > 0) { out(UTF8ArrayToString(tty.output, 0)); tty.output = []; } }, - ioctl_tcgets:function(tty) { + ioctl_tcgets(tty) { // typical setting return { c_iflag: 25856, @@ -4586,16 +4462,16 @@ function dbg(text) { ] }; }, - ioctl_tcsets:function(tty, optional_actions, data) { + ioctl_tcsets(tty, optional_actions, data) { // currently just ignore return 0; }, - ioctl_tiocgwinsz:function(tty) { + ioctl_tiocgwinsz(tty) { return [24, 80]; }, }, default_tty1_ops:{ - put_char:function(tty, val) { + put_char(tty, val) { if (val === null || val === 10) { err(UTF8ArrayToString(tty.output, 0)); tty.output = []; @@ -4603,7 +4479,7 @@ function dbg(text) { if (val != 0) tty.output.push(val); } }, - fsync:function(tty) { + fsync(tty) { if (tty.output && tty.output.length > 0) { err(UTF8ArrayToString(tty.output, 0)); tty.output = []; @@ -4971,13 +4847,17 @@ function dbg(text) { }; + var FS_createDataFile = (parent, name, fileData, canRead, canWrite, canOwn) => { + FS.createDataFile(parent, name, fileData, canRead, canWrite, canOwn); + }; + var preloadPlugins = Module['preloadPlugins'] || []; - function FS_handledByPreloadPlugin(byteArray, fullname, finish, onerror) { + var FS_handledByPreloadPlugin = (byteArray, fullname, finish, onerror) => { // Ensure plugins are ready. if (typeof Browser != 'undefined') Browser.init(); var handled = false; - preloadPlugins.forEach(function(plugin) { + preloadPlugins.forEach((plugin) => { if (handled) return; if (plugin['canHandle'](fullname)) { plugin['handle'](byteArray, fullname, finish, onerror); @@ -4985,8 +4865,8 @@ function dbg(text) { } }); return handled; - } - function FS_createPreloadedFile(parent, name, url, canRead, canWrite, onload, onerror, dontCreateFile, canOwn, preFinish) { + }; + var FS_createPreloadedFile = (parent, name, url, canRead, canWrite, onload, onerror, dontCreateFile, canOwn, preFinish) => { // TODO we should allow people to just pass in a complete filename instead // of parent and name being that we just join them anyways var fullname = name ? PATH_FS.resolve(PATH.join2(parent, name)) : parent; @@ -4995,7 +4875,7 @@ function dbg(text) { function finish(byteArray) { if (preFinish) preFinish(); if (!dontCreateFile) { - FS.createDataFile(parent, name, byteArray, canRead, canWrite, canOwn); + FS_createDataFile(parent, name, byteArray, canRead, canWrite, canOwn); } if (onload) onload(); removeRunDependency(dep); @@ -5014,9 +4894,9 @@ function dbg(text) { } else { processData(url); } - } + }; - function FS_modeStringToFlags(str) { + var FS_modeStringToFlags = (str) => { var flagModes = { 'r': 0, 'r+': 2, @@ -5030,14 +4910,14 @@ function dbg(text) { throw new Error(`Unknown file open mode: ${str}`); } return flags; - } + }; - function FS_getMode(canRead, canWrite) { + var FS_getMode = (canRead, canWrite) => { var mode = 0; if (canRead) mode |= 292 | 73; if (canWrite) mode |= 146; return mode; - } + }; @@ -5165,13 +5045,134 @@ function dbg(text) { }; var ERRNO_CODES = { - }; + 'EPERM': 63, + 'ENOENT': 44, + 'ESRCH': 71, + 'EINTR': 27, + 'EIO': 29, + 'ENXIO': 60, + 'E2BIG': 1, + 'ENOEXEC': 45, + 'EBADF': 8, + 'ECHILD': 12, + 'EAGAIN': 6, + 'EWOULDBLOCK': 6, + 'ENOMEM': 48, + 'EACCES': 2, + 'EFAULT': 21, + 'ENOTBLK': 105, + 'EBUSY': 10, + 'EEXIST': 20, + 'EXDEV': 75, + 'ENODEV': 43, + 'ENOTDIR': 54, + 'EISDIR': 31, + 'EINVAL': 28, + 'ENFILE': 41, + 'EMFILE': 33, + 'ENOTTY': 59, + 'ETXTBSY': 74, + 'EFBIG': 22, + 'ENOSPC': 51, + 'ESPIPE': 70, + 'EROFS': 69, + 'EMLINK': 34, + 'EPIPE': 64, + 'EDOM': 18, + 'ERANGE': 68, + 'ENOMSG': 49, + 'EIDRM': 24, + 'ECHRNG': 106, + 'EL2NSYNC': 156, + 'EL3HLT': 107, + 'EL3RST': 108, + 'ELNRNG': 109, + 'EUNATCH': 110, + 'ENOCSI': 111, + 'EL2HLT': 112, + 'EDEADLK': 16, + 'ENOLCK': 46, + 'EBADE': 113, + 'EBADR': 114, + 'EXFULL': 115, + 'ENOANO': 104, + 'EBADRQC': 103, + 'EBADSLT': 102, + 'EDEADLOCK': 16, + 'EBFONT': 101, + 'ENOSTR': 100, + 'ENODATA': 116, + 'ETIME': 117, + 'ENOSR': 118, + 'ENONET': 119, + 'ENOPKG': 120, + 'EREMOTE': 121, + 'ENOLINK': 47, + 'EADV': 122, + 'ESRMNT': 123, + 'ECOMM': 124, + 'EPROTO': 65, + 'EMULTIHOP': 36, + 'EDOTDOT': 125, + 'EBADMSG': 9, + 'ENOTUNIQ': 126, + 'EBADFD': 127, + 'EREMCHG': 128, + 'ELIBACC': 129, + 'ELIBBAD': 130, + 'ELIBSCN': 131, + 'ELIBMAX': 132, + 'ELIBEXEC': 133, + 'ENOSYS': 52, + 'ENOTEMPTY': 55, + 'ENAMETOOLONG': 37, + 'ELOOP': 32, + 'EOPNOTSUPP': 138, + 'EPFNOSUPPORT': 139, + 'ECONNRESET': 15, + 'ENOBUFS': 42, + 'EAFNOSUPPORT': 5, + 'EPROTOTYPE': 67, + 'ENOTSOCK': 57, + 'ENOPROTOOPT': 50, + 'ESHUTDOWN': 140, + 'ECONNREFUSED': 14, + 'EADDRINUSE': 3, + 'ECONNABORTED': 13, + 'ENETUNREACH': 40, + 'ENETDOWN': 38, + 'ETIMEDOUT': 73, + 'EHOSTDOWN': 142, + 'EHOSTUNREACH': 23, + 'EINPROGRESS': 26, + 'EALREADY': 7, + 'EDESTADDRREQ': 17, + 'EMSGSIZE': 35, + 'EPROTONOSUPPORT': 66, + 'ESOCKTNOSUPPORT': 137, + 'EADDRNOTAVAIL': 4, + 'ENETRESET': 39, + 'EISCONN': 30, + 'ENOTCONN': 53, + 'ETOOMANYREFS': 141, + 'EUSERS': 136, + 'EDQUOT': 19, + 'ESTALE': 72, + 'ENOTSUP': 138, + 'ENOMEDIUM': 148, + 'EILSEQ': 25, + 'EOVERFLOW': 61, + 'ECANCELED': 11, + 'ENOTRECOVERABLE': 56, + 'EOWNERDEAD': 62, + 'ESTRPIPE': 135, + }; - function demangle(func) { + var demangle = (func) => { warnOnce('warning: build with -sDEMANGLE_SUPPORT to link in libcxxabi demangling'); return func; - } - function demangleAll(text) { + }; + var demangleAll = (text) => { var regex = /\b_Z[\w\d_]+/g; return text.replace(regex, @@ -5179,7 +5180,7 @@ function dbg(text) { var y = demangle(x); return x === y ? x : (y + ' [' + x + ']'); }); - } + }; var FS = { root:null, mounts:[], @@ -5196,7 +5197,7 @@ function dbg(text) { }, filesystems:null, syncFSRequests:0, - lookupPath:(path, opts = {}) => { + lookupPath(path, opts = {}) { path = PATH_FS.resolve(path); if (!path) return { path: '', node: null }; @@ -5255,7 +5256,7 @@ function dbg(text) { return { path: current_path, node: current }; }, - getPath:(node) => { + getPath(node) { var path; while (true) { if (FS.isRoot(node)) { @@ -5267,7 +5268,7 @@ function dbg(text) { node = node.parent; } }, - hashName:(parentid, name) => { + hashName(parentid, name) { var hash = 0; for (var i = 0; i < name.length; i++) { @@ -5275,12 +5276,12 @@ function dbg(text) { } return ((parentid + hash) >>> 0) % FS.nameTable.length; }, - hashAddNode:(node) => { + hashAddNode(node) { var hash = FS.hashName(node.parent.id, node.name); node.name_next = FS.nameTable[hash]; FS.nameTable[hash] = node; }, - hashRemoveNode:(node) => { + hashRemoveNode(node) { var hash = FS.hashName(node.parent.id, node.name); if (FS.nameTable[hash] === node) { FS.nameTable[hash] = node.name_next; @@ -5295,7 +5296,7 @@ function dbg(text) { } } }, - lookupNode:(parent, name) => { + lookupNode(parent, name) { var errCode = FS.mayLookup(parent); if (errCode) { throw new FS.ErrnoError(errCode, parent); @@ -5310,7 +5311,7 @@ function dbg(text) { // if we failed to find it in the cache, call into the VFS return FS.lookup(parent, name); }, - createNode:(parent, name, mode, rdev) => { + createNode(parent, name, mode, rdev) { assert(typeof parent == 'object') var node = new FS.FSNode(parent, name, mode, rdev); @@ -5318,44 +5319,44 @@ function dbg(text) { return node; }, - destroyNode:(node) => { + destroyNode(node) { FS.hashRemoveNode(node); }, - isRoot:(node) => { + isRoot(node) { return node === node.parent; }, - isMountpoint:(node) => { + isMountpoint(node) { return !!node.mounted; }, - isFile:(mode) => { + isFile(mode) { return (mode & 61440) === 32768; }, - isDir:(mode) => { + isDir(mode) { return (mode & 61440) === 16384; }, - isLink:(mode) => { + isLink(mode) { return (mode & 61440) === 40960; }, - isChrdev:(mode) => { + isChrdev(mode) { return (mode & 61440) === 8192; }, - isBlkdev:(mode) => { + isBlkdev(mode) { return (mode & 61440) === 24576; }, - isFIFO:(mode) => { + isFIFO(mode) { return (mode & 61440) === 4096; }, - isSocket:(mode) => { + isSocket(mode) { return (mode & 49152) === 49152; }, - flagsToPermissionString:(flag) => { + flagsToPermissionString(flag) { var perms = ['r', 'w', 'rw'][flag & 3]; if ((flag & 512)) { perms += 'w'; } return perms; }, - nodePermissions:(node, perms) => { + nodePermissions(node, perms) { if (FS.ignorePermissions) { return 0; } @@ -5369,13 +5370,13 @@ function dbg(text) { } return 0; }, - mayLookup:(dir) => { + mayLookup(dir) { var errCode = FS.nodePermissions(dir, 'x'); if (errCode) return errCode; if (!dir.node_ops.lookup) return 2; return 0; }, - mayCreate:(dir, name) => { + mayCreate(dir, name) { try { var node = FS.lookupNode(dir, name); return 20; @@ -5383,7 +5384,7 @@ function dbg(text) { } return FS.nodePermissions(dir, 'wx'); }, - mayDelete:(dir, name, isdir) => { + mayDelete(dir, name, isdir) { var node; try { node = FS.lookupNode(dir, name); @@ -5408,7 +5409,7 @@ function dbg(text) { } return 0; }, - mayOpen:(node, flags) => { + mayOpen(node, flags) { if (!node) { return 44; } @@ -5423,7 +5424,7 @@ function dbg(text) { return FS.nodePermissions(node, FS.flagsToPermissionString(flags)); }, MAX_OPEN_FDS:4096, - nextfd:() => { + nextfd() { for (var fd = 0; fd <= FS.MAX_OPEN_FDS; fd++) { if (!FS.streams[fd]) { return fd; @@ -5431,7 +5432,7 @@ function dbg(text) { } throw new FS.ErrnoError(33); }, - getStreamChecked:(fd) => { + getStreamChecked(fd) { var stream = FS.getStream(fd); if (!stream) { throw new FS.ErrnoError(8); @@ -5439,7 +5440,7 @@ function dbg(text) { return stream; }, getStream:(fd) => FS.streams[fd], - createStream:(stream, fd = -1) => { + createStream(stream, fd = -1) { if (!FS.FSStream) { FS.FSStream = /** @constructor */ function() { this.shared = { }; @@ -5487,11 +5488,11 @@ function dbg(text) { FS.streams[fd] = stream; return stream; }, - closeStream:(fd) => { + closeStream(fd) { FS.streams[fd] = null; }, chrdev_stream_ops:{ - open:(stream) => { + open(stream) { var device = FS.getDevice(stream.node.rdev); // override node's stream ops with the device's stream.stream_ops = device.stream_ops; @@ -5500,18 +5501,18 @@ function dbg(text) { stream.stream_ops.open(stream); } }, - llseek:() => { + llseek() { throw new FS.ErrnoError(70); }, }, major:(dev) => ((dev) >> 8), minor:(dev) => ((dev) & 0xff), makedev:(ma, mi) => ((ma) << 8 | (mi)), - registerDevice:(dev, ops) => { + registerDevice(dev, ops) { FS.devices[dev] = { stream_ops: ops }; }, getDevice:(dev) => FS.devices[dev], - getMounts:(mount) => { + getMounts(mount) { var mounts = []; var check = [mount]; @@ -5525,7 +5526,7 @@ function dbg(text) { return mounts; }, - syncfs:(populate, callback) => { + syncfs(populate, callback) { if (typeof populate == 'function') { callback = populate; populate = false; @@ -5567,7 +5568,7 @@ function dbg(text) { mount.type.syncfs(mount, populate, done); }); }, - mount:(type, opts, mountpoint) => { + mount(type, opts, mountpoint) { if (typeof type == 'string') { // The filesystem was not included, and instead we have an error // message stored in the variable. @@ -5620,7 +5621,7 @@ function dbg(text) { return mountRoot; }, - unmount:(mountpoint) => { + unmount(mountpoint) { var lookup = FS.lookupPath(mountpoint, { follow_mount: false }); if (!FS.isMountpoint(lookup.node)) { @@ -5654,10 +5655,10 @@ function dbg(text) { assert(idx !== -1); node.mount.mounts.splice(idx, 1); }, - lookup:(parent, name) => { + lookup(parent, name) { return parent.node_ops.lookup(parent, name); }, - mknod:(path, mode, dev) => { + mknod(path, mode, dev) { var lookup = FS.lookupPath(path, { parent: true }); var parent = lookup.node; var name = PATH.basename(path); @@ -5673,19 +5674,19 @@ function dbg(text) { } return parent.node_ops.mknod(parent, name, mode, dev); }, - create:(path, mode) => { + create(path, mode) { mode = mode !== undefined ? mode : 438 /* 0666 */; mode &= 4095; mode |= 32768; return FS.mknod(path, mode, 0); }, - mkdir:(path, mode) => { + mkdir(path, mode) { mode = mode !== undefined ? mode : 511 /* 0777 */; mode &= 511 | 512; mode |= 16384; return FS.mknod(path, mode, 0); }, - mkdirTree:(path, mode) => { + mkdirTree(path, mode) { var dirs = path.split('/'); var d = ''; for (var i = 0; i < dirs.length; ++i) { @@ -5698,7 +5699,7 @@ function dbg(text) { } } }, - mkdev:(path, mode, dev) => { + mkdev(path, mode, dev) { if (typeof dev == 'undefined') { dev = mode; mode = 438 /* 0666 */; @@ -5706,7 +5707,7 @@ function dbg(text) { mode |= 8192; return FS.mknod(path, mode, dev); }, - symlink:(oldpath, newpath) => { + symlink(oldpath, newpath) { if (!PATH_FS.resolve(oldpath)) { throw new FS.ErrnoError(44); } @@ -5725,7 +5726,7 @@ function dbg(text) { } return parent.node_ops.symlink(parent, newname, oldpath); }, - rename:(old_path, new_path) => { + rename(old_path, new_path) { var old_dirname = PATH.dirname(old_path); var new_dirname = PATH.dirname(new_path); var old_name = PATH.basename(old_path); @@ -5807,7 +5808,7 @@ function dbg(text) { FS.hashAddNode(old_node); } }, - rmdir:(path) => { + rmdir(path) { var lookup = FS.lookupPath(path, { parent: true }); var parent = lookup.node; var name = PATH.basename(path); @@ -5825,7 +5826,7 @@ function dbg(text) { parent.node_ops.rmdir(parent, name); FS.destroyNode(node); }, - readdir:(path) => { + readdir(path) { var lookup = FS.lookupPath(path, { follow: true }); var node = lookup.node; if (!node.node_ops.readdir) { @@ -5833,7 +5834,7 @@ function dbg(text) { } return node.node_ops.readdir(node); }, - unlink:(path) => { + unlink(path) { var lookup = FS.lookupPath(path, { parent: true }); var parent = lookup.node; if (!parent) { @@ -5857,7 +5858,7 @@ function dbg(text) { parent.node_ops.unlink(parent, name); FS.destroyNode(node); }, - readlink:(path) => { + readlink(path) { var lookup = FS.lookupPath(path); var link = lookup.node; if (!link) { @@ -5868,7 +5869,7 @@ function dbg(text) { } return PATH_FS.resolve(FS.getPath(link.parent), link.node_ops.readlink(link)); }, - stat:(path, dontFollow) => { + stat(path, dontFollow) { var lookup = FS.lookupPath(path, { follow: !dontFollow }); var node = lookup.node; if (!node) { @@ -5879,10 +5880,10 @@ function dbg(text) { } return node.node_ops.getattr(node); }, - lstat:(path) => { + lstat(path) { return FS.stat(path, true); }, - chmod:(path, mode, dontFollow) => { + chmod(path, mode, dontFollow) { var node; if (typeof path == 'string') { var lookup = FS.lookupPath(path, { follow: !dontFollow }); @@ -5898,14 +5899,14 @@ function dbg(text) { timestamp: Date.now() }); }, - lchmod:(path, mode) => { + lchmod(path, mode) { FS.chmod(path, mode, true); }, - fchmod:(fd, mode) => { + fchmod(fd, mode) { var stream = FS.getStreamChecked(fd); FS.chmod(stream.node, mode); }, - chown:(path, uid, gid, dontFollow) => { + chown(path, uid, gid, dontFollow) { var node; if (typeof path == 'string') { var lookup = FS.lookupPath(path, { follow: !dontFollow }); @@ -5921,14 +5922,14 @@ function dbg(text) { // we ignore the uid / gid for now }); }, - lchown:(path, uid, gid) => { + lchown(path, uid, gid) { FS.chown(path, uid, gid, true); }, - fchown:(fd, uid, gid) => { + fchown(fd, uid, gid) { var stream = FS.getStreamChecked(fd); FS.chown(stream.node, uid, gid); }, - truncate:(path, len) => { + truncate(path, len) { if (len < 0) { throw new FS.ErrnoError(28); } @@ -5957,21 +5958,21 @@ function dbg(text) { timestamp: Date.now() }); }, - ftruncate:(fd, len) => { + ftruncate(fd, len) { var stream = FS.getStreamChecked(fd); if ((stream.flags & 2097155) === 0) { throw new FS.ErrnoError(28); } FS.truncate(stream.node, len); }, - utime:(path, atime, mtime) => { + utime(path, atime, mtime) { var lookup = FS.lookupPath(path, { follow: true }); var node = lookup.node; node.node_ops.setattr(node, { timestamp: Math.max(atime, mtime) }); }, - open:(path, flags, mode) => { + open(path, flags, mode) { if (path === "") { throw new FS.ErrnoError(44); } @@ -6061,7 +6062,7 @@ function dbg(text) { } return stream; }, - close:(stream) => { + close(stream) { if (FS.isClosed(stream)) { throw new FS.ErrnoError(8); } @@ -6077,10 +6078,10 @@ function dbg(text) { } stream.fd = null; }, - isClosed:(stream) => { + isClosed(stream) { return stream.fd === null; }, - llseek:(stream, offset, whence) => { + llseek(stream, offset, whence) { if (FS.isClosed(stream)) { throw new FS.ErrnoError(8); } @@ -6094,7 +6095,7 @@ function dbg(text) { stream.ungotten = []; return stream.position; }, - read:(stream, buffer, offset, length, position) => { + read(stream, buffer, offset, length, position) { assert(offset >= 0); if (length < 0 || position < 0) { throw new FS.ErrnoError(28); @@ -6121,7 +6122,7 @@ function dbg(text) { if (!seeking) stream.position += bytesRead; return bytesRead; }, - write:(stream, buffer, offset, length, position, canOwn) => { + write(stream, buffer, offset, length, position, canOwn) { assert(offset >= 0); if (length < 0 || position < 0) { throw new FS.ErrnoError(28); @@ -6152,7 +6153,7 @@ function dbg(text) { if (!seeking) stream.position += bytesWritten; return bytesWritten; }, - allocate:(stream, offset, length) => { + allocate(stream, offset, length) { if (FS.isClosed(stream)) { throw new FS.ErrnoError(8); } @@ -6170,7 +6171,7 @@ function dbg(text) { } stream.stream_ops.allocate(stream, offset, length); }, - mmap:(stream, length, position, prot, flags) => { + mmap(stream, length, position, prot, flags) { // User requests writing to file (prot & PROT_WRITE != 0). // Checking if we have permissions to write to the file unless // MAP_PRIVATE flag is set. According to POSIX spec it is possible @@ -6190,7 +6191,7 @@ function dbg(text) { } return stream.stream_ops.mmap(stream, length, position, prot, flags); }, - msync:(stream, buffer, offset, length, mmapFlags) => { + msync(stream, buffer, offset, length, mmapFlags) { assert(offset >= 0); if (!stream.stream_ops.msync) { return 0; @@ -6198,13 +6199,13 @@ function dbg(text) { return stream.stream_ops.msync(stream, buffer, offset, length, mmapFlags); }, munmap:(stream) => 0, - ioctl:(stream, cmd, arg) => { + ioctl(stream, cmd, arg) { if (!stream.stream_ops.ioctl) { throw new FS.ErrnoError(59); } return stream.stream_ops.ioctl(stream, cmd, arg); }, - readFile:(path, opts = {}) => { + readFile(path, opts = {}) { opts.flags = opts.flags || 0; opts.encoding = opts.encoding || 'binary'; if (opts.encoding !== 'utf8' && opts.encoding !== 'binary') { @@ -6224,7 +6225,7 @@ function dbg(text) { FS.close(stream); return ret; }, - writeFile:(path, data, opts = {}) => { + writeFile(path, data, opts = {}) { opts.flags = opts.flags || 577; var stream = FS.open(path, opts.flags, opts.mode); if (typeof data == 'string') { @@ -6239,7 +6240,7 @@ function dbg(text) { FS.close(stream); }, cwd:() => FS.currentPath, - chdir:(path) => { + chdir(path) { var lookup = FS.lookupPath(path, { follow: true }); if (lookup.node === null) { throw new FS.ErrnoError(44); @@ -6253,12 +6254,12 @@ function dbg(text) { } FS.currentPath = lookup.path; }, - createDefaultDirectories:() => { + createDefaultDirectories() { FS.mkdir('/tmp'); FS.mkdir('/home'); FS.mkdir('/home/web_user'); }, - createDefaultDevices:() => { + createDefaultDevices() { // create /dev FS.mkdir('/dev'); // setup /dev/null @@ -6290,17 +6291,17 @@ function dbg(text) { FS.mkdir('/dev/shm'); FS.mkdir('/dev/shm/tmp'); }, - createSpecialDirectories:() => { + createSpecialDirectories() { // create /proc/self/fd which allows /proc/self/fd/6 => readlink gives the // name of the stream for fd 6 (see test_unistd_ttyname) FS.mkdir('/proc'); var proc_self = FS.mkdir('/proc/self'); FS.mkdir('/proc/self/fd'); FS.mount({ - mount: () => { + mount() { var node = FS.createNode(proc_self, 'fd', 16384 | 511 /* 0777 */, 73); node.node_ops = { - lookup: (parent, name) => { + lookup(parent, name) { var fd = +name; var stream = FS.getStreamChecked(fd); var ret = { @@ -6316,7 +6317,7 @@ function dbg(text) { } }, {}, '/proc/self/fd'); }, - createStandardStreams:() => { + createStandardStreams() { // TODO deprecate the old functionality of a single // input / output callback and that utilizes FS.createDevice // and instead require a unique set of stream ops @@ -6349,7 +6350,7 @@ function dbg(text) { assert(stdout.fd === 1, `invalid handle for stdout (${stdout.fd})`); assert(stderr.fd === 2, `invalid handle for stderr (${stderr.fd})`); }, - ensureErrnoError:() => { + ensureErrnoError() { if (FS.ErrnoError) return; FS.ErrnoError = /** @this{Object} */ function ErrnoError(errno, node) { // We set the `name` property to be able to identify `FS.ErrnoError` @@ -6388,7 +6389,7 @@ function dbg(text) { FS.genericErrors[code].stack = ''; }); }, - staticInit:() => { + staticInit() { FS.ensureErrnoError(); FS.nameTable = new Array(4096); @@ -6403,7 +6404,7 @@ function dbg(text) { 'MEMFS': MEMFS, }; }, - init:(input, output, error) => { + init(input, output, error) { assert(!FS.init.initialized, 'FS.init was previously called. If you want to initialize later with custom parameters, remove any earlier calls (note that one is automatically added to the generated code)'); FS.init.initialized = true; @@ -6416,7 +6417,7 @@ function dbg(text) { FS.createStandardStreams(); }, - quit:() => { + quit() { FS.init.initialized = false; // force-flush all streams, so we get musl std streams printed out _fflush(0); @@ -6429,14 +6430,14 @@ function dbg(text) { FS.close(stream); } }, - findObject:(path, dontResolveLastLink) => { + findObject(path, dontResolveLastLink) { var ret = FS.analyzePath(path, dontResolveLastLink); if (!ret.exists) { return null; } return ret.object; }, - analyzePath:(path, dontResolveLastLink) => { + analyzePath(path, dontResolveLastLink) { // operate from within the context of the symlink's target try { var lookup = FS.lookupPath(path, { follow: !dontResolveLastLink }); @@ -6464,7 +6465,7 @@ function dbg(text) { }; return ret; }, - createPath:(parent, path, canRead, canWrite) => { + createPath(parent, path, canRead, canWrite) { parent = typeof parent == 'string' ? parent : FS.getPath(parent); var parts = path.split('/').reverse(); while (parts.length) { @@ -6480,12 +6481,12 @@ function dbg(text) { } return current; }, - createFile:(parent, name, properties, canRead, canWrite) => { + createFile(parent, name, properties, canRead, canWrite) { var path = PATH.join2(typeof parent == 'string' ? parent : FS.getPath(parent), name); var mode = FS_getMode(canRead, canWrite); return FS.create(path, mode); }, - createDataFile:(parent, name, data, canRead, canWrite, canOwn) => { + createDataFile(parent, name, data, canRead, canWrite, canOwn) { var path = name; if (parent) { parent = typeof parent == 'string' ? parent : FS.getPath(parent); @@ -6506,9 +6507,8 @@ function dbg(text) { FS.close(stream); FS.chmod(node, mode); } - return node; }, - createDevice:(parent, name, input, output) => { + createDevice(parent, name, input, output) { var path = PATH.join2(typeof parent == 'string' ? parent : FS.getPath(parent), name); var mode = FS_getMode(!!input, !!output); if (!FS.createDevice.major) FS.createDevice.major = 64; @@ -6516,16 +6516,16 @@ function dbg(text) { // Create a fake device that a set of stream ops to emulate // the old behavior. FS.registerDevice(dev, { - open: (stream) => { + open(stream) { stream.seekable = false; }, - close: (stream) => { + close(stream) { // flush any pending line data if (output && output.buffer && output.buffer.length) { output(10); } }, - read: (stream, buffer, offset, length, pos /* ignored */) => { + read(stream, buffer, offset, length, pos /* ignored */) { var bytesRead = 0; for (var i = 0; i < length; i++) { var result; @@ -6546,7 +6546,7 @@ function dbg(text) { } return bytesRead; }, - write: (stream, buffer, offset, length, pos) => { + write(stream, buffer, offset, length, pos) { for (var i = 0; i < length; i++) { try { output(buffer[offset+i]); @@ -6562,7 +6562,7 @@ function dbg(text) { }); return FS.mkdev(path, mode, dev); }, - forceLoadFile:(obj) => { + forceLoadFile(obj) { if (obj.isDevice || obj.isFolder || obj.link || obj.contents) return true; if (typeof XMLHttpRequest != 'undefined') { throw new Error("Lazy loading should have been performed (contents set) in createLazyFile, but it was not. Lazy loading only works in web workers. Use --embed-file or --preload-file in emcc on the main thread."); @@ -6580,7 +6580,7 @@ function dbg(text) { throw new Error('Cannot load without read() or XMLHttpRequest.'); } }, - createLazyFile:(parent, name, url, canRead, canWrite) => { + createLazyFile(parent, name, url, canRead, canWrite) { // Lazy chunked Uint8Array (implements get and length from Uint8Array). Actual getting is abstracted away for eventual reuse. /** @constructor */ function LazyUint8Array() { @@ -6748,29 +6748,29 @@ function dbg(text) { node.stream_ops = stream_ops; return node; }, - absolutePath:() => { + absolutePath() { abort('FS.absolutePath has been removed; use PATH_FS.resolve instead'); }, - createFolder:() => { + createFolder() { abort('FS.createFolder has been removed; use FS.mkdir instead'); }, - createLink:() => { + createLink() { abort('FS.createLink has been removed; use FS.symlink instead'); }, - joinPath:() => { + joinPath() { abort('FS.joinPath has been removed; use PATH.join instead'); }, - mmapAlloc:() => { + mmapAlloc() { abort('FS.mmapAlloc has been replaced by the top level function mmapAlloc'); }, - standardizePath:() => { + standardizePath() { abort('FS.standardizePath has been removed; use PATH.normalize instead'); }, }; var SYSCALLS = { DEFAULT_POLLMASK:5, - calculateAt:function(dirfd, path, allowEmpty) { + calculateAt(dirfd, path, allowEmpty) { if (PATH.isAbs(path)) { return path; } @@ -6790,7 +6790,7 @@ function dbg(text) { } return PATH.join2(dir, path); }, - doStat:function(func, path, buf) { + doStat(func, path, buf) { try { var stat = func(path); } catch (e) { @@ -6806,22 +6806,22 @@ function dbg(text) { HEAP32[(((buf)+(12))>>2)] = stat.uid; HEAP32[(((buf)+(16))>>2)] = stat.gid; HEAP32[(((buf)+(20))>>2)] = stat.rdev; - (tempI64 = [stat.size>>>0,(tempDouble=stat.size,(+(Math.abs(tempDouble))) >= 1.0 ? (tempDouble > 0.0 ? (+(Math.floor((tempDouble)/4294967296.0)))>>>0 : (~~((+(Math.ceil((tempDouble - +(((~~(tempDouble)))>>>0))/4294967296.0)))))>>>0) : 0)], HEAP32[(((buf)+(24))>>2)] = tempI64[0],HEAP32[(((buf)+(28))>>2)] = tempI64[1]); + (tempI64 = [stat.size>>>0,(tempDouble = stat.size,(+(Math.abs(tempDouble))) >= 1.0 ? (tempDouble > 0.0 ? (+(Math.floor((tempDouble)/4294967296.0)))>>>0 : (~~((+(Math.ceil((tempDouble - +(((~~(tempDouble)))>>>0))/4294967296.0)))))>>>0) : 0)], HEAP32[(((buf)+(24))>>2)] = tempI64[0],HEAP32[(((buf)+(28))>>2)] = tempI64[1]); HEAP32[(((buf)+(32))>>2)] = 4096; HEAP32[(((buf)+(36))>>2)] = stat.blocks; var atime = stat.atime.getTime(); var mtime = stat.mtime.getTime(); var ctime = stat.ctime.getTime(); - (tempI64 = [Math.floor(atime / 1000)>>>0,(tempDouble=Math.floor(atime / 1000),(+(Math.abs(tempDouble))) >= 1.0 ? (tempDouble > 0.0 ? (+(Math.floor((tempDouble)/4294967296.0)))>>>0 : (~~((+(Math.ceil((tempDouble - +(((~~(tempDouble)))>>>0))/4294967296.0)))))>>>0) : 0)], HEAP32[(((buf)+(40))>>2)] = tempI64[0],HEAP32[(((buf)+(44))>>2)] = tempI64[1]); + (tempI64 = [Math.floor(atime / 1000)>>>0,(tempDouble = Math.floor(atime / 1000),(+(Math.abs(tempDouble))) >= 1.0 ? (tempDouble > 0.0 ? (+(Math.floor((tempDouble)/4294967296.0)))>>>0 : (~~((+(Math.ceil((tempDouble - +(((~~(tempDouble)))>>>0))/4294967296.0)))))>>>0) : 0)], HEAP32[(((buf)+(40))>>2)] = tempI64[0],HEAP32[(((buf)+(44))>>2)] = tempI64[1]); HEAPU32[(((buf)+(48))>>2)] = (atime % 1000) * 1000; - (tempI64 = [Math.floor(mtime / 1000)>>>0,(tempDouble=Math.floor(mtime / 1000),(+(Math.abs(tempDouble))) >= 1.0 ? (tempDouble > 0.0 ? (+(Math.floor((tempDouble)/4294967296.0)))>>>0 : (~~((+(Math.ceil((tempDouble - +(((~~(tempDouble)))>>>0))/4294967296.0)))))>>>0) : 0)], HEAP32[(((buf)+(56))>>2)] = tempI64[0],HEAP32[(((buf)+(60))>>2)] = tempI64[1]); + (tempI64 = [Math.floor(mtime / 1000)>>>0,(tempDouble = Math.floor(mtime / 1000),(+(Math.abs(tempDouble))) >= 1.0 ? (tempDouble > 0.0 ? (+(Math.floor((tempDouble)/4294967296.0)))>>>0 : (~~((+(Math.ceil((tempDouble - +(((~~(tempDouble)))>>>0))/4294967296.0)))))>>>0) : 0)], HEAP32[(((buf)+(56))>>2)] = tempI64[0],HEAP32[(((buf)+(60))>>2)] = tempI64[1]); HEAPU32[(((buf)+(64))>>2)] = (mtime % 1000) * 1000; - (tempI64 = [Math.floor(ctime / 1000)>>>0,(tempDouble=Math.floor(ctime / 1000),(+(Math.abs(tempDouble))) >= 1.0 ? (tempDouble > 0.0 ? (+(Math.floor((tempDouble)/4294967296.0)))>>>0 : (~~((+(Math.ceil((tempDouble - +(((~~(tempDouble)))>>>0))/4294967296.0)))))>>>0) : 0)], HEAP32[(((buf)+(72))>>2)] = tempI64[0],HEAP32[(((buf)+(76))>>2)] = tempI64[1]); + (tempI64 = [Math.floor(ctime / 1000)>>>0,(tempDouble = Math.floor(ctime / 1000),(+(Math.abs(tempDouble))) >= 1.0 ? (tempDouble > 0.0 ? (+(Math.floor((tempDouble)/4294967296.0)))>>>0 : (~~((+(Math.ceil((tempDouble - +(((~~(tempDouble)))>>>0))/4294967296.0)))))>>>0) : 0)], HEAP32[(((buf)+(72))>>2)] = tempI64[0],HEAP32[(((buf)+(76))>>2)] = tempI64[1]); HEAPU32[(((buf)+(80))>>2)] = (ctime % 1000) * 1000; - (tempI64 = [stat.ino>>>0,(tempDouble=stat.ino,(+(Math.abs(tempDouble))) >= 1.0 ? (tempDouble > 0.0 ? (+(Math.floor((tempDouble)/4294967296.0)))>>>0 : (~~((+(Math.ceil((tempDouble - +(((~~(tempDouble)))>>>0))/4294967296.0)))))>>>0) : 0)], HEAP32[(((buf)+(88))>>2)] = tempI64[0],HEAP32[(((buf)+(92))>>2)] = tempI64[1]); + (tempI64 = [stat.ino>>>0,(tempDouble = stat.ino,(+(Math.abs(tempDouble))) >= 1.0 ? (tempDouble > 0.0 ? (+(Math.floor((tempDouble)/4294967296.0)))>>>0 : (~~((+(Math.ceil((tempDouble - +(((~~(tempDouble)))>>>0))/4294967296.0)))))>>>0) : 0)], HEAP32[(((buf)+(88))>>2)] = tempI64[0],HEAP32[(((buf)+(92))>>2)] = tempI64[1]); return 0; }, - doMsync:function(addr, stream, len, flags, offset) { + doMsync(addr, stream, len, flags, offset) { if (!FS.isFile(stream.node.mode)) { throw new FS.ErrnoError(43); } @@ -6835,22 +6835,24 @@ function dbg(text) { varargs:undefined, get() { assert(SYSCALLS.varargs != undefined); + // the `+` prepended here is necessary to convince the JSCompiler that varargs is indeed a number. + var ret = HEAP32[((+SYSCALLS.varargs)>>2)]; SYSCALLS.varargs += 4; - var ret = HEAP32[(((SYSCALLS.varargs)-(4))>>2)]; return ret; }, + getp() { return SYSCALLS.get() }, getStr(ptr) { var ret = UTF8ToString(ptr); return ret; }, - getStreamFromFD:function(fd) { + getStreamFromFD(fd) { var stream = FS.getStreamChecked(fd); return stream; }, }; var _environ_get = (__environ, environ_buf) => { var bufSize = 0; - getEnvStrings().forEach(function(string, i) { + getEnvStrings().forEach((string, i) => { var ptr = environ_buf + bufSize; HEAPU32[(((__environ)+(i*4))>>2)] = ptr; stringToAscii(string, ptr); @@ -6864,9 +6866,7 @@ function dbg(text) { var strings = getEnvStrings(); HEAPU32[((penviron_count)>>2)] = strings.length; var bufSize = 0; - strings.forEach(function(string) { - bufSize += string.length + 1; - }); + strings.forEach((string) => bufSize += string.length + 1); HEAPU32[((penviron_buf_size)>>2)] = bufSize; return 0; }; @@ -6890,7 +6890,7 @@ function dbg(text) { var ptr = HEAPU32[((iov)>>2)]; var len = HEAPU32[(((iov)+(4))>>2)]; iov += 8; - var curr = FS.read(stream, HEAP8,ptr, len, offset); + var curr = FS.read(stream, HEAP8, ptr, len, offset); if (curr < 0) return -1; ret += curr; if (curr < len) break; // nothing more to read @@ -6915,11 +6915,11 @@ function dbg(text) { } - function convertI32PairToI53Checked(lo, hi) { + var convertI32PairToI53Checked = (lo, hi) => { assert(lo == (lo >>> 0) || lo == (lo|0)); // lo should either be a i32 or a u32 assert(hi === (hi|0)); // hi should be a i32 return ((hi + 0x200000) >>> 0 < 0x400001 - !!lo) ? (lo >>> 0) + hi * 4294967296 : NaN; - } + }; function _fd_seek(fd,offset_low, offset_high,whence,newOffset) { var offset = convertI32PairToI53Checked(offset_low, offset_high);; @@ -6929,7 +6929,7 @@ function dbg(text) { if (isNaN(offset)) return 61; var stream = SYSCALLS.getStreamFromFD(fd); FS.llseek(stream, offset, whence); - (tempI64 = [stream.position>>>0,(tempDouble=stream.position,(+(Math.abs(tempDouble))) >= 1.0 ? (tempDouble > 0.0 ? (+(Math.floor((tempDouble)/4294967296.0)))>>>0 : (~~((+(Math.ceil((tempDouble - +(((~~(tempDouble)))>>>0))/4294967296.0)))))>>>0) : 0)], HEAP32[((newOffset)>>2)] = tempI64[0],HEAP32[(((newOffset)+(4))>>2)] = tempI64[1]); + (tempI64 = [stream.position>>>0,(tempDouble = stream.position,(+(Math.abs(tempDouble))) >= 1.0 ? (tempDouble > 0.0 ? (+(Math.floor((tempDouble)/4294967296.0)))>>>0 : (~~((+(Math.ceil((tempDouble - +(((~~(tempDouble)))>>>0))/4294967296.0)))))>>>0) : 0)], HEAP32[((newOffset)>>2)] = tempI64[0],HEAP32[(((newOffset)+(4))>>2)] = tempI64[1]); if (stream.getdents && offset === 0 && whence === 0) stream.getdents = null; // reset readdir state return 0; } catch (e) { @@ -6946,7 +6946,7 @@ function dbg(text) { var ptr = HEAPU32[((iov)>>2)]; var len = HEAPU32[(((iov)+(4))>>2)]; iov += 8; - var curr = FS.write(stream, HEAP8,ptr, len, offset); + var curr = FS.write(stream, HEAP8, ptr, len, offset); if (curr < 0) return -1; ret += curr; if (typeof offset !== 'undefined') { @@ -6969,9 +6969,7 @@ function dbg(text) { } } - var isLeapYear = (year) => { - return year%4 === 0 && (year%100 !== 0 || year%400 === 0); - }; + var isLeapYear = (year) => year%4 === 0 && (year%100 !== 0 || year%400 === 0); var arraySum = (array, index) => { var sum = 0; @@ -7024,7 +7022,7 @@ function dbg(text) { // size_t strftime(char *restrict s, size_t maxsize, const char *restrict format, const struct tm *restrict timeptr); // http://pubs.opengroup.org/onlinepubs/009695399/functions/strftime.html - var tm_zone = HEAP32[(((tm)+(40))>>2)]; + var tm_zone = HEAPU32[(((tm)+(40))>>2)]; var date = { tm_sec: HEAP32[((tm)>>2)], @@ -7039,6 +7037,7 @@ function dbg(text) { tm_gmtoff: HEAP32[(((tm)+(36))>>2)], tm_zone: tm_zone ? UTF8ToString(tm_zone) : '' }; + var pattern = UTF8ToString(format); @@ -7330,213 +7329,161 @@ UnboundTypeError = Module['UnboundTypeError'] = extendError(Error, 'UnboundTypeE FS.FSNode = FSNode; FS.createPreloadedFile = FS_createPreloadedFile; FS.staticInit();; -ERRNO_CODES = { - 'EPERM': 63, - 'ENOENT': 44, - 'ESRCH': 71, - 'EINTR': 27, - 'EIO': 29, - 'ENXIO': 60, - 'E2BIG': 1, - 'ENOEXEC': 45, - 'EBADF': 8, - 'ECHILD': 12, - 'EAGAIN': 6, - 'EWOULDBLOCK': 6, - 'ENOMEM': 48, - 'EACCES': 2, - 'EFAULT': 21, - 'ENOTBLK': 105, - 'EBUSY': 10, - 'EEXIST': 20, - 'EXDEV': 75, - 'ENODEV': 43, - 'ENOTDIR': 54, - 'EISDIR': 31, - 'EINVAL': 28, - 'ENFILE': 41, - 'EMFILE': 33, - 'ENOTTY': 59, - 'ETXTBSY': 74, - 'EFBIG': 22, - 'ENOSPC': 51, - 'ESPIPE': 70, - 'EROFS': 69, - 'EMLINK': 34, - 'EPIPE': 64, - 'EDOM': 18, - 'ERANGE': 68, - 'ENOMSG': 49, - 'EIDRM': 24, - 'ECHRNG': 106, - 'EL2NSYNC': 156, - 'EL3HLT': 107, - 'EL3RST': 108, - 'ELNRNG': 109, - 'EUNATCH': 110, - 'ENOCSI': 111, - 'EL2HLT': 112, - 'EDEADLK': 16, - 'ENOLCK': 46, - 'EBADE': 113, - 'EBADR': 114, - 'EXFULL': 115, - 'ENOANO': 104, - 'EBADRQC': 103, - 'EBADSLT': 102, - 'EDEADLOCK': 16, - 'EBFONT': 101, - 'ENOSTR': 100, - 'ENODATA': 116, - 'ETIME': 117, - 'ENOSR': 118, - 'ENONET': 119, - 'ENOPKG': 120, - 'EREMOTE': 121, - 'ENOLINK': 47, - 'EADV': 122, - 'ESRMNT': 123, - 'ECOMM': 124, - 'EPROTO': 65, - 'EMULTIHOP': 36, - 'EDOTDOT': 125, - 'EBADMSG': 9, - 'ENOTUNIQ': 126, - 'EBADFD': 127, - 'EREMCHG': 128, - 'ELIBACC': 129, - 'ELIBBAD': 130, - 'ELIBSCN': 131, - 'ELIBMAX': 132, - 'ELIBEXEC': 133, - 'ENOSYS': 52, - 'ENOTEMPTY': 55, - 'ENAMETOOLONG': 37, - 'ELOOP': 32, - 'EOPNOTSUPP': 138, - 'EPFNOSUPPORT': 139, - 'ECONNRESET': 15, - 'ENOBUFS': 42, - 'EAFNOSUPPORT': 5, - 'EPROTOTYPE': 67, - 'ENOTSOCK': 57, - 'ENOPROTOOPT': 50, - 'ESHUTDOWN': 140, - 'ECONNREFUSED': 14, - 'EADDRINUSE': 3, - 'ECONNABORTED': 13, - 'ENETUNREACH': 40, - 'ENETDOWN': 38, - 'ETIMEDOUT': 73, - 'EHOSTDOWN': 142, - 'EHOSTUNREACH': 23, - 'EINPROGRESS': 26, - 'EALREADY': 7, - 'EDESTADDRREQ': 17, - 'EMSGSIZE': 35, - 'EPROTONOSUPPORT': 66, - 'ESOCKTNOSUPPORT': 137, - 'EADDRNOTAVAIL': 4, - 'ENETRESET': 39, - 'EISCONN': 30, - 'ENOTCONN': 53, - 'ETOOMANYREFS': 141, - 'EUSERS': 136, - 'EDQUOT': 19, - 'ESTALE': 72, - 'ENOTSUP': 138, - 'ENOMEDIUM': 148, - 'EILSEQ': 25, - 'EOVERFLOW': 61, - 'ECANCELED': 11, - 'ENOTRECOVERABLE': 56, - 'EOWNERDEAD': 62, - 'ESTRPIPE': 135, - };; function checkIncomingModuleAPI() { ignoredModuleProp('fetchSettings'); } var wasmImports = { + /** @export */ __assert_fail: ___assert_fail, + /** @export */ __cxa_throw: ___cxa_throw, + /** @export */ _embind_create_inheriting_constructor: __embind_create_inheriting_constructor, + /** @export */ _embind_finalize_value_array: __embind_finalize_value_array, + /** @export */ _embind_finalize_value_object: __embind_finalize_value_object, + /** @export */ _embind_register_bigint: __embind_register_bigint, + /** @export */ _embind_register_bool: __embind_register_bool, + /** @export */ _embind_register_class: __embind_register_class, + /** @export */ _embind_register_class_class_function: __embind_register_class_class_function, + /** @export */ _embind_register_class_class_property: __embind_register_class_class_property, + /** @export */ _embind_register_class_constructor: __embind_register_class_constructor, + /** @export */ _embind_register_class_function: __embind_register_class_function, + /** @export */ _embind_register_class_property: __embind_register_class_property, + /** @export */ _embind_register_constant: __embind_register_constant, + /** @export */ _embind_register_emval: __embind_register_emval, + /** @export */ _embind_register_enum: __embind_register_enum, + /** @export */ _embind_register_enum_value: __embind_register_enum_value, + /** @export */ _embind_register_float: __embind_register_float, + /** @export */ _embind_register_function: __embind_register_function, + /** @export */ _embind_register_integer: __embind_register_integer, + /** @export */ _embind_register_memory_view: __embind_register_memory_view, + /** @export */ _embind_register_smart_ptr: __embind_register_smart_ptr, + /** @export */ _embind_register_std_string: __embind_register_std_string, + /** @export */ _embind_register_std_wstring: __embind_register_std_wstring, + /** @export */ _embind_register_value_array: __embind_register_value_array, + /** @export */ _embind_register_value_array_element: __embind_register_value_array_element, + /** @export */ _embind_register_value_object: __embind_register_value_object, + /** @export */ _embind_register_value_object_field: __embind_register_value_object_field, + /** @export */ _embind_register_void: __embind_register_void, + /** @export */ _emval_as: __emval_as, + /** @export */ _emval_as_int64: __emval_as_int64, + /** @export */ _emval_as_uint64: __emval_as_uint64, + /** @export */ _emval_await: __emval_await, + /** @export */ _emval_call: __emval_call, + /** @export */ _emval_call_method: __emval_call_method, - _emval_call_void_method: __emval_call_void_method, + /** @export */ _emval_decref: __emval_decref, + /** @export */ _emval_delete: __emval_delete, + /** @export */ _emval_equals: __emval_equals, + /** @export */ _emval_get_global: __emval_get_global, + /** @export */ _emval_get_method_caller: __emval_get_method_caller, + /** @export */ _emval_get_module_property: __emval_get_module_property, + /** @export */ _emval_get_property: __emval_get_property, + /** @export */ _emval_in: __emval_in, + /** @export */ _emval_incref: __emval_incref, + /** @export */ _emval_instanceof: __emval_instanceof, + /** @export */ _emval_is_number: __emval_is_number, + /** @export */ _emval_is_string: __emval_is_string, - _emval_new: __emval_new, + /** @export */ + _emval_iter_begin: __emval_iter_begin, + /** @export */ + _emval_iter_next: __emval_iter_next, + /** @export */ _emval_new_array: __emval_new_array, + /** @export */ _emval_new_array_from_memory_view: __emval_new_array_from_memory_view, + /** @export */ _emval_new_cstring: __emval_new_cstring, + /** @export */ _emval_new_object: __emval_new_object, + /** @export */ _emval_new_u16string: __emval_new_u16string, + /** @export */ _emval_new_u8string: __emval_new_u8string, + /** @export */ _emval_register_symbol: __emval_register_symbol, + /** @export */ _emval_run_destructors: __emval_run_destructors, + /** @export */ _emval_set_property: __emval_set_property, + /** @export */ _emval_strictly_equals: __emval_strictly_equals, + /** @export */ _emval_take_value: __emval_take_value, + /** @export */ _emval_throw: __emval_throw, + /** @export */ _emval_typeof: __emval_typeof, + /** @export */ abort: _abort, - emscripten_memcpy_big: _emscripten_memcpy_big, + /** @export */ + emscripten_memcpy_js: _emscripten_memcpy_js, + /** @export */ emscripten_resize_heap: _emscripten_resize_heap, + /** @export */ environ_get: _environ_get, + /** @export */ environ_sizes_get: _environ_sizes_get, + /** @export */ fd_close: _fd_close, + /** @export */ fd_read: _fd_read, + /** @export */ fd_seek: _fd_seek, + /** @export */ fd_write: _fd_write, + /** @export */ strftime_l: _strftime_l }; -var asm = createWasm(); +var wasmExports = createWasm(); var ___wasm_call_ctors = createExportWrapper('__wasm_call_ctors'); var _malloc = Module['_malloc'] = createExportWrapper('malloc'); var _set_c_u64 = Module['_set_c_u64'] = createExportWrapper('set_c_u64'); var _set_c_u32 = Module['_set_c_u32'] = createExportWrapper('set_c_u32'); var ___getTypeName = createExportWrapper('__getTypeName'); -var __embind_initialize_bindings = Module['__embind_initialize_bindings'] = createExportWrapper('_embind_initialize_bindings'); var ___errno_location = createExportWrapper('__errno_location'); var _fflush = Module['_fflush'] = createExportWrapper('fflush'); var _free = Module['_free'] = createExportWrapper('free'); @@ -7594,11 +7541,11 @@ var missingLibrarySymbols = [ 'listenOnce', 'autoResumeAudioContext', 'handleException', + 'keepRuntimeAlive', 'runtimeKeepalivePush', 'runtimeKeepalivePop', 'callUserCallback', 'maybeExit', - 'safeSetTimeout', 'asmjsMangle', 'getNativeTypeSize', 'STACK_SIZE', @@ -7674,6 +7621,7 @@ var missingLibrarySymbols = [ 'wasiRightsToMuslOFlags', 'wasiOFlagsToMuslOFlags', 'createDyncallWrapper', + 'safeSetTimeout', 'setImmediateWrapped', 'clearImmediateWrapped', 'polyfillSetImmediate', @@ -7685,6 +7633,8 @@ var missingLibrarySymbols = [ 'setMainLoop', 'getSocketFromFD', 'getSocketAddress', + 'FS_unlink', + 'FS_mkdirTree', '_setNetworkCallback', 'heapObjectForWebGLType', 'heapAccessShiftForWebGLHeap', @@ -7709,12 +7659,12 @@ var missingLibrarySymbols = [ 'SDL_unicode', 'SDL_ttfContext', 'SDL_audio', - 'GLFW_Window', 'ALLOC_NORMAL', 'ALLOC_STACK', 'allocate', 'writeStringToMemory', 'writeAsciiToMemory', + 'getFunctionArgsName', ]; missingLibrarySymbols.forEach(missingLibrarySymbol) @@ -7729,18 +7679,15 @@ var unexportedSymbols = [ 'removeRunDependency', 'FS_createFolder', 'FS_createPath', - 'FS_createDataFile', 'FS_createLazyFile', 'FS_createLink', 'FS_createDevice', - 'FS_unlink', + 'FS_readFile', 'out', 'err', 'callMain', 'abort', - 'keepRuntimeAlive', 'wasmMemory', - 'wasmTable', 'wasmExports', 'stackAlloc', 'stackSave', @@ -7782,6 +7729,8 @@ var unexportedSymbols = [ 'mmapAlloc', 'handleAllocatorInit', 'HandleAllocator', + 'wasmTable', + 'noExitRuntime', 'freeTableIndexes', 'functionsInTableMap', 'setValue', @@ -7829,6 +7778,7 @@ var unexportedSymbols = [ 'FS_stdin_getChar_buffer', 'FS_stdin_getChar', 'FS', + 'FS_createDataFile', 'MEMFS', 'TTY', 'PIPEFS', @@ -7845,7 +7795,6 @@ var unexportedSymbols = [ 'IDBStore', 'SDL', 'SDL_gfx', - 'GLFW', 'allocateUTF8', 'allocateUTF8OnStack', 'InternalError', @@ -7863,10 +7812,12 @@ var unexportedSymbols = [ 'embind_init_charCodes', 'readLatin1String', 'getTypeName', + 'getFunctionName', 'heap32VectorToArray', 'requireRegisteredType', 'UnboundTypeError', 'PureVirtualError', + 'GenericWireTypeSize', 'init_embind', 'throwUnboundTypeError', 'ensureOverloadTable', @@ -7884,11 +7835,11 @@ var unexportedSymbols = [ 'getLiveInheritedInstances', 'registeredPointers', 'registerType', - 'getShiftFromSize', 'integerReadValueFromPointer', 'enumReadValueFromPointer', 'floatReadValueFromPointer', 'simpleReadValueFromPointer', + 'readPointer', 'runDestructors', 'newFunc', 'craftInvokerFunction', @@ -7898,9 +7849,6 @@ var unexportedSymbols = [ 'nonConstNoSmartPtrRawPointerToWireType', 'init_RegisteredPointer', 'RegisteredPointer', - 'RegisteredPointer_getPointee', - 'RegisteredPointer_destructor', - 'RegisteredPointer_deleteObject', 'RegisteredPointer_fromWireType', 'runDestructor', 'releaseClassHandle', @@ -7911,13 +7859,8 @@ var unexportedSymbols = [ 'makeClassHandle', 'init_ClassHandle', 'ClassHandle', - 'ClassHandle_isAliasOf', 'throwInstanceAlreadyDeleted', - 'ClassHandle_clone', - 'ClassHandle_delete', 'deletionQueue', - 'ClassHandle_isDeleted', - 'ClassHandle_deleteLater', 'flushPendingDeletes', 'delayFunction', 'setDelayFunction', @@ -7935,14 +7878,12 @@ var unexportedSymbols = [ 'count_emval_handles', 'getStringOrSymbol', 'Emval', - 'emval_newers', - 'craftEmvalAllocator', 'emval_get_global', + 'emval_returnValue', 'emval_lookupTypes', - 'emval_allocateDestructors', 'emval_methodCallers', 'emval_addMethodCaller', - 'emval_registeredMethods', + 'reflectConstruct', ]; unexportedSymbols.forEach(unexportedRuntimeSymbol); diff --git a/testdata/wasm/tests.wasm b/testdata/wasm/tests.wasm index eb6e28d..aef056e 100755 Binary files a/testdata/wasm/tests.wasm and b/testdata/wasm/tests.wasm differ diff --git a/wazero.go b/wazero.go index 3ce6160..bb6a143 100644 --- a/wazero.go +++ b/wazero.go @@ -230,19 +230,50 @@ func (e functionExporter) ExportFunctions(b wazero.HostModuleBuilder) error { WithGoModuleFunction(internal.EmvalRunDestructors, []api.ValueType{api.ValueTypeI32}, []api.ValueType{}). Export("_emval_run_destructors") - b.NewFunctionBuilder(). - WithName("_emval_get_method_caller"). - WithParameterNames("argCount", "argTypes"). - WithResultNames("id"). - WithGoModuleFunction(internal.EmvalGetMethodCaller, []api.ValueType{api.ValueTypeI32, api.ValueTypeI32}, []api.ValueType{api.ValueTypeI32}). - Export("_emval_get_method_caller") + importedEmvalGetMethodCaller := e.GetImportedFunction("_emval_get_method_caller") + if importedEmvalGetMethodCaller != nil { + // Since Emscripten 3.1.48, _emval_get_method_caller has 3 params. + // The new param is called "kind". + emvalGetMethodCallerHasKindParam := len(importedEmvalGetMethodCaller.ParamTypes()) == 3 + if emvalGetMethodCallerHasKindParam { + b.NewFunctionBuilder(). + WithName("_emval_get_method_caller"). + WithParameterNames("argCount", "argTypes", "kind"). + WithResultNames("id"). + WithGoModuleFunction(internal.EmvalGetMethodCaller(true), []api.ValueType{api.ValueTypeI32, api.ValueTypeI32, api.ValueTypeI32}, []api.ValueType{api.ValueTypeI32}). + Export("_emval_get_method_caller") + } else { + b.NewFunctionBuilder(). + WithName("_emval_get_method_caller"). + WithParameterNames("argCount", "argTypes"). + WithResultNames("id"). + WithGoModuleFunction(internal.EmvalGetMethodCaller(false), []api.ValueType{api.ValueTypeI32, api.ValueTypeI32}, []api.ValueType{api.ValueTypeI32}). + Export("_emval_get_method_caller") + } + } - b.NewFunctionBuilder(). - WithName("_emval_call"). - WithParameterNames("handle", "argCount", "argTypes", "argv"). - WithResultNames("handle"). - WithGoModuleFunction(internal.EmvalCall, []api.ValueType{api.ValueTypeI32, api.ValueTypeI32, api.ValueTypeI32, api.ValueTypeI32}, []api.ValueType{api.ValueTypeI32}). - Export("_emval_call") + importedEmvalCall := e.GetImportedFunction("_emval_call") + if importedEmvalCall != nil { + // Since Emscripten 3.1.48, _emval_call has a F64 return. + importedEmvalCallHasF64Return := importedEmvalCall.ResultTypes()[0] == api.ValueTypeF64 + if importedEmvalCallHasF64Return { + b.NewFunctionBuilder(). + WithName("_emval_call"). + WithParameterNames("handle", "argCount", "argTypes", "argv"). + WithResultNames("handle"). + WithGoModuleFunction(internal.EmvalCall(true), []api.ValueType{api.ValueTypeI32, api.ValueTypeI32, api.ValueTypeI32, api.ValueTypeI32}, []api.ValueType{api.ValueTypeF64}). + Export("_emval_call") + + } else { + b.NewFunctionBuilder(). + WithName("_emval_call"). + WithParameterNames("handle", "argCount", "argTypes", "argv"). + WithResultNames("handle"). + WithGoModuleFunction(internal.EmvalCall(false), []api.ValueType{api.ValueTypeI32, api.ValueTypeI32, api.ValueTypeI32, api.ValueTypeI32}, []api.ValueType{api.ValueTypeI32}). + Export("_emval_call") + + } + } b.NewFunctionBuilder(). WithName("_emval_call_method").