refactor(common): 重构 Conn 实体并优化地图进入逻辑
- 优化 Conn 实体的 SendPack 方法,提高代码复用性 - 添加 goja 模块到 go.work 文件 - 重构地图进入逻辑,增加玩家广播和刷怪功能 - 调整 OutInfo 结构中的 Vip 和 Viped 字段类型 - 简化 MonsterRefresh 结构体定义
This commit is contained in:
304
common/utils/goja/object_goarray_reflect_test.go
Normal file
304
common/utils/goja/object_goarray_reflect_test.go
Normal file
@@ -0,0 +1,304 @@
|
||||
package goja
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestGoReflectArray(t *testing.T) {
|
||||
vm := New()
|
||||
vm.Set("a", [...]int{1, 2, 3})
|
||||
_, err := vm.RunString(`
|
||||
if (!Array.isArray(a)) {
|
||||
throw new Error("isArray() returned false");
|
||||
}
|
||||
if (a[0] !== 1 || a[1] !== 2 || a[2] !== 3) {
|
||||
throw new Error("Array contents is incorrect");
|
||||
}
|
||||
if (!a.hasOwnProperty("length")) {
|
||||
throw new Error("hasOwnProperty() returned false");
|
||||
}
|
||||
let desc = Object.getOwnPropertyDescriptor(a, "length");
|
||||
if (desc.value !== 3 || desc.writable || desc.enumerable || desc.configurable) {
|
||||
throw new Error("incorrect property descriptor: " + JSON.stringify(desc));
|
||||
}
|
||||
`)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGoReflectArraySort(t *testing.T) {
|
||||
vm := New()
|
||||
vm.Set("a", [...]int{3, 1, 2})
|
||||
v, err := vm.RunString(`
|
||||
a.sort();
|
||||
if (a[0] !== 1 || a[1] !== 2 || a[2] !== 3) {
|
||||
throw new Error(a.toString());
|
||||
}
|
||||
a;
|
||||
`)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
res := v.Export()
|
||||
if a, ok := res.([3]int); ok {
|
||||
if a[0] != 1 || a[1] != 2 || a[2] != 3 {
|
||||
t.Fatal(a)
|
||||
}
|
||||
} else {
|
||||
t.Fatalf("Wrong type: %T", res)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGoReflectArrayCopyOnChange(t *testing.T) {
|
||||
vm := New()
|
||||
|
||||
v, err := vm.RunString(`
|
||||
a => {
|
||||
let tmp = a[0];
|
||||
if (tmp !== a[0]) {
|
||||
throw new Error("tmp !== a[0]");
|
||||
}
|
||||
|
||||
a[0] = a[1];
|
||||
if (tmp === a[0]) {
|
||||
throw new Error("tmp === a[0]");
|
||||
}
|
||||
if (tmp.Test !== "1") {
|
||||
throw new Error("tmp.Test: " + tmp.Test + " (" + typeof tmp.Test + ")");
|
||||
}
|
||||
if (a[0].Test !== "2") {
|
||||
throw new Error("a[0].Test: " + a[0].Test);
|
||||
}
|
||||
|
||||
a[0].Test = "3";
|
||||
if (a[0].Test !== "3") {
|
||||
throw new Error("a[0].Test (1): " + a[0].Test);
|
||||
}
|
||||
|
||||
tmp = a[0];
|
||||
tmp.Test = "4";
|
||||
if (a[0].Test !== "4") {
|
||||
throw new Error("a[0].Test (2): " + a[0].Test);
|
||||
}
|
||||
|
||||
delete a[0];
|
||||
if (a[0] && a[0].Test !== "") {
|
||||
throw new Error("a[0].Test (3): " + a[0].Test);
|
||||
}
|
||||
if (tmp.Test !== "4") {
|
||||
throw new Error("tmp.Test (1): " + tmp.Test);
|
||||
}
|
||||
|
||||
a[1] = tmp;
|
||||
if (a[1].Test !== "4") {
|
||||
throw new Error("a[1].Test: " + a[1].Test);
|
||||
}
|
||||
|
||||
// grow
|
||||
tmp = a[1];
|
||||
a.push(null);
|
||||
if (a.length !== 3) {
|
||||
throw new Error("a.length after push: " + a.length);
|
||||
}
|
||||
|
||||
tmp.Test = "5";
|
||||
if (a[1].Test !== "5") {
|
||||
throw new Error("a[1].Test (1): " + a[1].Test);
|
||||
}
|
||||
|
||||
// shrink
|
||||
a.length = 1;
|
||||
if (a.length !== 1) {
|
||||
throw new Error("a.length after shrink: " + a.length);
|
||||
}
|
||||
|
||||
if (tmp.Test !== "5") {
|
||||
throw new Error("tmp.Test (shrink): " + tmp.Test);
|
||||
}
|
||||
}
|
||||
`)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
fn, ok := AssertFunction(v)
|
||||
if !ok {
|
||||
t.Fatal("Not a function")
|
||||
}
|
||||
|
||||
t.Run("[]struct", func(t *testing.T) {
|
||||
a := []struct {
|
||||
Test string
|
||||
}{{"1"}, {"2"}}
|
||||
_, err := fn(nil, vm.ToValue(a))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if a[0].Test != "" {
|
||||
t.Fatalf("a[0]: %#v", a[0])
|
||||
}
|
||||
|
||||
if a[1].Test != "4" {
|
||||
t.Fatalf("a0[1]: %#v", a[1])
|
||||
}
|
||||
})
|
||||
|
||||
// The copy-on-change mechanism doesn't apply to the types below because the contained values are references.
|
||||
// These tests are here for completeness and to prove that the behaviour is consistent.
|
||||
|
||||
t.Run("[]I", func(t *testing.T) {
|
||||
type I interface {
|
||||
Get() string
|
||||
}
|
||||
|
||||
a := []I{&testGoReflectMethod_O{Test: "1"}, &testGoReflectMethod_O{Test: "2"}}
|
||||
|
||||
_, err = fn(nil, vm.ToValue(a))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("[]interface{}", func(t *testing.T) {
|
||||
a := []interface{}{&testGoReflectMethod_O{Test: "1"}, &testGoReflectMethod_O{Test: "2"}}
|
||||
|
||||
_, err = fn(nil, vm.ToValue(a))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestCopyOnChangeReflectSlice(t *testing.T) {
|
||||
vm := New()
|
||||
v, err := vm.RunString(`
|
||||
s => {
|
||||
s.A.push(1);
|
||||
if (s.A.length !== 1) {
|
||||
throw new Error("s.A.length: " + s.A.length);
|
||||
}
|
||||
if (s.A[0] !== 1) {
|
||||
throw new Error("s.A[0]: " + s.A[0]);
|
||||
}
|
||||
let tmp = s.A;
|
||||
if (tmp !== s.A) {
|
||||
throw new Error("tmp !== s.A");
|
||||
}
|
||||
s.A = [2];
|
||||
if (tmp === s.A) {
|
||||
throw new Error("tmp === s.A");
|
||||
}
|
||||
if (tmp[0] !== 1) {
|
||||
throw new Error("tmp[0]: " + tmp[0]);
|
||||
}
|
||||
if (s.A[0] !== 2) {
|
||||
throw new Error("s.A[0] (1): " + s.A[0]);
|
||||
}
|
||||
}
|
||||
`)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
fn, ok := AssertFunction(v)
|
||||
if !ok {
|
||||
t.Fatal("Not a function")
|
||||
}
|
||||
|
||||
t.Run("[]int", func(t *testing.T) {
|
||||
type S struct {
|
||||
A []int
|
||||
}
|
||||
var s S
|
||||
_, err := fn(nil, vm.ToValue(&s))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(s.A) != 1 {
|
||||
t.Fatal(s)
|
||||
}
|
||||
if s.A[0] != 2 {
|
||||
t.Fatal(s.A)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("[]interface{}", func(t *testing.T) {
|
||||
type S struct {
|
||||
A []interface{}
|
||||
}
|
||||
var s S
|
||||
_, err := fn(nil, vm.ToValue(&s))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(s.A) != 1 {
|
||||
t.Fatal(s)
|
||||
}
|
||||
if s.A[0] != int64(2) {
|
||||
t.Fatal(s.A)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestCopyOnChangeSort(t *testing.T) {
|
||||
a := []struct {
|
||||
Test string
|
||||
}{{"2"}, {"1"}}
|
||||
|
||||
vm := New()
|
||||
vm.Set("a", &a)
|
||||
|
||||
_, err := vm.RunString(`
|
||||
let a0 = a[0];
|
||||
let a1 = a[1];
|
||||
a.sort((a, b) => a.Test.localeCompare(b.Test));
|
||||
if (a[0].Test !== "1") {
|
||||
throw new Error("a[0]: " + a[0]);
|
||||
}
|
||||
if (a[1].Test !== "2") {
|
||||
throw new Error("a[1]: " + a[1]);
|
||||
}
|
||||
if (a0 !== a[1]) {
|
||||
throw new Error("a0 !== a[1]");
|
||||
}
|
||||
if (a1 !== a[0]) {
|
||||
throw new Error("a1 !== a[0]");
|
||||
}
|
||||
`)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if a[0].Test != "1" || a[1].Test != "2" {
|
||||
t.Fatal(a)
|
||||
}
|
||||
}
|
||||
|
||||
type testStringerArray [8]byte
|
||||
|
||||
func (a testStringerArray) String() string {
|
||||
return "X"
|
||||
}
|
||||
|
||||
func TestReflectArrayToString(t *testing.T) {
|
||||
vm := New()
|
||||
var a testStringerArray
|
||||
vm.Set("a", &a)
|
||||
res, err := vm.RunString("`${a}`")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if exp := res.Export(); exp != "X" {
|
||||
t.Fatal(exp)
|
||||
}
|
||||
|
||||
var a1 [2]byte
|
||||
vm.Set("a", &a1)
|
||||
res, err = vm.RunString("`${a}`")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if exp := res.Export(); exp != "0,0" {
|
||||
t.Fatal(exp)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user