Skip to content

Commit

Permalink
Don't require InstanceCore to be embeded
Browse files Browse the repository at this point in the history
Also rename it as it now makes less sense to be called that way. As well
as remove GenerateExports and make module authors to actually specify
exactly what they will export.
  • Loading branch information
mstoykov committed Nov 11, 2021
1 parent fc73d7c commit 1e4c50f
Show file tree
Hide file tree
Showing 4 changed files with 21 additions and 58 deletions.
6 changes: 3 additions & 3 deletions js/modules/k6/execution/execution.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ type (

// ModuleInstance represents an instance of the execution module.
ModuleInstance struct {
modules.InstanceCore
modules.InstanceParams
obj *goja.Object
}
)
Expand All @@ -57,8 +57,8 @@ func New() *RootModule {

// NewModuleInstance implements the modules.IsModuleV2 interface to return
// a new instance for each VU.
func (*RootModule) NewModuleInstance(m modules.InstanceCore) modules.Instance {
mi := &ModuleInstance{InstanceCore: m}
func (*RootModule) NewModuleInstance(m modules.InstanceParams) modules.Instance {
mi := &ModuleInstance{InstanceParams: m}
rt := m.GetRuntime()
o := rt.NewObject()
defProp := func(name string, newInfo func() (*goja.Object, error)) {
Expand Down
19 changes: 13 additions & 6 deletions js/modules/k6/metrics/metrics.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ import (

type Metric struct {
metric *stats.Metric
core modules.InstanceCore
core modules.InstanceParams
}

// ErrMetricsAddInInitContext is error returned when adding to metric is done in the init context
Expand All @@ -58,7 +58,7 @@ func (mi *ModuleInstance) newMetric(call goja.ConstructorCall, t stats.MetricTyp
if err != nil {
return nil, err
}
metric := &Metric{metric: m, core: mi.InstanceCore}
metric := &Metric{metric: m, core: mi.InstanceParams}
o := rt.NewObject()
err = o.DefineDataProperty("name", rt.ToValue(name), goja.FLAG_FALSE, goja.FLAG_FALSE, goja.FLAG_TRUE)
if err != nil {
Expand Down Expand Up @@ -139,7 +139,7 @@ type (
RootModule struct{}
// ModuleInstance represents an instance of the metrics module
ModuleInstance struct {
modules.InstanceCore
modules.InstanceParams
}
)

Expand All @@ -149,8 +149,8 @@ var (
)

// NewModuleInstance implements modules.IsModuleV2 interface
func (*RootModule) NewModuleInstance(m modules.InstanceCore) modules.Instance {
return &ModuleInstance{InstanceCore: m}
func (*RootModule) NewModuleInstance(m modules.InstanceParams) modules.Instance {
return &ModuleInstance{InstanceParams: m}
}

// New returns a new RootModule.
Expand All @@ -160,7 +160,14 @@ func New() *RootModule {

// Exports returns the exports of the metrics module
func (mi *ModuleInstance) Exports() modules.Exports {
return modules.GenerateExports(mi)
return modules.Exports{
Named: map[string]interface{}{
"Counter": mi.XCounter,
"Gauge": mi.XGauge,
"Trend": mi.XTrend,
"Rate": mi.XRate,
},
}
}

// XCounter is a counter constructor
Expand Down
52 changes: 4 additions & 48 deletions js/modules/modules.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ type Module interface {
// NewModuleInstance will get InstanceCore that should provide the module with *everything* it needs and return an
// Instance implementation (embedding the InstanceCore).
// This method will be called for *each* require/import and return an object for VUs.
NewModuleInstance(InstanceCore) Instance
NewModuleInstance(InstanceParams) Instance
}

// checks that modules implement HasModuleInstancePerVU
Expand All @@ -92,7 +92,6 @@ func GetJSModules() map[string]interface{} {

// Instance is what a module needs to return
type Instance interface {
InstanceCore
Exports() Exports
}

Expand All @@ -108,8 +107,9 @@ func getInterfaceMethods() []string {
return result
}

// InstanceCore is something that will be provided to modules and they need to embed it in ModuleInstance
type InstanceCore interface {
// InstanceParams is something that will be provided to module instance on initialization so that it can get access to
// everything it needs
type InstanceParams interface {
GetContext() context.Context

// GetInitEnv returns common.InitEnvironment instance if present
Expand All @@ -120,9 +120,6 @@ type InstanceCore interface {

// GetRuntime returns the goja.Runtime for the current VU
GetRuntime() *goja.Runtime

// sealing field will help probably with pointing users that they just need to embed this in their Instance
// implementations
}

// Exports is representation of ESM exports of a module
Expand All @@ -132,44 +129,3 @@ type Exports struct {
// Named is the named exports of a module
Named map[string]interface{}
}

// GenerateExports generates an Exports from a module akin to how common.Bind does now.
// it also skips anything that is expected will not want to be exported such as methods and fields coming from
// interfaces defined in this package.
func GenerateExports(v interface{}) Exports {
exports := make(map[string]interface{})
val := reflect.ValueOf(v)
typ := val.Type()
badNames := getInterfaceMethods()
outer:
for i := 0; i < typ.NumMethod(); i++ {
meth := typ.Method(i)
for _, badname := range badNames {
if meth.Name == badname {
continue outer
}
}
name := common.MethodName(typ, meth)

fn := val.Method(i)
exports[name] = fn.Interface()
}

// If v is a pointer, we need to indirect it to access its fields.
if typ.Kind() == reflect.Ptr {
val = val.Elem()
typ = val.Type()
}
var mic InstanceCore // TODO move this out
for i := 0; i < typ.NumField(); i++ {
field := typ.Field(i)
if field.Type == reflect.TypeOf(&mic).Elem() {
continue
}
name := common.FieldName(typ, field)
if name != "" {
exports[name] = val.Field(i).Interface()
}
}
return Exports{Default: exports, Named: exports}
}
2 changes: 1 addition & 1 deletion js/modulestest/modulestest.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ import (
"go.k6.io/k6/lib"
)

var _ modules.InstanceCore = &InstanceCore{}
var _ modules.InstanceParams = &InstanceCore{}

// InstanceCore is a modules.InstanceCore implementation meant to be used within tests
type InstanceCore struct {
Expand Down

0 comments on commit 1e4c50f

Please sign in to comment.