Skip to content

Commit ddc7abd

Browse files
authored
fix: prevent misuse of transformOptions (#389)
1 parent 380c124 commit ddc7abd

File tree

7 files changed

+51
-29
lines changed

7 files changed

+51
-29
lines changed

browser.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ func (b *browserImpl) NewContext(options ...BrowserNewContextOptions) (BrowserCo
7676
options[0].RecordHarContent = nil
7777
options[0].RecordHarOmitContent = nil
7878
}
79-
channel, err := b.channel.Send("newContext", overrides, options)
79+
channel, err := b.channel.Send("newContext", options, overrides)
8080
if err != nil {
8181
return nil, fmt.Errorf("could not send message: %w", err)
8282
}

browser_type.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ func (b *browserTypeImpl) Launch(options ...BrowserTypeLaunchOptions) (Browser,
2323
overrides["env"] = serializeMapToNameAndValue(options[0].Env)
2424
options[0].Env = nil
2525
}
26-
channel, err := b.channel.Send("launch", overrides, options)
26+
channel, err := b.channel.Send("launch", options, overrides)
2727
if err != nil {
2828
return nil, fmt.Errorf("could not send message: %w", err)
2929
}
@@ -79,7 +79,7 @@ func (b *browserTypeImpl) LaunchPersistentContext(userDataDir string, options ..
7979
options[0].RecordHarOmitContent = nil
8080
}
8181
}
82-
channel, err := b.channel.Send("launchPersistentContext", overrides, options)
82+
channel, err := b.channel.Send("launchPersistentContext", options, overrides)
8383
if err != nil {
8484
return nil, fmt.Errorf("could not send message: %w", err)
8585
}
@@ -92,7 +92,7 @@ func (b *browserTypeImpl) Connect(wsEndpoint string, options ...BrowserTypeConne
9292
"wsEndpoint": wsEndpoint,
9393
}
9494
localUtils := b.connection.LocalUtils()
95-
pipe, err := localUtils.channel.SendReturnAsDict("connect", overrides, options)
95+
pipe, err := localUtils.channel.SendReturnAsDict("connect", options, overrides)
9696
if err != nil {
9797
return nil, err
9898
}
@@ -138,7 +138,7 @@ func (b *browserTypeImpl) ConnectOverCDP(endpointURL string, options ...BrowserT
138138
options[0].Headers = nil
139139
}
140140
}
141-
response, err := b.channel.SendReturnAsDict("connectOverCDP", overrides, options)
141+
response, err := b.channel.SendReturnAsDict("connectOverCDP", options, overrides)
142142
if err != nil {
143143
return nil, err
144144
}

fetch.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ func (r *apiRequestImpl) NewContext(options ...APIRequestNewContextOptions) (API
3535
}
3636
}
3737

38-
channel, err := r.channel.Send("newRequest", overrides, options)
38+
channel, err := r.channel.Send("newRequest", options, overrides)
3939
if err != nil {
4040
return nil, fmt.Errorf("could not send message: %w", err)
4141
}
@@ -178,7 +178,7 @@ func (r *apiRequestContextImpl) innerFetch(url string, request Request, options
178178
}
179179
}
180180

181-
response, err := r.channel.Send("fetch", overrides, options)
181+
response, err := r.channel.Send("fetch", options, overrides)
182182
if err != nil {
183183
return nil, err
184184
}

