8000 [JSC] Implement `SuppressedError` from Explicit Resource Management P… · annevk/WebKit@17f3c11 · GitHub
[go: up one dir, main page]

Skip to content

Commit 17f3c11

Browse files
committed
[JSC] Implement SuppressedError from Explicit Resource Management Proposal
https://bugs.webkit.org/show_bug.cgi?id=292747 Reviewed by Yusuke Suzuki. This patch implements new `SuppressedError`[1] built-in from Explicit Resource Management Proposal[2]. [1]: https://tc39.es/proposal-explicit-resource-management/#sec-suppressederror-objects [2]: https://github.com/tc39/proposal-explicit-resource-management * JSTests/stress/suppressed-error-basic.js: Added. (shouldBe): (shouldBe.OurSuppressedError): * JSTests/test262/config.yaml: * Source/JavaScriptCore/Sources.txt: * Source/JavaScriptCore/runtime/CommonIdentifiers.h: * Source/JavaScriptCore/runtime/Error.cpp: (JSC::createError): * Source/JavaScriptCore/runtime/ErrorType.h: * Source/JavaScriptCore/runtime/JSGlobalObject.cpp: (JSC::JSGlobalObject::initializeSuppressedErrorConstructor): (JSC::JSGlobalObject::init): * Source/JavaScriptCore/runtime/JSGlobalObject.h: * Source/JavaScriptCore/runtime/JSGlobalObjectInlines.h: (JSC::JSGlobalObject::errorStructure const): * Source/JavaScriptCore/runtime/SuppressedError.cpp: Copied from Source/JavaScriptCore/runtime/ErrorType.h. (JSC::createSuppressedError): * Source/JavaScriptCore/runtime/SuppressedError.h: Copied from Source/JavaScriptCore/runtime/ErrorType.h. * Source/JavaScriptCore/runtime/SuppressedErrorConstructor.cpp: Added. (JSC::SuppressedErrorConstructor::SuppressedError 10000 Constructor): (JSC::SuppressedErrorConstructor::finishCreation): (JSC::JSC_DEFINE_HOST_FUNCTION): * Source/JavaScriptCore/runtime/SuppressedErrorConstructor.h: Copied from Source/JavaScriptCore/runtime/ErrorType.h. * Source/JavaScriptCore/runtime/SuppressedErrorConstructorInlines.h: Copied from Source/JavaScriptCore/runtime/ErrorType.h. (JSC::SuppressedErrorConstructor::createStructure): * Source/JavaScriptCore/runtime/SuppressedErrorPrototype.cpp: Copied from Source/JavaScriptCore/runtime/ErrorType.h. (JSC::SuppressedErrorPrototype::SuppressedErrorPrototype): (JSC::SuppressedErrorPrototype::finishCreation): * Source/JavaScriptCore/runtime/SuppressedErrorPrototype.h: Copied from Source/JavaScriptCore/runtime/ErrorType.h. * Source/JavaScriptCore/runtime/SuppressedErrorPrototypeInlines.h: Copied from Source/JavaScriptCore/runtime/ErrorType.h. (JSC::SuppressedErrorPrototype::createStructure): Canonical link: https://commits.webkit.org/294774@main
1 parent 95f2b2a commit 17f3c11

17 files changed

