Browse Source

Implemented `{Array,String,%TypedArray%}.prototype.at` (#384)

Co-authored-by: satyrnwastaken <[email protected]>
satyrn 3 years ago
parent
commit
e1f9dc0755
4 changed files with 54 additions and 4 deletions
  1. 18 0
      builtin_array.go
  2. 16 1
      builtin_string.go
  3. 20 0
      builtin_typedarrays.go
  4. 0 3
      tc39_test.go

+ 18 - 0
builtin_array.go

@@ -528,6 +528,23 @@ func (r *Runtime) arrayproto_unshift(call FunctionCall) Value {
 	return newLen
 }
 
+func (r *Runtime) arrayproto_at(call FunctionCall) Value {
+	o := call.This.ToObject(r)
+	idx := call.Argument(0).ToInteger()
+	length := toLength(o.self.getStr("length", nil))
+	if idx < 0 {
+		idx = length + idx
+	}
+	if idx >= length || idx < 0 {
+		return _undefined
+	}
+	i := valueInt(idx)
+	if o.self.hasPropertyIdx(i) {
+		return o.self.getIdx(i, nil)
+	}
+	return _undefined
+}
+
 func (r *Runtime) arrayproto_indexOf(call FunctionCall) Value {
 	o := call.This.ToObject(r)
 	length := toLength(o.self.getStr("length", nil))
@@ -1335,6 +1352,7 @@ func (r *Runtime) createArrayProto(val *Object) objectImpl {
 	}
 	o.init()
 
+	o._putProp("at", r.newNativeFunc(r.arrayproto_at, nil, "at", nil, 1), true, false, true)
 	o._putProp("constructor", r.global.Array, true, false, true)
 	o._putProp("concat", r.newNativeFunc(r.arrayproto_concat, nil, "concat", nil, 1), true, false, true)
 	o._putProp("copyWithin", r.newNativeFunc(r.arrayproto_copyWithin, nil, "copyWithin", nil, 2), true, false, true)

+ 16 - 1
builtin_string.go

@@ -157,6 +157,20 @@ func (r *Runtime) string_raw(call FunctionCall) Value {
 	}
 }
 
+func (r *Runtime) stringproto_at(call FunctionCall) Value {
+	r.checkObjectCoercible(call.This)
+	s := call.This.toString()
+	pos := call.Argument(0).ToInteger()
+	length := int64(s.length())
+	if pos < 0 {
+		pos = length + pos
+	}
+	if pos >= length || pos < 0 {
+		return _undefined
+	}
+	return s.substring(int(pos), int(pos+1))
+}
+
 func (r *Runtime) stringproto_charAt(call FunctionCall) Value {
 	r.checkObjectCoercible(call.This)
 	s := call.This.toString()
@@ -164,7 +178,7 @@ func (r *Runtime) stringproto_charAt(call FunctionCall) Value {
 	if pos < 0 || pos >= int64(s.length()) {
 		return stringEmpty
 	}
-	return newStringValue(string(s.charAt(toIntStrict(pos))))
+	return s.substring(int(pos), int(pos+1))
 }
 
 func (r *Runtime) stringproto_charCodeAt(call FunctionCall) Value {
@@ -947,6 +961,7 @@ func (r *Runtime) initString() {
 	r.global.StringPrototype = r.builtin_newString([]Value{stringEmpty}, r.global.ObjectPrototype)
 
 	o := r.global.StringPrototype.self
+	o._putProp("at", r.newNativeFunc(r.stringproto_at, nil, "at", nil, 1), true, false, true)
 	o._putProp("charAt", r.newNativeFunc(r.stringproto_charAt, nil, "charAt", nil, 1), true, false, true)
 	o._putProp("charCodeAt", r.newNativeFunc(r.stringproto_charCodeAt, nil, "charCodeAt", nil, 1), true, false, true)
 	o._putProp("codePointAt", r.newNativeFunc(r.stringproto_codePointAt, nil, "codePointAt", nil, 1), true, false, true)

+ 20 - 0
builtin_typedarrays.go

@@ -637,6 +637,25 @@ func (r *Runtime) typedArrayProto_includes(call FunctionCall) Value {
 	panic(r.NewTypeError("Method TypedArray.prototype.includes called on incompatible receiver %s", r.objectproto_toString(FunctionCall{This: call.This})))
 }
 
+func (r *Runtime) typedArrayProto_at(call FunctionCall) Value {
+	if ta, ok := r.toObject(call.This).self.(*typedArrayObject); ok {
+		ta.viewedArrayBuf.ensureNotDetached(true)
+		idx := call.Argument(0).ToInteger()
+		length := int64(ta.length)
+		if idx < 0 {
+			idx = length + idx
+		}
+		if idx >= length || idx < 0 {
+			return _undefined
+		}
+		if ta.viewedArrayBuf.ensureNotDetached(false) {
+			return ta.typedArray.get(ta.offset + int(idx))
+		}
+		return _undefined
+	}
+	panic(r.NewTypeError("Method TypedArray.prototype.at called on incompatible receiver %s", r.objectproto_toString(FunctionCall{This: call.This})))
+}
+
 func (r *Runtime) typedArrayProto_indexOf(call FunctionCall) Value {
 	if ta, ok := r.toObject(call.This).self.(*typedArrayObject); ok {
 		ta.viewedArrayBuf.ensureNotDetached(true)
@@ -1419,6 +1438,7 @@ func (r *Runtime) createTypedArrayProto(val *Object) objectImpl {
 		configurable: true,
 		getterFunc:   r.newNativeFunc(r.typedArrayProto_getByteOffset, nil, "get byteOffset", nil, 0),
 	})
+	b._putProp("at", r.newNativeFunc(r.typedArrayProto_at, nil, "at", nil, 1), true, false, true)
 	b._putProp("constructor", r.global.TypedArray, true, false, true)
 	b._putProp("copyWithin", r.newNativeFunc(r.typedArrayProto_copyWithin, nil, "copyWithin", nil, 2), true, false, true)
 	b._putProp("entries", r.newNativeFunc(r.typedArrayProto_entries, nil, "entries", nil, 0), true, false, true)

+ 0 - 3
tc39_test.go

@@ -218,11 +218,8 @@ var (
 		"super",
 		"generators",
 		"String.prototype.replaceAll",
-		"String.prototype.at",
 		"resizable-arraybuffer",
 		"array-find-from-last",
-		"Array.prototype.at",
-		"TypedArray.prototype.at",
 		"regexp-named-groups",
 		"regexp-dotall",
 		"regexp-unicode-property-escapes",