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"
|
"gopkg.in/godo.v2/glob"
|
||||||
)
|
)
|
||||||
|
|
||||||
var contextPattern, expressionPattern, operatorPattern *regexp.Regexp
|
var expressionPattern, operatorPattern *regexp.Regexp
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
contextPattern = regexp.MustCompile(`^([^.]*(?:\[.+])*)(?:\.([\w-]+))?(.*)$`)
|
|
||||||
expressionPattern = regexp.MustCompile(`\${{\s*(.+?)\s*}}`)
|
expressionPattern = regexp.MustCompile(`\${{\s*(.+?)\s*}}`)
|
||||||
operatorPattern = regexp.MustCompile("^[!=><|&]+$")
|
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.
|
// Rewrite tries to transform any javascript property accessor into its bracket notation.
|
||||||
// For instance, "object.property" would become "object['property']".
|
// For instance, "object.property" would become "object['property']".
|
||||||
func (ee *expressionEvaluator) Rewrite(in string) string {
|
func (ee *expressionEvaluator) Rewrite(in string) string {
|
||||||
re := in
|
var buf strings.Builder
|
||||||
|
r := strings.NewReader(in)
|
||||||
for {
|
for {
|
||||||
matches := contextPattern.FindStringSubmatch(re)
|
c, _, err := r.ReadRune()
|
||||||
if matches == nil {
|
if err == io.EOF {
|
||||||
// No global match, we're done!
|
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
if matches[2] == "" {
|
//nolint
|
||||||
// No property match, we're done!
|
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
|
break
|
||||||
}
|
}
|
||||||
|
w.WriteString(`\'`) //nolint
|
||||||
re = fmt.Sprintf("%s['%s']%s", matches[1], matches[2], matches[3])
|
|
||||||
}
|
}
|
||||||
|
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 {
|
func (rc *RunContext) newVM() *otto.Otto {
|
||||||
|
|
|
@ -89,6 +89,8 @@ func TestEvaluate(t *testing.T) {
|
||||||
{"(fromJson('{\"foo\":\"bar\"}')).foo", "bar", ""},
|
{"(fromJson('{\"foo\":\"bar\"}')).foo", "bar", ""},
|
||||||
{"hashFiles('**/non-extant-files')", "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", ""},
|
{"hashFiles('**/non-extant-files')", "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", ""},
|
||||||
{"hashFiles('**/non-extant-files', '**/more-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", ""},
|
{"success()", "true", ""},
|
||||||
{"failure()", "false", ""},
|
{"failure()", "false", ""},
|
||||||
{"always()", "true", ""},
|
{"always()", "true", ""},
|
||||||
|
|
Loading…
Reference in a new issue