+494
-2
lines changed
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
//@ requireOptions("--useExplicitResourceManagement=1")
2+
3+
function shouldBe(a, b) {
4+
if (a !== b)
5+
throw new Error(`Expected ${b} but got ${a}`);
6+
}
7+
8+
shouldBe(SuppressedError.prototype.constructor, SuppressedError);
9+
shouldBe(SuppressedError.prototype.message, "");
10+
shouldBe(SuppressedError.prototype.name, "SuppressedError");
11+
12+
{
13+
class OurSuppressedError extends SuppressedError {
14+
constructor(...args) {
15+
super(...args);
16+
}
17+
}
18+
const e1 = new OurSuppressedError();
19+
shouldBe(e1 instanceof Error, true);
20+
shouldBe(e1 instanceof SuppressedError, true);
21+
}
22+
23+
{
24+
let toStringCallCount = 0;
25+
const obj = {
26+
toString() {
27+
toStringCallCount++;
28+
return "this is error message";
29+
}
30+
};
31+
const e1 = new SuppressedError(undefined, undefined, obj);
32+
shouldBe(toStringCallCount, 1);
33+
shouldBe(e1.message, "this is error message");
34+
35+
const e2 = SuppressedError(undefined, undefined, obj);
36+
shouldBe(toStringCallCount, 2);
37+
shouldBe(e2.message, "this is error message");
38+
39+
}
40+
41+
{
42+
const error = {};
43+
const suppressed = {};
44+
const message = "message";
45+
46+
const e1 = new SuppressedError(error, suppressed, message);
47+
shouldBe(e1.error, error);
48+
shouldBe(e1.suppressed, suppressed);
49+
shouldBe(e1.message, message);
50+
51+
const e2 = SuppressedError(error, suppressed, message);
52+
shouldBe(e2.error, error);
53+
shouldBe(e2.suppressed, suppressed);
54+
shouldBe(e2.message, message);
55+
}

JSTests/test262/config.yaml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,6 @@ skip:
4949
- test/staging/explicit-resource-management
5050
- test/built-ins/DisposableStack
5151
- test/built-ins/AsyncDisposableStack
52-
- test/built-ins/NativeErrors/SuppressedError
5352
- test/language/statements/using
5453
- test/language/statements/await-using
5554
files:

Source/JavaScriptCore/Sources.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1064,6 +1064,9 @@ runtime/Structure.cpp
10641064
runtime/StructureCache.cpp
10651065
runtime/StructureChain.cpp
10661066
runtime/StructureRareData.cpp
1067+
runtime/SuppressedError.cpp
1068+
runtime/SuppressedErrorConstructor.cpp
1069+
runtime/SuppressedErrorPrototype.cpp
10671070
runtime/Symbol.cpp
10681071
runtime/SymbolConstructor.cpp
10691072
runtime/SymbolObject.cpp

Source/JavaScriptCore/runtime/CommonIdentifiers.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -315,7 +315,10 @@
315315
macro(written) \
316316
macro(year) \
317317
macro(years) \
318-
macro(yearsDisplay)
318+
macro(yearsDisplay) \
319+
macro(error) \
320+
macro(suppressed) \
321+
macro(SuppressedError)
319322

320323
#define JSC_COMMON_IDENTIFIERS_EACH_PRIVATE_FIELD(macro) \
321324
macro(constructor)

Source/JavaScriptCore/runtime/Error.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,8 @@ JSObject* createError(JSGlobalObject* globalObject, ErrorTypeWithExtension error
105105
return createURIError(globalObject, message);
106106
case ErrorTypeWithExtension::AggregateError:
107107
break;
108+
case ErrorTypeWithExtension::SuppressedError:
109+
break;
108110
case ErrorTypeWithExtension::OutOfMemoryError:
109111
return createOutOfMemoryError(globalObject, message);
110112
}

