Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

REALMC-11689: add arrow functions, typed array fixes, more date-time formats, ... #47

Merged
merged 19 commits into from
Feb 4, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
c095cd6
Fixed typed arrays' defineProperty and indexing. Fixes #308.
dop251 Jul 24, 2021
3923f3e
Fix Proxy creation panicing on target not callable
mstoykov Jul 22, 2021
73539f9
Do not modify sb for variadic calls as it breaks local variables reso…
dop251 Jul 24, 2021
e10028f
Support patterns in catch clause. See #305
dop251 Jul 25, 2021
9cf58f8
Fixed the handling of Symbol properties in destructuring assignments.…
dop251 Jul 26, 2021
867c110
Ensure ToPropertyKey happens earlier when assigning computed keys. Fi…
dop251 Jul 26, 2021
d374f34
Aligned detached buffer semantics with the latest specs. Fixes #315.
dop251 Jul 26, 2021
23ea7f2
More typed arrays fixes
dop251 Jul 26, 2021
77c7d64
Fixed accessor and property key function names. Fixes #314.
dop251 Jul 29, 2021
3c275b3
Fixed possible panic when sorting non-standard arrays.
dop251 Aug 2, 2021
1110c7a
Added nil-safety checks for values returned by get*() methods
dop251 Aug 2, 2021
9b4f991
Fixed panics in parser on some invalid inputs. Fixes #318.
dop251 Aug 2, 2021
44fbc76
Arrow function (#319)
dop251 Aug 4, 2021
78b20b6
Allow arrow functions to contain 'use strict' for simple parameter li…
dop251 Aug 10, 2021
a5b4da6
Fixed argument variable reference resolution in stashless functions
dop251 Aug 17, 2021
e1aedbe
Treat date-only formats as UTC and date-time as local timezone. Added…
dop251 Sep 4, 2021
7cdbcc8
Use correct createArgsRest variant when arguments are not in stash. F…
dop251 Sep 11, 2021
18cd651
Fixed formatting for go 1.17
dop251 Sep 11, 2021
2c4edae
Report 'length' as own property for Go slices. Fixes #328.
dop251 Sep 12, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
122 changes: 6 additions & 116 deletions array.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ func (ai *arrayIterObject) next() Value {
if ai.kind == iterationKindKey {
return ai.val.runtime.createIterResultObject(idxVal, false)
}
elementValue := ai.obj.self.getIdx(idxVal, nil)
elementValue := nilSafe(ai.obj.self.getIdx(idxVal, nil))
var result Value
if ai.kind == iterationKindValue {
result = elementValue
Expand Down Expand Up @@ -162,7 +162,7 @@ func (a *arrayObject) getIdx(idx valueInt, receiver Value) Value {

func (a *arrayObject) getOwnPropStr(name unistring.String) Value {
if len(a.values) > 0 {
if i := strToIdx(name); i != math.MaxUint32 {
if i := strToArrayIdx(name); i != math.MaxUint32 {
if i < uint32(len(a.values)) {
return a.values[i]
}
Expand Down Expand Up @@ -264,7 +264,7 @@ func (a *arrayObject) _setOwnIdx(idx uint32, val Value, throw bool) bool {
}

func (a *arrayObject) setOwnStr(name unistring.String, val Value, throw bool) bool {
if idx := strToIdx(name); idx != math.MaxUint32 {
if idx := strToArrayIdx(name); idx != math.MaxUint32 {
return a._setOwnIdx(idx, val, throw)
} else {
if name == "length" {
Expand Down Expand Up @@ -325,7 +325,7 @@ func (a *arrayObject) ownKeys(all bool, accum []Value) []Value {
}

func (a *arrayObject) hasOwnPropertyStr(name unistring.String) bool {
if idx := strToIdx(name); idx != math.MaxUint32 {
if idx := strToArrayIdx(name); idx != math.MaxUint32 {
return idx < uint32(len(a.values)) && a.values[idx] != nil
} else {
return a.baseObject.hasOwnPropertyStr(name)
Expand Down Expand Up @@ -433,7 +433,7 @@ func (a *arrayObject) _defineIdxProperty(idx uint32, desc PropertyDescriptor, th
}

func (a *arrayObject) defineOwnPropertyStr(name unistring.String, descr PropertyDescriptor, throw bool) bool {
if idx := strToIdx(name); idx != math.MaxUint32 {
if idx := strToArrayIdx(name); idx != math.MaxUint32 {
return a._defineIdxProperty(idx, descr, throw)
}
if name == "length" {
Expand Down Expand Up @@ -467,7 +467,7 @@ func (a *arrayObject) _deleteIdxProp(idx uint32, throw bool) bool {
}

func (a *arrayObject) deleteStr(name unistring.String, throw bool) bool {
if idx := strToIdx(name); idx != math.MaxUint32 {
if idx := strToArrayIdx(name); idx != math.MaxUint32 {
return a._deleteIdxProp(idx, throw)
}
return a.baseObject.deleteStr(name, throw)
Expand Down Expand Up @@ -522,116 +522,6 @@ func toIdx(v valueInt) uint32 {
return math.MaxUint32
}

func strToIdx64(s unistring.String) int64 {
if s == "" {
return -1
}
l := len(s)
if s[0] == '0' {
if l == 1 {
return 0
}
return -1
}
var n int64
if l < 19 {
// guaranteed not to overflow
for i := 0; i < len(s); i++ {
c := s[i]
if c < '0' || c > '9' {
return -1
}
n = n*10 + int64(c-'0')
}
return n
}
if l > 19 {
// guaranteed to overflow
return -1
}
c18 := s[18]
if c18 < '0' || c18 > '9' {
return -1
}
for i := 0; i < 18; i++ {
c := s[i]
if c < '0' || c > '9' {
return -1
}
n = n*10 + int64(c-'0')
}
if n >= math.MaxInt64/10+1 {
return -1
}
n *= 10
n1 := n + int64(c18-'0')
if n1 < n {
return -1
}
return n1
}

func strToIdx(s unistring.String) uint32 {
if s == "" {
return math.MaxUint32
}
l := len(s)
if s[0] == '0' {
if l == 1 {
return 0
}
return math.MaxUint32
}
var n uint32
if l < 10 {
// guaranteed not to overflow
for i := 0; i < len(s); i++ {
c := s[i]
if c < '0' || c > '9' {
return math.MaxUint32
}
n = n*10 + uint32(c-'0')
}
return n
}
if l > 10 {
// guaranteed to overflow
return math.MaxUint32
}
c9 := s[9]
if c9 < '0' || c9 > '9' {
return math.MaxUint32
}
for i := 0; i < 9; i++ {
c := s[i]
if c < '0' || c > '9' {
return math.MaxUint32
}
n = n*10 + uint32(c-'0')
}
if n >= math.MaxUint32/10+1 {
return math.MaxUint32
}
n *= 10
n1 := n + uint32(c9-'0')
if n1 < n {
return math.MaxUint32
}

return n1
}

func strToGoIdx(s unistring.String) int {
if bits.UintSize == 64 {
return int(strToIdx64(s))
}
i := strToIdx(s)
if i >= math.MaxInt32 {
return -1
}
return int(i)
}

func (a *arrayObject) MemUsage(ctx *MemUsageContext) (uint64, error) {
if a == nil || ctx.IsObjVisited(a) {
return SizeEmpty, nil
Expand Down
10 changes: 5 additions & 5 deletions array_sparse.go
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ func (a *sparseArrayObject) getLengthProp() Value {
}

func (a *sparseArrayObject) getOwnPropStr(name unistring.String) Value {
if idx := strToIdx(name); idx != math.MaxUint32 {
if idx := strToArrayIdx(name); idx != math.MaxUint32 {
return a._getIdx(idx)
}
if name == "length" {
Expand Down Expand Up @@ -214,7 +214,7 @@ func (a *sparseArrayObject) _setOwnIdx(idx uint32, val Value, throw bool) bool {
}

func (a *sparseArrayObject) setOwnStr(name unistring.String, val Value, throw bool) bool {
if idx := strToIdx(name); idx != math.MaxUint32 {
if idx := strToArrayIdx(name); idx != math.MaxUint32 {
return a._setOwnIdx(idx, val, throw)
} else {
if name == "length" {
Expand Down Expand Up @@ -295,7 +295,7 @@ func (a *sparseArrayObject) setValues(values []Value, objCount int) {
}

func (a *sparseArrayObject) hasOwnPropertyStr(name unistring.String) bool {
if idx := strToIdx(name); idx != math.MaxUint32 {
if idx := strToArrayIdx(name); idx != math.MaxUint32 {
i := a.findIdx(idx)
return i < len(a.items) && a.items[i].idx == idx
} else {
Expand Down Expand Up @@ -372,7 +372,7 @@ func (a *sparseArrayObject) _defineIdxProperty(idx uint32, desc PropertyDescript
}

func (a *sparseArrayObject) defineOwnPropertyStr(name unistring.String, descr PropertyDescriptor, throw bool) bool {
if idx := strToIdx(name); idx != math.MaxUint32 {
if idx := strToArrayIdx(name); idx != math.MaxUint32 {
return a._defineIdxProperty(idx, descr, throw)
}
if name == "length" {
Expand Down Expand Up @@ -406,7 +406,7 @@ func (a *sparseArrayObject) _deleteIdxProp(idx uint32, throw bool) bool {
}

func (a *sparseArrayObject) deleteStr(name unistring.String, throw bool) bool {
if idx := strToIdx(name); idx != math.MaxUint32 {
if idx := strToArrayIdx(name); idx != math.MaxUint32 {
return a._deleteIdxProp(idx, throw)
}
return a.baseObject.deleteStr(name, throw)
Expand Down
13 changes: 13 additions & 0 deletions array_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,19 @@ func TestArrayExportProps(t *testing.T) {
}
}

func TestArrayCanonicalIndex(t *testing.T) {
const SCRIPT = `
var a = [];
a["00"] = 1;
a["01"] = 2;
if (a[0] !== undefined) {
throw new Error("a[0]");
}
`

testScript1(SCRIPT, _undefined, t)
}

func BenchmarkArrayGetStr(b *testing.B) {
b.StopTimer()
r := New()
Expand Down
28 changes: 27 additions & 1 deletion ast/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,23 @@ type (
DeclarationList []*VariableDeclaration
}

ConciseBody interface {
Node
_conciseBody()
}

ExpressionBody struct {
Expression Expression
}

ArrowFunctionLiteral struct {
Start file.Idx
ParameterList *ParameterList
Body ConciseBody
Source string
DeclarationList []*VariableDeclaration
}

Identifier struct {
Name unistring.String
Idx file.Idx
Expand Down Expand Up @@ -238,6 +255,7 @@ func (*CallExpression) _expressionNode() {}
func (*ConditionalExpression) _expressionNode() {}
func (*DotExpression) _expressionNode() {}
func (*FunctionLiteral) _expressionNode() {}
func (*ArrowFunctionLiteral) _expressionNode() {}
func (*Identifier) _expressionNode() {}
func (*NewExpression) _expressionNode() {}
func (*NullLiteral) _expressionNode() {}
Expand Down Expand Up @@ -292,7 +310,7 @@ type (

CatchStatement struct {
Catch file.Idx
Parameter *Identifier
Parameter BindingTarget
Body *BlockStatement
}

Expand Down Expand Up @@ -497,6 +515,9 @@ func (*SpreadElement) _property() {}

func (*Identifier) _bindingTarget() {}

func (*BlockStatement) _conciseBody() {}
func (*ExpressionBody) _conciseBody() {}

// ==== //
// Node //
// ==== //
Expand Down Expand Up @@ -525,6 +546,7 @@ func (self *CallExpression) Idx0() file.Idx { return self.Callee.Idx0() }
func (self *ConditionalExpression) Idx0() file.Idx { return self.Test.Idx0() }
func (self *DotExpression) Idx0() file.Idx { return self.Left.Idx0() }
func (self *FunctionLiteral) Idx0() file.Idx { return self.Function }
func (self *ArrowFunctionLiteral) Idx0() file.Idx { return self.Start }
func (self *Identifier) Idx0() file.Idx { return self.Idx }
func (self *NewExpression) Idx0() file.Idx { return self.New }
func (self *NullLiteral) Idx0() file.Idx { return self.Idx }
Expand Down Expand Up @@ -566,6 +588,7 @@ func (self *Binding) Idx0() file.Idx { return self.Target.Idx0() }
func (self *ForLoopInitializerVarDeclList) Idx0() file.Idx { return self.List[0].Idx0() }
func (self *PropertyShort) Idx0() file.Idx { return self.Name.Idx }
func (self *PropertyKeyed) Idx0() file.Idx { return self.Key.Idx0() }
func (self *ExpressionBody) Idx0() file.Idx { return self.Expression.Idx0() }

// ==== //
// Idx1 //
Expand All @@ -582,6 +605,7 @@ func (self *CallExpression) Idx1() file.Idx { return self.RightParenthesi
func (self *ConditionalExpression) Idx1() file.Idx { return self.Test.Idx1() }
func (self *DotExpression) Idx1() file.Idx { return self.Identifier.Idx1() }
func (self *FunctionLiteral) Idx1() file.Idx { return self.Body.Idx1() }
func (self *ArrowFunctionLiteral) Idx1() file.Idx { return self.Body.Idx1() }
func (self *Identifier) Idx1() file.Idx { return file.Idx(int(self.Idx) + len(self.Name)) }
func (self *NewExpression) Idx1() file.Idx { return self.RightParenthesis + 1 }
func (self *NullLiteral) Idx1() file.Idx { return file.Idx(int(self.Idx) + 4) } // "null"
Expand Down Expand Up @@ -656,3 +680,5 @@ func (self *PropertyShort) Idx1() file.Idx {
}

func (self *PropertyKeyed) Idx1() file.Idx { return self.Value.Idx1() }

func (self *ExpressionBody) Idx1() file.Idx { return self.Expression.Idx1() }
Loading