From 8b7a9f8fc0d99f14a4673a7d6a973fe761feb582 Mon Sep 17 00:00:00 2001 From: Tzvetan Mikov Date: Wed, 28 Aug 2024 11:13:46 -0700 Subject: [PATCH] JSError: look for stack data in the prototype chain (#1497) Summary: Pull Request resolved: https://github.com/facebook/hermes/pull/1497 Look for stack data in the entire prototype chain in order to accommodate usage like the one in the test. See https://github.com/facebook/hermes/issues/1496 Reviewed By: avp Differential Revision: D61870728 fbshipit-source-id: 9a1008cddcd8a87f96363922691460aa7f85224a --- lib/VM/JSError.cpp | 8 +++++++- test/hermes/error-in-proto.js | 27 +++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) create mode 100644 test/hermes/error-in-proto.js diff --git a/lib/VM/JSError.cpp b/lib/VM/JSError.cpp index e951fed378b..0a4867d6a05 100644 --- a/lib/VM/JSError.cpp +++ b/lib/VM/JSError.cpp @@ -54,7 +54,11 @@ void JSErrorBuildMeta(const GCCell *cell, Metadata::Builder &mb) { CallResult> JSError::getErrorFromStackTarget( Runtime &runtime, Handle targetHandle) { - if (targetHandle) { + MutableHandle mutHnd = + runtime.makeMutableHandle(targetHandle.get()); + targetHandle = mutHnd; + + while (targetHandle) { NamedPropertyDescriptor desc; bool exists = JSObject::getOwnNamedDescriptor( targetHandle, @@ -68,6 +72,8 @@ CallResult> JSError::getErrorFromStackTarget( if (vmisa(*targetHandle)) { return Handle::vmcast(targetHandle); } + + mutHnd.set(targetHandle->getParent(runtime)); } return runtime.raiseTypeError( "Error.stack getter called with an invalid receiver"); diff --git a/test/hermes/error-in-proto.js b/test/hermes/error-in-proto.js new file mode 100644 index 00000000000..f53f0c70c6f --- /dev/null +++ b/test/hermes/error-in-proto.js @@ -0,0 +1,27 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +// RUN: %hermes %s | %FileCheck --match-full-lines %s +// RUN: %shermes -exec %s | %FileCheck --match-full-lines %s + +const MyError = function(message) { + this.message = message; +}; +MyError.prototype = new Error; +MyError.prototype.name = 'MyError'; + + +try { + throw new MyError('1234') +} catch (e) { + if (e instanceof Error) + print("Caught Error", e.stack); + else + print("Caught non-Error"); +} +// CHECK: Caught Error MyError: 1234 +// CHECK-NEXT: at global{{.*}}