add error stack accessor tests
diff --git a/features.txt b/features.txt
index 3aa05db..4acec76 100644
--- a/features.txt
+++ b/features.txt
@@ -93,6 +93,10 @@
 # https://github.com/tc39/proposal-await-dictionary
 await-dictionary
 
+# Error Stack Accessor
+# https://github.com/tc39/proposal-error-stack-accessor
+error-stack-accessor
+
 ## Standard language features
 #
 # Language features that have been included in a published version of the
diff --git a/test/built-ins/Error/prototype/stack/getter-aggregate-error-prototype.js b/test/built-ins/Error/prototype/stack/getter-aggregate-error-prototype.js
new file mode 100644
index 0000000..1029426
--- /dev/null
+++ b/test/built-ins/Error/prototype/stack/getter-aggregate-error-prototype.js
@@ -0,0 +1,21 @@
+// Copyright (C) 2026 Jordan Harband. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-get-error.prototype.stack
+description: >
+  The getter returns undefined when called on AggregateError.prototype, which
+  is an ordinary object that does not have an [[ErrorData]] internal slot.
+info: |
+  get Error.prototype.stack
+
+  1. Let E be the this value.
+  2. If E is not an Object, throw a TypeError exception.
+  3. If E does not have an [[ErrorData]] internal slot, return undefined.
+  4. Return an implementation-defined string that represents the stack trace of E.
+features: [error-stack-accessor, AggregateError]
+---*/
+
+var get = Object.getOwnPropertyDescriptor(Error.prototype, 'stack').get;
+
+assert.sameValue(get.call(AggregateError.prototype), undefined);
diff --git a/test/built-ins/Error/prototype/stack/getter-aggregate-error.js b/test/built-ins/Error/prototype/stack/getter-aggregate-error.js
new file mode 100644
index 0000000..5539316
--- /dev/null
+++ b/test/built-ins/Error/prototype/stack/getter-aggregate-error.js
@@ -0,0 +1,27 @@
+// Copyright (C) 2026 Jordan Harband. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-get-error.prototype.stack
+description: >
+  The getter returns a String when called on an AggregateError instance.
+info: |
+  get Error.prototype.stack
+
+  1. Let E be the this value.
+  2. If E is not an Object, throw a TypeError exception.
+  3. If E does not have an [[ErrorData]] internal slot, return undefined.
+  4. Return an implementation-defined string that represents the stack trace of E.
+
+  AggregateError instances are ordinary objects that inherit properties from
+  their AggregateError prototype object and have an [[ErrorData]] internal slot
+  whose value is undefined.
+features: [error-stack-accessor, AggregateError]
+---*/
+
+var get = Object.getOwnPropertyDescriptor(Error.prototype, 'stack').get;
+
+var err = new AggregateError([new Error('inner')], 'outer');
+
+assert.sameValue(typeof get.call(err), 'string', 'AggregateError instance via get.call');
+assert.sameValue(typeof err.stack, 'string', 'AggregateError instance via property access');
diff --git a/test/built-ins/Error/prototype/stack/getter-cross-realm.js b/test/built-ins/Error/prototype/stack/getter-cross-realm.js
new file mode 100644
index 0000000..6aabbad
--- /dev/null
+++ b/test/built-ins/Error/prototype/stack/getter-cross-realm.js
@@ -0,0 +1,51 @@
+// Copyright (C) 2026 Jordan Harband. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-get-error.prototype.stack
+description: >
+  The getter's [[ErrorData]] check is realm-agnostic: a getter from realm A
+  invoked on an Error instance from realm B returns a String, since the
+  internal-slot check examines object identity of the slot, not realm origin.
+info: |
+  get Error.prototype.stack
+
+  1. Let E be the this value.
+  2. If E is not an Object, throw a TypeError exception.
+  3. If E does not have an [[ErrorData]] internal slot, return undefined.
+  4. Return an implementation-defined string that represents the stack trace of E.
+features: [error-stack-accessor, cross-realm]
+---*/
+
+var getA = Object.getOwnPropertyDescriptor(Error.prototype, 'stack').get;
+
+var realmB = $262.createRealm().global;
+
+assert.notSameValue(
+  Error.prototype,
+  realmB.Error.prototype,
+  'precondition: the two realms have distinct Error.prototype objects'
+);
+
+// (a) Realm A's getter on a realm B Error instance: the instance has
+// [[ErrorData]], so the getter returns a string regardless of which realm
+// owns the slot.
+var errB = new realmB.Error('msg');
+assert.sameValue(typeof getA.call(errB), 'string', 'cross-realm Error instance returns a string');
+
+// (b) Realm A's getter on a realm B plain object: no [[ErrorData]], returns
+// undefined.
+var plainB = new realmB.Object();
+assert.sameValue(getA.call(plainB), undefined, 'cross-realm plain object returns undefined');
+
+// (c) Realm A's getter on realm B's Error.prototype: the prototype object
+// itself has no [[ErrorData]] slot, so the getter returns undefined.
+assert.sameValue(getA.call(realmB.Error.prototype), undefined, 'cross-realm Error.prototype returns undefined');
+
+// (d) Realm B's getter on a realm A Error instance: same logic in reverse.
+var getB = Object.getOwnPropertyDescriptor(realmB.Error.prototype, 'stack').get;
+assert.sameValue(typeof getB, 'function', 'realm B has its own getter');
+assert.notSameValue(getA, getB, 'the two realms have distinct getter functions');
+
+var errA = new Error('msg');
+assert.sameValue(typeof getB.call(errA), 'string', 'realm B getter on realm A Error instance returns a string');
diff --git a/test/built-ins/Error/prototype/stack/getter-data-property-shadows.js b/test/built-ins/Error/prototype/stack/getter-data-property-shadows.js
new file mode 100644
index 0000000..f23e2cc
--- /dev/null
+++ b/test/built-ins/Error/prototype/stack/getter-data-property-shadows.js
@@ -0,0 +1,46 @@
+// Copyright (C) 2026 Jordan Harband. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-get-error.prototype.stack
+description: >
+  An own data property named "stack" on an Error instance shadows the inherited
+  accessor when accessed via property lookup.
+info: |
+  get Error.prototype.stack
+
+  1. Let E be the this value.
+  2. If E is not an Object, throw a TypeError exception.
+  3. If E does not have an [[ErrorData]] internal slot, return undefined.
+  4. Return an implementation-defined string that represents the stack trace of E.
+features: [error-stack-accessor]
+---*/
+
+var get = Object.getOwnPropertyDescriptor(Error.prototype, 'stack').get;
+
+var nativeErrors = [
+  Error,
+  EvalError,
+  RangeError,
+  ReferenceError,
+  SyntaxError,
+  TypeError,
+  URIError
+];
+
+for (var i = 0; i < nativeErrors.length; ++i) {
+  var Ctor = nativeErrors[i];
+  var err = new Ctor('msg');
+  Object.defineProperty(err, 'stack', {
+    value: 'sentinel',
+    writable: true,
+    enumerable: true,
+    configurable: true,
+  });
+
+  assert.sameValue(err.stack, 'sentinel', Ctor.name + ': own data property is returned by [[Get]]');
+
+  // The inherited accessor still produces a string when invoked directly,
+  // because the algorithm operates on the [[ErrorData]] slot, not on properties.
+  assert.sameValue(typeof get.call(err), 'string', Ctor.name + ': inherited accessor still returns a string');
+}
diff --git a/test/built-ins/Error/prototype/stack/getter-error-as-prototype.js b/test/built-ins/Error/prototype/stack/getter-error-as-prototype.js
new file mode 100644
index 0000000..4f67db0
--- /dev/null
+++ b/test/built-ins/Error/prototype/stack/getter-error-as-prototype.js
@@ -0,0 +1,47 @@
+// Copyright (C) 2026 Jordan Harband. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-get-error.prototype.stack
+description: >
+  An object whose prototype is an Error instance does not itself have an
+  [[ErrorData]] internal slot, so the getter returns undefined. The slot is
+  not inherited through the prototype chain.
+info: |
+  get Error.prototype.stack
+
+  1. Let E be the this value.
+  2. If E is not an Object, throw a TypeError exception.
+  3. If E does not have an [[ErrorData]] internal slot, return undefined.
+  4. Return an implementation-defined string that represents the stack trace of E.
+features: [error-stack-accessor, __proto__]
+---*/
+
+var get = Object.getOwnPropertyDescriptor(Error.prototype, 'stack').get;
+
+var nativeErrors = [
+  Error,
+  EvalError,
+  RangeError,
+  ReferenceError,
+  SyntaxError,
+  TypeError,
+  URIError
+];
+
+for (var i = 0; i < nativeErrors.length; ++i) {
+  var Ctor = nativeErrors[i];
+  var protoErr = new Ctor('outer');
+  var o = { __proto__: protoErr };
+
+  assert.sameValue(get.call(o), undefined, Ctor.name + ': get.call on object with instance as proto');
+
+  // Property access walks the prototype chain to find the accessor on
+  // Error.prototype, then calls the getter with this set to the original
+  // receiver (o). Because o lacks [[ErrorData]], the result is undefined.
+  assert.sameValue(o.stack, undefined, Ctor.name + ': property access on object with instance as proto');
+
+  // The inherited instance still produces a string when the getter is invoked
+  // on it directly.
+  assert.sameValue(typeof get.call(protoErr), 'string', Ctor.name + ': get.call on the underlying instance');
+}
diff --git a/test/built-ins/Error/prototype/stack/getter-error-instance.js b/test/built-ins/Error/prototype/stack/getter-error-instance.js
new file mode 100644
index 0000000..bd7e155
--- /dev/null
+++ b/test/built-ins/Error/prototype/stack/getter-error-instance.js
@@ -0,0 +1,41 @@
+// Copyright (C) 2026 Jordan Harband. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-get-error.prototype.stack
+description: >
+  Returns a String when called on an Error instance.
+info: |
+  get Error.prototype.stack
+
+  1. Let E be the this value.
+  2. If E is not an Object, throw a TypeError exception.
+  3. If E does not have an [[ErrorData]] internal slot, return undefined.
+  4. Return an implementation-defined string that represents the stack trace of E.
+features: [error-stack-accessor]
+---*/
+
+var get = Object.getOwnPropertyDescriptor(Error.prototype, 'stack').get;
+
+var nativeErrors = [
+  Error,
+  EvalError,
+  RangeError,
+  ReferenceError,
+  SyntaxError,
+  TypeError,
+  URIError
+];
+
+for (var i = 0; i < nativeErrors.length; ++i) {
+  var Ctor = nativeErrors[i];
+
+  var err = new Ctor('msg');
+  assert.sameValue(typeof get.call(err), 'string', Ctor.name + ': new Ctor instance via get.call');
+  assert.sameValue(typeof err.stack, 'string', Ctor.name + ': new Ctor instance via property access');
+
+  var err2 = Ctor('msg');
+  assert.sameValue(typeof get.call(err2), 'string', Ctor.name + ': Ctor called without new');
+
+  assert.sameValue(typeof get.call(err), 'string', Ctor.name + ': second call still returns a string');
+}
diff --git a/test/built-ins/Error/prototype/stack/getter-error-prototype.js b/test/built-ins/Error/prototype/stack/getter-error-prototype.js
new file mode 100644
index 0000000..8155979
--- /dev/null
+++ b/test/built-ins/Error/prototype/stack/getter-error-prototype.js
@@ -0,0 +1,36 @@
+// Copyright (C) 2026 Jordan Harband. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-get-error.prototype.stack
+description: >
+  The getter returns undefined when called on Error.prototype itself, because
+  the Error prototype object is not an Error instance and does not have an
+  [[ErrorData]] internal slot.
+info: |
+  get Error.prototype.stack
+
+  1. Let E be the this value.
+  2. If E is not an Object, throw a TypeError exception.
+  3. If E does not have an [[ErrorData]] internal slot, return undefined.
+  4. Return an implementation-defined string that represents the stack trace of E.
+
+  Properties of the Error Prototype Object
+
+  The Error prototype object:
+    [...]
+    is not an Error instance and does not have an [[ErrorData]] internal slot.
+features: [error-stack-accessor]
+---*/
+
+var get = Object.getOwnPropertyDescriptor(Error.prototype, 'stack').get;
+
+assert.sameValue(get.call(Error.prototype), undefined, 'Error.prototype');
+assert.sameValue(Error.prototype.stack, undefined, 'access via property');
+
+assert.sameValue(get.call(EvalError.prototype), undefined, 'EvalError.prototype');
+assert.sameValue(get.call(RangeError.prototype), undefined, 'RangeError.prototype');
+assert.sameValue(get.call(ReferenceError.prototype), undefined, 'ReferenceError.prototype');
+assert.sameValue(get.call(SyntaxError.prototype), undefined, 'SyntaxError.prototype');
+assert.sameValue(get.call(TypeError.prototype), undefined, 'TypeError.prototype');
+assert.sameValue(get.call(URIError.prototype), undefined, 'URIError.prototype');
diff --git a/test/built-ins/Error/prototype/stack/getter-foreign-new-target.js b/test/built-ins/Error/prototype/stack/getter-foreign-new-target.js
new file mode 100644
index 0000000..1ddce62
--- /dev/null
+++ b/test/built-ins/Error/prototype/stack/getter-foreign-new-target.js
@@ -0,0 +1,55 @@
+// Copyright (C) 2026 Jordan Harband. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-get-error.prototype.stack
+description: >
+  An Error instance constructed with a non-Error new.target acquires the
+  [[ErrorData]] internal slot from Error's [[Construct]], so the getter
+  returns a String when invoked directly. Property access via the result
+  does NOT find the inherited accessor, because the result's [[Prototype]]
+  is the new.target's prototype, not Error.prototype.
+info: |
+  get Error.prototype.stack
+
+  1. Let E be the this value.
+  2. If E is not an Object, throw a TypeError exception.
+  3. If E does not have an [[ErrorData]] internal slot, return undefined.
+  4. Return an implementation-defined string that represents the stack trace of E.
+features: [error-stack-accessor, Reflect.construct]
+---*/
+
+var get = Object.getOwnPropertyDescriptor(Error.prototype, 'stack').get;
+
+function NotAnError() {}
+
+var nativeErrors = [
+  Error,
+  EvalError,
+  RangeError,
+  ReferenceError,
+  SyntaxError,
+  TypeError,
+  URIError
+];
+
+for (var i = 0; i < nativeErrors.length; ++i) {
+  var Ctor = nativeErrors[i];
+  var e = Reflect.construct(Ctor, ['msg'], NotAnError);
+
+  assert.sameValue(
+    Object.getPrototypeOf(e),
+    NotAnError.prototype,
+    Ctor.name + ': [[Prototype]] is the new.target prototype'
+  );
+
+  // The internal slot is set by Ctor's [[Construct]] regardless of new.target,
+  // so the getter (called directly) still produces a string.
+  assert.sameValue(typeof get.call(e), 'string', Ctor.name + ': via get.call');
+
+  // Property access on the instance does NOT find the inherited accessor:
+  // Error.prototype is not on e's prototype chain (it's only on Ctor.prototype,
+  // which is bypassed by the foreign new.target). The lookup walks
+  // NotAnError.prototype then Object.prototype and returns undefined.
+  assert.sameValue(e.stack, undefined, Ctor.name + ': property access returns undefined');
+}
diff --git a/test/built-ins/Error/prototype/stack/getter-length.js b/test/built-ins/Error/prototype/stack/getter-length.js
new file mode 100644
index 0000000..375b64f
--- /dev/null
+++ b/test/built-ins/Error/prototype/stack/getter-length.js
@@ -0,0 +1,33 @@
+// Copyright (C) 2026 Jordan Harband. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-get-error.prototype.stack
+description: >
+  get Error.prototype.stack.length is 0.
+info: |
+  get Error.prototype.stack
+
+  17 ECMAScript Standard Built-in Objects:
+    Every built-in function object, including constructors, has a length
+    property whose value is an integer. Unless otherwise specified, this
+    value is equal to the largest number of named arguments shown in the
+    subclause headings for the function description, including optional
+    parameters. However, rest parameters shown using the form "...name"
+    are not included in the default argument count.
+
+    Unless otherwise specified, the length property of a built-in function
+    object has the attributes { [[Writable]]: false, [[Enumerable]]: false,
+    [[Configurable]]: true }.
+includes: [propertyHelper.js]
+features: [error-stack-accessor]
+---*/
+
+var get = Object.getOwnPropertyDescriptor(Error.prototype, 'stack').get;
+
+verifyProperty(get, 'length', {
+  value: 0,
+  writable: false,
+  enumerable: false,
+  configurable: true,
+});
diff --git a/test/built-ins/Error/prototype/stack/getter-name.js b/test/built-ins/Error/prototype/stack/getter-name.js
new file mode 100644
index 0000000..1259a17
--- /dev/null
+++ b/test/built-ins/Error/prototype/stack/getter-name.js
@@ -0,0 +1,30 @@
+// Copyright (C) 2026 Jordan Harband. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-get-error.prototype.stack
+description: >
+  get Error.prototype.stack.name is "get stack".
+info: |
+  get Error.prototype.stack
+
+  17 ECMAScript Standard Built-in Objects
+
+  Functions that are specified as get or set accessor functions of built-in
+  properties have "get " or "set " prepended to the property name string.
+
+  Unless otherwise specified, the name property of a built-in function object,
+  if it exists, has the attributes { [[Writable]]: false, [[Enumerable]]: false,
+  [[Configurable]]: true }.
+includes: [propertyHelper.js]
+features: [error-stack-accessor]
+---*/
+
+var get = Object.getOwnPropertyDescriptor(Error.prototype, 'stack').get;
+
+verifyProperty(get, 'name', {
+  value: 'get stack',
+  writable: false,
+  enumerable: false,
+  configurable: true,
+});
diff --git a/test/built-ins/Error/prototype/stack/getter-no-error-data-arraybuffer.js b/test/built-ins/Error/prototype/stack/getter-no-error-data-arraybuffer.js
new file mode 100644
index 0000000..219aac3
--- /dev/null
+++ b/test/built-ins/Error/prototype/stack/getter-no-error-data-arraybuffer.js
@@ -0,0 +1,21 @@
+// Copyright (C) 2026 Jordan Harband. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-get-error.prototype.stack
+description: >
+  Returns undefined when called on an ArrayBuffer, which does not have an
+  [[ErrorData]] internal slot.
+info: |
+  get Error.prototype.stack
+
+  1. Let E be the this value.
+  2. If E is not an Object, throw a TypeError exception.
+  3. If E does not have an [[ErrorData]] internal slot, return undefined.
+  4. Return an implementation-defined string that represents the stack trace of E.
+features: [error-stack-accessor, ArrayBuffer]
+---*/
+
+var get = Object.getOwnPropertyDescriptor(Error.prototype, 'stack').get;
+
+assert.sameValue(get.call(new ArrayBuffer(0)), undefined);
diff --git a/test/built-ins/Error/prototype/stack/getter-no-error-data-map.js b/test/built-ins/Error/prototype/stack/getter-no-error-data-map.js
new file mode 100644
index 0000000..4f300a7
--- /dev/null
+++ b/test/built-ins/Error/prototype/stack/getter-no-error-data-map.js
@@ -0,0 +1,21 @@
+// Copyright (C) 2026 Jordan Harband. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-get-error.prototype.stack
+description: >
+  Returns undefined when called on a Map, which does not have an
+  [[ErrorData]] internal slot.
+info: |
+  get Error.prototype.stack
+
+  1. Let E be the this value.
+  2. If E is not an Object, throw a TypeError exception.
+  3. If E does not have an [[ErrorData]] internal slot, return undefined.
+  4. Return an implementation-defined string that represents the stack trace of E.
+features: [error-stack-accessor, Map]
+---*/
+
+var get = Object.getOwnPropertyDescriptor(Error.prototype, 'stack').get;
+
+assert.sameValue(get.call(new Map()), undefined);
diff --git a/test/built-ins/Error/prototype/stack/getter-no-error-data-promise.js b/test/built-ins/Error/prototype/stack/getter-no-error-data-promise.js
new file mode 100644
index 0000000..5fad443
--- /dev/null
+++ b/test/built-ins/Error/prototype/stack/getter-no-error-data-promise.js
@@ -0,0 +1,21 @@
+// Copyright (C) 2026 Jordan Harband. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-get-error.prototype.stack
+description: >
+  Returns undefined when called on a Promise, which does not have an
+  [[ErrorData]] internal slot.
+info: |
+  get Error.prototype.stack
+
+  1. Let E be the this value.
+  2. If E is not an Object, throw a TypeError exception.
+  3. If E does not have an [[ErrorData]] internal slot, return undefined.
+  4. Return an implementation-defined string that represents the stack trace of E.
+features: [error-stack-accessor, Promise]
+---*/
+
+var get = Object.getOwnPropertyDescriptor(Error.prototype, 'stack').get;
+
+assert.sameValue(get.call(new Promise(function () {})), undefined);
diff --git a/test/built-ins/Error/prototype/stack/getter-no-error-data-set.js b/test/built-ins/Error/prototype/stack/getter-no-error-data-set.js
new file mode 100644
index 0000000..77d2a37
--- /dev/null
+++ b/test/built-ins/Error/prototype/stack/getter-no-error-data-set.js
@@ -0,0 +1,21 @@
+// Copyright (C) 2026 Jordan Harband. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-get-error.prototype.stack
+description: >
+  Returns undefined when called on a Set, which does not have an
+  [[ErrorData]] internal slot.
+info: |
+  get Error.prototype.stack
+
+  1. Let E be the this value.
+  2. If E is not an Object, throw a TypeError exception.
+  3. If E does not have an [[ErrorData]] internal slot, return undefined.
+  4. Return an implementation-defined string that represents the stack trace of E.
+features: [error-stack-accessor, Set]
+---*/
+
+var get = Object.getOwnPropertyDescriptor(Error.prototype, 'stack').get;
+
+assert.sameValue(get.call(new Set()), undefined);
diff --git a/test/built-ins/Error/prototype/stack/getter-no-error-data-typedarray.js b/test/built-ins/Error/prototype/stack/getter-no-error-data-typedarray.js
new file mode 100644
index 0000000..a2618e0
--- /dev/null
+++ b/test/built-ins/Error/prototype/stack/getter-no-error-data-typedarray.js
@@ -0,0 +1,21 @@
+// Copyright (C) 2026 Jordan Harband. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-get-error.prototype.stack
+description: >
+  Returns undefined when called on a TypedArray, which does not have an
+  [[ErrorData]] internal slot.
+info: |
+  get Error.prototype.stack
+
+  1. Let E be the this value.
+  2. If E is not an Object, throw a TypeError exception.
+  3. If E does not have an [[ErrorData]] internal slot, return undefined.
+  4. Return an implementation-defined string that represents the stack trace of E.
+features: [error-stack-accessor, TypedArray]
+---*/
+
+var get = Object.getOwnPropertyDescriptor(Error.prototype, 'stack').get;
+
+assert.sameValue(get.call(new Int8Array()), undefined);
diff --git a/test/built-ins/Error/prototype/stack/getter-no-error-data-weakmap.js b/test/built-ins/Error/prototype/stack/getter-no-error-data-weakmap.js
new file mode 100644
index 0000000..227f99e
--- /dev/null
+++ b/test/built-ins/Error/prototype/stack/getter-no-error-data-weakmap.js
@@ -0,0 +1,21 @@
+// Copyright (C) 2026 Jordan Harband. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-get-error.prototype.stack
+description: >
+  Returns undefined when called on a WeakMap, which does not have an
+  [[ErrorData]] internal slot.
+info: |
+  get Error.prototype.stack
+
+  1. Let E be the this value.
+  2. If E is not an Object, throw a TypeError exception.
+  3. If E does not have an [[ErrorData]] internal slot, return undefined.
+  4. Return an implementation-defined string that represents the stack trace of E.
+features: [error-stack-accessor, WeakMap]
+---*/
+
+var get = Object.getOwnPropertyDescriptor(Error.prototype, 'stack').get;
+
+assert.sameValue(get.call(new WeakMap()), undefined);
diff --git a/test/built-ins/Error/prototype/stack/getter-no-error-data-weakset.js b/test/built-ins/Error/prototype/stack/getter-no-error-data-weakset.js
new file mode 100644
index 0000000..13f24ac
--- /dev/null
+++ b/test/built-ins/Error/prototype/stack/getter-no-error-data-weakset.js
@@ -0,0 +1,21 @@
+// Copyright (C) 2026 Jordan Harband. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-get-error.prototype.stack
+description: >
+  Returns undefined when called on a WeakSet, which does not have an
+  [[ErrorData]] internal slot.
+info: |
+  get Error.prototype.stack
+
+  1. Let E be the this value.
+  2. If E is not an Object, throw a TypeError exception.
+  3. If E does not have an [[ErrorData]] internal slot, return undefined.
+  4. Return an implementation-defined string that represents the stack trace of E.
+features: [error-stack-accessor, WeakSet]
+---*/
+
+var get = Object.getOwnPropertyDescriptor(Error.prototype, 'stack').get;
+
+assert.sameValue(get.call(new WeakSet()), undefined);
diff --git a/test/built-ins/Error/prototype/stack/getter-no-error-data.js b/test/built-ins/Error/prototype/stack/getter-no-error-data.js
new file mode 100644
index 0000000..6eb9b4d
--- /dev/null
+++ b/test/built-ins/Error/prototype/stack/getter-no-error-data.js
@@ -0,0 +1,41 @@
+// Copyright (C) 2026 Jordan Harband. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-get-error.prototype.stack
+description: >
+  Returns undefined when called on an object that does not have an
+  [[ErrorData]] internal slot.
+info: |
+  get Error.prototype.stack
+
+  1. Let E be the this value.
+  2. If E is not an Object, throw a TypeError exception.
+  3. If E does not have an [[ErrorData]] internal slot, return undefined.
+  4. Return an implementation-defined string that represents the stack trace of E.
+features: [error-stack-accessor]
+---*/
+
+var get = Object.getOwnPropertyDescriptor(Error.prototype, 'stack').get;
+
+assert.sameValue(get.call({}), undefined, 'plain object');
+assert.sameValue(get.call([]), undefined, 'array');
+assert.sameValue(get.call(function () {}), undefined, 'function');
+assert.sameValue(get.call(/re/), undefined, 'RegExp');
+assert.sameValue(get.call(new Date()), undefined, 'Date');
+assert.sameValue(get.call(new Boolean(true)), undefined, 'Boolean wrapper');
+assert.sameValue(get.call(new Number(0)), undefined, 'Number wrapper');
+assert.sameValue(get.call(new String('')), undefined, 'String wrapper');
+
+// An object that inherits from Error.prototype but lacks [[ErrorData]] still
+// returns undefined: the getter checks for the internal slot, not the prototype.
+var fakeError = Object.create(Error.prototype);
+assert.sameValue(get.call(fakeError), undefined, 'object with Error.prototype on its prototype chain');
+
+var fakeErrorWithStack = Object.create(Error.prototype);
+Object.defineProperty(fakeErrorWithStack, 'stack', { value: 'imposter', writable: true, enumerable: true, configurable: true });
+assert.sameValue(
+  get.call(fakeErrorWithStack),
+  undefined,
+  'an existing own "stack" data property is ignored by the getter on a non-Error object'
+);
diff --git a/test/built-ins/Error/prototype/stack/getter-not-a-constructor.js b/test/built-ins/Error/prototype/stack/getter-not-a-constructor.js
new file mode 100644
index 0000000..2a59489
--- /dev/null
+++ b/test/built-ins/Error/prototype/stack/getter-not-a-constructor.js
@@ -0,0 +1,28 @@
+// Copyright (C) 2026 Jordan Harband. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-get-error.prototype.stack
+description: >
+  get Error.prototype.stack does not implement [[Construct]], is not new-able
+info: |
+  ECMAScript Function Objects
+
+  Built-in function objects that are not identified as constructors do not
+  implement the [[Construct]] internal method unless otherwise specified in
+  the description of a particular function.
+includes: [isConstructor.js]
+features: [error-stack-accessor, Reflect.construct]
+---*/
+
+var get = Object.getOwnPropertyDescriptor(Error.prototype, 'stack').get;
+
+assert.sameValue(
+  isConstructor(get),
+  false,
+  'isConstructor(get Error.prototype.stack) must return false'
+);
+
+assert.throws(TypeError, function () {
+  new get();
+});
diff --git a/test/built-ins/Error/prototype/stack/getter-null-proto-receiver.js b/test/built-ins/Error/prototype/stack/getter-null-proto-receiver.js
new file mode 100644
index 0000000..5a453a5
--- /dev/null
+++ b/test/built-ins/Error/prototype/stack/getter-null-proto-receiver.js
@@ -0,0 +1,22 @@
+// Copyright (C) 2026 Jordan Harband. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-get-error.prototype.stack
+description: >
+  The getter returns undefined when called on a null-prototype object, since
+  it has no [[ErrorData]] internal slot. The check does not depend on
+  inherited machinery from Object.prototype.
+info: |
+  get Error.prototype.stack
+
+  1. Let E be the this value.
+  2. If E is not an Object, throw a TypeError exception.
+  3. If E does not have an [[ErrorData]] internal slot, return undefined.
+  4. Return an implementation-defined string that represents the stack trace of E.
+features: [error-stack-accessor, __proto__]
+---*/
+
+var get = Object.getOwnPropertyDescriptor(Error.prototype, 'stack').get;
+
+assert.sameValue(get.call({ __proto__: null }), undefined);
diff --git a/test/built-ins/Error/prototype/stack/getter-proxy-receiver.js b/test/built-ins/Error/prototype/stack/getter-proxy-receiver.js
new file mode 100644
index 0000000..4c57892
--- /dev/null
+++ b/test/built-ins/Error/prototype/stack/getter-proxy-receiver.js
@@ -0,0 +1,61 @@
+// Copyright (C) 2026 Jordan Harband. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-get-error.prototype.stack
+description: >
+  The getter operates on the receiver's [[ErrorData]] internal slot directly.
+  When the receiver is a Proxy, the proxy's traps are not consulted: a Proxy
+  has no [[ErrorData]] internal slot regardless of its target, so the getter
+  returns undefined.
+info: |
+  get Error.prototype.stack
+
+  1. Let E be the this value.
+  2. If E is not an Object, throw a TypeError exception.
+  3. If E does not have an [[ErrorData]] internal slot, return undefined.
+  4. Return an implementation-defined string that represents the stack trace of E.
+features: [error-stack-accessor, Proxy, Reflect]
+---*/
+
+var get = Object.getOwnPropertyDescriptor(Error.prototype, 'stack').get;
+
+function noTraps(label) {
+  return new Proxy(new Error('inner'), {
+    get: function () { throw new Test262Error(label + ': get trap should not fire'); },
+    getOwnPropertyDescriptor: function () { throw new Test262Error(label + ': getOwnPropertyDescriptor trap should not fire'); },
+    has: function () { throw new Test262Error(label + ': has trap should not fire'); },
+    getPrototypeOf: function () { throw new Test262Error(label + ': getPrototypeOf trap should not fire'); },
+    ownKeys: function () { throw new Test262Error(label + ': ownKeys trap should not fire'); },
+  });
+}
+
+// (a) Proxy wrapping an Error instance: the Proxy itself has no [[ErrorData]],
+// so the getter returns undefined without consulting the wrapped target.
+assert.sameValue(get.call(noTraps('a')), undefined, 'Proxy wrapping Error returns undefined');
+
+// (b) Same for property access through the Proxy: the [[Get]] forwards the
+// access to the proxy's get trap (which would throw), but the receiver passed
+// through to the inherited accessor on Error.prototype is the proxy itself.
+// Since the proxy lacks [[ErrorData]], the getter returns undefined; however,
+// because [[Get]] on the proxy first invokes the get trap, this exercises a
+// different code path. Use a separate proxy whose get trap forwards to the
+// target so the inherited accessor still receives the proxy as `this`.
+var stackTrapCalls = 0;
+var pB = new Proxy(new Error('inner'), {
+  get: function (t, key, receiver) {
+    if (key === 'stack') {
+      stackTrapCalls += 1;
+    }
+    return Reflect.get(t, key, receiver);
+  },
+});
+assert.sameValue(pB.stack, undefined, 'property access on proxy: receiver is proxy, no [[ErrorData]]');
+assert.sameValue(stackTrapCalls, 1, 'get trap fired once for the property access');
+
+// (c) Proxy wrapping a non-Error: still undefined.
+assert.sameValue(
+  get.call(new Proxy({}, {})),
+  undefined,
+  'Proxy wrapping plain object returns undefined'
+);
diff --git a/test/built-ins/Error/prototype/stack/getter-subclass.js b/test/built-ins/Error/prototype/stack/getter-subclass.js
new file mode 100644
index 0000000..faf184d
--- /dev/null
+++ b/test/built-ins/Error/prototype/stack/getter-subclass.js
@@ -0,0 +1,38 @@
+// Copyright (C) 2026 Jordan Harband. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-get-error.prototype.stack
+description: >
+  The getter returns a String when called on a subclass of Error or any
+  NativeError, since subclasses inherit the [[ErrorData]] internal slot.
+info: |
+  get Error.prototype.stack
+
+  1. Let E be the this value.
+  2. If E is not an Object, throw a TypeError exception.
+  3. If E does not have an [[ErrorData]] internal slot, return undefined.
+  4. Return an implementation-defined string that represents the stack trace of E.
+features: [error-stack-accessor, class]
+---*/
+
+var get = Object.getOwnPropertyDescriptor(Error.prototype, 'stack').get;
+
+var nativeErrors = [
+  Error,
+  EvalError,
+  RangeError,
+  ReferenceError,
+  SyntaxError,
+  TypeError,
+  URIError
+];
+
+for (var i = 0; i < nativeErrors.length; ++i) {
+  var Ctor = nativeErrors[i];
+  var Sub = class extends Ctor {};
+  var e = new Sub('msg');
+
+  assert.sameValue(typeof get.call(e), 'string', Ctor.name + ': subclass via get.call');
+  assert.sameValue(typeof e.stack, 'string', Ctor.name + ': subclass via property access');
+}
diff --git a/test/built-ins/Error/prototype/stack/getter-suppressed-error-prototype.js b/test/built-ins/Error/prototype/stack/getter-suppressed-error-prototype.js
new file mode 100644
index 0000000..d5c3f68
--- /dev/null
+++ b/test/built-ins/Error/prototype/stack/getter-suppressed-error-prototype.js
@@ -0,0 +1,28 @@
+// Copyright (C) 2026 Jordan Harband. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-get-error.prototype.stack
+description: >
+  The getter returns undefined when called on SuppressedError.prototype, which
+  is an ordinary object that does not have an [[ErrorData]] internal slot.
+info: |
+  get Error.prototype.stack
+
+  1. Let E be the this value.
+  2. If E is not an Object, throw a TypeError exception.
+  3. If E does not have an [[ErrorData]] internal slot, return undefined.
+  4. Return an implementation-defined string that represents the stack trace of E.
+
+  Properties of the SuppressedError Prototype Object
+
+  The SuppressedError prototype object:
+    [...]
+    is not an Error instance or a SuppressedError instance and does not have
+    an [[ErrorData]] internal slot.
+features: [error-stack-accessor, explicit-resource-management]
+---*/
+
+var get = Object.getOwnPropertyDescriptor(Error.prototype, 'stack').get;
+
+assert.sameValue(get.call(SuppressedError.prototype), undefined);
diff --git a/test/built-ins/Error/prototype/stack/getter-suppressed-error.js b/test/built-ins/Error/prototype/stack/getter-suppressed-error.js
new file mode 100644
index 0000000..cade260
--- /dev/null
+++ b/test/built-ins/Error/prototype/stack/getter-suppressed-error.js
@@ -0,0 +1,27 @@
+// Copyright (C) 2026 Jordan Harband. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-get-error.prototype.stack
+description: >
+  The getter returns a String when called on a SuppressedError instance.
+info: |
+  get Error.prototype.stack
+
+  1. Let E be the this value.
+  2. If E is not an Object, throw a TypeError exception.
+  3. If E does not have an [[ErrorData]] internal slot, return undefined.
+  4. Return an implementation-defined string that represents the stack trace of E.
+
+  SuppressedError instances are ordinary objects that inherit properties from
+  their SuppressedError prototype object and have an [[ErrorData]] internal
+  slot whose value is undefined.
+features: [error-stack-accessor, explicit-resource-management]
+---*/
+
+var get = Object.getOwnPropertyDescriptor(Error.prototype, 'stack').get;
+
+var err = new SuppressedError(new Error('inner'), new Error('suppressed'), 'msg');
+
+assert.sameValue(typeof get.call(err), 'string', 'SuppressedError instance via get.call');
+assert.sameValue(typeof err.stack, 'string', 'SuppressedError instance via property access');
diff --git a/test/built-ins/Error/prototype/stack/getter-this-not-object-bigint.js b/test/built-ins/Error/prototype/stack/getter-this-not-object-bigint.js
new file mode 100644
index 0000000..8329f79
--- /dev/null
+++ b/test/built-ins/Error/prototype/stack/getter-this-not-object-bigint.js
@@ -0,0 +1,20 @@
+// Copyright (C) 2026 Jordan Harband. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-get-error.prototype.stack
+description: >
+  Throws a TypeError if the this value is a BigInt.
+info: |
+  get Error.prototype.stack
+
+  1. Let E be the this value.
+  2. If E is not an Object, throw a TypeError exception.
+features: [error-stack-accessor, BigInt]
+---*/
+
+var get = Object.getOwnPropertyDescriptor(Error.prototype, 'stack').get;
+
+assert.throws(TypeError, function () {
+  get.call(0n);
+});
diff --git a/test/built-ins/Error/prototype/stack/getter-this-not-object-symbol.js b/test/built-ins/Error/prototype/stack/getter-this-not-object-symbol.js
new file mode 100644
index 0000000..86ccf0a
--- /dev/null
+++ b/test/built-ins/Error/prototype/stack/getter-this-not-object-symbol.js
@@ -0,0 +1,20 @@
+// Copyright (C) 2026 Jordan Harband. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-get-error.prototype.stack
+description: >
+  Throws a TypeError if the this value is a Symbol.
+info: |
+  get Error.prototype.stack
+
+  1. Let E be the this value.
+  2. If E is not an Object, throw a TypeError exception.
+features: [error-stack-accessor, Symbol]
+---*/
+
+var get = Object.getOwnPropertyDescriptor(Error.prototype, 'stack').get;
+
+assert.throws(TypeError, function () {
+  get.call(Symbol('s'));
+});
diff --git a/test/built-ins/Error/prototype/stack/getter-this-not-object.js b/test/built-ins/Error/prototype/stack/getter-this-not-object.js
new file mode 100644
index 0000000..1f367ec
--- /dev/null
+++ b/test/built-ins/Error/prototype/stack/getter-this-not-object.js
@@ -0,0 +1,42 @@
+// Copyright (C) 2026 Jordan Harband. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-get-error.prototype.stack
+description: >
+  Throws a TypeError if the this value is not an Object.
+info: |
+  get Error.prototype.stack
+
+  1. Let E be the this value.
+  2. If E is not an Object, throw a TypeError exception.
+features: [error-stack-accessor]
+---*/
+
+var get = Object.getOwnPropertyDescriptor(Error.prototype, 'stack').get;
+
+assert.sameValue(typeof get, 'function');
+
+assert.throws(TypeError, function () {
+  get.call(undefined);
+}, 'undefined');
+
+assert.throws(TypeError, function () {
+  get.call(null);
+}, 'null');
+
+assert.throws(TypeError, function () {
+  get.call(true);
+}, 'true');
+
+assert.throws(TypeError, function () {
+  get.call(false);
+}, 'false');
+
+assert.throws(TypeError, function () {
+  get.call(1);
+}, 'number');
+
+assert.throws(TypeError, function () {
+  get.call('');
+}, 'string');
diff --git a/test/built-ins/Error/prototype/stack/instance-no-own-stack.js b/test/built-ins/Error/prototype/stack/instance-no-own-stack.js
new file mode 100644
index 0000000..ae27ce6
--- /dev/null
+++ b/test/built-ins/Error/prototype/stack/instance-no-own-stack.js
@@ -0,0 +1,62 @@
+// Copyright (C) 2026 Jordan Harband. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-properties-of-error-instances
+description: >
+  A freshly-constructed Error instance has no own "stack" property; the
+  property is reached via the inherited accessor on Error.prototype.
+info: |
+  Properties of Error Instances
+
+  Error instances are ordinary objects that inherit properties from the Error
+  prototype object and have an [[ErrorData]] internal slot whose value is
+  undefined.
+
+  Error.prototype.stack is an accessor property with attributes
+  { [[Enumerable]]: false, [[Configurable]]: true }.
+features: [error-stack-accessor]
+---*/
+
+var nativeErrors = [
+  Error,
+  EvalError,
+  RangeError,
+  ReferenceError,
+  SyntaxError,
+  TypeError,
+  URIError
+];
+
+for (var i = 0; i < nativeErrors.length; ++i) {
+  var Ctor = nativeErrors[i];
+  var err = new Ctor('msg');
+
+  assert.sameValue(
+    Object.prototype.hasOwnProperty.call(err, 'stack'),
+    false,
+    Ctor.name + ': hasOwnProperty("stack") is false'
+  );
+
+  assert.sameValue(
+    Object.getOwnPropertyDescriptor(err, 'stack'),
+    undefined,
+    Ctor.name + ': getOwnPropertyDescriptor returns undefined'
+  );
+
+  // For NativeErrors, the immediate prototype is e.g. TypeError.prototype,
+  // which does NOT have its own "stack" property; the accessor lives only on
+  // Error.prototype, two links up.
+  if (Ctor !== Error) {
+    assert.sameValue(
+      Object.getOwnPropertyDescriptor(Object.getPrototypeOf(err), 'stack'),
+      undefined,
+      Ctor.name + ': stack is not an own property of NativeError.prototype'
+    );
+  }
+
+  var desc = Object.getOwnPropertyDescriptor(Error.prototype, 'stack');
+  assert.notSameValue(desc, undefined, Ctor.name + ': Error.prototype has the accessor');
+  assert.sameValue(typeof desc.get, 'function', Ctor.name + ': accessor get is a function');
+  assert.sameValue(typeof desc.set, 'function', Ctor.name + ': accessor set is a function');
+}
diff --git a/test/built-ins/Error/prototype/stack/instance-not-enumerable.js b/test/built-ins/Error/prototype/stack/instance-not-enumerable.js
new file mode 100644
index 0000000..be7b52e
--- /dev/null
+++ b/test/built-ins/Error/prototype/stack/instance-not-enumerable.js
@@ -0,0 +1,84 @@
+// Copyright (C) 2026 Jordan Harband. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-get-error.prototype-stack
+description: >
+  "stack" is a non-enumerable accessor on Error.prototype, and Error instances
+  do not have an own "stack" property, so "stack" is not visible via
+  Object.keys, for-in, propertyIsEnumerable, or JSON.stringify.
+info: |
+  Error.prototype.stack is an accessor property with attributes
+  { [[Enumerable]]: false, [[Configurable]]: true }.
+
+  Properties of Error Instances
+
+  Error instances are ordinary objects that inherit properties from the Error
+  prototype object and have an [[ErrorData]] internal slot whose value is
+  undefined.
+features: [error-stack-accessor]
+---*/
+
+var nativeErrors = [
+  Error,
+  EvalError,
+  RangeError,
+  ReferenceError,
+  SyntaxError,
+  TypeError,
+  URIError
+];
+
+for (var i = 0; i < nativeErrors.length; ++i) {
+  var Ctor = nativeErrors[i];
+  var err = new Ctor('msg');
+
+  assert.sameValue(
+    Object.keys(err).indexOf('stack'),
+    -1,
+    Ctor.name + ': Object.keys does not include "stack"'
+  );
+
+  assert.sameValue(
+    Object.getOwnPropertyNames(err).indexOf('stack'),
+    -1,
+    Ctor.name + ': getOwnPropertyNames does not include "stack"'
+  );
+
+  var sawStack = false;
+  for (var key in err) {
+    if (key === 'stack') {
+      sawStack = true;
+    }
+  }
+  assert.sameValue(sawStack, false, Ctor.name + ': for-in does not yield "stack"');
+
+  assert.sameValue(
+    Object.prototype.propertyIsEnumerable.call(err, 'stack'),
+    false,
+    Ctor.name + ': propertyIsEnumerable returns false'
+  );
+
+  assert.sameValue(
+    Object.prototype.propertyIsEnumerable.call(Error.prototype, 'stack'),
+    false,
+    Ctor.name + ': Error.prototype.propertyIsEnumerable("stack") is false'
+  );
+
+  // JSON.stringify omits non-enumerable / non-own properties; a fresh Error
+  // instance has no enumerable own properties at all.
+  assert.sameValue(
+    JSON.stringify(err),
+    '{}',
+    Ctor.name + ': JSON.stringify output is empty object'
+  );
+
+  // Object.assign reads only enumerable own properties; the inherited
+  // accessor is not own, so "stack" is not copied.
+  var copy = Object.assign({}, err);
+  assert.sameValue(
+    Object.prototype.hasOwnProperty.call(copy, 'stack'),
+    false,
+    Ctor.name + ': Object.assign({}, err) does not copy "stack"'
+  );
+}
diff --git a/test/built-ins/Error/prototype/stack/prop-desc.js b/test/built-ins/Error/prototype/stack/prop-desc.js
new file mode 100644
index 0000000..fa66bdc
--- /dev/null
+++ b/test/built-ins/Error/prototype/stack/prop-desc.js
@@ -0,0 +1,21 @@
+// Copyright (C) 2026 Jordan Harband. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-get-error.prototype-stack
+description: >
+  Property descriptor of Error.prototype.stack
+info: |
+  Error.prototype.stack is an accessor property with attributes
+  { [[Enumerable]]: false, [[Configurable]]: true }.
+features: [error-stack-accessor]
+---*/
+
+var desc = Object.getOwnPropertyDescriptor(Error.prototype, 'stack');
+
+assert.sameValue(typeof desc.get, 'function', 'typeof desc.get');
+assert.sameValue(typeof desc.set, 'function', 'typeof desc.set');
+assert.sameValue(desc.value, undefined, 'desc.value');
+assert.sameValue(desc.writable, undefined, 'desc.writable');
+assert.sameValue(desc.enumerable, false, 'desc.enumerable');
+assert.sameValue(desc.configurable, true, 'desc.configurable');
diff --git a/test/built-ins/Error/prototype/stack/setter-aggregate-error.js b/test/built-ins/Error/prototype/stack/setter-aggregate-error.js
new file mode 100644
index 0000000..c651642
--- /dev/null
+++ b/test/built-ins/Error/prototype/stack/setter-aggregate-error.js
@@ -0,0 +1,38 @@
+// Copyright (C) 2026 Jordan Harband. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-set-error.prototype.stack
+description: >
+  The setter installs an own "stack" data property on AggregateError instances.
+info: |
+  set Error.prototype.stack
+
+  1. Let E be the this value.
+  2. If E is not an Object, throw a TypeError exception.
+  3. If v is not a String, throw a TypeError exception.
+  4. Perform ? SetterThatIgnoresPrototypeProperties(this value, %Error.prototype%, "stack", v).
+  5. Return undefined.
+includes: [propertyHelper.js]
+features: [error-stack-accessor, AggregateError]
+---*/
+
+var set = Object.getOwnPropertyDescriptor(Error.prototype, 'stack').set;
+
+var err = new AggregateError([new Error('inner')], 'outer');
+
+assert.sameValue(
+  Object.prototype.hasOwnProperty.call(err, 'stack'),
+  false,
+  'precondition: AggregateError instance has no own "stack" property at construction'
+);
+
+var result = set.call(err, 'sentinel');
+assert.sameValue(result, undefined, 'setter returns undefined');
+
+verifyProperty(err, 'stack', {
+  value: 'sentinel',
+  writable: true,
+  enumerable: true,
+  configurable: true,
+});
diff --git a/test/built-ins/Error/prototype/stack/setter-creates-own-property.js b/test/built-ins/Error/prototype/stack/setter-creates-own-property.js
new file mode 100644
index 0000000..6171fcf
--- /dev/null
+++ b/test/built-ins/Error/prototype/stack/setter-creates-own-property.js
@@ -0,0 +1,71 @@
+// Copyright (C) 2026 Jordan Harband. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-set-error.prototype.stack
+description: >
+  When the receiver does not have an own "stack" property, the setter creates
+  one as a writable, enumerable, configurable data property whose value is v.
+info: |
+  set Error.prototype.stack
+
+  1. Let E be the this value.
+  2. If E is not an Object, throw a TypeError exception.
+  3. If v is not a String, throw a TypeError exception.
+  4. Perform ? SetterThatIgnoresPrototypeProperties(this value, %Error.prototype%, "stack", v).
+  5. Return undefined.
+
+  SetterThatIgnoresPrototypeProperties ( this, home, p, v )
+
+  [...]
+  3. Let desc be ? this.[[GetOwnProperty]](p).
+  4. If desc is undefined, then
+    a. Perform ? CreateDataPropertyOrThrow(this, p, v).
+  [...]
+includes: [propertyHelper.js]
+features: [error-stack-accessor]
+---*/
+
+var set = Object.getOwnPropertyDescriptor(Error.prototype, 'stack').set;
+
+var nativeErrors = [
+  Error,
+  EvalError,
+  RangeError,
+  ReferenceError,
+  SyntaxError,
+  TypeError,
+  URIError
+];
+
+for (var i = 0; i < nativeErrors.length; ++i) {
+  var Ctor = nativeErrors[i];
+  var err = new Ctor('msg');
+
+  assert.sameValue(
+    Object.prototype.hasOwnProperty.call(err, 'stack'),
+    false,
+    Ctor.name + ': precondition: instance has no own "stack" property at construction'
+  );
+
+  var result = set.call(err, 'sentinel-' + Ctor.name);
+  assert.sameValue(result, undefined, Ctor.name + ': setter returns undefined');
+
+  verifyProperty(err, 'stack', {
+    value: 'sentinel-' + Ctor.name,
+    writable: true,
+    enumerable: true,
+    configurable: true,
+  });
+}
+
+// The same applies to a plain object that lacks [[ErrorData]]: the setter
+// does not check for the internal slot before installing the property.
+var plain = {};
+set.call(plain, 'on-plain');
+verifyProperty(plain, 'stack', {
+  value: 'on-plain',
+  writable: true,
+  enumerable: true,
+  configurable: true,
+});
diff --git a/test/built-ins/Error/prototype/stack/setter-cross-realm.js b/test/built-ins/Error/prototype/stack/setter-cross-realm.js
new file mode 100644
index 0000000..d699a76
--- /dev/null
+++ b/test/built-ins/Error/prototype/stack/setter-cross-realm.js
@@ -0,0 +1,90 @@
+// Copyright (C) 2026 Jordan Harband. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-set-error.prototype.stack
+description: >
+  The setter's home-object (SameValue) check is realm-scoped: a setter from
+  realm A locks against realm A's %Error.prototype% only. Cross-realm objects
+  are accepted as receivers (they pass the SameValue check), and an Error
+  instance from another realm gets an own "stack" data property installed.
+info: |
+  set Error.prototype.stack
+
+  [...]
+  4. Perform ? SetterThatIgnoresPrototypeProperties(this value, %Error.prototype%, "stack", v).
+
+  SetterThatIgnoresPrototypeProperties ( this, home, p, v )
+
+  [...]
+  2. If SameValue(this, home) is true, then
+    a. Throw a TypeError exception.
+  3. Let desc be ? this.[[GetOwnProperty]](p).
+  4. If desc is undefined, then
+    a. Perform ? CreateDataPropertyOrThrow(this, p, v).
+includes: [propertyHelper.js]
+features: [error-stack-accessor, cross-realm]
+---*/
+
+var setA = Object.getOwnPropertyDescriptor(Error.prototype, 'stack').set;
+
+var realmB = $262.createRealm().global;
+
+assert.notSameValue(
+  Error.prototype,
+  realmB.Error.prototype,
+  'precondition: the two realms have distinct Error.prototype objects'
+);
+
+// (a) Realm A's setter on a realm B Error instance: passes SameValue (the
+// instance is not realm A's Error.prototype), and the instance has no own
+// "stack" property at construction, so CreateDataPropertyOrThrow installs one.
+var errB = new realmB.Error('msg');
+assert.sameValue(
+  Object.prototype.hasOwnProperty.call(errB, 'stack'),
+  false,
+  'precondition: cross-realm Error instance has no own "stack" property'
+);
+
+setA.call(errB, 'sentinel');
+
+verifyProperty(errB, 'stack', {
+  value: 'sentinel',
+  writable: true,
+  enumerable: true,
+  configurable: true,
+});
+
+// (b) Realm A's setter on a plain object from realm B: same path, installs an
+// own data property.
+var plainB = new realmB.Object();
+setA.call(plainB, 'plain');
+
+verifyProperty(plainB, 'stack', {
+  value: 'plain',
+  writable: true,
+  enumerable: true,
+  configurable: true,
+});
+
+// (c) Realm A's setter is structurally distinct from realm B's setter.
+var setB = Object.getOwnPropertyDescriptor(realmB.Error.prototype, 'stack').set;
+assert.sameValue(typeof setB, 'function', 'realm B has its own setter');
+assert.notSameValue(setA, setB, 'the two realms have distinct setter functions');
+
+// (d) Realm A's setter on realm B's Error.prototype passes realm A's
+// SameValue check (the two prototypes are distinct objects), so step 2 of
+// SetterThatIgnoresPrototypeProperties does not fire. Step 3 finds realm B's
+// own "stack" accessor descriptor and proceeds to step 5: Set(O, p, v, true)
+// invokes that accessor's setter, which is realm B's setter. Realm B's setter
+// then throws via its own SameValue check (this === realm B's Error.prototype).
+// The thrown TypeError is realm B's TypeError.
+assert.throws(realmB.TypeError, function () {
+  setA.call(realmB.Error.prototype, 'should-throw');
+}, 'realm A setter on realm B Error.prototype throws (via realm B setter)');
+
+// (e) Realm A's setter on realm A's own Error.prototype throws via step 2
+// (SameValue with realm A's home).
+assert.throws(TypeError, function () {
+  setA.call(Error.prototype, 'should-throw');
+}, 'realm A setter on realm A Error.prototype throws via SameValue');
diff --git a/test/built-ins/Error/prototype/stack/setter-delete-round-trip.js b/test/built-ins/Error/prototype/stack/setter-delete-round-trip.js
new file mode 100644
index 0000000..2a13da7
--- /dev/null
+++ b/test/built-ins/Error/prototype/stack/setter-delete-round-trip.js
@@ -0,0 +1,74 @@
+// Copyright (C) 2026 Jordan Harband. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-set-error.prototype.stack
+description: >
+  After the setter installs an own "stack" data property, deleting it
+  re-exposes the inherited accessor on Error.prototype.
+info: |
+  set Error.prototype.stack
+
+  1. Let E be the this value.
+  2. If E is not an Object, throw a TypeError exception.
+  3. If v is not a String, throw a TypeError exception.
+  4. Perform ? SetterThatIgnoresPrototypeProperties(this value, %Error.prototype%, "stack", v).
+  5. Return undefined.
+
+  SetterThatIgnoresPrototypeProperties ( this, home, p, v )
+
+  [...]
+  4. If desc is undefined, then
+    a. Perform ? CreateDataPropertyOrThrow(this, p, v).
+features: [error-stack-accessor]
+---*/
+
+var get = Object.getOwnPropertyDescriptor(Error.prototype, 'stack').get;
+var set = Object.getOwnPropertyDescriptor(Error.prototype, 'stack').set;
+
+var nativeErrors = [
+  Error,
+  EvalError,
+  RangeError,
+  ReferenceError,
+  SyntaxError,
+  TypeError,
+  URIError
+];
+
+for (var i = 0; i < nativeErrors.length; ++i) {
+  var Ctor = nativeErrors[i];
+  var err = new Ctor('msg');
+
+  // delete on a fresh instance: nothing to remove, returns true.
+  assert.sameValue(delete err.stack, true, Ctor.name + ': delete on fresh instance returns true');
+  assert.sameValue(
+    Object.prototype.hasOwnProperty.call(err, 'stack'),
+    false,
+    Ctor.name + ': still no own property after delete'
+  );
+
+  // The inherited accessor still produces a string.
+  assert.sameValue(typeof get.call(err), 'string', Ctor.name + ': accessor still works');
+
+  // After setting, an own data property is installed.
+  set.call(err, 'sentinel');
+  assert.sameValue(
+    Object.prototype.hasOwnProperty.call(err, 'stack'),
+    true,
+    Ctor.name + ': own property installed after set'
+  );
+  assert.sameValue(err.stack, 'sentinel', Ctor.name + ': data property shadows accessor');
+
+  // delete removes the own data property.
+  assert.sameValue(delete err.stack, true, Ctor.name + ': delete removes own data property');
+  assert.sameValue(
+    Object.prototype.hasOwnProperty.call(err, 'stack'),
+    false,
+    Ctor.name + ': own property removed'
+  );
+
+  // The inherited accessor is exposed again, and [[ErrorData]] still drives it.
+  assert.sameValue(typeof err.stack, 'string', Ctor.name + ': inherited accessor re-exposed');
+  assert.sameValue(typeof get.call(err), 'string', Ctor.name + ': accessor still returns a string');
+}
diff --git a/test/built-ins/Error/prototype/stack/setter-empty-string.js b/test/built-ins/Error/prototype/stack/setter-empty-string.js
new file mode 100644
index 0000000..92e12c7
--- /dev/null
+++ b/test/built-ins/Error/prototype/stack/setter-empty-string.js
@@ -0,0 +1,47 @@
+// Copyright (C) 2026 Jordan Harband. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-set-error.prototype.stack
+description: >
+  An empty string is a String, so the setter accepts it.
+info: |
+  set Error.prototype.stack
+
+  1. Let E be the this value.
+  2. If E is not an Object, throw a TypeError exception.
+  3. If v is not a String, throw a TypeError exception.
+  4. Perform ? SetterThatIgnoresPrototypeProperties(this value, %Error.prototype%, "stack", v).
+  5. Return undefined.
+includes: [propertyHelper.js]
+features: [error-stack-accessor]
+---*/
+
+var set = Object.getOwnPropertyDescriptor(Error.prototype, 'stack').set;
+
+var nativeErrors = [
+  Error,
+  EvalError,
+  RangeError,
+  ReferenceError,
+  SyntaxError,
+  TypeError,
+  URIError
+];
+
+for (var i = 0; i < nativeErrors.length; ++i) {
+  var Ctor = nativeErrors[i];
+  var err = new Ctor('msg');
+  set.call(err, '');
+
+  // Verify the round-trip via property access before invoking verifyProperty
+  // (which deletes the configurable own property as part of its check).
+  assert.sameValue(err.stack, '', Ctor.name + ': empty string round-trips through property access');
+
+  verifyProperty(err, 'stack', {
+    value: '',
+    writable: true,
+    enumerable: true,
+    configurable: true,
+  });
+}
diff --git a/test/built-ins/Error/prototype/stack/setter-existing-own-property.js b/test/built-ins/Error/prototype/stack/setter-existing-own-property.js
new file mode 100644
index 0000000..a20846c
--- /dev/null
+++ b/test/built-ins/Error/prototype/stack/setter-existing-own-property.js
@@ -0,0 +1,62 @@
+// Copyright (C) 2026 Jordan Harband. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-set-error.prototype.stack
+description: >
+  When the receiver already has an own "stack" data property, the setter
+  performs a [[Set]] on it (preserving its current attributes).
+info: |
+  set Error.prototype.stack
+
+  1. Let E be the this value.
+  2. If E is not an Object, throw a TypeError exception.
+  3. If v is not a String, throw a TypeError exception.
+  4. Perform ? SetterThatIgnoresPrototypeProperties(this value, %Error.prototype%, "stack", v).
+  5. Return undefined.
+
+  SetterThatIgnoresPrototypeProperties ( this, home, p, v )
+
+  [...]
+  3. Let desc be ? this.[[GetOwnProperty]](p).
+  4. If desc is undefined, then
+    a. Perform ? CreateDataPropertyOrThrow(this, p, v).
+  5. Else,
+    a. Perform ? Set(this, p, v, true).
+  [...]
+includes: [propertyHelper.js]
+features: [error-stack-accessor]
+---*/
+
+var set = Object.getOwnPropertyDescriptor(Error.prototype, 'stack').set;
+
+var nativeErrors = [
+  Error,
+  EvalError,
+  RangeError,
+  ReferenceError,
+  SyntaxError,
+  TypeError,
+  URIError
+];
+
+for (var i = 0; i < nativeErrors.length; ++i) {
+  var Ctor = nativeErrors[i];
+  var err = new Ctor('msg');
+  Object.defineProperty(err, 'stack', {
+    value: 'original',
+    writable: true,
+    enumerable: false,
+    configurable: false,
+  });
+
+  set.call(err, 'updated');
+
+  // The existing descriptor is preserved; only the value changes (per [[Set]]).
+  verifyProperty(err, 'stack', {
+    value: 'updated',
+    writable: true,
+    enumerable: false,
+    configurable: false,
+  });
+}
diff --git a/test/built-ins/Error/prototype/stack/setter-length.js b/test/built-ins/Error/prototype/stack/setter-length.js
new file mode 100644
index 0000000..d85ffa8
--- /dev/null
+++ b/test/built-ins/Error/prototype/stack/setter-length.js
@@ -0,0 +1,31 @@
+// Copyright (C) 2026 Jordan Harband. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-set-error.prototype.stack
+description: >
+  set Error.prototype.stack.length is 1.
+info: |
+  set Error.prototype.stack
+
+  17 ECMAScript Standard Built-in Objects:
+    Every built-in function object, including constructors, has a length
+    property whose value is an integer. Unless otherwise specified, this
+    value is equal to the largest number of named arguments shown in the
+    subclause headings for the function description.
+
+    Unless otherwise specified, the length property of a built-in function
+    object has the attributes { [[Writable]]: false, [[Enumerable]]: false,
+    [[Configurable]]: true }.
+includes: [propertyHelper.js]
+features: [error-stack-accessor]
+---*/
+
+var set = Object.getOwnPropertyDescriptor(Error.prototype, 'stack').set;
+
+verifyProperty(set, 'length', {
+  value: 1,
+  writable: false,
+  enumerable: false,
+  configurable: true,
+});
diff --git a/test/built-ins/Error/prototype/stack/setter-name.js b/test/built-ins/Error/prototype/stack/setter-name.js
new file mode 100644
index 0000000..2a17203
--- /dev/null
+++ b/test/built-ins/Error/prototype/stack/setter-name.js
@@ -0,0 +1,30 @@
+// Copyright (C) 2026 Jordan Harband. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-set-error.prototype.stack
+description: >
+  set Error.prototype.stack.name is "set stack".
+info: |
+  set Error.prototype.stack
+
+  17 ECMAScript Standard Built-in Objects
+
+  Functions that are specified as get or set accessor functions of built-in
+  properties have "get " or "set " prepended to the property name string.
+
+  Unless otherwise specified, the name property of a built-in function object,
+  if it exists, has the attributes { [[Writable]]: false, [[Enumerable]]: false,
+  [[Configurable]]: true }.
+includes: [propertyHelper.js]
+features: [error-stack-accessor]
+---*/
+
+var set = Object.getOwnPropertyDescriptor(Error.prototype, 'stack').set;
+
+verifyProperty(set, 'name', {
+  value: 'set stack',
+  writable: false,
+  enumerable: false,
+  configurable: true,
+});
diff --git a/test/built-ins/Error/prototype/stack/setter-no-argument.js b/test/built-ins/Error/prototype/stack/setter-no-argument.js
new file mode 100644
index 0000000..91865ad
--- /dev/null
+++ b/test/built-ins/Error/prototype/stack/setter-no-argument.js
@@ -0,0 +1,37 @@
+// Copyright (C) 2026 Jordan Harband. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-set-error.prototype.stack
+description: >
+  When the setter is called with no argument, v is undefined, which is not a
+  String, so a TypeError is thrown.
+info: |
+  set Error.prototype.stack
+
+  1. Let E be the this value.
+  2. If E is not an Object, throw a TypeError exception.
+  3. If v is not a String, throw a TypeError exception.
+features: [error-stack-accessor]
+---*/
+
+var set = Object.getOwnPropertyDescriptor(Error.prototype, 'stack').set;
+
+var nativeErrors = [
+  Error,
+  EvalError,
+  RangeError,
+  ReferenceError,
+  SyntaxError,
+  TypeError,
+  URIError
+];
+
+for (var i = 0; i < nativeErrors.length; ++i) {
+  var Ctor = nativeErrors[i];
+  var err = new Ctor('msg');
+
+  assert.throws(TypeError, function () {
+    set.call(err);
+  }, Ctor.name);
+}
diff --git a/test/built-ins/Error/prototype/stack/setter-non-error-receiver.js b/test/built-ins/Error/prototype/stack/setter-non-error-receiver.js
new file mode 100644
index 0000000..221628e
--- /dev/null
+++ b/test/built-ins/Error/prototype/stack/setter-non-error-receiver.js
@@ -0,0 +1,61 @@
+// Copyright (C) 2026 Jordan Harband. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-set-error.prototype.stack
+description: >
+  The setter does not check for the [[ErrorData]] internal slot, so it works
+  on any extensible object that is not %Error.prototype%.
+info: |
+  set Error.prototype.stack
+
+  1. Let E be the this value.
+  2. If E is not an Object, throw a TypeError exception.
+  3. If v is not a String, throw a TypeError exception.
+  4. Perform ? SetterThatIgnoresPrototypeProperties(this value, %Error.prototype%, "stack", v).
+  5. Return undefined.
+includes: [propertyHelper.js]
+features: [error-stack-accessor]
+---*/
+
+var set = Object.getOwnPropertyDescriptor(Error.prototype, 'stack').set;
+
+// Plain object: installs an own data property.
+var plain = {};
+set.call(plain, 'plain');
+verifyProperty(plain, 'stack', {
+  value: 'plain',
+  writable: true,
+  enumerable: true,
+  configurable: true,
+});
+
+// Array: installs an own data property.
+var arr = [];
+set.call(arr, 'array');
+verifyProperty(arr, 'stack', {
+  value: 'array',
+  writable: true,
+  enumerable: true,
+  configurable: true,
+});
+
+// Function: installs an own data property.
+var fn = function () {};
+set.call(fn, 'function');
+verifyProperty(fn, 'stack', {
+  value: 'function',
+  writable: true,
+  enumerable: true,
+  configurable: true,
+});
+
+// Object whose prototype is Error.prototype but lacks [[ErrorData]]: still works.
+var fakeError = Object.create(Error.prototype);
+set.call(fakeError, 'fake');
+verifyProperty(fakeError, 'stack', {
+  value: 'fake',
+  writable: true,
+  enumerable: true,
+  configurable: true,
+});
diff --git a/test/built-ins/Error/prototype/stack/setter-non-extensible-receiver.js b/test/built-ins/Error/prototype/stack/setter-non-extensible-receiver.js
new file mode 100644
index 0000000..bf99d63
--- /dev/null
+++ b/test/built-ins/Error/prototype/stack/setter-non-extensible-receiver.js
@@ -0,0 +1,85 @@
+// Copyright (C) 2026 Jordan Harband. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-set-error.prototype.stack
+description: >
+  When the receiver lacks an own "stack" property and has any integrity level
+  applied (preventExtensions, seal, freeze), the setter throws a TypeError
+  because CreateDataPropertyOrThrow cannot add a property to a non-extensible
+  object.
+info: |
+  set Error.prototype.stack
+
+  [...]
+  4. Perform ? SetterThatIgnoresPrototypeProperties(this value, %Error.prototype%, "stack", v).
+
+  SetterThatIgnoresPrototypeProperties ( this, home, p, v )
+
+  [...]
+  3. Let desc be ? this.[[GetOwnProperty]](p).
+  4. If desc is undefined, then
+    a. Perform ? CreateDataPropertyOrThrow(this, p, v).
+
+  CreateDataPropertyOrThrow ( O, P, V )
+
+  [...]
+  3. Let success be ? CreateDataProperty(O, P, V).
+  4. If success is false, throw a TypeError exception.
+features: [error-stack-accessor]
+---*/
+
+var set = Object.getOwnPropertyDescriptor(Error.prototype, 'stack').set;
+
+var nativeErrors = [
+  Error,
+  EvalError,
+  RangeError,
+  ReferenceError,
+  SyntaxError,
+  TypeError,
+  URIError
+];
+
+var integrityLevels = [
+  { name: 'preventExtensions', fn: Object.preventExtensions },
+  { name: 'seal', fn: Object.seal },
+  { name: 'freeze', fn: Object.freeze }
+];
+
+for (var i = 0; i < nativeErrors.length; ++i) {
+  var Ctor = nativeErrors[i];
+
+  for (var j = 0; j < integrityLevels.length; ++j) {
+    var level = integrityLevels[j];
+    var label = Ctor.name + '/' + level.name;
+
+    var err = new Ctor('msg');
+    assert.sameValue(
+      Object.prototype.hasOwnProperty.call(err, 'stack'),
+      false,
+      label + ': precondition: instance has no own "stack" property at construction'
+    );
+
+    level.fn(err);
+
+    assert.throws(TypeError, function () {
+      set.call(err, 'sentinel');
+    }, label + ': instance without own "stack" rejects setter');
+
+    assert.sameValue(
+      Object.prototype.hasOwnProperty.call(err, 'stack'),
+      false,
+      label + ': no own "stack" property was created'
+    );
+  }
+}
+
+// Same behavior on plain objects at each integrity level.
+for (var k = 0; k < integrityLevels.length; ++k) {
+  var lvl = integrityLevels[k];
+  var obj = lvl.fn({});
+  assert.throws(TypeError, function () {
+    set.call(obj, 'sentinel');
+  }, lvl.name + ' plain object without own "stack"');
+}
diff --git a/test/built-ins/Error/prototype/stack/setter-non-string-value-bigint.js b/test/built-ins/Error/prototype/stack/setter-non-string-value-bigint.js
new file mode 100644
index 0000000..3366661
--- /dev/null
+++ b/test/built-ins/Error/prototype/stack/setter-non-string-value-bigint.js
@@ -0,0 +1,36 @@
+// Copyright (C) 2026 Jordan Harband. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-set-error.prototype.stack
+description: >
+  Throws a TypeError if the value being assigned is a BigInt.
+info: |
+  set Error.prototype.stack
+
+  1. Let E be the this value.
+  2. If E is not an Object, throw a TypeError exception.
+  3. If v is not a String, throw a TypeError exception.
+features: [error-stack-accessor, BigInt]
+---*/
+
+var set = Object.getOwnPropertyDescriptor(Error.prototype, 'stack').set;
+
+var nativeErrors = [
+  Error,
+  EvalError,
+  RangeError,
+  ReferenceError,
+  SyntaxError,
+  TypeError,
+  URIError
+];
+
+for (var i = 0; i < nativeErrors.length; ++i) {
+  var Ctor = nativeErrors[i];
+  var err = new Ctor('msg');
+
+  assert.throws(TypeError, function () {
+    set.call(err, 0n);
+  }, Ctor.name);
+}
diff --git a/test/built-ins/Error/prototype/stack/setter-non-string-value-symbol.js b/test/built-ins/Error/prototype/stack/setter-non-string-value-symbol.js
new file mode 100644
index 0000000..dd01797
--- /dev/null
+++ b/test/built-ins/Error/prototype/stack/setter-non-string-value-symbol.js
@@ -0,0 +1,36 @@
+// Copyright (C) 2026 Jordan Harband. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-set-error.prototype.stack
+description: >
+  Throws a TypeError if the value being assigned is a Symbol.
+info: |
+  set Error.prototype.stack
+
+  1. Let E be the this value.
+  2. If E is not an Object, throw a TypeError exception.
+  3. If v is not a String, throw a TypeError exception.
+features: [error-stack-accessor, Symbol]
+---*/
+
+var set = Object.getOwnPropertyDescriptor(Error.prototype, 'stack').set;
+
+var nativeErrors = [
+  Error,
+  EvalError,
+  RangeError,
+  ReferenceError,
+  SyntaxError,
+  TypeError,
+  URIError
+];
+
+for (var i = 0; i < nativeErrors.length; ++i) {
+  var Ctor = nativeErrors[i];
+  var err = new Ctor('msg');
+
+  assert.throws(TypeError, function () {
+    set.call(err, Symbol('s'));
+  }, Ctor.name);
+}
diff --git a/test/built-ins/Error/prototype/stack/setter-non-string-value.js b/test/built-ins/Error/prototype/stack/setter-non-string-value.js
new file mode 100644
index 0000000..2046a7a
--- /dev/null
+++ b/test/built-ins/Error/prototype/stack/setter-non-string-value.js
@@ -0,0 +1,75 @@
+// Copyright (C) 2026 Jordan Harband. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-set-error.prototype.stack
+description: >
+  Throws a TypeError if the value being assigned is not a String.
+info: |
+  set Error.prototype.stack
+
+  1. Let E be the this value.
+  2. If E is not an Object, throw a TypeError exception.
+  3. If v is not a String, throw a TypeError exception.
+features: [error-stack-accessor]
+---*/
+
+var set = Object.getOwnPropertyDescriptor(Error.prototype, 'stack').set;
+
+var nativeErrors = [
+  Error,
+  EvalError,
+  RangeError,
+  ReferenceError,
+  SyntaxError,
+  TypeError,
+  URIError
+];
+
+for (var i = 0; i < nativeErrors.length; ++i) {
+  var Ctor = nativeErrors[i];
+  var err = new Ctor('msg');
+
+  assert.throws(TypeError, function () {
+    set.call(err, undefined);
+  }, Ctor.name + ': undefined');
+
+  assert.throws(TypeError, function () {
+    set.call(err, null);
+  }, Ctor.name + ': null');
+
+  assert.throws(TypeError, function () {
+    set.call(err, true);
+  }, Ctor.name + ': true');
+
+  assert.throws(TypeError, function () {
+    set.call(err, false);
+  }, Ctor.name + ': false');
+
+  assert.throws(TypeError, function () {
+    set.call(err, 1);
+  }, Ctor.name + ': number');
+
+  assert.throws(TypeError, function () {
+    set.call(err, {});
+  }, Ctor.name + ': object');
+
+  assert.throws(TypeError, function () {
+    set.call(err, []);
+  }, Ctor.name + ': array');
+
+  // An object with a toString method is not coerced; the algorithm requires v
+  // to already be a String.
+  var coercible = {
+    toString: function () { return 'coerced'; },
+    valueOf: function () { return 'coerced'; },
+  };
+  assert.throws(TypeError, function () {
+    set.call(err, coercible);
+  }, Ctor.name + ': object with toString');
+
+  // Boxed strings are still objects, not Strings.
+  assert.throws(TypeError, function () {
+    set.call(err, new String('boxed'));
+  }, Ctor.name + ': String wrapper object');
+}
diff --git a/test/built-ins/Error/prototype/stack/setter-non-writable-stack.js b/test/built-ins/Error/prototype/stack/setter-non-writable-stack.js
new file mode 100644
index 0000000..0f46930
--- /dev/null
+++ b/test/built-ins/Error/prototype/stack/setter-non-writable-stack.js
@@ -0,0 +1,80 @@
+// Copyright (C) 2026 Jordan Harband. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-set-error.prototype.stack
+description: >
+  When the receiver has an own non-writable "stack" data property, the setter
+  throws a TypeError because the underlying [[Set]] is invoked with Throw=true.
+info: |
+  set Error.prototype.stack
+
+  [...]
+  4. Perform ? SetterThatIgnoresPrototypeProperties(this value, %Error.prototype%, "stack", v).
+
+  SetterThatIgnoresPrototypeProperties ( this, home, p, v )
+
+  [...]
+  3. Let desc be ? this.[[GetOwnProperty]](p).
+  [...]
+  5. Else,
+    a. Perform ? Set(this, p, v, true).
+includes: [propertyHelper.js]
+features: [error-stack-accessor]
+---*/
+
+var set = Object.getOwnPropertyDescriptor(Error.prototype, 'stack').set;
+
+var nativeErrors = [
+  Error,
+  EvalError,
+  RangeError,
+  ReferenceError,
+  SyntaxError,
+  TypeError,
+  URIError
+];
+
+for (var i = 0; i < nativeErrors.length; ++i) {
+  var Ctor = nativeErrors[i];
+
+  var err = new Ctor('msg');
+  Object.defineProperty(err, 'stack', {
+    value: 'original',
+    writable: false,
+    enumerable: false,
+    configurable: true,
+  });
+
+  assert.throws(TypeError, function () {
+    set.call(err, 'updated');
+  }, Ctor.name + ': non-writable own "stack"');
+
+  verifyProperty(err, 'stack', {
+    value: 'original',
+    writable: false,
+    enumerable: false,
+    configurable: true,
+  });
+
+  // Frozen instance with an own "stack" data property: still throws.
+  var frozen = new Ctor('msg');
+  Object.defineProperty(frozen, 'stack', {
+    value: 'frozen-original',
+    writable: false,
+    enumerable: false,
+    configurable: false,
+  });
+  Object.preventExtensions(frozen);
+
+  assert.throws(TypeError, function () {
+    set.call(frozen, 'updated');
+  }, Ctor.name + ': frozen with non-writable own "stack"');
+
+  verifyProperty(frozen, 'stack', {
+    value: 'frozen-original',
+    writable: false,
+    enumerable: false,
+    configurable: false,
+  });
+}
diff --git a/test/built-ins/Error/prototype/stack/setter-not-a-constructor.js b/test/built-ins/Error/prototype/stack/setter-not-a-constructor.js
new file mode 100644
index 0000000..4229fb2
--- /dev/null
+++ b/test/built-ins/Error/prototype/stack/setter-not-a-constructor.js
@@ -0,0 +1,28 @@
+// Copyright (C) 2026 Jordan Harband. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-set-error.prototype.stack
+description: >
+  set Error.prototype.stack does not implement [[Construct]], is not new-able
+info: |
+  ECMAScript Function Objects
+
+  Built-in function objects that are not identified as constructors do not
+  implement the [[Construct]] internal method unless otherwise specified in
+  the description of a particular function.
+includes: [isConstructor.js]
+features: [error-stack-accessor, Reflect.construct]
+---*/
+
+var set = Object.getOwnPropertyDescriptor(Error.prototype, 'stack').set;
+
+assert.sameValue(
+  isConstructor(set),
+  false,
+  'isConstructor(set Error.prototype.stack) must return false'
+);
+
+assert.throws(TypeError, function () {
+  new set('');
+});
diff --git a/test/built-ins/Error/prototype/stack/setter-null-proto-receiver.js b/test/built-ins/Error/prototype/stack/setter-null-proto-receiver.js
new file mode 100644
index 0000000..c34191b
--- /dev/null
+++ b/test/built-ins/Error/prototype/stack/setter-null-proto-receiver.js
@@ -0,0 +1,31 @@
+// Copyright (C) 2026 Jordan Harband. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-set-error.prototype.stack
+description: >
+  The setter installs an own "stack" data property on a null-prototype object.
+  The setter does not depend on inherited machinery from Object.prototype.
+info: |
+  set Error.prototype.stack
+
+  1. Let E be the this value.
+  2. If E is not an Object, throw a TypeError exception.
+  3. If v is not a String, throw a TypeError exception.
+  4. Perform ? SetterThatIgnoresPrototypeProperties(this value, %Error.prototype%, "stack", v).
+  5. Return undefined.
+includes: [propertyHelper.js]
+features: [error-stack-accessor, __proto__]
+---*/
+
+var set = Object.getOwnPropertyDescriptor(Error.prototype, 'stack').set;
+
+var nullProto = { __proto__: null };
+set.call(nullProto, 'null-proto');
+
+verifyProperty(nullProto, 'stack', {
+  value: 'null-proto',
+  writable: true,
+  enumerable: true,
+  configurable: true,
+});
diff --git a/test/built-ins/Error/prototype/stack/setter-own-accessor.js b/test/built-ins/Error/prototype/stack/setter-own-accessor.js
new file mode 100644
index 0000000..5d7dc6f
--- /dev/null
+++ b/test/built-ins/Error/prototype/stack/setter-own-accessor.js
@@ -0,0 +1,65 @@
+// Copyright (C) 2026 Jordan Harband. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-set-error.prototype.stack
+description: >
+  When the receiver has an own "stack" accessor property, the setter performs
+  [[Set]] which invokes the own setter (or throws if the accessor has no
+  setter).
+info: |
+  set Error.prototype.stack
+
+  [...]
+  4. Perform ? SetterThatIgnoresPrototypeProperties(this value, %Error.prototype%, "stack", v).
+
+  SetterThatIgnoresPrototypeProperties ( this, home, p, v )
+
+  [...]
+  3. Let desc be ? this.[[GetOwnProperty]](p).
+  [...]
+  5. Else,
+    a. Perform ? Set(this, p, v, true).
+features: [error-stack-accessor]
+---*/
+
+var set = Object.getOwnPropertyDescriptor(Error.prototype, 'stack').set;
+
+var nativeErrors = [
+  Error,
+  EvalError,
+  RangeError,
+  ReferenceError,
+  SyntaxError,
+  TypeError,
+  URIError
+];
+
+for (var i = 0; i < nativeErrors.length; ++i) {
+  var Ctor = nativeErrors[i];
+
+  // (a) Own accessor with a setter: the own setter receives v.
+  var observed;
+  var withSetter = new Ctor('msg');
+  Object.defineProperty(withSetter, 'stack', {
+    get: function () { return observed; },
+    set: function (v) { observed = v; },
+    enumerable: false,
+    configurable: true,
+  });
+
+  set.call(withSetter, 'sentinel');
+  assert.sameValue(observed, 'sentinel', Ctor.name + ': own setter received the value');
+
+  // (b) Own accessor with no setter: Set with Throw=true throws TypeError.
+  var withoutSetter = new Ctor('msg');
+  Object.defineProperty(withoutSetter, 'stack', {
+    get: function () { return 'getter-only'; },
+    enumerable: false,
+    configurable: true,
+  });
+
+  assert.throws(TypeError, function () {
+    set.call(withoutSetter, 'sentinel');
+  }, Ctor.name + ': own accessor without a setter');
+}
diff --git a/test/built-ins/Error/prototype/stack/setter-proxy-receiver.js b/test/built-ins/Error/prototype/stack/setter-proxy-receiver.js
new file mode 100644
index 0000000..5c7ab4f
--- /dev/null
+++ b/test/built-ins/Error/prototype/stack/setter-proxy-receiver.js
@@ -0,0 +1,98 @@
+// Copyright (C) 2026 Jordan Harband. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-set-error.prototype.stack
+description: >
+  The setter calls [[GetOwnProperty]] and either [[DefineOwnProperty]] (via
+  CreateDataPropertyOrThrow) or [[Set]] on the receiver, observably invoking
+  Proxy traps.
+info: |
+  SetterThatIgnoresPrototypeProperties ( this, home, p, v )
+
+  [...]
+  3. Let desc be ? this.[[GetOwnProperty]](p).
+  4. If desc is undefined, then
+    a. Perform ? CreateDataPropertyOrThrow(this, p, v).
+  5. Else,
+    a. Perform ? Set(this, p, v, true).
+features: [error-stack-accessor, Proxy, Reflect]
+---*/
+
+var set = Object.getOwnPropertyDescriptor(Error.prototype, 'stack').set;
+
+// (a) Proxy with no own "stack": getOwnPropertyDescriptor then defineProperty.
+var trapLog = [];
+var target1 = {};
+var p1 = new Proxy(target1, {
+  getOwnPropertyDescriptor: function (t, key) {
+    trapLog.push(['gOPD', key]);
+    return Object.getOwnPropertyDescriptor(t, key);
+  },
+  defineProperty: function (t, key, desc) {
+    trapLog.push(['define', key, desc]);
+    return Reflect.defineProperty(t, key, desc);
+  },
+  set: function () {
+    trapLog.push(['set']);
+    throw new Test262Error('set trap should not be invoked when no own property exists');
+  },
+});
+
+set.call(p1, 'sentinel');
+assert(trapLog.length >= 2, 'at least getOwnPropertyDescriptor and defineProperty were called');
+assert.sameValue(trapLog[0][0], 'gOPD', 'first trap is getOwnPropertyDescriptor');
+assert.sameValue(trapLog[0][1], 'stack', 'getOwnPropertyDescriptor was called for "stack"');
+
+var lastDefine = null;
+for (var i = 0; i < trapLog.length; ++i) {
+  if (trapLog[i][0] === 'define') {
+    lastDefine = trapLog[i];
+  }
+}
+assert.notSameValue(lastDefine, null, 'defineProperty trap was invoked');
+assert.sameValue(lastDefine[1], 'stack', 'defineProperty was called for "stack"');
+
+// CreateDataProperty constructs the descriptor record
+// { [[Value]]: V, [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true };
+// FromPropertyDescriptor converts that into a plain Object with exactly those
+// four own properties before invoking the defineProperty trap.
+var passedDesc = lastDefine[2];
+assert.sameValue(passedDesc.value, 'sentinel', 'descriptor.value');
+assert.sameValue(passedDesc.writable, true, 'descriptor.writable');
+assert.sameValue(passedDesc.enumerable, true, 'descriptor.enumerable');
+assert.sameValue(passedDesc.configurable, true, 'descriptor.configurable');
+assert.sameValue('get' in passedDesc, false, 'descriptor has no get key');
+assert.sameValue('set' in passedDesc, false, 'descriptor has no set key');
+assert.sameValue(target1.stack, 'sentinel', 'value reached the underlying target');
+
+// (b) Proxy with own "stack": getOwnPropertyDescriptor then set trap.
+var trapLog2 = [];
+var target2 = { stack: 'old' };
+var p2 = new Proxy(target2, {
+  getOwnPropertyDescriptor: function (t, key) {
+    trapLog2.push(['gOPD', key]);
+    return Object.getOwnPropertyDescriptor(t, key);
+  },
+  set: function (t, key, value) {
+    trapLog2.push(['set', key, value]);
+    t[key] = value;
+    return true;
+  },
+  defineProperty: function () {
+    trapLog2.push(['define']);
+    throw new Test262Error('defineProperty trap should not be invoked when own property exists');
+  },
+});
+
+set.call(p2, 'updated');
+var sawSet = false;
+for (var j = 0; j < trapLog2.length; ++j) {
+  if (trapLog2[j][0] === 'set') {
+    sawSet = true;
+    assert.sameValue(trapLog2[j][1], 'stack', 'set was called for "stack"');
+    assert.sameValue(trapLog2[j][2], 'updated', 'set received the value');
+  }
+}
+assert.sameValue(sawSet, true, 'set trap was invoked');
+assert.sameValue(target2.stack, 'updated', 'value reached the underlying target');
diff --git a/test/built-ins/Error/prototype/stack/setter-proxy-trap-rejects.js b/test/built-ins/Error/prototype/stack/setter-proxy-trap-rejects.js
new file mode 100644
index 0000000..8b35620
--- /dev/null
+++ b/test/built-ins/Error/prototype/stack/setter-proxy-trap-rejects.js
@@ -0,0 +1,59 @@
+// Copyright (C) 2026 Jordan Harband. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-set-error.prototype.stack
+description: >
+  When a Proxy receiver's defineProperty trap returns false during the
+  CreateDataPropertyOrThrow path, or its set trap returns false during the
+  Set-with-Throw=true path, the setter throws TypeError.
+info: |
+  set Error.prototype.stack
+
+  [...]
+  4. Perform ? SetterThatIgnoresPrototypeProperties(this value, %Error.prototype%, "stack", v).
+
+  SetterThatIgnoresPrototypeProperties ( this, home, p, v )
+
+  [...]
+  3. Let desc be ? this.[[GetOwnProperty]](p).
+  4. If desc is undefined, then
+    a. Perform ? CreateDataPropertyOrThrow(this, p, v).
+  5. Else,
+    a. Perform ? Set(this, p, v, true).
+
+  CreateDataPropertyOrThrow ( O, P, V )
+
+  [...]
+  3. Let success be ? CreateDataProperty(O, P, V).
+  4. If success is false, throw a TypeError exception.
+
+  Set ( O, P, V, Throw )
+
+  [...]
+  3. Let success be ? O.[[Set]](P, V, O).
+  4. If success is false and Throw is true, throw a TypeError exception.
+features: [error-stack-accessor, Proxy]
+---*/
+
+var set = Object.getOwnPropertyDescriptor(Error.prototype, 'stack').set;
+
+// (a) defineProperty trap returns false (no own stack: CreateDataPropertyOrThrow path).
+var pA = new Proxy({}, {
+  defineProperty: function () {
+    return false;
+  },
+});
+assert.throws(TypeError, function () {
+  set.call(pA, 'v');
+}, 'defineProperty returns false');
+
+// (b) set trap returns false (own stack present: Set with Throw=true path).
+var pB = new Proxy({ stack: 'old' }, {
+  set: function () {
+    return false;
+  },
+});
+assert.throws(TypeError, function () {
+  set.call(pB, 'v');
+}, 'set trap returns false');
diff --git a/test/built-ins/Error/prototype/stack/setter-proxy-trap-throws.js b/test/built-ins/Error/prototype/stack/setter-proxy-trap-throws.js
new file mode 100644
index 0000000..89bafda
--- /dev/null
+++ b/test/built-ins/Error/prototype/stack/setter-proxy-trap-throws.js
@@ -0,0 +1,58 @@
+// Copyright (C) 2026 Jordan Harband. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-set-error.prototype.stack
+description: >
+  Errors thrown by Proxy traps invoked during the setter propagate out via
+  the ? abstract operations in SetterThatIgnoresPrototypeProperties.
+info: |
+  set Error.prototype.stack
+
+  [...]
+  4. Perform ? SetterThatIgnoresPrototypeProperties(this value, %Error.prototype%, "stack", v).
+
+  SetterThatIgnoresPrototypeProperties ( this, home, p, v )
+
+  [...]
+  3. Let desc be ? this.[[GetOwnProperty]](p).
+  4. If desc is undefined, then
+    a. Perform ? CreateDataPropertyOrThrow(this, p, v).
+  5. Else,
+    a. Perform ? Set(this, p, v, true).
+features: [error-stack-accessor, Proxy]
+---*/
+
+var set = Object.getOwnPropertyDescriptor(Error.prototype, 'stack').set;
+
+function Sentinel() {}
+
+// (a) getOwnPropertyDescriptor trap throws: error propagates from step 3.
+var pA = new Proxy({}, {
+  getOwnPropertyDescriptor: function () {
+    throw new Sentinel();
+  },
+});
+assert.throws(Sentinel, function () {
+  set.call(pA, 'v');
+}, 'getOwnPropertyDescriptor trap throw');
+
+// (b) defineProperty trap throws (no own stack: CreateDataPropertyOrThrow path).
+var pB = new Proxy({}, {
+  defineProperty: function () {
+    throw new Sentinel();
+  },
+});
+assert.throws(Sentinel, function () {
+  set.call(pB, 'v');
+}, 'defineProperty trap throw');
+
+// (c) set trap throws (own stack present: Set path).
+var pC = new Proxy({ stack: 'old' }, {
+  set: function () {
+    throw new Sentinel();
+  },
+});
+assert.throws(Sentinel, function () {
+  set.call(pC, 'v');
+}, 'set trap throw');
diff --git a/test/built-ins/Error/prototype/stack/setter-proxy-wrapping-prototype.js b/test/built-ins/Error/prototype/stack/setter-proxy-wrapping-prototype.js
new file mode 100644
index 0000000..d528fea
--- /dev/null
+++ b/test/built-ins/Error/prototype/stack/setter-proxy-wrapping-prototype.js
@@ -0,0 +1,65 @@
+// Copyright (C) 2026 Jordan Harband. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-set-error.prototype.stack
+description: >
+  The home-object check uses SameValue on object identity. A Proxy wrapping
+  %Error.prototype% is not the same object as %Error.prototype% itself, so
+  step 2 of SetterThatIgnoresPrototypeProperties does not fire; the algorithm
+  proceeds to consult the proxy's [[GetOwnProperty]] / [[Set]] traps.
+info: |
+  set Error.prototype.stack
+
+  [...]
+  4. Perform ? SetterThatIgnoresPrototypeProperties(this value, %Error.prototype%, "stack", v).
+
+  SetterThatIgnoresPrototypeProperties ( this, home, p, v )
+
+  [...]
+  2. If SameValue(this, home) is true, then
+    a. Throw a TypeError exception.
+  3. Let desc be ? this.[[GetOwnProperty]](p).
+  4. If desc is undefined, then
+    a. Perform ? CreateDataPropertyOrThrow(this, p, v).
+  5. Else,
+    a. Perform ? Set(this, p, v, true).
+features: [error-stack-accessor, Proxy]
+---*/
+
+var set = Object.getOwnPropertyDescriptor(Error.prototype, 'stack').set;
+
+var trapLog = [];
+var p = new Proxy(Error.prototype, {
+  getOwnPropertyDescriptor: function (t, key) {
+    trapLog.push(['gOPD', key]);
+    return Object.getOwnPropertyDescriptor(t, key);
+  },
+  set: function (t, key, value) {
+    trapLog.push(['set', key, value]);
+    // Don't actually mutate Error.prototype; just acknowledge.
+    return true;
+  },
+});
+
+// SameValue(p, Error.prototype) is false: a Proxy is a distinct object from
+// its target. Step 2 does not throw; the algorithm proceeds to query the
+// proxy's traps.
+set.call(p, 'sentinel');
+
+assert(trapLog.length >= 1, 'at least one trap was invoked');
+assert.sameValue(trapLog[0][0], 'gOPD', 'getOwnPropertyDescriptor trap fired first');
+assert.sameValue(trapLog[0][1], 'stack', 'getOwnPropertyDescriptor trap was called for "stack"');
+
+// Error.prototype's own "stack" descriptor is an accessor, so step 5 of
+// SetterThatIgnoresPrototypeProperties takes the Set path, which invokes the
+// proxy's set trap.
+var sawSet = false;
+for (var i = 0; i < trapLog.length; ++i) {
+  if (trapLog[i][0] === 'set') {
+    sawSet = true;
+    assert.sameValue(trapLog[i][1], 'stack', 'set trap was called for "stack"');
+    assert.sameValue(trapLog[i][2], 'sentinel', 'set trap received the value');
+  }
+}
+assert.sameValue(sawSet, true, 'set trap was invoked');
diff --git a/test/built-ins/Error/prototype/stack/setter-receiver-is-aggregate-error-prototype.js b/test/built-ins/Error/prototype/stack/setter-receiver-is-aggregate-error-prototype.js
new file mode 100644
index 0000000..d0d5efe
--- /dev/null
+++ b/test/built-ins/Error/prototype/stack/setter-receiver-is-aggregate-error-prototype.js
@@ -0,0 +1,40 @@
+// Copyright (C) 2026 Jordan Harband. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-set-error.prototype.stack
+description: >
+  Calling the setter with AggregateError.prototype as the receiver does NOT
+  throw via the home-object check (which is locked to %Error.prototype%); it
+  installs an own data property on AggregateError.prototype.
+info: |
+  set Error.prototype.stack
+
+  [...]
+  4. Perform ? SetterThatIgnoresPrototypeProperties(this value, %Error.prototype%, "stack", v).
+includes: [propertyHelper.js]
+features: [error-stack-accessor, AggregateError]
+---*/
+
+var set = Object.getOwnPropertyDescriptor(Error.prototype, 'stack').set;
+
+assert.sameValue(
+  Object.getOwnPropertyDescriptor(AggregateError.prototype, 'stack'),
+  undefined,
+  'precondition: AggregateError.prototype has no own "stack"'
+);
+
+set.call(AggregateError.prototype, 'sentinel');
+
+verifyProperty(AggregateError.prototype, 'stack', {
+  value: 'sentinel',
+  writable: true,
+  enumerable: true,
+  configurable: true,
+});
+
+assert.sameValue(
+  Object.getOwnPropertyDescriptor(AggregateError.prototype, 'stack'),
+  undefined,
+  'cleanup'
+);
diff --git a/test/built-ins/Error/prototype/stack/setter-receiver-is-other-prototype.js b/test/built-ins/Error/prototype/stack/setter-receiver-is-other-prototype.js
new file mode 100644
index 0000000..13cd021
--- /dev/null
+++ b/test/built-ins/Error/prototype/stack/setter-receiver-is-other-prototype.js
@@ -0,0 +1,70 @@
+// Copyright (C) 2026 Jordan Harband. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-set-error.prototype.stack
+description: >
+  The SameValue check in SetterThatIgnoresPrototypeProperties is locked to
+  %Error.prototype% only. Calling the setter with any other prototype object
+  (NativeError prototypes, AggregateError.prototype) as the receiver does NOT
+  throw via the home-object check; it installs an own data property on that
+  prototype.
+info: |
+  set Error.prototype.stack
+
+  [...]
+  4. Perform ? SetterThatIgnoresPrototypeProperties(this value, %Error.prototype%, "stack", v).
+
+  SetterThatIgnoresPrototypeProperties ( this, home, p, v )
+
+  [...]
+  2. If SameValue(this, home) is true, then
+    a. NOTE: Throwing here emulates assignment to a non-writable data property
+       on the home object in strict mode code.
+    b. Throw a TypeError exception.
+  3. Let desc be ? this.[[GetOwnProperty]](p).
+  4. If desc is undefined, then
+    a. Perform ? CreateDataPropertyOrThrow(this, p, v).
+includes: [propertyHelper.js]
+features: [error-stack-accessor]
+---*/
+
+var set = Object.getOwnPropertyDescriptor(Error.prototype, 'stack').set;
+
+var nativeErrors = [
+  EvalError,
+  RangeError,
+  ReferenceError,
+  SyntaxError,
+  TypeError,
+  URIError
+];
+
+for (var i = 0; i < nativeErrors.length; ++i) {
+  var Ctor = nativeErrors[i];
+  var proto = Ctor.prototype;
+
+  assert.sameValue(
+    Object.getOwnPropertyDescriptor(proto, 'stack'),
+    undefined,
+    Ctor.name + '.prototype: precondition: no own "stack" property'
+  );
+
+  set.call(proto, 'sentinel-' + Ctor.name);
+
+  verifyProperty(proto, 'stack', {
+    value: 'sentinel-' + Ctor.name,
+    writable: true,
+    enumerable: true,
+    configurable: true,
+  });
+
+  // verifyProperty above asserts configurable: true, which causes the helper
+  // to delete the property as part of its check; confirm the mutation didn't
+  // leak.
+  assert.sameValue(
+    Object.getOwnPropertyDescriptor(proto, 'stack'),
+    undefined,
+    Ctor.name + '.prototype: cleanup'
+  );
+}
diff --git a/test/built-ins/Error/prototype/stack/setter-receiver-is-prototype.js b/test/built-ins/Error/prototype/stack/setter-receiver-is-prototype.js
new file mode 100644
index 0000000..6dc1736
--- /dev/null
+++ b/test/built-ins/Error/prototype/stack/setter-receiver-is-prototype.js
@@ -0,0 +1,48 @@
+// Copyright (C) 2026 Jordan Harband. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-set-error.prototype.stack
+description: >
+  Throws a TypeError if the receiver is %Error.prototype% itself.
+info: |
+  set Error.prototype.stack
+
+  1. Let E be the this value.
+  2. If E is not an Object, throw a TypeError exception.
+  3. If v is not a String, throw a TypeError exception.
+  4. Perform ? SetterThatIgnoresPrototypeProperties(this value, %Error.prototype%, "stack", v).
+  5. Return undefined.
+
+  SetterThatIgnoresPrototypeProperties ( this, home, p, v )
+
+  1. If this is not an Object, throw a TypeError exception.
+  2. If SameValue(this, home) is true, then
+    a. NOTE: Throwing here emulates assignment to a non-writable data property
+       on the home object in strict mode code.
+    b. Throw a TypeError exception.
+  [...]
+features: [error-stack-accessor]
+---*/
+
+var set = Object.getOwnPropertyDescriptor(Error.prototype, 'stack').set;
+
+assert.throws(TypeError, function () {
+  set.call(Error.prototype, '');
+}, 'set.call(Error.prototype, "")');
+
+// Property assignment also throws. The setter throws unconditionally via
+// SetterThatIgnoresPrototypeProperties; the throw originates inside the
+// accessor function and propagates regardless of the caller's strict-mode
+// flag. (test262 runs this file in both strict and sloppy modes by default.)
+assert.throws(TypeError, function () {
+  Error.prototype.stack = '';
+}, 'assignment to Error.prototype.stack');
+
+// The accessor descriptor on Error.prototype is unchanged.
+var desc = Object.getOwnPropertyDescriptor(Error.prototype, 'stack');
+assert.notSameValue(desc, undefined, 'Error.prototype still has its own "stack" property');
+assert.sameValue(typeof desc.get, 'function', 'getter is still installed');
+assert.sameValue(typeof desc.set, 'function', 'setter is still installed');
+assert.sameValue(desc.value, undefined, 'descriptor has no value (still an accessor)');
+assert.sameValue(desc.writable, undefined, 'descriptor has no writable (still an accessor)');
diff --git a/test/built-ins/Error/prototype/stack/setter-receiver-is-suppressed-error-prototype.js b/test/built-ins/Error/prototype/stack/setter-receiver-is-suppressed-error-prototype.js
new file mode 100644
index 0000000..dbb0d46
--- /dev/null
+++ b/test/built-ins/Error/prototype/stack/setter-receiver-is-suppressed-error-prototype.js
@@ -0,0 +1,40 @@
+// Copyright (C) 2026 Jordan Harband. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-set-error.prototype.stack
+description: >
+  Calling the setter with SuppressedError.prototype as the receiver does NOT
+  throw via the home-object check (which is locked to %Error.prototype%); it
+  installs an own data property on SuppressedError.prototype.
+info: |
+  set Error.prototype.stack
+
+  [...]
+  4. Perform ? SetterThatIgnoresPrototypeProperties(this value, %Error.prototype%, "stack", v).
+includes: [propertyHelper.js]
+features: [error-stack-accessor, explicit-resource-management]
+---*/
+
+var set = Object.getOwnPropertyDescriptor(Error.prototype, 'stack').set;
+
+assert.sameValue(
+  Object.getOwnPropertyDescriptor(SuppressedError.prototype, 'stack'),
+  undefined,
+  'precondition: SuppressedError.prototype has no own "stack"'
+);
+
+set.call(SuppressedError.prototype, 'sentinel');
+
+verifyProperty(SuppressedError.prototype, 'stack', {
+  value: 'sentinel',
+  writable: true,
+  enumerable: true,
+  configurable: true,
+});
+
+assert.sameValue(
+  Object.getOwnPropertyDescriptor(SuppressedError.prototype, 'stack'),
+  undefined,
+  'cleanup'
+);
diff --git a/test/built-ins/Error/prototype/stack/setter-suppressed-error.js b/test/built-ins/Error/prototype/stack/setter-suppressed-error.js
new file mode 100644
index 0000000..0d89411
--- /dev/null
+++ b/test/built-ins/Error/prototype/stack/setter-suppressed-error.js
@@ -0,0 +1,38 @@
+// Copyright (C) 2026 Jordan Harband. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-set-error.prototype.stack
+description: >
+  The setter installs an own "stack" data property on a SuppressedError instance.
+info: |
+  set Error.prototype.stack
+
+  1. Let E be the this value.
+  2. If E is not an Object, throw a TypeError exception.
+  3. If v is not a String, throw a TypeError exception.
+  4. Perform ? SetterThatIgnoresPrototypeProperties(this value, %Error.prototype%, "stack", v).
+  5. Return undefined.
+includes: [propertyHelper.js]
+features: [error-stack-accessor, explicit-resource-management]
+---*/
+
+var set = Object.getOwnPropertyDescriptor(Error.prototype, 'stack').set;
+
+var err = new SuppressedError(new Error('inner'), new Error('suppressed'), 'msg');
+
+assert.sameValue(
+  Object.prototype.hasOwnProperty.call(err, 'stack'),
+  false,
+  'precondition: SuppressedError instance has no own "stack" property at construction'
+);
+
+var result = set.call(err, 'sentinel');
+assert.sameValue(result, undefined, 'setter returns undefined');
+
+verifyProperty(err, 'stack', {
+  value: 'sentinel',
+  writable: true,
+  enumerable: true,
+  configurable: true,
+});
diff --git a/test/built-ins/Error/prototype/stack/setter-this-not-object-bigint.js b/test/built-ins/Error/prototype/stack/setter-this-not-object-bigint.js
new file mode 100644
index 0000000..f654e4d
--- /dev/null
+++ b/test/built-ins/Error/prototype/stack/setter-this-not-object-bigint.js
@@ -0,0 +1,20 @@
+// Copyright (C) 2026 Jordan Harband. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-set-error.prototype.stack
+description: >
+  Throws a TypeError if the this value is a BigInt.
+info: |
+  set Error.prototype.stack
+
+  1. Let E be the this value.
+  2. If E is not an Object, throw a TypeError exception.
+features: [error-stack-accessor, BigInt]
+---*/
+
+var set = Object.getOwnPropertyDescriptor(Error.prototype, 'stack').set;
+
+assert.throws(TypeError, function () {
+  set.call(0n, '');
+});
diff --git a/test/built-ins/Error/prototype/stack/setter-this-not-object-symbol.js b/test/built-ins/Error/prototype/stack/setter-this-not-object-symbol.js
new file mode 100644
index 0000000..99da89d
--- /dev/null
+++ b/test/built-ins/Error/prototype/stack/setter-this-not-object-symbol.js
@@ -0,0 +1,20 @@
+// Copyright (C) 2026 Jordan Harband. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-set-error.prototype.stack
+description: >
+  Throws a TypeError if the this value is a Symbol.
+info: |
+  set Error.prototype.stack
+
+  1. Let E be the this value.
+  2. If E is not an Object, throw a TypeError exception.
+features: [error-stack-accessor, Symbol]
+---*/
+
+var set = Object.getOwnPropertyDescriptor(Error.prototype, 'stack').set;
+
+assert.throws(TypeError, function () {
+  set.call(Symbol('s'), '');
+});
diff --git a/test/built-ins/Error/prototype/stack/setter-this-not-object.js b/test/built-ins/Error/prototype/stack/setter-this-not-object.js
new file mode 100644
index 0000000..c910ed1
--- /dev/null
+++ b/test/built-ins/Error/prototype/stack/setter-this-not-object.js
@@ -0,0 +1,53 @@
+// Copyright (C) 2026 Jordan Harband. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-set-error.prototype.stack
+description: >
+  Throws a TypeError if the this value is not an Object.
+info: |
+  set Error.prototype.stack
+
+  1. Let E be the this value.
+  2. If E is not an Object, throw a TypeError exception.
+features: [error-stack-accessor]
+---*/
+
+var set = Object.getOwnPropertyDescriptor(Error.prototype, 'stack').set;
+
+assert.sameValue(typeof set, 'function');
+
+assert.throws(TypeError, function () {
+  set.call(undefined, '');
+}, 'undefined');
+
+assert.throws(TypeError, function () {
+  set.call(null, '');
+}, 'null');
+
+assert.throws(TypeError, function () {
+  set.call(true, '');
+}, 'true');
+
+assert.throws(TypeError, function () {
+  set.call(false, '');
+}, 'false');
+
+assert.throws(TypeError, function () {
+  set.call(1, '');
+}, 'number');
+
+assert.throws(TypeError, function () {
+  set.call('s', '');
+}, 'string');
+
+// A non-Object this combined with a non-String v throws TypeError. The spec
+// runs step 2 (this not Object) before step 3 (v not String), but both steps
+// throw TypeError, so the failure is observably the same either way.
+assert.throws(TypeError, function () {
+  set.call(undefined, 0);
+}, 'undefined this with non-String v');
+
+assert.throws(TypeError, function () {
+  set.call(null, {});
+}, 'null this with non-String v');
diff --git a/test/built-ins/Error/prototype/stack/setter-via-assignment.js b/test/built-ins/Error/prototype/stack/setter-via-assignment.js
new file mode 100644
index 0000000..be32a07
--- /dev/null
+++ b/test/built-ins/Error/prototype/stack/setter-via-assignment.js
@@ -0,0 +1,79 @@
+// Copyright (C) 2026 Jordan Harband. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+esid: sec-set-error.prototype.stack
+description: >
+  Property assignment (e.g. err.stack = v) goes through the inherited setter.
+info: |
+  set Error.prototype.stack
+
+  1. Let E be the this value.
+  2. If E is not an Object, throw a TypeError exception.
+  3. If v is not a String, throw a TypeError exception.
+  4. Perform ? SetterThatIgnoresPrototypeProperties(this value, %Error.prototype%, "stack", v).
+  5. Return undefined.
+includes: [propertyHelper.js]
+features: [error-stack-accessor]
+---*/
+
+var get = Object.getOwnPropertyDescriptor(Error.prototype, 'stack').get;
+
+// Plain object inheriting the accessor: assignment installs an own data property.
+var plain = Object.create(Error.prototype);
+plain.stack = 'sentinel';
+
+verifyProperty(plain, 'stack', {
+  value: 'sentinel',
+  writable: true,
+  enumerable: true,
+  configurable: true,
+});
+
+var nativeErrors = [
+  Error,
+  EvalError,
+  RangeError,
+  ReferenceError,
+  SyntaxError,
+  TypeError,
+  URIError
+];
+
+for (var i = 0; i < nativeErrors.length; ++i) {
+  var Ctor = nativeErrors[i];
+  var err = new Ctor('msg');
+
+  // Assigning a non-string still throws TypeError (step 3 of the setter).
+  // The `err.stack = null` form covered the "release memory" pattern in V8/JSC
+  // before this proposal; it now throws.
+  assert.throws(TypeError, function () {
+    err.stack = null;
+  }, Ctor.name + ': null assignment');
+
+  assert.throws(TypeError, function () {
+    err.stack = 0;
+  }, Ctor.name + ': numeric assignment');
+
+  assert.throws(TypeError, function () {
+    err.stack = undefined;
+  }, Ctor.name + ': undefined assignment');
+
+  // The failed setter does not affect the [[ErrorData]] slot: the inherited
+  // accessor still produces a string (Issue 13: a failed setter must not
+  // clobber the slot).
+  assert.sameValue(typeof get.call(err), 'string', Ctor.name + ': [[ErrorData]] preserved across failed setters');
+
+  // Assigning a string installs/updates the own data property.
+  err.stack = 'updated';
+  assert.sameValue(err.stack, 'updated', Ctor.name + ': string assignment is observable');
+}
+
+// Assigning to %Error.prototype%.stack always throws, because the setter
+// function itself throws via SetterThatIgnoresPrototypeProperties; the throw
+// originates inside the accessor function and propagates regardless of the
+// caller's strict-mode flag. (test262 runs this file in both strict and
+// sloppy modes by default, so the bare assignment exercises both.)
+assert.throws(TypeError, function () {
+  Error.prototype.stack = 'top-level';
+});