2018-09-25 23:58:57 +02:00
|
|
|
package eval
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
2018-10-11 18:39:03 +02:00
|
|
|
"encoding/json"
|
2018-09-25 23:58:57 +02:00
|
|
|
"fmt"
|
2019-02-21 04:24:05 +02:00
|
|
|
|
2018-09-25 23:58:57 +02:00
|
|
|
"github.com/MontFerret/ferret/pkg/runtime/core"
|
|
|
|
"github.com/MontFerret/ferret/pkg/runtime/values"
|
|
|
|
"github.com/mafredri/cdp"
|
|
|
|
"github.com/mafredri/cdp/protocol/runtime"
|
|
|
|
)
|
|
|
|
|
|
|
|
func PrepareEval(exp string) string {
|
|
|
|
return fmt.Sprintf("((function () {%s})())", exp)
|
|
|
|
}
|
|
|
|
|
2019-02-21 04:24:05 +02:00
|
|
|
func Eval(ctx context.Context, client *cdp.Client, exp string, ret bool, async bool) (core.Value, error) {
|
2018-09-25 23:58:57 +02:00
|
|
|
args := runtime.
|
|
|
|
NewEvaluateArgs(PrepareEval(exp)).
|
|
|
|
SetReturnByValue(ret).
|
|
|
|
SetAwaitPromise(async)
|
|
|
|
|
2019-02-21 04:24:05 +02:00
|
|
|
out, err := client.Runtime.Evaluate(ctx, args)
|
2018-09-25 23:58:57 +02:00
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
return values.None, err
|
|
|
|
}
|
|
|
|
|
|
|
|
if out.ExceptionDetails != nil {
|
|
|
|
ex := out.ExceptionDetails
|
|
|
|
|
|
|
|
return values.None, core.Error(
|
|
|
|
core.ErrUnexpected,
|
|
|
|
fmt.Sprintf("%s: %s", ex.Text, *ex.Exception.Description),
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
if out.Result.Type != "undefined" {
|
2018-09-26 01:04:07 +02:00
|
|
|
return values.Unmarshal(out.Result.Value)
|
|
|
|
}
|
|
|
|
|
|
|
|
return Unmarshal(&out.Result)
|
|
|
|
}
|
|
|
|
|
|
|
|
func Property(
|
|
|
|
ctx context.Context,
|
|
|
|
client *cdp.Client,
|
2018-10-11 18:39:03 +02:00
|
|
|
objectID runtime.RemoteObjectID,
|
2018-09-26 01:04:07 +02:00
|
|
|
propName string,
|
|
|
|
) (core.Value, error) {
|
|
|
|
res, err := client.Runtime.GetProperties(
|
|
|
|
ctx,
|
2018-10-11 18:39:03 +02:00
|
|
|
runtime.NewGetPropertiesArgs(objectID),
|
2018-09-26 01:04:07 +02:00
|
|
|
)
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
return values.None, err
|
|
|
|
}
|
|
|
|
|
|
|
|
if res.ExceptionDetails != nil {
|
|
|
|
return values.None, res.ExceptionDetails
|
|
|
|
}
|
|
|
|
|
|
|
|
// all props
|
|
|
|
if propName == "" {
|
|
|
|
var arr *values.Array
|
|
|
|
arr = values.NewArray(len(res.Result))
|
2018-09-25 23:58:57 +02:00
|
|
|
|
2018-09-26 01:04:07 +02:00
|
|
|
for _, prop := range res.Result {
|
|
|
|
val, err := Unmarshal(prop.Value)
|
2018-09-25 23:58:57 +02:00
|
|
|
|
2018-09-26 01:04:07 +02:00
|
|
|
if err != nil {
|
|
|
|
return values.None, err
|
|
|
|
}
|
|
|
|
|
|
|
|
arr.Push(val)
|
2018-09-25 23:58:57 +02:00
|
|
|
}
|
|
|
|
|
2018-09-26 01:04:07 +02:00
|
|
|
return arr, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, prop := range res.Result {
|
|
|
|
if prop.Name == propName {
|
|
|
|
return Unmarshal(prop.Value)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return values.None, nil
|
|
|
|
}
|
|
|
|
|
2018-10-11 18:39:03 +02:00
|
|
|
func Method(
|
|
|
|
ctx context.Context,
|
|
|
|
client *cdp.Client,
|
|
|
|
objectID runtime.RemoteObjectID,
|
|
|
|
methodName string,
|
|
|
|
args []runtime.CallArgument,
|
|
|
|
) (*runtime.RemoteObject, error) {
|
|
|
|
found, err := client.Runtime.CallFunctionOn(
|
|
|
|
ctx,
|
|
|
|
runtime.NewCallFunctionOnArgs(methodName).
|
|
|
|
SetObjectID(objectID).
|
|
|
|
SetArguments(args),
|
|
|
|
)
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
if found.ExceptionDetails != nil {
|
|
|
|
return nil, found.ExceptionDetails
|
|
|
|
}
|
|
|
|
|
|
|
|
if found.Result.ObjectID == nil {
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
return &found.Result, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func MethodQuerySelector(
|
|
|
|
ctx context.Context,
|
|
|
|
client *cdp.Client,
|
|
|
|
objectID runtime.RemoteObjectID,
|
|
|
|
selector string,
|
|
|
|
) (runtime.RemoteObjectID, error) {
|
|
|
|
bytes, err := json.Marshal(selector)
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
|
|
|
|
obj, err := Method(ctx, client, objectID, "querySelector", []runtime.CallArgument{
|
|
|
|
{
|
|
|
|
Value: json.RawMessage(bytes),
|
|
|
|
},
|
|
|
|
})
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
|
|
|
|
if obj.ObjectID == nil {
|
|
|
|
return "", nil
|
|
|
|
}
|
|
|
|
|
|
|
|
return *obj.ObjectID, nil
|
|
|
|
}
|
|
|
|
|
2018-09-26 01:04:07 +02:00
|
|
|
func Unmarshal(obj *runtime.RemoteObject) (core.Value, error) {
|
|
|
|
if obj == nil {
|
|
|
|
return values.None, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
if obj.Type != "undefined" {
|
|
|
|
return values.Unmarshal(obj.Value)
|
2018-09-25 23:58:57 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return values.None, nil
|
|
|
|
}
|