From db6d12e202e15f7a446d8848d6ca8f7abb3cfb32 Mon Sep 17 00:00:00 2001 From: Tzvetan Mikov Date: Sun, 8 Sep 2024 15:21:43 -0700 Subject: [PATCH] JSError: look for stack data in the prototype chain Summary: Imported from static_h Original Author: tmikov@meta.com Original Git: 8b7a9f8fc0d99f14a4673a7d6a973fe761feb582 Original Reviewed By: avp Original Revision: D61870728 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: fbmal7 Differential Revision: D62357838 fbshipit-source-id: 3873bfd8bcb5c16998dbec67f44ad4c098179758 --- lib/VM/JSError.cpp | 8 +++++++- test/hermes/error-in-proto.js | 26 ++++++++++++++++++++++++++ 2 files changed, 33 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 f012fc11b87..fc8c9801373 100644 --- a/lib/VM/JSError.cpp +++ b/lib/VM/JSError.cpp @@ -57,7 +57,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, @@ -71,6 +75,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..250acb86660 --- /dev/null +++ b/test/hermes/error-in-proto.js @@ -0,0 +1,26 @@ +/** + * 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 + +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{{.*}}