2021-09-02 11:09:48 -04:00
|
|
|
package eval
|
|
|
|
|
|
|
|
import (
|
|
|
|
"github.com/MontFerret/ferret/pkg/runtime/core"
|
|
|
|
"github.com/mafredri/cdp/protocol/runtime"
|
2021-09-07 16:33:30 -04:00
|
|
|
"github.com/rs/zerolog"
|
|
|
|
"github.com/wI2L/jettison"
|
2021-09-02 11:09:48 -04:00
|
|
|
"strings"
|
|
|
|
)
|
|
|
|
|
|
|
|
type (
|
|
|
|
FunctionReturnType int
|
|
|
|
|
2021-09-07 16:33:30 -04:00
|
|
|
FunctionArguments []runtime.CallArgument
|
|
|
|
|
2021-09-02 11:09:48 -04:00
|
|
|
Function struct {
|
|
|
|
exp string
|
2021-09-07 16:33:30 -04:00
|
|
|
ownerID runtime.RemoteObjectID
|
|
|
|
args FunctionArguments
|
2021-09-02 11:09:48 -04:00
|
|
|
returnType FunctionReturnType
|
|
|
|
async bool
|
|
|
|
}
|
|
|
|
)
|
|
|
|
|
2021-09-07 16:33:30 -04:00
|
|
|
const defaultArgsCount = 5
|
|
|
|
|
2021-09-02 11:09:48 -04:00
|
|
|
const (
|
|
|
|
ReturnNothing FunctionReturnType = iota
|
|
|
|
ReturnValue
|
|
|
|
ReturnRef
|
|
|
|
)
|
|
|
|
|
2021-09-07 16:33:30 -04:00
|
|
|
func F(exp string) *Function {
|
2021-09-02 11:09:48 -04:00
|
|
|
op := new(Function)
|
|
|
|
op.exp = exp
|
|
|
|
op.returnType = ReturnNothing
|
|
|
|
|
2021-09-07 16:33:30 -04:00
|
|
|
return op
|
|
|
|
}
|
|
|
|
|
|
|
|
func (fn *Function) AsPartOf(id runtime.RemoteObjectID) *Function {
|
|
|
|
fn.ownerID = id
|
|
|
|
|
|
|
|
return fn
|
|
|
|
}
|
|
|
|
|
|
|
|
func (fn *Function) AsAsync() *Function {
|
|
|
|
fn.async = true
|
|
|
|
|
|
|
|
return fn
|
|
|
|
}
|
|
|
|
|
|
|
|
func (fn *Function) AsSync() *Function {
|
|
|
|
fn.async = false
|
|
|
|
|
|
|
|
return fn
|
|
|
|
}
|
|
|
|
|
|
|
|
func (fn *Function) WithArgRef(id runtime.RemoteObjectID) *Function {
|
|
|
|
return fn.withArg(runtime.CallArgument{
|
|
|
|
ObjectID: &id,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
func (fn *Function) WithArgValue(value core.Value) *Function {
|
|
|
|
raw, err := value.MarshalJSON()
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
2021-09-02 11:09:48 -04:00
|
|
|
}
|
|
|
|
|
2021-09-07 16:33:30 -04:00
|
|
|
return fn.withArg(runtime.CallArgument{
|
|
|
|
Value: raw,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
func (fn *Function) WithArg(value interface{}) *Function {
|
|
|
|
raw, err := jettison.MarshalOpts(value, jettison.NoHTMLEscaping())
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return fn.withArg(runtime.CallArgument{
|
|
|
|
Value: raw,
|
|
|
|
})
|
2021-09-02 11:09:48 -04:00
|
|
|
}
|
|
|
|
|
2021-09-07 16:33:30 -04:00
|
|
|
func (fn *Function) String() string {
|
|
|
|
return fn.exp
|
2021-09-02 11:09:48 -04:00
|
|
|
}
|
|
|
|
|
2021-09-07 16:33:30 -04:00
|
|
|
func (fn *Function) returnRef() *Function {
|
|
|
|
fn.returnType = ReturnRef
|
|
|
|
|
|
|
|
return fn
|
|
|
|
}
|
|
|
|
|
|
|
|
func (fn *Function) returnValue() *Function {
|
|
|
|
fn.returnType = ReturnValue
|
|
|
|
|
|
|
|
return fn
|
|
|
|
}
|
|
|
|
|
|
|
|
func (fn *Function) withArg(arg runtime.CallArgument) *Function {
|
|
|
|
if fn.args == nil {
|
|
|
|
fn.args = make([]runtime.CallArgument, 0, defaultArgsCount)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn.args = append(fn.args, arg)
|
|
|
|
|
|
|
|
return fn
|
|
|
|
}
|
|
|
|
|
|
|
|
func (fn *Function) build(ctx runtime.ExecutionContextID) *runtime.CallFunctionOnArgs {
|
2021-09-02 11:09:48 -04:00
|
|
|
exp := strings.TrimSpace(fn.exp)
|
|
|
|
|
|
|
|
if !strings.HasPrefix(exp, "(") && !strings.HasPrefix(exp, "function") {
|
2021-09-07 16:33:30 -04:00
|
|
|
exp = wrapExp(exp, len(fn.args))
|
2021-09-02 11:09:48 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
call := runtime.NewCallFunctionOnArgs(exp).
|
|
|
|
SetAwaitPromise(fn.async)
|
|
|
|
|
|
|
|
if fn.returnType == ReturnValue {
|
|
|
|
call.SetReturnByValue(true)
|
|
|
|
}
|
|
|
|
|
|
|
|
if ctx != EmptyExecutionContextID {
|
|
|
|
call.SetExecutionContextID(ctx)
|
|
|
|
}
|
|
|
|
|
2021-09-07 16:33:30 -04:00
|
|
|
if fn.ownerID != "" {
|
|
|
|
call.SetObjectID(fn.ownerID)
|
2021-09-02 11:09:48 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
if len(fn.args) > 0 {
|
|
|
|
call.SetArguments(fn.args)
|
|
|
|
}
|
|
|
|
|
|
|
|
return call
|
|
|
|
}
|
|
|
|
|
2021-09-07 16:33:30 -04:00
|
|
|
func (rt FunctionReturnType) String() string {
|
|
|
|
switch rt {
|
|
|
|
case ReturnValue:
|
|
|
|
return "value"
|
|
|
|
case ReturnRef:
|
|
|
|
return "reference"
|
|
|
|
default:
|
|
|
|
return "nothing"
|
2021-09-02 11:09:48 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-09-07 16:33:30 -04:00
|
|
|
func (args FunctionArguments) MarshalZerologArray(a *zerolog.Array) {
|
|
|
|
for _, arg := range args {
|
|
|
|
if arg.ObjectID != nil {
|
|
|
|
a.Str(string(*arg.ObjectID))
|
2021-09-02 11:09:48 -04:00
|
|
|
} else {
|
2021-09-07 16:33:30 -04:00
|
|
|
a.RawJSON(arg.Value)
|
2021-09-02 11:09:48 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|