From bef77dc1448202dd47e53c2d614faac2e3ce1766 Mon Sep 17 00:00:00 2001
From: Valerie R Young <valerie@bocoup.com>
Date: Wed, 1 Nov 2017 21:59:11 -0400
Subject: [PATCH] classfields: PrivateFieldSet and PrivateFieldGet

---
 .../class/privatefieldget-success-1.js        | 46 +++++++++++++++
 .../class/privatefieldget-success-2.js        | 44 ++++++++++++++
 .../class/privatefieldget-success-3.js        | 41 +++++++++++++
 .../class/privatefieldget-success-4.js        | 40 +++++++++++++
 .../class/privatefieldget-success-5.js        | 40 +++++++++++++
 .../class/privatefieldget-typeerror-1.js      | 39 ++++++++++++
 .../class/privatefieldget-typeerror-2.js      | 55 +++++++++++++++++
 .../class/privatefieldget-typeerror-3.js      | 55 +++++++++++++++++
 .../class/privatefieldget-typeerror-4.js      | 53 +++++++++++++++++
 .../class/privatefieldget-typeerror-5.js      | 58 ++++++++++++++++++
 .../class/privatefieldset-typeerror-1.js      | 39 ++++++++++++
 .../class/privatefieldset-typeerror-2.js      | 55 +++++++++++++++++
 .../class/privatefieldset-typeerror-3.js      | 55 +++++++++++++++++
 .../class/privatefieldset-typeerror-4.js      | 53 +++++++++++++++++
 .../class/privatefieldset-typeerror-5.js      | 59 +++++++++++++++++++
 15 files changed, 732 insertions(+)
 create mode 100644 test/language/statements/class/privatefieldget-success-1.js
 create mode 100644 test/language/statements/class/privatefieldget-success-2.js
 create mode 100644 test/language/statements/class/privatefieldget-success-3.js
 create mode 100644 test/language/statements/class/privatefieldget-success-4.js
 create mode 100644 test/language/statements/class/privatefieldget-success-5.js
 create mode 100644 test/language/statements/class/privatefieldget-typeerror-1.js
 create mode 100644 test/language/statements/class/privatefieldget-typeerror-2.js
 create mode 100644 test/language/statements/class/privatefieldget-typeerror-3.js
 create mode 100644 test/language/statements/class/privatefieldget-typeerror-4.js
 create mode 100644 test/language/statements/class/privatefieldget-typeerror-5.js
 create mode 100644 test/language/statements/class/privatefieldset-typeerror-1.js
 create mode 100644 test/language/statements/class/privatefieldset-typeerror-2.js
 create mode 100644 test/language/statements/class/privatefieldset-typeerror-3.js
 create mode 100644 test/language/statements/class/privatefieldset-typeerror-4.js
 create mode 100644 test/language/statements/class/privatefieldset-typeerror-5.js

