Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix minor defects and replace SandBox runs by try-catch #1248

Merged
merged 2 commits into from
Aug 11, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/builtins/BuiltinArrayBuffer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,13 @@ static Value builtinArrayBufferConstructor(ExecutionState& state, Value thisValu
{
if (!newTarget.hasValue()) {
ErrorObject::throwBuiltinError(state, ErrorCode::TypeError, ErrorObject::Messages::GlobalObject_ConstructorRequiresNew);
return Value();
}

uint64_t byteLength = argv[0].toIndex(state);
if (UNLIKELY(byteLength == Value::InvalidIndexValue)) {
ErrorObject::throwBuiltinError(state, ErrorCode::RangeError, state.context()->staticStrings().ArrayBuffer.string(), false, String::emptyString, ErrorObject::Messages::GlobalObject_FirstArgumentInvalidLength);
return Value();
}

Optional<uint64_t> maxByteLength;
Expand Down
1 change: 1 addition & 0 deletions src/builtins/BuiltinDataView.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ static Value builtinDataViewConstructor(ExecutionState& state, Value thisValue,
{
if (!newTarget.hasValue()) {
ErrorObject::throwBuiltinError(state, ErrorCode::TypeError, ErrorObject::Messages::GlobalObject_ConstructorRequiresNew);
return Value();
}
if (!(argv[0].isObject() && argv[0].asPointerValue()->isArrayBuffer())) {
ErrorObject::throwBuiltinError(state, ErrorCode::TypeError, state.context()->staticStrings().DataView.string(), false, String::emptyString, ErrorObject::Messages::GlobalObject_ThisNotArrayBufferObject);
Expand Down
1 change: 1 addition & 0 deletions src/builtins/BuiltinFinalizationRegistry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ static Value builtinFinalizationRegistryConstructor(ExecutionState& state, Value
{
if (!newTarget.hasValue()) {
ErrorObject::throwBuiltinError(state, ErrorCode::TypeError, ErrorObject::Messages::GlobalObject_ConstructorRequiresNew);
return Value();
}
if (argc == 0 || !argv[0].isCallable()) {
ErrorObject::throwBuiltinError(state, ErrorCode::TypeError, "cleanup Callback is not callable");
Expand Down
5 changes: 5 additions & 0 deletions src/builtins/BuiltinIntl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -449,6 +449,7 @@ static Value builtinIntlPluralRulesConstructor(ExecutionState& state, Value this
// If NewTarget is undefined, throw a TypeError exception.
if (!newTarget) {
ErrorObject::throwBuiltinError(state, ErrorCode::TypeError, ErrorObject::Messages::GlobalObject_ConstructorRequiresNew);
return Value();
}

#if defined(ENABLE_RUNTIME_ICU_BINDER)
Expand Down Expand Up @@ -570,6 +571,7 @@ static Value builtinIntlLocaleConstructor(ExecutionState& state, Value thisValue
// If NewTarget is undefined, throw a TypeError exception.
if (!newTarget) {
ErrorObject::throwBuiltinError(state, ErrorCode::TypeError, ErrorObject::Messages::GlobalObject_ConstructorRequiresNew);
return Value();
}

Value tagValue = argv[0];
Expand Down Expand Up @@ -908,6 +910,7 @@ static Value builtinIntlRelativeTimeFormatConstructor(ExecutionState& state, Val
// If NewTarget is undefined, throw a TypeError exception.
if (!newTarget) {
ErrorObject::throwBuiltinError(state, ErrorCode::TypeError, ErrorObject::Messages::GlobalObject_ConstructorRequiresNew);
return Value();
}

#if defined(ENABLE_RUNTIME_ICU_BINDER)
Expand Down Expand Up @@ -1002,6 +1005,7 @@ static Value builtinIntlDisplayNamesConstructor(ExecutionState& state, Value thi
// If NewTarget is undefined, throw a TypeError exception.
if (!newTarget) {
ErrorObject::throwBuiltinError(state, ErrorCode::TypeError, ErrorObject::Messages::GlobalObject_ConstructorRequiresNew);
return Value();
}

Object* proto = Object::getPrototypeFromConstructor(state, newTarget.value(), [](ExecutionState& state, Context* realm) -> Object* {
Expand Down Expand Up @@ -1046,6 +1050,7 @@ static Value builtinIntlListFormatConstructor(ExecutionState& state, Value thisV
// If NewTarget is undefined, throw a TypeError exception.
if (!newTarget) {
ErrorObject::throwBuiltinError(state, ErrorCode::TypeError, ErrorObject::Messages::GlobalObject_ConstructorRequiresNew);
return Value();
}

Object* proto = Object::getPrototypeFromConstructor(state, newTarget.value(), [](ExecutionState& state, Context* realm) -> Object* {
Expand Down
1 change: 1 addition & 0 deletions src/builtins/BuiltinMap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ static Value builtinMapConstructor(ExecutionState& state, Value thisValue, size_
{
if (!newTarget.hasValue()) {
ErrorObject::throwBuiltinError(state, ErrorCode::TypeError, ErrorObject::Messages::GlobalObject_ConstructorRequiresNew);
return Value();
}

// Let map be ? OrdinaryCreateFromConstructor(NewTarget, "%MapPrototype%", « [[MapData]] »).
Expand Down
19 changes: 9 additions & 10 deletions src/builtins/BuiltinPromise.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ static Value builtinPromiseConstructor(ExecutionState& state, Value thisValue, s
auto strings = &state.context()->staticStrings();
if (!newTarget.hasValue()) {
ErrorObject::throwBuiltinError(state, ErrorCode::TypeError, strings->Promise.string(), false, String::emptyString, "%s: Promise constructor should be called with new Promise()");
return Value();
}

Value executor = argv[0];
Expand All @@ -59,15 +60,12 @@ static Value builtinPromiseConstructor(ExecutionState& state, Value thisValue, s
state.context()->vmInstance()->triggerPromiseHook(state, VMInstance::PromiseHookType::Init, promise, (argc > 1) ? argv[1] : Value());
}

SandBox sb(state.context());
auto res = sb.run([&]() -> Value {
try {
Value arguments[] = { capability.m_resolveFunction, capability.m_rejectFunction };
Object::call(state, executor, Value(), 2, arguments);
return Value();
});
if (!res.error.isEmpty()) {
Value arguments[] = { res.error };
Object::call(state, capability.m_rejectFunction, Value(), 1, arguments);
} catch (const Value& v) {
Value thrownValue = v;
Object::call(state, capability.m_rejectFunction, Value(), 1, &thrownValue);
}

return promise;
Expand Down Expand Up @@ -567,6 +565,7 @@ static Value builtinPromiseAllSettled(ExecutionState& state, Value thisValue, si
try {
result = IteratorObject::iteratorClose(state, iteratorRecord, exceptionValue, true);
} catch (const Value& v) {
exceptionValue = v;
// IfAbruptRejectPromise(result, promiseCapability).
// If value is an abrupt completion,
// Perform ? Call(capability.[[Reject]], undefined, « value.[[Value]] »).
Expand Down Expand Up @@ -609,7 +608,7 @@ static Value performPromiseAny(ExecutionState& state, IteratorRecord* iteratorRe
next = IteratorObject::iteratorStep(state, iteratorRecord);
} catch (const Value& v) {
iteratorRecord->m_done = true;
throw v;
state.throwException(v);
}

// If next is false, then
Expand All @@ -627,7 +626,7 @@ static Value performPromiseAny(ExecutionState& state, IteratorRecord* iteratorRe
ObjectPropertyDescriptor(Object::createArrayFromList(state, *errors),
(ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent | ObjectPropertyDescriptor::WritablePresent)));
// Return ThrowCompletion(error).
throw Value(error);
state.throwException(error);
}
// Return resultCapability.[[Promise]].
return resultCapability.m_promise;
Expand All @@ -641,7 +640,7 @@ static Value performPromiseAny(ExecutionState& state, IteratorRecord* iteratorRe
// If nextValue is an abrupt completion, set iteratorRecord.[[Done]] to true.
iteratorRecord->m_done = true;
// ReturnIfAbrupt(nextValue).
throw v;
state.throwException(v);
}
// Append undefined to errors.
errors->pushBack(Value());
Expand Down
1 change: 1 addition & 0 deletions src/builtins/BuiltinSet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ static Value builtinSetConstructor(ExecutionState& state, Value thisValue, size_
// If NewTarget is undefined, throw a TypeError exception.
if (!newTarget.hasValue()) {
ErrorObject::throwBuiltinError(state, ErrorCode::TypeError, ErrorObject::Messages::GlobalObject_ConstructorRequiresNew);
return Value();
}

// Let set be ? OrdinaryCreateFromConstructor(NewTarget, "%SetPrototype%", « [[SetData]] »).
Expand Down
1 change: 1 addition & 0 deletions src/builtins/BuiltinTypedArray.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -379,6 +379,7 @@ static Value builtinTypedArrayConstructor(ExecutionState& state, Value thisValue
uint64_t elemlen = firstArg.toIndex(state);
if (elemlen == Value::InvalidIndexValue) {
ErrorObject::throwBuiltinError(state, ErrorCode::RangeError, state.context()->staticStrings().TypedArray.string(), false, String::emptyString, ErrorObject::Messages::GlobalObject_FirstArgumentInvalidLength);
return Value();
}
return TA::allocateTypedArray(state, newTarget.value(), elemlen);
}
Expand Down
1 change: 1 addition & 0 deletions src/builtins/BuiltinWeakMap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ static Value builtinWeakMapConstructor(ExecutionState& state, Value thisValue, s
{
if (!newTarget.hasValue()) {
ErrorObject::throwBuiltinError(state, ErrorCode::TypeError, ErrorObject::Messages::GlobalObject_ConstructorRequiresNew);
return Value();
}

Object* proto = Object::getPrototypeFromConstructor(state, newTarget.value(), [](ExecutionState& state, Context* constructorRealm) -> Object* {
Expand Down
1 change: 1 addition & 0 deletions src/builtins/BuiltinWeakRef.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ static Value builtinWeakRefConstructor(ExecutionState& state, Value thisValue, s
{
if (!newTarget.hasValue()) {
ErrorObject::throwBuiltinError(state, ErrorCode::TypeError, ErrorObject::Messages::GlobalObject_ConstructorRequiresNew);
return Value();
}
if (argc == 0 || !argv[0].isObject()) {
ErrorObject::throwBuiltinError(state, ErrorCode::TypeError, "target is not object");
Expand Down
1 change: 1 addition & 0 deletions src/builtins/BuiltinWeakSet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ static Value builtinWeakSetConstructor(ExecutionState& state, Value thisValue, s
{
if (!newTarget.hasValue()) {
ErrorObject::throwBuiltinError(state, ErrorCode::TypeError, ErrorObject::Messages::GlobalObject_ConstructorRequiresNew);
return Value();
}

Object* proto = Object::getPrototypeFromConstructor(state, newTarget.value(), [](ExecutionState& state, Context* constructorRealm) -> Object* {
Expand Down
2 changes: 1 addition & 1 deletion src/interpreter/ByteCode.h
Original file line number Diff line number Diff line change
Expand Up @@ -3004,7 +3004,7 @@ class End : public ByteCode {
#ifndef NDEBUG
void dump()
{
printf("end(return with r[%u])", m_registerIndex);
printf("end(return with r%u)", m_registerIndex);
}
#endif
};
Expand Down
4 changes: 2 additions & 2 deletions src/interpreter/ByteCodeInterpreter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3083,7 +3083,7 @@ NEVER_INLINE Value InterpreterSlowPath::tryOperation(ExecutionState*& state, siz
return Value();
}
} catch (const Value& val) {
stackTraceDataVector = newState->context()->vmInstance()->currentSandBox()->stackTraceDataVector();
stackTraceDataVector = std::move(newState->context()->vmInstance()->currentSandBox()->stackTraceDataVector());
newState->rareData()->m_controlFlowRecord->back() = new ControlFlowRecord(ControlFlowRecord::NeedsThrow, val);
}
}
Expand Down Expand Up @@ -3156,7 +3156,7 @@ NEVER_INLINE Value InterpreterSlowPath::tryOperation(ExecutionState*& state, siz
return Value(Value::EmptyValue);
}
} else if (record->reason() == ControlFlowRecord::NeedsThrow) {
state->context()->vmInstance()->currentSandBox()->rethrowPreviouslyCaughtException(*state, record->value(), stackTraceDataVector);
state->context()->vmInstance()->currentSandBox()->rethrowPreviouslyCaughtException(*state, record->value(), std::move(stackTraceDataVector));
ASSERT_NOT_REACHED();
// never get here. but I add return statement for removing compile warning
return Value(Value::EmptyValue);
Expand Down
1 change: 1 addition & 0 deletions src/parser/Script.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ Script* Script::loadModuleFromScript(ExecutionState& state, ModuleRequest& reque
Platform::LoadModuleResult result = Global::platform()->onLoadModule(context(), this, request.m_specifier, request.m_type);
if (!result.script) {
ErrorObject::throwBuiltinError(state, (ErrorCode)result.errorCode, result.errorMessage->toNonGCUTF8StringData().data());
return nullptr;
}
if (!result.script->moduleData()->m_didCallLoadedCallback) {
Global::platform()->didLoadModule(context(), this, result.script.value());
Expand Down
1 change: 1 addition & 0 deletions src/runtime/ExecutionState.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,7 @@ Object* ExecutionState::findPrivateMemberContextObject()
auto o = mostNearestHomeObject();
if (!o) {
ErrorObject::throwBuiltinError(*this, ErrorCode::TypeError, "Cannot read/write private member here");
return nullptr;
}
return convertHomeObjectIntoPrivateMemberContextObject(o.value());
}
Expand Down
19 changes: 7 additions & 12 deletions src/runtime/FinalizationRegistryObject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -178,18 +178,13 @@ void FinalizationRegistryObject::finalizer(Object* self, void* data)
}

if (!wasCallbackDeleted) {
SandBox sb(item->source->m_realm);
struct ExecutionData {
FinalizationRegistryObjectItem* item;
} ed;
ed.item = item;
sb.run([](ExecutionState& state, void* data) -> Value {
ExecutionData* ed = (ExecutionData*)data;
Value argv = ed->item->heldValue;
Object::call(state, ed->item->source->m_cleanupCallback.value(), Value(), 1, &argv);
return Value();
},
&ed);
try {
ExecutionState tempState(item->source->m_realm);
Value argv = item->heldValue;
Object::call(tempState, item->source->m_cleanupCallback.value(), Value(), 1, &argv);
} catch (const Value& v) {
// do nothing
}
}
}

Expand Down
43 changes: 21 additions & 22 deletions src/runtime/Job.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,26 +64,25 @@ SandBox::SandBoxResult PromiseReactionJob::run()
return Object::call(state, m_reaction.m_capability.m_rejectFunction, Value(), 1, value);
}

SandBox sb(state.context());
auto res = sb.run([&]() -> Value {
Value arguments[] = { m_argument };
Value res = Object::call(state, m_reaction.m_handler, Value(), 1, arguments);
Value res;
try {
Value argument = m_argument;
res = Object::call(state, m_reaction.m_handler, Value(), 1, &argument);
// m_reaction.m_capability can be null when there was no result capability when promise.then()
if (m_reaction.m_capability.m_promise == nullptr) {
return Value();
if (m_reaction.m_capability.m_promise != nullptr) {
Value value[] = { res };
Object::call(state, m_reaction.m_capability.m_resolveFunction, Value(), 1, value);
}
Value value[] = { res };
return Object::call(state, m_reaction.m_capability.m_resolveFunction, Value(), 1, value);
});
if (!res.error.isEmpty()) {
} catch (const Value& v) {
Value reason = v;
if (m_reaction.m_capability.m_rejectFunction) {
Value reason[] = { res.error };
return Object::call(state, m_reaction.m_capability.m_rejectFunction, Value(), 1, reason);
return Object::call(state, m_reaction.m_capability.m_rejectFunction, Value(), 1, &reason);
} else {
state.throwException(res.error);
state.throwException(reason);
}
}
return res.result;

return res;
});

#ifdef ESCARGOT_DEBUGGER
Expand All @@ -110,16 +109,16 @@ SandBox::SandBoxResult PromiseResolveThenableJob::run()
auto strings = &state.context()->staticStrings();
PromiseReaction::Capability capability = m_promise->createResolvingFunctions(state);

SandBox sb(state.context());
auto res = sb.run([&]() -> Value {
Value result;
try {
Value arguments[] = { capability.m_resolveFunction, capability.m_rejectFunction };
return Object::call(state, m_then, m_thenable, 2, arguments);
});
if (!res.error.isEmpty()) {
Value reason[] = { res.error };
return Object::call(state, capability.m_rejectFunction, Value(), 1, reason);
result = Object::call(state, m_then, m_thenable, 2, arguments);
} catch (const Value& v) {
Value reason = v;
return Object::call(state, capability.m_rejectFunction, Value(), 1, &reason);
}
return res.result;

return result;
});
}

Expand Down
13 changes: 6 additions & 7 deletions src/runtime/PromiseObject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -319,15 +319,14 @@ static Value promiseResolveFunctions(ExecutionState& state, Value thisValue, siz
}
Object* resolution = resolutionValue.asObject();

SandBox sb(state.context());
auto res = sb.run([&]() -> Value {
return resolution->get(state, strings->then).value(state, resolution);
});
if (!res.error.isEmpty()) {
promise->reject(state, res.error);
Value then;
try {
then = resolution->get(state, strings->then).value(state, resolution);
} catch (const Value& v) {
Value reason = v;
promise->reject(state, reason);
return Value();
}
Value then = res.result;

if (then.isCallable()) {
state.context()->vmInstance()->enqueueJob(new PromiseResolveThenableJob(state.context(), promise, resolution, then.asObject()));
Expand Down
10 changes: 5 additions & 5 deletions src/runtime/SandBox.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -300,7 +300,7 @@ void SandBox::throwException(ExecutionState& state, const Value& exception)
throw exception;
}

void SandBox::rethrowPreviouslyCaughtException(ExecutionState& state, Value exception, const StackTraceDataVector& stackTraceDataVector)
void SandBox::rethrowPreviouslyCaughtException(ExecutionState& state, Value exception, StackTraceDataVector&& stackTraceDataVector)
{
m_stackTraceDataVector = stackTraceDataVector;
// update stack trace data if needs
Expand Down Expand Up @@ -353,8 +353,7 @@ void ErrorObject::StackTraceData::buildStackTrace(Context* context, StringBuilde
{
if (exception.isObject()) {
ExecutionState state(context);
SandBox sb(context);
sb.run([&]() -> Value {
try {
auto getResult = exception.asObject()->get(state, state.context()->staticStrings().name);
if (getResult.hasValue()) {
builder.appendString(getResult.value(state, exception.asObject()).toString(state));
Expand All @@ -365,8 +364,9 @@ void ErrorObject::StackTraceData::buildStackTrace(Context* context, StringBuilde
builder.appendString(getResult.value(state, exception.asObject()).toString(state));
builder.appendChar('\n');
}
return Value();
});
} catch (const Value& v) {
// ignore exception
}
}

ByteCodeLOCDataMap locMap;
Expand Down
2 changes: 1 addition & 1 deletion src/runtime/SandBox.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ class SandBox : public gc {
static bool createStackTrace(StackTraceDataVector& stackTraceDataVector, ExecutionState& state, bool stopAtPause = false);

void throwException(ExecutionState& state, const Value& exception);
void rethrowPreviouslyCaughtException(ExecutionState& state, Value exception, const StackTraceDataVector& stackTraceDataVector);
void rethrowPreviouslyCaughtException(ExecutionState& state, Value exception, StackTraceDataVector&& stackTraceDataVector);

StackTraceDataVector& stackTraceDataVector()
{
Expand Down
3 changes: 1 addition & 2 deletions src/runtime/ScriptClassConstructorFunctionObject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -146,8 +146,7 @@ Value ScriptClassConstructorFunctionObject::construct(ExecutionState& state, con
// Return envRec.GetThisBinding().
// -> perform at ScriptClassConstructorFunctionObjectReturnValueBinderWithConstruct
return FunctionObjectProcessCallGenerator::processCall<ScriptClassConstructorFunctionObject, true, true, true, ScriptClassConstructorFunctionObjectThisValueBinder,
ScriptClassConstructorFunctionObjectNewTargetBinderWithConstruct, ScriptClassConstructorFunctionObjectReturnValueBinderWithConstruct>(state, this, thisArgument, argc, argv, newTarget)
.asObject();
ScriptClassConstructorFunctionObjectNewTargetBinderWithConstruct, ScriptClassConstructorFunctionObjectReturnValueBinderWithConstruct>(state, this, thisArgument, argc, argv, newTarget);
}

void ScriptClassConstructorFunctionObject::initInstanceFieldMembers(ExecutionState& state, Object* instance)
Expand Down
Loading