v8/test/mjsunit/error-stack.js
Simon Zünd 0381794b8c Add tests for accessing Error.stack on error objects in dictionary mode
This CL adds two mjsunit tests that transition an error object to
dictionary mode before and after Error.stack is formatted and verify
that the custom 'stack' property accessor works as intended.

Bug: v8:8742
Change-Id: I4beb52c75b94533c10fac007f41117ab8915fac8
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1649789
Reviewed-by: Benedikt Meurer <bmeurer@chromium.org>
Commit-Queue: Benedikt Meurer <bmeurer@chromium.org>
Auto-Submit: Simon Zünd <szuend@chromium.org>
Cr-Commit-Position: refs/heads/master@{#62078}
2019-06-11 09:16:43 +00:00

104 lines
3.0 KiB
JavaScript

// Copyright 2019 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// Flags: --allow-natives-syntax
(function TestErrorObjectsRetainMap() {
const error1 = new Error("foo");
const error2 = new Error("bar");
assertTrue(%HaveSameMap(error1, error2));
// Trigger serialization of the stack-trace.
error1.stack;
assertTrue(%HaveSameMap(error1, error2));
error2.stack;
assertTrue(%HaveSameMap(error1, error2));
})();
(function TestPrepareStackTraceCallback() {
Error.prepareStackTrace = (error, frame) => {
return "custom stack trace No. 42";
};
const error = new Error("foo");
// Check it twice, so both code paths in the accessor are exercised.
assertEquals(error.stack, "custom stack trace No. 42");
assertEquals(error.stack, "custom stack trace No. 42");
})();
(function TestPrepareStackTraceCallbackMessesWithProperty() {
Error.prepareStackTrace = (error, frames) => {
error.stack = "Yes, we can write to this!";
return 42;
};
const error = new Error("foo");
// Check it twice. The first returns the formatting result,
// the second the value of the private symbol.
assertEquals(error.stack, 42);
assertEquals(error.stack, 42);
})();
(function TestPrepareStackTraceCallbackInstallsGetter() {
Error.prepareStackTrace = (error, frames) => {
Object.defineProperty(error, "stack", { get: () => 42 });
return "<formatted stack trace>";
};
const error = new Error("foo");
// Check it twice. The second time the accessor should be used.
assertEquals(error.stack, "<formatted stack trace>");
assertEquals(error.stack, 42);
})();
(function TestPrepareStackTraceCallbackInstallsSetter() {
Error.prepareStackTrace = (error, frames) => {
Object.defineProperty(error, "stack", { set: (x) => {
error[42] = x;
}});
return "<formatted stack trace>";
};
const error = new Error("foo");
// Cause the accessor to get installed.
error.stack;
error.stack = "Who needs stack traces anyway?";
assertEquals(error[42], "Who needs stack traces anyway?");
assertEquals(error.stack, undefined); // No getter.
})();
(function TestFormatStackPropertyInDictionaryMode() {
Error.prepareStackTrace = (error, frames) => {
return "<formatted stack trace>";
};
const error = new Error("foo");
error[%MaxSmi()] = 42;
assertTrue(%HasDictionaryElements(error));
// Check it twice.
assertEquals(error.stack, "<formatted stack trace>");
assertEquals(error.stack, "<formatted stack trace>");
})();
(function TestTransitionToDictionaryModeAfterFormatting() {
Error.prepareStackTrace = (error, frames) => {
return "<formatted stack trace>";
};
const error = new Error("foo");
assertFalse(%HasDictionaryElements(error));
assertEquals(error.stack, "<formatted stack trace>");
error[%MaxSmi()] = 42;
assertTrue(%HasDictionaryElements(error));
assertEquals(error.stack, "<formatted stack trace>");
})();