github.com/nuvolaris/goja@v0.0.0-20230825100449-967811910c6d/object_gomap_test.go (about)

     1  package goja
     2  
     3  import "testing"
     4  
     5  func TestGomapProp(t *testing.T) {
     6  	const SCRIPT = `
     7  	o.a + o.b;
     8  	`
     9  	r := New()
    10  	r.Set("o", map[string]interface{}{
    11  		"a": 40,
    12  		"b": 2,
    13  	})
    14  	v, err := r.RunString(SCRIPT)
    15  	if err != nil {
    16  		t.Fatal(err)
    17  	}
    18  	if i := v.ToInteger(); i != 42 {
    19  		t.Fatalf("Expected 42, got: %d", i)
    20  	}
    21  }
    22  
    23  func TestGomapEnumerate(t *testing.T) {
    24  	const SCRIPT = `
    25  	var hasX = false;
    26  	var hasY = false;
    27  	for (var key in o) {
    28  		switch (key) {
    29  		case "x":
    30  			if (hasX) {
    31  				throw "Already have x";
    32  			}
    33  			hasX = true;
    34  			break;
    35  		case "y":
    36  			if (hasY) {
    37  				throw "Already have y";
    38  			}
    39  			hasY = true;
    40  			break;
    41  		default:
    42  			throw "Unexpected property: " + key;
    43  		}
    44  	}
    45  	hasX && hasY;
    46  	`
    47  	r := New()
    48  	r.Set("o", map[string]interface{}{
    49  		"x": 40,
    50  		"y": 2,
    51  	})
    52  	v, err := r.RunString(SCRIPT)
    53  	if err != nil {
    54  		t.Fatal(err)
    55  	}
    56  
    57  	if !v.StrictEquals(valueTrue) {
    58  		t.Fatalf("Expected true, got %v", v)
    59  	}
    60  }
    61  
    62  func TestGomapDeleteWhileEnumerate(t *testing.T) {
    63  	const SCRIPT = `
    64  	var hasX = false;
    65  	var hasY = false;
    66  	for (var key in o) {
    67  		switch (key) {
    68  		case "x":
    69  			if (hasX) {
    70  				throw "Already have x";
    71  			}
    72  			hasX = true;
    73  			delete o.y;
    74  			break;
    75  		case "y":
    76  			if (hasY) {
    77  				throw "Already have y";
    78  			}
    79  			hasY = true;
    80  			delete o.x;
    81  			break;
    82  		default:
    83  			throw "Unexpected property: " + key;
    84  		}
    85  	}
    86  	hasX && !hasY || hasY && !hasX;
    87  	`
    88  	r := New()
    89  	r.Set("o", map[string]interface{}{
    90  		"x": 40,
    91  		"y": 2,
    92  	})
    93  	v, err := r.RunString(SCRIPT)
    94  	if err != nil {
    95  		t.Fatal(err)
    96  	}
    97  
    98  	if !v.StrictEquals(valueTrue) {
    99  		t.Fatalf("Expected true, got %v", v)
   100  	}
   101  }
   102  
   103  func TestGomapInstanceOf(t *testing.T) {
   104  	const SCRIPT = `
   105  	(o instanceof Object) && !(o instanceof Error);
   106  	`
   107  	r := New()
   108  	r.Set("o", map[string]interface{}{})
   109  	v, err := r.RunString(SCRIPT)
   110  	if err != nil {
   111  		t.Fatal(err)
   112  	}
   113  
   114  	if !v.StrictEquals(valueTrue) {
   115  		t.Fatalf("Expected true, got %v", v)
   116  	}
   117  }
   118  
   119  func TestGomapTypeOf(t *testing.T) {
   120  	const SCRIPT = `
   121  	typeof o;
   122  	`
   123  	r := New()
   124  	r.Set("o", map[string]interface{}{})
   125  	v, err := r.RunString(SCRIPT)
   126  	if err != nil {
   127  		t.Fatal(err)
   128  	}
   129  
   130  	if !v.StrictEquals(asciiString("object")) {
   131  		t.Fatalf("Expected object, got %v", v)
   132  	}
   133  }
   134  
   135  func TestGomapProto(t *testing.T) {
   136  	const SCRIPT = `
   137  	o.hasOwnProperty("test");
   138  	`
   139  	r := New()
   140  	r.Set("o", map[string]interface{}{
   141  		"test": 42,
   142  	})
   143  	v, err := r.RunString(SCRIPT)
   144  	if err != nil {
   145  		t.Fatal(err)
   146  	}
   147  
   148  	if !v.StrictEquals(valueTrue) {
   149  		t.Fatalf("Expected true, got %v", v)
   150  	}
   151  }
   152  
   153  func TestGoMapExtensibility(t *testing.T) {
   154  	const SCRIPT = `
   155  	"use strict";
   156  	o.test = 42;
   157  	Object.preventExtensions(o);
   158  	o.test = 43;
   159  	try {
   160  		o.test1 = 42;
   161  	} catch (e) {
   162  		if (!(e instanceof TypeError)) {
   163  			throw e;
   164  		}
   165  	}
   166  	o.test === 43 && o.test1 === undefined;
   167  	`
   168  
   169  	r := New()
   170  	r.Set("o", map[string]interface{}{})
   171  	v, err := r.RunString(SCRIPT)
   172  	if err != nil {
   173  		if ex, ok := err.(*Exception); ok {
   174  			t.Fatal(ex.String())
   175  		} else {
   176  			t.Fatal(err)
   177  		}
   178  	}
   179  
   180  	if !v.StrictEquals(valueTrue) {
   181  		t.Fatalf("Expected true, got %v", v)
   182  	}
   183  
   184  }
   185  
   186  func TestGoMapWithProto(t *testing.T) {
   187  	vm := New()
   188  	m := map[string]interface{}{
   189  		"t": "42",
   190  	}
   191  	vm.Set("m", m)
   192  	vm.testScriptWithTestLib(`
   193  	(function() {
   194  	'use strict';
   195  	var proto = {};
   196  	var getterAllowed = false;
   197  	var setterAllowed = false;
   198  	var tHolder = "proto t";
   199  	Object.defineProperty(proto, "t", {
   200  		get: function() {
   201  			if (!getterAllowed) throw new Error("getter is called");
   202  			return tHolder;
   203  		},
   204  		set: function(v) {
   205  			if (!setterAllowed) throw new Error("setter is called");
   206  			tHolder = v;
   207  		}
   208  	});
   209  	var t1Holder;
   210  	Object.defineProperty(proto, "t1", {
   211  		get: function() {
   212  			return t1Holder;
   213  		},
   214  		set: function(v) {
   215  			t1Holder = v;
   216  		}
   217  	});
   218  	Object.setPrototypeOf(m, proto);
   219  	assert.sameValue(m.t, "42");
   220  	m.t = 43;
   221  	assert.sameValue(m.t, 43);
   222  	t1Holder = "test";
   223  	assert.sameValue(m.t1, "test");
   224  	m.t1 = "test1";
   225  	assert.sameValue(m.t1, "test1");
   226  	delete m.t;
   227  	getterAllowed = true;
   228  	assert.sameValue(m.t, "proto t", "after delete");
   229  	setterAllowed = true;
   230  	m.t = true;
   231  	assert.sameValue(m.t, true);
   232  	assert.sameValue(tHolder, true);
   233  	Object.preventExtensions(m);
   234  	assert.throws(TypeError, function() {
   235  		m.t2 = 1;
   236  	});
   237  	m.t1 = "test2";
   238  	assert.sameValue(m.t1, "test2");
   239  	})();
   240  	`, _undefined, t)
   241  }
   242  
   243  func TestGoMapProtoProp(t *testing.T) {
   244  	const SCRIPT = `
   245  	(function() {
   246  	"use strict";
   247  	var proto = {};
   248  	Object.defineProperty(proto, "ro", {value: 42});
   249  	Object.setPrototypeOf(m, proto);
   250  	assert.throws(TypeError, function() {
   251  		m.ro = 43;
   252  	});
   253  	Object.defineProperty(m, "ro", {value: 43});
   254  	assert.sameValue(m.ro, 43);
   255  	})();
   256  	`
   257  
   258  	r := New()
   259  	r.Set("m", map[string]interface{}{})
   260  	r.testScriptWithTestLib(SCRIPT, _undefined, t)
   261  }
   262  
   263  func TestGoMapProtoPropChain(t *testing.T) {
   264  	const SCRIPT = `
   265  	(function() {
   266  	"use strict";
   267  	var p1 = Object.create(null);
   268  	m.__proto__ = p1;
   269  	
   270  	Object.defineProperty(p1, "test", {
   271  		value: 42
   272  	});
   273  	
   274  	Object.defineProperty(m, "test", {
   275  		value: 43,
   276  		writable: true,
   277  	});
   278  	var o = Object.create(m);
   279  	o.test = 44;
   280  	assert.sameValue(o.test, 44);
   281  
   282  	var sym = Symbol(true);
   283  	Object.defineProperty(p1, sym, {
   284  		value: 42
   285  	});
   286  	
   287  	Object.defineProperty(m, sym, {
   288  		value: 43,
   289  		writable: true,
   290  	});
   291  	o[sym] = 44;
   292  	assert.sameValue(o[sym], 44);
   293  	})();
   294  	`
   295  
   296  	r := New()
   297  	r.Set("m", map[string]interface{}{})
   298  	r.testScriptWithTestLib(SCRIPT, _undefined, t)
   299  }
   300  
   301  func TestGoMapUnicode(t *testing.T) {
   302  	const SCRIPT = `
   303  	Object.setPrototypeOf(m, s);
   304  	if (m.Тест !== "passed") {
   305  		throw new Error("m.Тест: " + m.Тест);
   306  	}
   307  	m["é"];
   308  	`
   309  	type S struct {
   310  		Тест string
   311  	}
   312  	vm := New()
   313  	m := map[string]interface{}{
   314  		"é": 42,
   315  	}
   316  	s := S{
   317  		Тест: "passed",
   318  	}
   319  	vm.Set("m", m)
   320  	vm.Set("s", &s)
   321  	res, err := vm.RunString(SCRIPT)
   322  	if err != nil {
   323  		t.Fatal(err)
   324  	}
   325  	if res == nil || !res.StrictEquals(valueInt(42)) {
   326  		t.Fatalf("Unexpected value: %v", res)
   327  	}
   328  }