Shouldn't rewrite dot in a string to index syntax (#502)
Co-authored-by: Casey Lee <cplee@nektos.com>
This commit is contained in:
parent
fc46f506e3
commit
316b078f8c
2 changed files with 79 additions and 12 deletions
|
@ -16,10 +16,9 @@ import (
|
|||
"gopkg.in/godo.v2/glob"
|
||||
)
|
||||
|
||||
var contextPattern, expressionPattern, operatorPattern *regexp.Regexp
|
||||
var expressionPattern, operatorPattern *regexp.Regexp
|
||||
|
||||
func init() {
|
||||
contextPattern = regexp.MustCompile(`^([^.]*(?:\[.+])*)(?:\.([\w-]+))?(.*)$`)
|
||||
expressionPattern = regexp.MustCompile(`\${{\s*(.+?)\s*}}`)
|
||||
operatorPattern = regexp.MustCompile("^[!=><|&]+$")
|
||||
}
|
||||
|
@ -123,22 +122,88 @@ func (ee *expressionEvaluator) InterpolateWithStringCheck(in string) (string, bo
|
|||
// Rewrite tries to transform any javascript property accessor into its bracket notation.
|
||||
// For instance, "object.property" would become "object['property']".
|
||||
func (ee *expressionEvaluator) Rewrite(in string) string {
|
||||
re := in
|
||||
var buf strings.Builder
|
||||
r := strings.NewReader(in)
|
||||
for {
|
||||
matches := contextPattern.FindStringSubmatch(re)
|
||||
if matches == nil {
|
||||
// No global match, we're done!
|
||||
c, _, err := r.ReadRune()
|
||||
if err == io.EOF {
|
||||
break
|
||||
}
|
||||
if matches[2] == "" {
|
||||
// No property match, we're done!
|
||||
//nolint
|
||||
switch {
|
||||
default:
|
||||
buf.WriteRune(c)
|
||||
case c == '\'':
|
||||
buf.WriteRune(c)
|
||||
ee.advString(&buf, r)
|
||||
case c == '.':
|
||||
buf.WriteString("['")
|
||||
ee.advPropertyName(&buf, r)
|
||||
buf.WriteString("']")
|
||||
}
|
||||
}
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
func (*expressionEvaluator) advString(w *strings.Builder, r *strings.Reader) error {
|
||||
for {
|
||||
c, _, err := r.ReadRune()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if c != '\'' {
|
||||
w.WriteRune(c) //nolint
|
||||
continue
|
||||
}
|
||||
|
||||
// Handles a escaped string: ex. 'It''s ok'
|
||||
c, _, err = r.ReadRune()
|
||||
if err != nil {
|
||||
w.WriteString("'") //nolint
|
||||
return err
|
||||
}
|
||||
if c != '\'' {
|
||||
w.WriteString("'") //nolint
|
||||
if err := r.UnreadRune(); err != nil {
|
||||
return err
|
||||
}
|
||||
break
|
||||
}
|
||||
|
||||
re = fmt.Sprintf("%s['%s']%s", matches[1], matches[2], matches[3])
|
||||
w.WriteString(`\'`) //nolint
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
return re
|
||||
func (*expressionEvaluator) advPropertyName(w *strings.Builder, r *strings.Reader) error {
|
||||
for {
|
||||
c, _, err := r.ReadRune()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !isLetter(c) {
|
||||
if err := r.UnreadRune(); err != nil {
|
||||
return err
|
||||
}
|
||||
break
|
||||
}
|
||||
w.WriteRune(c) //nolint
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func isLetter(c rune) bool {
|
||||
switch {
|
||||
case c >= 'a' && c <= 'z':
|
||||
return true
|
||||
case c >= 'A' && c <= 'Z':
|
||||
return true
|
||||
case c >= '0' && c <= '9':
|
||||
return true
|
||||
case c == '_' || c == '-':
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
func (rc *RunContext) newVM() *otto.Otto {
|
||||
|
|
|
@ -89,6 +89,8 @@ func TestEvaluate(t *testing.T) {
|
|||
{"(fromJson('{\"foo\":\"bar\"}')).foo", "bar", ""},
|
||||
{"hashFiles('**/non-extant-files')", "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", ""},
|
||||
{"hashFiles('**/non-extant-files', '**/more-non-extant-files')", "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", ""},
|
||||
{"hashFiles('**/non.extant.files')", "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", ""},
|
||||
{"hashFiles('**/non''extant''files')", "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", ""},
|
||||
{"success()", "true", ""},
|
||||
{"failure()", "false", ""},
|
||||
{"always()", "true", ""},
|
||||
|
|
Loading…
Reference in a new issue