Source/JavaScriptCore/runtime/ErrorType.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ namespace JSC {
3838
macro(TypeError) \
3939
macro(URIError) \
4040
macro(AggregateError) \
41+
macro(SuppressedError) \
4142

4243
#define JSC_ERROR_TYPES_WITH_EXTENSION(macro) \
4344
JSC_ERROR_TYPES(macro) \

Source/JavaScriptCore/runtime/JSGlobalObject.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,9 @@
236236
#include "StringIteratorPrototypeInlines.h"
237237
#include "StringObjectInlines.h"
238238
#include "StringPrototypeInlines.h"
239+
#include "SuppressedError.h"
240+
#include "SuppressedErrorConstructorInlines.h"
241+
#include "SuppressedErrorPrototypeInlines.h"
239242
#include "SymbolConstructorInlines.h"
240243
#include "SymbolObjectInlines.h"
241244
#include "SymbolPrototypeInlines.h"
@@ -821,6 +824,13 @@ void JSGlobalObject::initializeAggregateErrorConstructor(LazyClassStructure::Ini
821824
init.setConstructor(AggregateErrorConstructor::create(init.vm, AggregateErrorConstructor::createStructure(init.vm, this, m_errorStructure.constructor(this)), jsCast<AggregateErrorPrototype*>(init.prototype)));
822825
}
823826

827+
void JSGlobalObject::initializeSuppressedErrorConstructor(LazyClassStructure::Initializer& init)
828+
{
829+
init.setPrototype(SuppressedErrorPrototype::create(init.vm, SuppressedErrorPrototype::createStructure(init.vm, this, m_errorStructure.prototype(this))));
830+
init.setStructure(ErrorInstance::createStructure(init.vm, this, init.prototype));
831+
init.setConstructor(SuppressedErrorConstructor::create(init.vm, SuppressedErrorConstructor::createStructure(init.vm, this, m_errorStructure.constructor(this)), jsCast<SuppressedErrorPrototype*>(init.prototype)));
832+
}
833+
824834
SUPPRESS_ASAN inline void JSGlobalObject::initStaticGlobals(VM& vm)
825835
{
826836
GlobalPropertyInfo staticGlobals[] = {
@@ -1272,6 +1282,12 @@ capitalName ## Constructor* lowerName ## Constructor = featureFlag ? capitalName
12721282
[] (LazyClassStructure::Initializer& init) {
12731283
init.global->initializeAggregateErrorConstructor(init);
12741284
});
1285+
if (Options::useExplicitResourceManagement()) {
1286+
m_suppressedErrorStructure.initLater(
1287+
[] (LazyClassStructure::Initializer& init) {
1288+
init.global->initializeSuppressedErrorConstructor(init);
1289+
});
1290+
}
12751291

12761292
m_generatorFunctionPrototype.set(vm, this, GeneratorFunctionPrototype::create(vm, GeneratorFunctionPrototype::createStructure(vm, this, m_functionPrototype.get())));
12771293
GeneratorFunctionConstructor* generatorFunctionConstructor = GeneratorFunctionConstructor::create(vm, GeneratorFunctionConstructor::createStructure(vm, this, functionConstructor), m_generatorFunctionPrototype.get());
@@ -1315,6 +1331,9 @@ capitalName ## Constructor* lowerName ## Constructor = featureFlag ? capitalName
13151331
if (Options::useSharedArrayBuffer())
13161332
putDirectWithoutTransition(vm, vm.propertyNames->SharedArrayBuffer, m_sharedArrayBufferStructure.constructor(this), static_cast<unsigned>(PropertyAttribute::DontEnum));
13171333

1334+
if (Options::useExplicitResourceManagement())
1335+< 1E0A /span>
putDirectWithoutTransition(vm, vm.propertyNames->SuppressedError, m_suppressedErrorStructure.constructor(this), static_cast<unsigned>(PropertyAttribute::DontEnum));
1336+
13181337
#define PUT_CONSTRUCTOR_FOR_SIMPLE_TYPE(capitalName, lowerName, properName, instanceType, jsName, prototypeBase, featureFlag) \
13191338
if (featureFlag) \
13201339
putDirectWithoutTransition(vm, vm.propertyNames-> jsName, lowerName ## Constructor, static_cast<unsigned>(PropertyAttribute::DontEnum));
@@ -2572,6 +2591,7 @@ void JSGlobalObject::visitChildrenImpl(JSCell* cell, Visitor& visitor)
25722591
thisObject->m_typeErrorStructure.visit(visitor);
25732592
thisObject->m_URIErrorStructure.visit(visitor);
25742593
thisObject->m_aggregateErrorStructure.visit(visitor);
2594+
thisObject->m_suppressedErrorStructure.visit(visitor);
25752595
visitor.append(thisObject->m_arrayConstructor);
25762596
visitor.append(thisObject->m_shadowRealmConstructor);
25772597
visitor.append(thisObject->m_regExpConstructor);

Source/JavaScriptCore/runtime/JSGlobalObject.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,7 @@ class JSGlobalObject : public JSSegmentedVariableObject {
239239
LazyClassStructure m_typeErrorStructure;
240240
LazyClassStructure m_URIErrorStructure;
241241
LazyClassStructure m_aggregateErrorStructure;
242+
LazyClassStructure m_suppressedErrorStructure;
242243

243244
WriteBarrier<ObjectConstructor> m_objectConstructor;
244245
WriteBarrier<ArrayConstructor> m_arrayConstructor;
@@ -1203,6 +1204,8 @@ class JSGlobalObject : public JSSegmentedVariableObject {
12031204

12041205
void initializeAggregateErrorConstructor(LazyClassStructure::Initializer&);
12051206

1207+
void initializeSuppressedErrorConstructor(LazyClassStructure::Initializer&);
1208+
12061209
JS_EXPORT_PRIVATE void init(VM&);
12071210
void initStaticGlobals(VM&);
12081211
void fixupPrototypeChainWithObjectPrototype(VM&);

Source/JavaScriptCore/runtime/JSGlobalObjectInlines.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -531,6 +531,8 @@ inline Structure* JSGlobalObject::errorStructure(ErrorType errorType) const
531531
return m_URIErrorStructure.get(this);
532532
case ErrorType::AggregateError:
533533
return m_aggregateErrorStructure.get(this);
534+
case ErrorType::SuppressedError:
535+
return m_suppressedErrorStructure.get(this);
534536
}
535537
ASSERT_NOT_REACHED();
536538
return nullptr;
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
/*
2+
* Copyright (C) 2025 Sosuke Suzuki <aosukeke@gmail.com>.
3+
*
4+
* Redistribution and use in source and binary forms, with or without
< E9B2 code>5+
* modification, are permitted provided that the following conditions
6+
* are met:
7+
* 1. Redistributions of source code must retain the above copyright
8+
* notice, this list of conditions and the following disclaimer.
9+
* 2. Redistributions in binary form must reproduce the above copyright
10+
* notice, this list of conditions and the following disclaimer in the
11+
* documentation and/or other materials provided with the distribution.
12+
*
13+
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14+
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15+
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16+
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17+
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18+
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19+
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20+
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21+
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22+
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23+
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24+
*/
25+
26+
#include "config.h"
27+
#include "SuppressedError.h"
28+
29+
#include "ExceptionScope.h"
30+
#include "JSCJSValueInlines.h"
31+
#include "JSGlobalObjectInlines.h"
32+
33+
namespace JSC {
34+
35+
ErrorInstance* createSuppressedError(JSGlobalObject* globalObject, VM& vm, Structure* structure, JSValue error, JSValue suppressed, JSValue message, ErrorInstance::SourceAppender appender, RuntimeType type, bool useCurrentFrame)
36+
{
37+
auto scope = DECLARE_THROW_SCOPE(vm);
38+
39+
String messageString = message.isUndefined() ? String() : message.toWTFString(globalObject);
40+
RETURN_IF_EXCEPTION(scope, nullptr);
41+
42+
auto* suppressedError = ErrorInstance::create(vm, structure, messageString, JSValue(), appender, type, ErrorType::SuppressedError, useCurrentFrame);
43+
44+
suppressedError->putDirect(vm, vm.propertyNames->error, error, static_cast<unsigned>(PropertyAttribute::DontEnum));
45+
RETURN_IF_EXCEPTION(scope, nullptr);
46+
47+
suppressedError->putDirect(vm, vm.propertyNames->suppressed, suppressed, static_cast<unsigned>(PropertyAttribute::DontEnum));
48+
RETURN_IF_EXCEPTION(scope, nullptr);
49+
50+
return suppressedError;
51+
}
52+
53+
} // namespace JSC

0 commit comments

Comments
 (0)
0