Pārlūkot izejas kodu

Merge branch 'master' into es6

Dmitry Panov 5 gadi atpakaļ
vecāks
revīzija
98bf47ee8f
4 mainītis faili ar 40 papildinājumiem un 5 dzēšanām
  1. 2 1
      README.md
  2. 1 4
      compiler_stmt.go
  3. 16 0
      compiler_test.go
  4. 21 0
      object_goreflect_test.go

+ 2 - 1
README.md

@@ -124,7 +124,8 @@ A map type with methods is converted into a host object where properties are met
 the map values are not accessible. This is to avoid ambiguity between m\["Property"\] and m.Property.
 the map values are not accessible. This is to avoid ambiguity between m\["Property"\] and m.Property.
 
 
 Any other type is converted to a generic reflect based host object. Depending on the underlying type it behaves similar
 Any other type is converted to a generic reflect based host object. Depending on the underlying type it behaves similar
-to a Number, String, Boolean or Object.
+to a Number, String, Boolean or Object. This includes pointers to primitive types (*string, *int, etc...).
+Internally they remain pointers, so changes to the pointed values will be reflected in JS.
 
 
 Note that these conversions wrap the original value which means any changes made inside JS
 Note that these conversions wrap the original value which means any changes made inside JS
 are reflected on the value and calling Export() returns the original value. This applies to all
 are reflected on the value and calling Export() returns the original value. This applies to all

+ 1 - 4
compiler_stmt.go

@@ -146,13 +146,10 @@ func (c *compiler) compileTryStatement(v *ast.TryStatement) {
 					code[pc] = setLocalP(remap(uint32(instr)))
 					code[pc] = setLocalP(remap(uint32(instr)))
 				}
 				}
 			}
 			}
+			c.p.code[start+1] = pop
 			if catchVarIdx, exists := m[0]; exists {
 			if catchVarIdx, exists := m[0]; exists {
 				c.p.code[start] = setLocal(catchVarIdx)
 				c.p.code[start] = setLocal(catchVarIdx)
-				c.p.code[start+1] = pop
 				catchOffset--
 				catchOffset--
-			} else {
-				c.p.code[start+1] = nil
-				catchOffset++
 			}
 			}
 		} else {
 		} else {
 			c.scope.accessed = true
 			c.scope.accessed = true

+ 16 - 0
compiler_test.go

@@ -2081,6 +2081,22 @@ func TestEvalCallee(t *testing.T) {
 	testScript1(SCRIPT, valueTrue, t)
 	testScript1(SCRIPT, valueTrue, t)
 }
 }
 
 
+func TestTryEmptyCatchStackLeak(t *testing.T) {
+	const SCRIPT = `
+	(function() {
+		var f;
+		// Make sure the outer function is not stashless as retStashless masks all stack leaks.
+		(function() {
+			f++;
+		})();
+		try {
+			throw new Error();
+		} catch(e) {}
+	})();
+	`
+	testScript1(SCRIPT, _undefined, t)
+}
+
 // FIXME
 // FIXME
 /*
 /*
 func TestDummyCompile(t *testing.T) {
 func TestDummyCompile(t *testing.T) {

+ 21 - 0
object_goreflect_test.go

@@ -968,6 +968,27 @@ func TestTagFieldNameMapperInvalidId(t *testing.T) {
 	}
 	}
 }
 }
 
 
+func TestPrimitivePtr(t *testing.T) {
+	vm := New()
+	s := "test"
+	vm.Set("s", &s)
+	res, err := vm.RunString(`s instanceof String && s == "test"`) // note non-strict equality
+	if err != nil {
+		t.Fatal(err)
+	}
+	if v := res.ToBoolean(); !v {
+		t.Fatalf("value: %#v", res)
+	}
+	s = "test1"
+	res, err = vm.RunString(`s == "test1"`)
+	if err != nil {
+		t.Fatal(err)
+	}
+	if v := res.ToBoolean(); !v {
+		t.Fatalf("value: %#v", res)
+	}
+}
+
 func ExampleTagFieldNameMapper() {
 func ExampleTagFieldNameMapper() {
 	vm := New()
 	vm := New()
 	vm.SetFieldNameMapper(TagFieldNameMapper("json", true))
 	vm.SetFieldNameMapper(TagFieldNameMapper("json", true))