ref: ac32db32e14093022a4e363f808659191ce43cca
parent: a5d269cda172e9612b99a5efca2e8d414dee3771
author: Philip Silva <[email protected]>
date: Sat Jan 30 18:30:47 EST 2021
gcs
--- a/LICENSE
+++ b/LICENSE
@@ -1,4 +1,4 @@
-Copyright (c) 2020, Philip Silva <[email protected]>
+Copyright (c) 2020-2021, Philip Silva <[email protected]>
All rights reserved.
Redistribution and use in source and binary forms, with or without
--- a/browser/website.go
+++ b/browser/website.go
@@ -120,7 +120,7 @@
log.Infof("Stop existing JS instance")
w.d.Stop()
}
- w.d = domino.NewDomino(w.html)
+ w.d = domino.NewDomino(w.html, nt)
w.d.Start()
jsProcessed, err := processJS2(w.d, nt, codes)
if err == nil {
--- a/domino/domino.go
+++ b/domino/domino.go
@@ -29,13 +29,15 @@
initialized bool
loop *eventloop.EventLoop
html string
+ nt *nodes.Node
outputHtml string
domChanged chan int
}
-func NewDomino(html string) (d *Domino) {
+func NewDomino(html string, nt *nodes.Node) (d *Domino) {
d = &Domino{
html: html,
+ nt: nt,
}
return
}
@@ -119,9 +121,28 @@
window.self = window;
addEventListener = function() {};
window.location.href = 'http://example.com';
- window.getComputedStyle = function() {
- // stub
- }
+ var ___fq;
+ ___fq = function(pre, el) {
+ var i, p = el.parentElement;
+
+ if (p) {
+ for (i = 0; i < p.children.length; i++) {
+ if (p.children[i] === el) {
+ return ___fq('', p) + ' > :nth-child(' + (i+1) + ')';
+ }
+ }
+ } else {
+ return el.tagName;
+ }
+ };
+ window.getComputedStyle = function(el, pseudo) {
+ this.el = el;
+ this.getPropertyValue = function(prop) {
+ return opossum.style(___fq('', el), pseudo, prop, arguments[2]);
+ };
+ return this;
+ };
+ Element.prototype.getClientRects = function() { /* I'm a stub */ return []; }
window.screen = {
width: 1280,
height: 1024
@@ -169,6 +190,7 @@
Buf string `json:"buf"`
HTML string `json:"html"`
Referrer func() string `json:"referrer"`
+ Style func(string, string, string, string) string `json:"style"`
}
vm.SetFieldNameMapper(goja.TagFieldNameMapper("json", true))
@@ -176,6 +198,18 @@
HTML: d.html,
Buf: "yolo",
Referrer: func() string { return "https://example.com" },
+ Style: func(sel, pseudo, prop, prop2 string) string {
+ res, err := d.nt.Query(sel)
+ if err != nil {
+ log.Errorf("query %v: %v", sel, err)
+ return ""
+ }
+ if len(res) != 1 {
+ log.Errorf("query %v: %v", res, err)
+ return ""
+ }
+ return res[0].Css(prop)
+ },
})
}
--- a/domino/domino_test.go
+++ b/domino/domino_test.go
@@ -3,6 +3,9 @@
import (
"io/ioutil"
"github.com/psilva261/opossum/logger"
+ "github.com/psilva261/opossum/nodes"
+ "github.com/psilva261/opossum/style"
+ "golang.org/x/net/html"
"strings"
"testing"
)
@@ -16,15 +19,16 @@
`
func init() {
+ f := false
t := true
DebugDumpJS = &t
- logger.Quiet = &t
+ logger.Quiet = &f
logger.Init()
log = &logger.Logger{Debug: true}
}
func TestSimple(t *testing.T) {
- d := NewDomino(simpleHTML)
+ d := NewDomino(simpleHTML, nil)
d.Start()
s := `
var state = 'empty';
@@ -52,7 +56,7 @@
}
func TestGlobals(t *testing.T) {
- d := NewDomino(simpleHTML)
+ d := NewDomino(simpleHTML, nil)
d.Start()
}
@@ -61,15 +65,9 @@
if err != nil {
t.Fatalf("%v", err)
}
- d := NewDomino(simpleHTML)
+ d := NewDomino(simpleHTML, nil)
d.Start()
script := `
- console.log('Hello!!');
- //console.log(window.jQuery);
- console.log(this);
- Object.assign(this, window);
- //console.log(this.jQuery);
- console.log($);
$(document).ready(function() {
gfgf
console.log('yolo');
@@ -95,12 +93,72 @@
d.Stop()
}
+func TestJQueryHide(t *testing.T) {
+ buf, err := ioutil.ReadFile("jquery-3.5.1.js")
+ if err != nil {
+ t.Fatalf("%v", err)
+ }
+ d := NewDomino(simpleHTML, nil)
+ d.Start()
+ script := `
+ $(document).ready(function() {
+ $('h1').hide();
+ });
+ `
+ _, err = d.Exec(string(buf) + ";" + script, true)
+ if err != nil {
+ t.Fatalf("%v", err)
+ }
+ res, err := d.Exec("$('h1').attr('style')", false)
+ t.Logf("res=%v", res)
+ if err != nil {
+ t.Fatalf("%v", err)
+ }
+ if res != "display: none;" {
+ t.Fatal()
+ }
+ d.Stop()
+}
+
+func TestJQueryCss(t *testing.T) {
+ buf, err := ioutil.ReadFile("jquery-3.5.1.js")
+ if err != nil {
+ t.Fatalf("%v", err)
+ }
+ h := `
+ <html>
+ <body>
+ <h1 id="title" style="display: inline-block;">Hello</h1>
+ </body>
+ </html>
+ `
+ d := NewDomino(h, nil)
+ r := strings.NewReader(h)
+ doc, err := html.Parse(r)
+ if err != nil { t.Fatalf(err.Error()) }
+ d.nt = nodes.NewNodeTree(doc, style.Map{}, make(map[*html.Node]style.Map), nil)
+ d.Start()
+ _, err = d.Exec(string(buf), true)
+ if err != nil {
+ t.Fatalf("%v", err)
+ }
+ res, err := d.Exec("$('h1').css('display')", false)
+ t.Logf("res=%v", res)
+ if err != nil {
+ t.Fatalf("%v", err)
+ }
+ if res != "inline-block" {
+ t.Fatal()
+ }
+ d.Stop()
+}
+
func TestGodoc(t *testing.T) {
buf, err := ioutil.ReadFile("godoc/pkg.html")
if err != nil {
t.Fatalf("%v", err)
}
- d := NewDomino(string(buf))
+ d := NewDomino(string(buf), nil)
d.Start()
script := `
Object.assign(this, window);
@@ -124,7 +182,7 @@
if err != nil {
t.Fatalf("%v", err)
}
- d := NewDomino(string(buf))
+ d := NewDomino(string(buf), nil)
d.Start()
script := `
Object.assign(this, window);
@@ -170,7 +228,7 @@
//elem.dispatchEvent(event);
console.log(window.location.href);
`
- d := NewDomino(simpleHTML)
+ d := NewDomino(simpleHTML, nil)
d.Start()
_, err = d.Exec(SCRIPT, true)
if err != nil {
@@ -206,7 +264,7 @@
});
});
`
- d := NewDomino(simpleHTML)
+ d := NewDomino(simpleHTML, nil)
d.Start()
_, err = d.Exec(SCRIPT, true)
if err != nil {
@@ -268,7 +326,7 @@
//elem.dispatchEvent(event);
console.log(window.location.href);
`
- d := NewDomino(simpleHTML)
+ d := NewDomino(simpleHTML, nil)
d.Start()
_, err = d.Exec(SCRIPT, true)
if err != nil {
@@ -292,7 +350,7 @@
}
func TestTrackChanges(t *testing.T) {
- d := NewDomino(simpleHTML)
+ d := NewDomino(simpleHTML, nil)
d.Start()
_, err := d.Exec(``, true)
if err != nil {
@@ -415,7 +473,7 @@
}*/
func TestES6(t *testing.T) {
- d := NewDomino(simpleHTML)
+ d := NewDomino(simpleHTML, nil)
d.Start()
script := `
console.log('Hello!!');
@@ -437,7 +495,7 @@
}
func TestWindowParent(t *testing.T) {
- d := NewDomino(simpleHTML)
+ d := NewDomino(simpleHTML, nil)
d.Start()
script := `
console.log('Hello!!')
@@ -458,7 +516,7 @@
}
func TestReferrer(t *testing.T) {
- d := NewDomino(simpleHTML)
+ d := NewDomino(simpleHTML, nil)
d.Start()
script := `
document.referrer;
--- a/nodes/experimental.go
+++ b/nodes/experimental.go
@@ -1,10 +1,39 @@
package nodes
import (
- //"golang.org/x/net/html"
- //"opossum/style"
- //"strings"
+ "fmt"
+ "github.com/andybalholm/cascadia"
+ "golang.org/x/net/html"
)
+
+func (n *Node) Query(s string) (ns []*Node, err error) {
+ cs, err := cascadia.Compile(s)
+ if err != nil {
+ return nil, fmt.Errorf("cssSel compile %v: %w", s, err)
+ }
+ var m func(doc *html.Node, nn *Node) *Node
+ m = func(doc *html.Node, nn *Node) *Node {
+ if nn.DomSubtree == doc {
+ return nn
+ }
+ for _, c := range nn.Children {
+ if res := m(doc, c); res != nil {
+ return res
+ }
+ }
+ return nil
+ }
+ if n == nil {
+ return nil, fmt.Errorf("nil node tree")
+ }
+ for _, el := range cascadia.QueryAll(n.DomSubtree, cs) {
+ if res := m(el, n); res != nil {
+ ns = append(ns, res)
+ }
+ }
+ return
+}
+
func (n *Node) NumVClusters() (m int) {
if n.IsFlex() {
if n.IsFlexDirectionRow() {
--- /dev/null
+++ b/nodes/experimental_test.go
@@ -1,0 +1,32 @@
+package nodes
+
+import (
+ "golang.org/x/net/html"
+ "github.com/psilva261/opossum/style"
+ "strings"
+ "testing"
+)
+
+func TestQuery(t *testing.T) {
+ buf := strings.NewReader(`
+ <html>
+ <body>
+ <p>
+ <b>bold stuff</b>
+ <i>italic stuff</i>
+ <a>link</a>
+ </p>
+ </body>
+ </html>`)
+ doc, err := html.Parse(buf)
+ if err != nil { t.Fatalf(err.Error()) }
+ nt := NewNodeTree(doc, style.Map{}, make(map[*html.Node]style.Map), nil)
+ res, _ := nt.Query("b")
+ if len(res) != 1 || res[0].Data() != "b" {
+ t.Errorf("%+v", res)
+ }
+ res, _ = nt.Query("HTML > :nth-child(2) > :nth-child(1) > :nth-child(2)")
+ if len(res) != 1 || res[0].Data() != "i" {
+ t.Errorf("%+v", res[0])
+ }
+}
\ No newline at end of file