helpers.go

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ func transformStructIntoMapIfNeeded(inStruct interface{}) map[string]interface{}
6262
for i := 0; i < v.NumField(); i++ {
6363
fi := typ.Field(i)
6464
// Skip the values when the field is a pointer (like *string) and nil.
65-
if !skipFieldSerialization(v.Field(i)) {
65+
if fi.IsExported() && !skipFieldSerialization(v.Field(i)) {
6666
// We use the JSON struct fields for getting the original names
6767
// out of the field.
6868
tagv := fi.Tag.Get("json")
@@ -97,10 +97,14 @@ func transformOptions(options ...interface{}) map[string]interface{} {
9797
base = make(map[string]interface{})
9898
option = options[0]
9999
} else if len(options) == 2 {
100-
// Case 3: two values are given. The first one needs to be a map and the
101-
// second one can be a struct or map. It will be then get merged into the first
100+
// Case 3: two values are given. The first one needs to be transformed
101+
// to a map, the sencond one will be then get merged into the first
102102
// base map.
103-
base = transformStructIntoMapIfNeeded(options[0])
103+
if reflect.ValueOf(options[0]).Kind() != reflect.Map {
104+
base = transformOptions(options[0])
105+
} else {
106+
base = transformStructIntoMapIfNeeded(options[0])
107+
}
104108
option = options[1]
105109
}
106110
v := reflect.ValueOf(option)

helpers_test.go

Lines changed: 34 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,10 @@ type testOptionsJSONSerialization struct {
1010
StringPointer *string `json:"stringPointer"`
1111
NormalString string `json:"normalString"`
1212
WithoutJSONTag string
13-
WithJSONTag string `json:"withJSONTag"`
14-
SkipNilPtrs *string `json:"skipNilPtrs"`
15-
SkipMe *int `json:"skipMe"`
13+
WithJSONTag string `json:"withJSONTag"`
14+
OverrideMe []string `json:"overrideMe"`
15+
SkipNilPtrs *string `json:"skipNilPtrs"`
16+
SkipMe *int `json:"skipMe"`
1617
}
1718

1819
func TestTransformOptions(t *testing.T) {
@@ -22,17 +23,18 @@ func TestTransformOptions(t *testing.T) {
2223
NormalString: "2",
2324
WithoutJSONTag: "3",
2425
WithJSONTag: "4",
26+
OverrideMe: []string{"5"},
2527
}
2628
var nilStrPtr *string
2729
testCases := []struct {
28-
name string
29-
baseMap map[string]interface{}
30-
optionalStruct interface{}
31-
expected interface{}
30+
name string
31+
firstOption interface{}
32+
secondOption interface{}
33+
expected interface{}
3234
}{
3335
{
3436
name: "No options supplied",
35-
baseMap: map[string]interface{}{
37+
firstOption: map[string]interface{}{
3638
"1234": nilStrPtr,
3739
"foo": "bar",
3840
},
@@ -42,44 +44,60 @@ func TestTransformOptions(t *testing.T) {
4244
},
4345
{
4446
name: "Options are nil",
45-
baseMap: map[string]interface{}{
47+
firstOption: map[string]interface{}{
4648
"foo": "bar",
4749
},
48-
optionalStruct: nil,
50+
secondOption: nil,
4951
expected: map[string]interface{}{
5052
"foo": "bar",
5153
},
5254
},
5355
{
5456
name: "JSON serialization works",
55-
baseMap: map[string]interface{}{
56-
"foo": "bar",
57+
firstOption: map[string]interface{}{
58+
"foo": "bar",
59+
"stringPointer": 1,
5760
},
58-
optionalStruct: structVar,
61+
secondOption: structVar,
5962
expected: map[string]interface{}{
6063
"foo": "bar",
6164
"stringPointer": String("1"),
6265
"normalString": "2",
6366
"WithoutJSONTag": "3",
6467
"withJSONTag": "4",
68+
"overrideMe": []interface{}{"5"},
6569
},
6670
},
6771
{
6872
name: "Second overwrites the first one",
69-
baseMap: map[string]interface{}{
73+
firstOption: map[string]interface{}{
7074
"foo": "1",
7175
},
72-
optionalStruct: map[string]interface{}{
76+
secondOption: map[string]interface{}{
7377
"foo": "2",
7478
},
7579
expected: map[string]interface{}{
7680
"foo": "2",
7781
},
7882
},
83+
{
84+
name: "Second overwrites the first one's value in different type",
85+
firstOption: structVar,
86+
secondOption: map[string]interface{}{
87+
"overrideMe": "5",
88+
},
89+
expected: map[string]interface{}{
90+
"stringPointer": String("1"),
91+
"normalString": "2",
92+
"WithoutJSONTag": "3",
93+
"withJSONTag": "4",
94+
"overrideMe": "5",
95+
},
96+
},
7997
}
8098
for _, tc := range testCases {
8199
t.Run(tc.name, func(t *testing.T) {
82-
require.Equal(t, tc.expected, transformOptions(tc.baseMap, tc.optionalStruct))
100+
require.Equal(t, tc.expected, transformOptions(tc.firstOption, tc.secondOption))
83101
})
84102
}
85103
}

page.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -337,7 +337,6 @@ func (p *pageImpl) Screenshot(options ...PageScreenshotOptions) ([]byte, error)
337337
}
338338
}
339339
overrides["mask"] = masks
340-
options[0].Mask = nil
341340
}
342341
}
343342
data, err := p.channel.Send("screenshot", options, overrides)
@@ -358,7 +357,7 @@ func (p *pageImpl) Screenshot(options ...PageScreenshotOptions) ([]byte, error)
358357

359358
func (p *pageImpl) PDF(options ...PagePdfOptions) ([]byte, error) {
360359
var path *string
361-
if len(options) > 0 {
360+
if len(options) == 1 {
362361
path = options[0].Path
363362
}
364363
data, err := p.channel.Send("pdf", options)

tests/page_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ func TestPageScreenshotWithMask(t *testing.T) {
9797
Mask: []playwright.Locator{
9898
sensElem,
9999
},
100+
MaskColor: playwright.String("red"),
100101
})
101102
require.NoError(t, err)
102103
require.True(t, filetype.IsImage(screenshot2))

0 commit comments

Comments
 (0)