diff --git a/test/language/statements/class/privatefieldget-success-1.js b/test/language/statements/class/privatefieldget-success-1.js
new file mode 100644
index 0000000000..73836bd040
--- /dev/null
+++ b/test/language/statements/class/privatefieldget-success-1.js
@@ -0,0 +1,46 @@
+// Copyright (C) 2017 Valerie Young. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: Successfully access private field
+esid: sec-getvalue
+info: |
+  GetValue ( V )
+    ...
+    5. If IsPropertyReference(V), then
+        ...
+        b. If IsPrivateReference(V), then
+            i. Let env be the running execution context's PrivateNameEnvironment.
+            ii. Let field be ? ResolveBinding(GetReferencedName(V), env).
+            iii. Assert: field is a Private Name.
+            iv. Return ? PrivateFieldGet(field, base).
+
+  PrivateFieldGet (P, O )
+    1. Assert: P is a Private Name value.
+    2. If O is not an object, throw a TypeError exception.
+    3. Let entry be PrivateFieldFind(P, O).
+    4. If entry is empty, throw a TypeError exception.
+    5. Return entry.[[PrivateFieldValue]].
+
+features: [class-fields]
+---*/
+
+class Outer {
+  #x = 42;
+
+  innerclass() {
+    var self = this;
+
+    return class extends Outer {
+      f() {
+        return self.#x;
+      }
+    }
+  }
+}
+
+var Inner = new Outer().innerclass();
+var i = new Inner();
+var value = i.f();
+
+assert.sameValue(value, 42)
diff --git a/test/language/statements/class/privatefieldget-success-2.js b/test/language/statements/class/privatefieldget-success-2.js
new file mode 100644
index 0000000000..adc4e9a10f
--- /dev/null
+++ b/test/language/statements/class/privatefieldget-success-2.js
@@ -0,0 +1,44 @@
+// Copyright (C) 2017 Valerie Young. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: Successfully access private field
+esid: sec-getvalue
+info: |
+  GetValue ( V )
+    ...
+    5. If IsPropertyReference(V), then
+        ...
+        b. If IsPrivateReference(V), then
+            i. Let env be the running execution context's PrivateNameEnvironment.
+            ii. Let field be ? ResolveBinding(GetReferencedName(V), env).
+            iii. Assert: field is a Private Name.
+            iv. Return ? PrivateFieldGet(field, base).
+
+  PrivateFieldGet (P, O )
+    1. Assert: P is a Private Name value.
+    2. If O is not an object, throw a TypeError exception.
+    3. Let entry be PrivateFieldFind(P, O).
+    4. If entry is empty, throw a TypeError exception.
+    5. Return entry.[[PrivateFieldValue]].
+
+features: [class-fields]
+---*/
+
+
+class A {
+  #x = 'Avalue';
+  x() {
+    return this.#x;
+  }
+}
+class B extends A {
+  #x = 'Bvalue';
+  x() {
+    return this.#x;
+  }
+}
+
+var b = new B();
+
+assert.sameValue(b.x(), 'Bvalue')
diff --git a/test/language/statements/class/privatefieldget-success-3.js b/test/language/statements/class/privatefieldget-success-3.js
new file mode 100644
index 0000000000..d9722f5639
--- /dev/null
+++ b/test/language/statements/class/privatefieldget-success-3.js
@@ -0,0 +1,41 @@
+// Copyright (C) 2017 Valerie Young. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: Successfully access private field
+esid: sec-getvalue
+info: |
+  GetValue ( V )
+    ...
+    5. If IsPropertyReference(V), then
+        ...
+        b. If IsPrivateReference(V), then
+            i. Let env be the running execution context's PrivateNameEnvironment.
+            ii. Let field be ? ResolveBinding(GetReferencedName(V), env).
+            iii. Assert: field is a Private Name.
+            iv. Return ? PrivateFieldGet(field, base).
+
+  PrivateFieldGet (P, O )
+    1. Assert: P is a Private Name value.
+    2. If O is not an object, throw a TypeError exception.
+    3. Let entry be PrivateFieldFind(P, O).
+    4. If entry is empty, throw a TypeError exception.
+    5. Return entry.[[PrivateFieldValue]].
+
+features: [class-fields]
+---*/
+
+
+class A {
+  #x = 'Avalue';
+  x() {
+    return this.#x;
+  }
+}
+class B extends A {
+  #x = 'Bvalue';
+}
+
+var b = new B();
+
+assert.sameValue(b.x(), 'Avalue')
diff --git a/test/language/statements/class/privatefieldget-success-4.js b/test/language/statements/class/privatefieldget-success-4.js
new file mode 100644
index 0000000000..7253d32f1c
--- /dev/null
+++ b/test/language/statements/class/privatefieldget-success-4.js
@@ -0,0 +1,40 @@
+// Copyright (C) 2017 Valerie Young. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: Successfully access private field
+esid: sec-getvalue
+info: |
+  GetValue ( V )
+    ...
+    5. If IsPropertyReference(V), then
+        ...
+        b. If IsPrivateReference(V), then
+            i. Let env be the running execution context's PrivateNameEnvironment.
+            ii. Let field be ? ResolveBinding(GetReferencedName(V), env).
+            iii. Assert: field is a Private Name.
+            iv. Return ? PrivateFieldGet(field, base).
+
+  PrivateFieldGet (P, O )
+    1. Assert: P is a Private Name value.
+    2. If O is not an object, throw a TypeError exception.
+    3. Let entry be PrivateFieldFind(P, O).
+    4. If entry is empty, throw a TypeError exception.
+    5. Return entry.[[PrivateFieldValue]].
+
+features: [class-fields]
+---*/
+
+
+class A {
+  #x = 'Avalue';
+  x() {
+    return this.#x;
+  }
+}
+class B extends A {
+}
+
+var b = new B();
+
+assert.sameValue(b.x(), 'Avalue')
diff --git a/test/language/statements/class/privatefieldget-success-5.js b/test/language/statements/class/privatefieldget-success-5.js
new file mode 100644
index 0000000000..9bf09e9ea4
--- /dev/null
+++ b/test/language/statements/class/privatefieldget-success-5.js
@@ -0,0 +1,40 @@
+// Copyright (C) 2017 Valerie Young. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: Successfully access private field
+esid: sec-getvalue
+info: |
+  GetValue ( V )
+    ...
+    5. If IsPropertyReference(V), then
+        ...
+        b. If IsPrivateReference(V), then
+            i. Let env be the running execution context's PrivateNameEnvironment.
+            ii. Let field be ? ResolveBinding(GetReferencedName(V), env).
+            iii. Assert: field is a Private Name.
+            iv. Return ? PrivateFieldGet(field, base).
+
+  PrivateFieldGet (P, O )
+    1. Assert: P is a Private Name value.
+    2. If O is not an object, throw a TypeError exception.
+    3. Let entry be PrivateFieldFind(P, O).
+    4. If entry is empty, throw a TypeError exception.
+    5. Return entry.[[PrivateFieldValue]].
+
+features: [class-fields]
+---*/
+
+
+class C {
+  #x = 42;
+  f() {
+    return this.#x;
+  }
+}
+
+var c1 = new C();
+var c2 = new C();
+var value = c2.f.call(c1);
+
+assert.sameValue(value, 'Avalue');
diff --git a/test/language/statements/class/privatefieldget-typeerror-1.js b/test/language/statements/class/privatefieldget-typeerror-1.js
new file mode 100644
index 0000000000..1f1f201449
--- /dev/null
+++ b/test/language/statements/class/privatefieldget-typeerror-1.js
@@ -0,0 +1,39 @@
+// Copyright (C) 2017 Valerie Young. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: Cannot access private field before the entry was added to [[PrivateFieldValues]]
+esid: sec-getvalue
+info: |
+  GetValue ( V )
+    ...
+    5. If IsPropertyReference(V), then
+        ...
+        b. If IsPrivateReference(V), then
+            i. Let env be the running execution context's PrivateNameEnvironment.
+            ii. Let field be ? ResolveBinding(GetReferencedName(V), env).
+            iii. Assert: field is a Private Name.
+            iv. Return ? PrivateFieldGet(field, base).
+
+  PrivateFieldGet (P, O )
+    1. Assert: P is a Private Name value.
+    2. If O is not an object, throw a TypeError exception.
+    3. Let entry be PrivateFieldFind(P, O).
+    4. If entry is empty, throw a TypeError exception.
+
+  PrivateFieldFind (P, O)
+    1. Assert: P is a Private Name value.
+    2. Assert: O is an object with a [[PrivateFieldValues]] internal slot.
+    3. For each element entry in O.[[PrivateFieldValues]],
+      a. If entry.[[PrivateName]] is P, return entry.
+    4. Return empty.
+
+features: [class-fields]
+---*/
+
+class C {
+  y = this.#x;
+  #x;
+}
+
+assert.throws(TypeError, function() { new C(); })
diff --git a/test/language/statements/class/privatefieldget-typeerror-2.js b/test/language/statements/class/privatefieldget-typeerror-2.js
new file mode 100644
index 0000000000..4a5f6be656
--- /dev/null
+++ b/test/language/statements/class/privatefieldget-typeerror-2.js
@@ -0,0 +1,55 @@
+// Copyright (C) 2017 Valerie Young. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: TypeError when referenced private field cannot be found in `this`'s [[PrivateFieldValues]]
+esid: sec-getvalue
+info: |
+  GetValue ( V )
+    ...
+    5. If IsPropertyReference(V), then
+        ...
+        b. If IsPrivateReference(V), then
+            i. Let env be the running execution context's PrivateNameEnvironment.
+            ii. Let field be ? ResolveBinding(GetReferencedName(V), env).
+            iii. Assert: field is a Private Name.
+            iv. Return ? PrivateFieldGet(field, base).
+
+  PrivateFieldGet (P, O )
+    1. Assert: P is a Private Name value.
+    2. If O is not an object, throw a TypeError exception.
+    3. Let entry be PrivateFieldFind(P, O).
+    4. If entry is empty, throw a TypeError exception.
+
+  PrivateFieldFind (P, O)
+    1. Assert: P is a Private Name value.
+    2. Assert: O is an object with a [[PrivateFieldValues]] internal slot.
+    3. For each element entry in O.[[PrivateFieldValues]],
+      a. If entry.[[PrivateName]] is P, return entry.
+    4. Return empty.
+
+features: [class-fields]
+---*/
+
+class Outer {
+  #x = 42;
+
+  innerclass() {
+
+    // create class within in Outerclass -- the PrivateNameEnvironment binding for
+    // private field `#x` is resolvable.
+    return class {
+      f() {
+	return this.#x;
+      }
+    }
+  }
+}
+
+var Inner = new Outer().innerclass();
+var i = new Inner();
+
+assert.throws(TypeError, function() {
+  // when f() is called, the private field will not be found in Inner's `this`
+  i.f();
+})
diff --git a/test/language/statements/class/privatefieldget-typeerror-3.js b/test/language/statements/class/privatefieldget-typeerror-3.js
new file mode 100644
index 0000000000..8c1ef2748b
--- /dev/null
+++ b/test/language/statements/class/privatefieldget-typeerror-3.js
@@ -0,0 +1,55 @@
+// Copyright (C) 2017 Valerie Young. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: TypeError when referenced private field cannot be found in `this`'s [[PrivateFieldValues]]
+esid: sec-getvalue
+info: |
+  GetValue ( V )
+    ...
+    5. If IsPropertyReference(V), then
+        ...
+        b. If IsPrivateReference(V), then
+            i. Let env be the running execution context's PrivateNameEnvironment.
+            ii. Let field be ? ResolveBinding(GetReferencedName(V), env).
+            iii. Assert: field is a Private Name.
+            iv. Return ? PrivateFieldGet(field, base).
+
+  PrivateFieldGet (P, O )
+    1. Assert: P is a Private Name value.
+    2. If O is not an object, throw a TypeError exception.
+    3. Let entry be PrivateFieldFind(P, O).
+    4. If entry is empty, throw a TypeError exception.
+
+  PrivateFieldFind (P, O)
+    1. Assert: P is a Private Name value.
+    2. Assert: O is an object with a [[PrivateFieldValues]] internal slot.
+    3. For each element entry in O.[[PrivateFieldValues]],
+      a. If entry.[[PrivateName]] is P, return entry.
+    4. Return empty.
+
+features: [class-fields]
+---*/
+
+class Outer {
+  #x = 42;
+
+  innerclass() {
+
+    // create class within in Outerclass -- the PrivateNameEnvironment binding for
+    // private field `#x` is resolvable.
+    return class extends Outer {
+      f() {
+	return this.#x;
+      }
+    }
+  }
+}
+
+var Inner = new Outer().innerclass();
+var i = new Inner();
+
+assert.throws(TypeError, function() {
+  // when f() is called, the private field will not be found in Inner's `this`
+  i.f();
+})
diff --git a/test/language/statements/class/privatefieldget-typeerror-4.js b/test/language/statements/class/privatefieldget-typeerror-4.js
new file mode 100644
index 0000000000..61f2d3a78d
--- /dev/null
+++ b/test/language/statements/class/privatefieldget-typeerror-4.js
@@ -0,0 +1,53 @@
+// Copyright (C) 2017 Valerie Young. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: TypeError when referenced private field cannot be found in `this`'s [[PrivateFieldValues]]
+esid: sec-getvalue
+info: |
+  GetValue ( V )
+    ...
+    5. If IsPropertyReference(V), then
+      ...
+      b. If IsPrivateReference(V), then
+        i. Let env be the running execution context's PrivateNameEnvironment.
+        ii. Let field be ? ResolveBinding(GetReferencedName(V), env).
+        iii. Assert: field is a Private Name.
+        iv. Return ? PrivateFieldGet(field, base).
+
+  PrivateFieldGet (P, O )
+    1. Assert: P is a Private Name value.
+    2. If O is not an object, throw a TypeError exception.
+    3. Let entry be PrivateFieldFind(P, O).
+    4. If entry is empty, throw a TypeError exception.
+
+  PrivateFieldFind (P, O)
+    1. Assert: P is a Private Name value.
+    2. Assert: O is an object with a [[PrivateFieldValues]] internal slot.
+    3. For each element entry in O.[[PrivateFieldValues]],
+      a. If entry.[[PrivateName]] is P, return entry.
+    4. Return empty.
+
+features: [class-fields]
+---*/
+
+function classfactory() {
+  return class {
+    #x;
+    f() {
+      this.#x;
+    }
+  }
+}
+
+var C1 = classfactory();
+var C2 = classfactory();
+
+c1 = new C1();
+c2 = new C2();
+
+assert.throws(TypeError, function() {
+  // when f() is called in class C1, the Private Name binding for #x in C1 will
+  // not found in C2's [[PrivateNameValues]]
+  c1.f.call(c2);
+})
diff --git a/test/language/statements/class/privatefieldget-typeerror-5.js b/test/language/statements/class/privatefieldget-typeerror-5.js
new file mode 100644
index 0000000000..ff1f3737c1
--- /dev/null
+++ b/test/language/statements/class/privatefieldget-typeerror-5.js
@@ -0,0 +1,58 @@
+// Copyright (C) 2017 Valerie Young. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: TypeError when referenced private field cannot be found in `this`'s [[PrivateFieldValues]]
+esid: sec-getvalue
+info: |
+  GetValue ( V )
+    ...
+    5. If IsPropertyReference(V), then
+      ...
+      b. If IsPrivateReference(V), then
+        i. Let env be the running execution context's PrivateNameEnvironment.
+        ii. Let field be ? ResolveBinding(GetReferencedName(V), env).
+        iii. Assert: field is a Private Name.
+        iv. Return ? PrivateFieldGet(field, base).
+
+  PrivateFieldGet (P, O )
+    1. Assert: P is a Private Name value.
+    2. If O is not an object, throw a TypeError exception.
+    3. Let entry be PrivateFieldFind(P, O).
+    4. If entry is empty, throw a TypeError exception.
+
+  PrivateFieldFind (P, O)
+    1. Assert: P is a Private Name value.
+    2. Assert: O is an object with a [[PrivateFieldValues]] internal slot.
+    3. For each element entry in O.[[PrivateFieldValues]],
+      a. If entry.[[PrivateName]] is P, return entry.
+    4. Return empty.
+
+features: [class-fields]
+---*/
+
+class Outer {
+  #x = 42;
+
+  innerclass() {
+    var self = this;
+
+    return class extends Outer {
+      #x = 'not42';
+      f() {
+	return self.#x;
+      }
+    }
+  }
+}
+
+var Inner = new Outer().innerclass();
+var i = new Inner();
+
+assert.throws(TypeError, function() {
+  // when f() is called, the entry in the PrivateNameEnironment's environment
+  // record for '#x' will contain the Inner class's Private Name for '#x'.
+  // When this Private Name is used for lookup on the `self` object, it
+  // will not be found (as the `self` object has the Outer's Private Name for #x)
+  i.f();
+})
diff --git a/test/language/statements/class/privatefieldset-typeerror-1.js b/test/language/statements/class/privatefieldset-typeerror-1.js
new file mode 100644
index 0000000000..ddd1a3f199
--- /dev/null
+++ b/test/language/statements/class/privatefieldset-typeerror-1.js
@@ -0,0 +1,39 @@
+// Copyright (C) 2017 Valerie Young. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: TypeError when setting private field before the entry was added to [[PrivateFieldValues]]
+esid: sec-putvalue
+info: |
+  PutValue ( V, W )
+    ...
+    5. Else if IsPropertyReference(V), then
+      ...
+      b. If IsPrivateReference(V), then
+        i. Let env be the running execution context's PrivateNameEnvironment.
+        ii. Let field be ? ResolveBinding(GetReferencedName(V), env).
+        iii. Assert: field is a Private Name.
+        iv. Perform ? PrivateFieldSet(field, base, W).
+
+  PrivateFieldSet (P, O, value )
+    1. Assert: P is a Private Name value.
+    2. If O is not an object, throw a TypeError exception.
+    3. Let entry be PrivateFieldFind(P, O).
+    4. If entry is empty, throw a TypeError exception.
+
+  PrivateFieldFind (P, O)
+    1. Assert: P is a Private Name value.
+    2. Assert: O is an object with a [[PrivateFieldValues]] internal slot.
+    3. For each element entry in O.[[PrivateFieldValues]],
+      a. If entry.[[PrivateName]] is P, return entry.
+    4. Return empty.
+
+features: [class-fields]
+---*/
+
+class C {
+  y = this.#x = 1;
+  #x;
+}
+
+assert.throws(TypeError, function() { new C(); })
diff --git a/test/language/statements/class/privatefieldset-typeerror-2.js b/test/language/statements/class/privatefieldset-typeerror-2.js
new file mode 100644
index 0000000000..8f83e513ea
--- /dev/null
+++ b/test/language/statements/class/privatefieldset-typeerror-2.js
@@ -0,0 +1,55 @@
+// Copyright (C) 2017 Valerie Young. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: TypeError when setting private field not in `this`'s [[PrivateFieldValues]]
+esid: sec-putvalue
+info: |
+  PutValue ( V, W )
+    ...
+    5. Else if IsPropertyReference(V), then
+      ...
+      b. If IsPrivateReference(V), then
+        i. Let env be the running execution context's PrivateNameEnvironment.
+        ii. Let field be ? ResolveBinding(GetReferencedName(V), env).
+        iii. Assert: field is a Private Name.
+        iv. Perform ? PrivateFieldSet(field, base, W).
+
+  PrivateFieldSet (P, O, value )
+    1. Assert: P is a Private Name value.
+    2. If O is not an object, throw a TypeError exception.
+    3. Let entry be PrivateFieldFind(P, O).
+    4. If entry is empty, throw a TypeError exception.
+
+  PrivateFieldFind (P, O)
+    1. Assert: P is a Private Name value.
+    2. Assert: O is an object with a [[PrivateFieldValues]] internal slot.
+    3. For each element entry in O.[[PrivateFieldValues]],
+      a. If entry.[[PrivateName]] is P, return entry.
+    4. Return empty.
+
+features: [class-fields]
+---*/
+
+class Outer {
+  #x = 42;
+
+  innerclass() {
+
+    // create class within in Outerclass -- the PrivateNameEnvironment binding for
+    // private field `#x` is resolvable.
+    return class {
+      f() {
+	this.#x = 1;
+      }
+    }
+  }
+}
+
+var Inner = new Outer().innerclass();
+var i = new Inner();
+
+assert.throws(TypeError, function() {
+  // when f() is called, the private field will not be found in Inner's `this`
+  i.f();
+})
diff --git a/test/language/statements/class/privatefieldset-typeerror-3.js b/test/language/statements/class/privatefieldset-typeerror-3.js
new file mode 100644
index 0000000000..4a0bfabd90
--- /dev/null
+++ b/test/language/statements/class/privatefieldset-typeerror-3.js
@@ -0,0 +1,55 @@
+// Copyright (C) 2017 Valerie Young. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: TypeError when setting private field not in `this`'s [[PrivateFieldValues]]
+esid: sec-putvalue
+info: |
+  PutValue ( V, W )
+    ...
+    5. Else if IsPropertyReference(V), then
+      ...
+      b. If IsPrivateReference(V), then
+        i. Let env be the running execution context's PrivateNameEnvironment.
+        ii. Let field be ? ResolveBinding(GetReferencedName(V), env).
+        iii. Assert: field is a Private Name.
+        iv. Perform ? PrivateFieldSet(field, base, W).
+
+  PrivateFieldSet (P, O, value )
+    1. Assert: P is a Private Name value.
+    2. If O is not an object, throw a TypeError exception.
+    3. Let entry be PrivateFieldFind(P, O).
+    4. If entry is empty, throw a TypeError exception.
+
+  PrivateFieldFind (P, O)
+    1. Assert: P is a Private Name value.
+    2. Assert: O is an object with a [[PrivateFieldValues]] internal slot.
+    3. For each element entry in O.[[PrivateFieldValues]],
+      a. If entry.[[PrivateName]] is P, return entry.
+    4. Return empty.
+
+features: [class-fields]
+---*/
+
+class Outer {
+  #x = 42;
+
+  innerclass() {
+
+    // create class within in Outerclass -- the PrivateNameEnvironment binding for
+    // private field `#x` is resolvable.
+    return class extends Outer {
+      f() {
+	this.#x = 1;
+      }
+    }
+  }
+}
+
+var Inner = new Outer().innerclass();
+var i = new Inner();
+
+assert.throws(TypeError, function() {
+  // when f() is called, the private field will not be found in Inner's `this`
+  i.f();
+})
diff --git a/test/language/statements/class/privatefieldset-typeerror-4.js b/test/language/statements/class/privatefieldset-typeerror-4.js
new file mode 100644
index 0000000000..d3dc0ab966
--- /dev/null
+++ b/test/language/statements/class/privatefieldset-typeerror-4.js
@@ -0,0 +1,53 @@
+// Copyright (C) 2017 Valerie Young. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: TypeError when setting private field not in `this`'s [[PrivateFieldValues]]
+esid: sec-putvalue
+info: |
+  PutValue ( V, W )
+    ...
+    5. Else if IsPropertyReference(V), then
+      ...
+      b. If IsPrivateReference(V), then
+        i. Let env be the running execution context's PrivateNameEnvironment.
+        ii. Let field be ? ResolveBinding(GetReferencedName(V), env).
+        iii. Assert: field is a Private Name.
+        iv. Perform ? PrivateFieldSet(field, base, W).
+
+  PrivateFieldSet (P, O, value )
+    1. Assert: P is a Private Name value.
+    2. If O is not an object, throw a TypeError exception.
+    3. Let entry be PrivateFieldFind(P, O).
+    4. If entry is empty, throw a TypeError exception.
+
+  PrivateFieldFind (P, O)
+    1. Assert: P is a Private Name value.
+    2. Assert: O is an object with a [[PrivateFieldValues]] internal slot.
+    3. For each element entry in O.[[PrivateFieldValues]],
+      a. If entry.[[PrivateName]] is P, return entry.
+    4. Return empty.
+
+features: [class-fields]
+---*/
+
+function classfactory() {
+  return class {
+    #x;
+    f() {
+      this.#x = 1;
+    }
+  }
+}
+
+var C1 = classfactory();
+var C2 = classfactory();
+
+c1 = new C1();
+c2 = new C2();
+
+assert.throws(TypeError, function() {
+  // when f() is called in class C1, the Private Name binding for #x in C1 will
+  // not found in C2's [[PrivateNameValues]]
+  c1.f.call(c2);
+})
diff --git a/test/language/statements/class/privatefieldset-typeerror-5.js b/test/language/statements/class/privatefieldset-typeerror-5.js
new file mode 100644
index 0000000000..7ccdc75e85
--- /dev/null
+++ b/test/language/statements/class/privatefieldset-typeerror-5.js
@@ -0,0 +1,59 @@
+// Copyright (C) 2017 Valerie Young. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+description: TypeError when setting private field not in `this`'s [[PrivateFieldValues]]
+esid: sec-putvalue
+info: |
+  PutValue ( V, W )
+    ...
+    5. Else if IsPropertyReference(V), then
+      ...
+      b. If IsPrivateReference(V), then
+        i. Let env be the running execution context's PrivateNameEnvironment.
+        ii. Let field be ? ResolveBinding(GetReferencedName(V), env).
+        iii. Assert: field is a Private Name.
+        iv. Perform ? PrivateFieldSet(field, base, W).
+
+  PrivateFieldSet (P, O, value )
+    1. Assert: P is a Private Name value.
+    2. If O is not an object, throw a TypeError exception.
+    3. Let entry be PrivateFieldFind(P, O).
+    4. If entry is empty, throw a TypeError exception.
+
+  PrivateFieldFind (P, O)
+    1. Assert: P is a Private Name value.
+    2. Assert: O is an object with a [[PrivateFieldValues]] internal slot.
+    3. For each element entry in O.[[PrivateFieldValues]],
+      a. If entry.[[PrivateName]] is P, return entry.
+    4. Return empty.
+
+features: [class-fields]
+---*/
+
+
+class Outer {
+  #x = 42;
+
+  innerclass() {
+    var self = this;
+
+    return class extends Outer {
+      #x = 'not42';
+      f() {
+	self.#x = 1;
+      }
+    }
+  }
+}
+
+var Inner = new Outer().innerclass();
+var i = new Inner();
+
+assert.throws(TypeError, function() {
+  // when f() is called, the entry in the PrivateNameEnironment's environment
+  // record for '#x' will contain the Inner class's Private Name for '#x'.
+  // When this Private Name is used for lookup on the `self` object, it
+  // will not be found (as the `self` object has the Outer's Private Name for #x)
+  i.f();
+})
-- 
GitLab