Skip to content

Commit

Permalink
REALMC-11689: add arrow functions, typed array fixes, more date-time …
Browse files Browse the repository at this point in the history
…formats, ... (#47)

* Fixed typed arrays' defineProperty and indexing. Fixes dop251#308.
* Fix Proxy creation panicing on target not callable
* Do not modify sb for variadic calls as it breaks local variables resolution. Instead place a marker on stack and use it to count the number of args. Fixes dop251#311.
* Support patterns in catch clause. See dop251#305
* Fixed the handling of Symbol properties in destructuring assignments. Fixes dop251#312.
* Ensure ToPropertyKey happens earlier when assigning computed keys. Fixes dop251#312.
* Aligned detached buffer semantics with the latest specs. Fixes dop251#315.
* More typed arrays fixes
* Fixed accessor and property key function names. Fixes dop251#314.
* Fixed possible panic when sorting non-standard arrays.
* Added nil-safety checks for values returned by get*() methods
* Fixed panics in parser on some invalid inputs. Fixes dop251#318.
* Arrow function (dop251#319)
* Implemented arrow functions. See dop251#304.
* Define the name property for anonymous functions (including arrow functions)
* Treat "arguments" as a lexical binding to match the latest specification
* Allow arrow functions to contain 'use strict' for simple parameter lists. Fixes dop251#323.
* Fixed argument variable reference resolution in stashless functions
* Treat date-only formats as UTC and date-time as local timezone. Added support for additional datetime formats. Fixes dop251#281, fixes dop251#292.
* Use correct createArgsRest variant when arguments are not in stash. Fixes dop251#327
* Fixed formatting for go 1.17
* Report 'length' as own property for Go slices. Fixes dop251#328.
  • Loading branch information
Gabri3l authored Feb 4, 2022
1 parent ef06792 commit ecdfff3
Show file tree
Hide file tree
Showing 46 changed files with 1,999 additions and 689 deletions.
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

0 comments on commit ecdfff3

Please sign in to comment.