diff options
author | 2021-09-19 03:43:17 -0700 | |
---|---|---|
committer | 2021-09-19 03:43:17 -0700 | |
commit | 60b5fb95b19b2f96dcfd851663b40e1155c9cc0e (patch) | |
tree | 483c76e2ff7b87e5a1fdf510b1cc577826055df8 /src/javascript/jsc/bindings/bindings.cpp | |
parent | 9ae35ec5811f7395f98988ccdcd07395cd731bb0 (diff) | |
download | bun-60b5fb95b19b2f96dcfd851663b40e1155c9cc0e.tar.gz bun-60b5fb95b19b2f96dcfd851663b40e1155c9cc0e.tar.zst bun-60b5fb95b19b2f96dcfd851663b40e1155c9cc0e.zip |
WIP macros
Diffstat (limited to 'src/javascript/jsc/bindings/bindings.cpp')
-rw-r--r-- | src/javascript/jsc/bindings/bindings.cpp | 537 |
1 files changed, 300 insertions, 237 deletions
diff --git a/src/javascript/jsc/bindings/bindings.cpp b/src/javascript/jsc/bindings/bindings.cpp index 50e6978b5..407b452d2 100644 --- a/src/javascript/jsc/bindings/bindings.cpp +++ b/src/javascript/jsc/bindings/bindings.cpp @@ -7,6 +7,7 @@ #include <JavaScriptCore/ErrorInstance.h> #include <JavaScriptCore/ExceptionScope.h> #include <JavaScriptCore/FunctionConstructor.h> +#include <JavaScriptCore/HashMapImplInlines.h> #include <JavaScriptCore/Identifier.h> #include <JavaScriptCore/IteratorOperations.h> #include <JavaScriptCore/JSArray.h> @@ -15,7 +16,9 @@ #include <JavaScriptCore/JSClassRef.h> #include <JavaScriptCore/JSInternalPromise.h> #include <JavaScriptCore/JSMap.h> +#include <JavaScriptCore/JSModuleEnvironment.h> #include <JavaScriptCore/JSModuleLoader.h> +#include <JavaScriptCore/JSModuleNamespaceObject.h> #include <JavaScriptCore/JSModuleRecord.h> #include <JavaScriptCore/JSNativeStdFunction.h> #include <JavaScriptCore/JSObject.h> @@ -27,6 +30,7 @@ #include <JavaScriptCore/StackFrame.h> #include <JavaScriptCore/StackVisitor.h> #include <JavaScriptCore/VM.h> +#include <JavaScriptCore/VMEntryScope.h> #include <JavaScriptCore/WasmFaultSignalHandler.h> #include <wtf/text/ExternalStringImpl.h> #include <wtf/text/StringCommon.h> @@ -92,6 +96,243 @@ void JSC__JSObject__putRecord(JSC__JSObject *object, JSC__JSGlobalObject *global object->putDirect(global->vm(), ident, descriptor.value()); scope.release(); } + +static void populateStackFrameMetadata(const JSC::StackFrame *stackFrame, ZigStackFrame *frame) { + frame->source_url = Zig::toZigString(stackFrame->sourceURL()); + + if (stackFrame->isWasmFrame()) { + frame->code_type = ZigStackFrameCodeWasm; + return; + } + + auto m_codeBlock = stackFrame->codeBlock(); + if (m_codeBlock) { + switch (m_codeBlock->codeType()) { + case JSC::EvalCode: { + frame->code_type = ZigStackFrameCodeEval; + return; + } + case JSC::ModuleCode: { + frame->code_type = ZigStackFrameCodeModule; + return; + } + case JSC::GlobalCode: { + frame->code_type = ZigStackFrameCodeGlobal; + return; + } + case JSC::FunctionCode: { + frame->code_type = + !m_codeBlock->isConstructor() ? ZigStackFrameCodeFunction : ZigStackFrameCodeConstructor; + break; + } + default: ASSERT_NOT_REACHED(); + } + } + + auto calleeCell = stackFrame->callee(); + if (!calleeCell || !calleeCell->isObject()) return; + + JSC::JSObject *callee = JSC::jsCast<JSC::JSObject *>(calleeCell); + // Does the code block have a user-defined name property? + JSC::JSValue name = callee->getDirect(m_codeBlock->vm(), m_codeBlock->vm().propertyNames->name); + if (name && name.isString()) { + auto str = name.toWTFString(m_codeBlock->globalObject()); + frame->function_name = Zig::toZigString(str); + return; + } + + /* For functions (either JSFunction or InternalFunction), fallback to their "native" name + * property. Based on JSC::getCalculatedDisplayName, "inlining" the + * JSFunction::calculatedDisplayName\InternalFunction::calculatedDisplayName calls */ + if (JSC::JSFunction *function = + JSC::jsDynamicCast<JSC::JSFunction *>(m_codeBlock->vm(), callee)) { + + WTF::String actualName = function->name(m_codeBlock->vm()); + if (!actualName.isEmpty() || function->isHostOrBuiltinFunction()) { + frame->function_name = Zig::toZigString(actualName); + return; + } + + auto inferred_name = function->jsExecutable()->name(); + frame->function_name = Zig::toZigString(inferred_name.string()); + } + + if (JSC::InternalFunction *function = + JSC::jsDynamicCast<JSC::InternalFunction *>(m_codeBlock->vm(), callee)) { + // Based on JSC::InternalFunction::calculatedDisplayName, skipping the "displayName" property + frame->function_name = Zig::toZigString(function->name()); + } +} +// Based on +// https://github.com/mceSystems/node-jsc/blob/master/deps/jscshim/src/shim/JSCStackTrace.cpp#L298 +static void populateStackFramePosition(const JSC::StackFrame *stackFrame, ZigString *source_lines, + int32_t *source_line_numbers, uint8_t source_lines_count, + ZigStackFramePosition *position) { + auto m_codeBlock = stackFrame->codeBlock(); + if (!m_codeBlock) return; + + JSC::BytecodeIndex bytecodeOffset = + stackFrame->hasBytecodeIndex() ? stackFrame->bytecodeIndex() : JSC::BytecodeIndex(); + + /* Get the "raw" position info. + * Note that we're using m_codeBlock->unlinkedCodeBlock()->expressionRangeForBytecodeOffset + * rather than m_codeBlock->expressionRangeForBytecodeOffset in order get the "raw" offsets and + * avoid the CodeBlock's expressionRangeForBytecodeOffset modifications to the line and column + * numbers, (we don't need the column number from it, and we'll calculate the line "fixes" + * ourselves). */ + int startOffset = 0; + int endOffset = 0; + int divotPoint = 0; + unsigned line = 0; + unsigned unusedColumn = 0; + m_codeBlock->unlinkedCodeBlock()->expressionRangeForBytecodeIndex( + bytecodeOffset, divotPoint, startOffset, endOffset, line, unusedColumn); + divotPoint += m_codeBlock->sourceOffset(); + + // TODO: evaluate if using the API from UnlinkedCodeBlock can be used instead of iterating + // through source text. + + /* On the first line of the source code, it seems that we need to "fix" the column with the + * starting offset. We currently use codeBlock->source()->startPosition().m_column.oneBasedInt() + * as the offset in the first line rather than codeBlock->firstLineColumnOffset(), which seems + * simpler (and what CodeBlock::expressionRangeForBytecodeOffset does). This is because + * firstLineColumnOffset values seems different from what we expect (according to v8's tests) + * and I haven't dove into the relevant parts in JSC (yet) to figure out why. */ + unsigned columnOffset = line ? 0 : m_codeBlock->source().startColumn().zeroBasedInt(); + + // "Fix" the line number + JSC::ScriptExecutable *executable = m_codeBlock->ownerExecutable(); + if (std::optional<int> overrideLine = executable->overrideLineNumber(m_codeBlock->vm())) { + line = overrideLine.value(); + } else { + line += executable->firstLine(); + } + + // Calculate the staring\ending offsets of the entire expression + int expressionStart = divotPoint - startOffset; + int expressionStop = divotPoint + endOffset; + + // Make sure the range is valid + WTF::StringView sourceString = m_codeBlock->source().provider()->source(); + if (!expressionStop || expressionStart > static_cast<int>(sourceString.length())) { return; } + + // Search for the beginning of the line + unsigned int lineStart = expressionStart; + while ((lineStart > 0) && ('\n' != sourceString[lineStart - 1])) { lineStart--; } + // Search for the end of the line + unsigned int lineStop = expressionStop; + unsigned int sourceLength = sourceString.length(); + while ((lineStop < sourceLength) && ('\n' != sourceString[lineStop])) { lineStop++; } + if (source_lines_count > 1 && source_lines != nullptr) { + auto chars = sourceString.characters8(); + + // Most of the time, when you look at a stack trace, you want a couple lines above + + source_lines[0] = {&chars[lineStart], lineStop - lineStart}; + source_line_numbers[0] = line; + + if (lineStart > 0) { + auto byte_offset_in_source_string = lineStart - 1; + uint8_t source_line_i = 1; + auto remaining_lines_to_grab = source_lines_count - 1; + + while (byte_offset_in_source_string > 0 && remaining_lines_to_grab > 0) { + unsigned int end_of_line_offset = byte_offset_in_source_string; + + // This should probably be code points instead of newlines + while (byte_offset_in_source_string > 0 && chars[byte_offset_in_source_string] != '\n') { + byte_offset_in_source_string--; + } + + // We are at the beginning of the line + source_lines[source_line_i] = {&chars[byte_offset_in_source_string], + end_of_line_offset - byte_offset_in_source_string + 1}; + + source_line_numbers[source_line_i] = line - source_line_i; + source_line_i++; + + remaining_lines_to_grab--; + + byte_offset_in_source_string -= byte_offset_in_source_string > 0; + } + } + } + + /* Finally, store the source "positions" info. + * Notes: + * - The retrieved column seem to point the "end column". To make sure we're current, we'll + *calculate the columns ourselves, since we've already found where the line starts. Note that in + *v8 it should be 0-based here (in contrast the 1-based column number in v8::StackFrame). + * - The static_casts are ugly, but comes from differences between JSC and v8's api, and should + *be OK since no source should be longer than "max int" chars. + * TODO: If expressionStart == expressionStop, then m_endColumn will be equal to m_startColumn. + *Should we handle this case? + */ + position->expression_start = expressionStart; + position->expression_stop = expressionStop; + position->line = WTF::OrdinalNumber::fromOneBasedInt(static_cast<int>(line)).zeroBasedInt(); + position->column_start = (expressionStart - lineStart) + columnOffset; + position->column_stop = position->column_start + (expressionStop - expressionStart); + position->line_start = lineStart; + position->line_stop = lineStop; + + return; +} +static void populateStackFrame(ZigStackTrace *trace, const JSC::StackFrame *stackFrame, + ZigStackFrame *frame, bool is_top) { + populateStackFrameMetadata(stackFrame, frame); + populateStackFramePosition(stackFrame, is_top ? trace->source_lines_ptr : nullptr, + is_top ? trace->source_lines_numbers : nullptr, + is_top ? trace->source_lines_to_collect : 0, &frame->position); +} +static void populateStackTrace(const WTF::Vector<JSC::StackFrame> &frames, ZigStackTrace *trace) { + uint8_t frame_i = 0; + size_t stack_frame_i = 0; + const size_t total_frame_count = frames.size(); + const uint8_t frame_count = + total_frame_count < trace->frames_len ? total_frame_count : trace->frames_len; + + while (frame_i < frame_count && stack_frame_i < total_frame_count) { + // Skip native frames + while (stack_frame_i < total_frame_count && !(&frames.at(stack_frame_i))->codeBlock() && + !(&frames.at(stack_frame_i))->isWasmFrame()) { + stack_frame_i++; + } + if (stack_frame_i >= total_frame_count) break; + + ZigStackFrame *frame = &trace->frames_ptr[frame_i]; + populateStackFrame(trace, &frames[stack_frame_i], frame, frame_i == 0); + stack_frame_i++; + frame_i++; + } + trace->frames_len = frame_i; +} +static void fromErrorInstance(ZigException *except, JSC::JSGlobalObject *global, + JSC::ErrorInstance *err, const Vector<JSC::StackFrame> *stackTrace, + JSC::JSValue val) { + JSC::JSObject *obj = JSC::jsDynamicCast<JSC::JSObject *>(global->vm(), val); + if (stackTrace != nullptr && stackTrace->size() > 0) { + populateStackTrace(*stackTrace, &except->stack); + } else if (err->stackTrace() != nullptr && err->stackTrace()->size() > 0) { + populateStackTrace(*err->stackTrace(), &except->stack); + } + + except->code = (unsigned char)err->errorType(); + if (err->isStackOverflowError()) { except->code = 253; } + if (err->isOutOfMemoryError()) { except->code = 8; } + + if (obj->hasProperty(global, global->vm().propertyNames->message)) { + except->message = Zig::toZigString( + obj->getDirect(global->vm(), global->vm().propertyNames->message).toWTFString(global)); + + } else { + except->message = Zig::toZigString(err->sanitizedMessageString(global)); + } + except->name = Zig::toZigString(err->sanitizedNameString(global)); + except->runtime_type = err->runtimeTypeForCause(); + + except->exception = err; +} void JSC__JSValue__putRecord(JSC__JSValue objectValue, JSC__JSGlobalObject *global, ZigString *key, ZigString *values, size_t valuesLen) { JSC::JSValue objValue = JSC::JSValue::decode(objectValue); @@ -268,6 +509,65 @@ bWTF__String JSC__JSString__value(JSC__JSString *arg0, JSC__JSGlobalObject *arg1 #pragma mark - JSC::JSModuleLoader +JSC__JSValue JSC__JSModuleLoader__callExportedFunction(JSC__JSGlobalObject *globalObject, + ZigString specifier, ZigString functionName, + JSC__JSValue *arguments, + unsigned char args_len, + ZigException *zig_exception) { + JSC::VM &vm = globalObject->vm(); + JSC::JSLockHolder lock(vm); + + JSC::JSObject *loader = JSC::jsDynamicCast<JSC::JSObject *>(vm, globalObject->moduleLoader()); + JSC::JSMap *registry = JSC::jsDynamicCast<JSC::JSMap *>( + vm, loader->getDirect(vm, JSC::Identifier::fromString(vm, "registry"))); + auto specifier_impl = WTF::ExternalStringImpl::createStatic(specifier.ptr, specifier.len); + auto specifier_ident = + JSC::jsOwnedString(vm, reinterpret_cast<WTF::UniquedStringImpl *>(specifier_impl.ptr())); + auto entry_cell = registry->get(globalObject, specifier_ident); + + if (JSC::JSObject *entry = JSC::jsDynamicCast<JSC::JSObject *>(vm, entry_cell)) { + auto recordIdentifier = JSC::Identifier::fromString(vm, "module"); + + if (JSC::JSModuleRecord *record = + JSC::jsDynamicCast<JSC::JSModuleRecord *>(vm, entry->getDirect(vm, recordIdentifier))) { + auto fn_impl = WTF::ExternalStringImpl::createStatic(functionName.ptr, functionName.len); + auto fn_ident = reinterpret_cast<WTF::UniquedStringImpl *>(specifier_impl.ptr()); + auto env = record->getModuleNamespace(globalObject); + + if (JSC::JSValue macroFunctionExport = + env->getIfPropertyExists(globalObject, JSC::PropertyName(fn_ident))) { + + if (JSC::JSObject *macroFunction = JSC::asObject(macroFunctionExport.asCell())) { + // auto functionNameImpl = + // WTF::ExternalStringImpl::createStatic(functionName.ptr, functionName.len); + JSC::VMEntryScope entryScope(vm, globalObject); + + auto callData = JSC::getCallData(vm, macroFunction); + if (callData.type == JSC::CallData::Type::None) return JSC::JSValue::encode({}); + + JSC::MarkedArgumentBuffer argList; + for (size_t i = 0; i < args_len; i++) argList.append(JSC::JSValue::decode(arguments[i])); + + NakedPtr<JSC::Exception> uncaughtException; + JSC::JSValue reval = JSC::call(globalObject, macroFunction, callData, + globalObject->globalThis(), argList, uncaughtException); + if (uncaughtException) { + if (JSC::ErrorInstance *error = + JSC::jsDynamicCast<JSC::ErrorInstance *>(vm, uncaughtException->value())) { + fromErrorInstance(zig_exception, globalObject, error, &uncaughtException->stack(), + JSC::JSValue(uncaughtException)); + return JSC::JSValue::encode({}); + } + } + return JSC::JSValue::encode(reval); + } + } + } + } + + return JSC::JSValue::encode({}); +} + // JSC__JSValue // JSC__JSModuleLoader__dependencyKeysIfEvaluated(JSC__JSModuleLoader* arg0, // JSC__JSGlobalObject* arg1, JSC__JSModuleRecord* arg2) { @@ -1032,243 +1332,6 @@ bWTF__String JSC__JSValue__toWTFString(JSC__JSValue JSValue0, JSC__JSGlobalObjec return Wrap<WTF::String, bWTF__String>::wrap(value.toWTFString(arg1)); }; -static void populateStackFrameMetadata(const JSC::StackFrame *stackFrame, ZigStackFrame *frame) { - frame->source_url = Zig::toZigString(stackFrame->sourceURL()); - - if (stackFrame->isWasmFrame()) { - frame->code_type = ZigStackFrameCodeWasm; - return; - } - - auto m_codeBlock = stackFrame->codeBlock(); - if (m_codeBlock) { - switch (m_codeBlock->codeType()) { - case JSC::EvalCode: { - frame->code_type = ZigStackFrameCodeEval; - return; - } - case JSC::ModuleCode: { - frame->code_type = ZigStackFrameCodeModule; - return; - } - case JSC::GlobalCode: { - frame->code_type = ZigStackFrameCodeGlobal; - return; - } - case JSC::FunctionCode: { - frame->code_type = - !m_codeBlock->isConstructor() ? ZigStackFrameCodeFunction : ZigStackFrameCodeConstructor; - break; - } - default: ASSERT_NOT_REACHED(); - } - } - - auto calleeCell = stackFrame->callee(); - if (!calleeCell || !calleeCell->isObject()) return; - - JSC::JSObject *callee = JSC::jsCast<JSC::JSObject *>(calleeCell); - // Does the code block have a user-defined name property? - JSC::JSValue name = callee->getDirect(m_codeBlock->vm(), m_codeBlock->vm().propertyNames->name); - if (name && name.isString()) { - auto str = name.toWTFString(m_codeBlock->globalObject()); - frame->function_name = Zig::toZigString(str); - return; - } - - /* For functions (either JSFunction or InternalFunction), fallback to their "native" name - * property. Based on JSC::getCalculatedDisplayName, "inlining" the - * JSFunction::calculatedDisplayName\InternalFunction::calculatedDisplayName calls */ - if (JSC::JSFunction *function = - JSC::jsDynamicCast<JSC::JSFunction *>(m_codeBlock->vm(), callee)) { - - WTF::String actualName = function->name(m_codeBlock->vm()); - if (!actualName.isEmpty() || function->isHostOrBuiltinFunction()) { - frame->function_name = Zig::toZigString(actualName); - return; - } - - auto inferred_name = function->jsExecutable()->name(); - frame->function_name = Zig::toZigString(inferred_name.string()); - } - - if (JSC::InternalFunction *function = - JSC::jsDynamicCast<JSC::InternalFunction *>(m_codeBlock->vm(), callee)) { - // Based on JSC::InternalFunction::calculatedDisplayName, skipping the "displayName" property - frame->function_name = Zig::toZigString(function->name()); - } -} -// Based on -// https://github.com/mceSystems/node-jsc/blob/master/deps/jscshim/src/shim/JSCStackTrace.cpp#L298 -static void populateStackFramePosition(const JSC::StackFrame *stackFrame, ZigString *source_lines, - int32_t *source_line_numbers, uint8_t source_lines_count, - ZigStackFramePosition *position) { - auto m_codeBlock = stackFrame->codeBlock(); - if (!m_codeBlock) return; - - JSC::BytecodeIndex bytecodeOffset = - stackFrame->hasBytecodeIndex() ? stackFrame->bytecodeIndex() : JSC::BytecodeIndex(); - - /* Get the "raw" position info. - * Note that we're using m_codeBlock->unlinkedCodeBlock()->expressionRangeForBytecodeOffset - * rather than m_codeBlock->expressionRangeForBytecodeOffset in order get the "raw" offsets and - * avoid the CodeBlock's expressionRangeForBytecodeOffset modifications to the line and column - * numbers, (we don't need the column number from it, and we'll calculate the line "fixes" - * ourselves). */ - int startOffset = 0; - int endOffset = 0; - int divotPoint = 0; - unsigned line = 0; - unsigned unusedColumn = 0; - m_codeBlock->unlinkedCodeBlock()->expressionRangeForBytecodeIndex( - bytecodeOffset, divotPoint, startOffset, endOffset, line, unusedColumn); - divotPoint += m_codeBlock->sourceOffset(); - - // TODO: evaluate if using the API from UnlinkedCodeBlock can be used instead of iterating - // through source text. - - /* On the first line of the source code, it seems that we need to "fix" the column with the - * starting offset. We currently use codeBlock->source()->startPosition().m_column.oneBasedInt() - * as the offset in the first line rather than codeBlock->firstLineColumnOffset(), which seems - * simpler (and what CodeBlock::expressionRangeForBytecodeOffset does). This is because - * firstLineColumnOffset values seems different from what we expect (according to v8's tests) - * and I haven't dove into the relevant parts in JSC (yet) to figure out why. */ - unsigned columnOffset = line ? 0 : m_codeBlock->source().startColumn().zeroBasedInt(); - - // "Fix" the line number - JSC::ScriptExecutable *executable = m_codeBlock->ownerExecutable(); - if (std::optional<int> overrideLine = executable->overrideLineNumber(m_codeBlock->vm())) { - line = overrideLine.value(); - } else { - line += executable->firstLine(); - } - - // Calculate the staring\ending offsets of the entire expression - int expressionStart = divotPoint - startOffset; - int expressionStop = divotPoint + endOffset; - - // Make sure the range is valid - WTF::StringView sourceString = m_codeBlock->source().provider()->source(); - if (!expressionStop || expressionStart > static_cast<int>(sourceString.length())) { return; } - - // Search for the beginning of the line - unsigned int lineStart = expressionStart; - while ((lineStart > 0) && ('\n' != sourceString[lineStart - 1])) { lineStart--; } - // Search for the end of the line - unsigned int lineStop = expressionStop; - unsigned int sourceLength = sourceString.length(); - while ((lineStop < sourceLength) && ('\n' != sourceString[lineStop])) { lineStop++; } - if (source_lines_count > 1 && source_lines != nullptr) { - auto chars = sourceString.characters8(); - - // Most of the time, when you look at a stack trace, you want a couple lines above - - source_lines[0] = {&chars[lineStart], lineStop - lineStart}; - source_line_numbers[0] = line; - - if (lineStart > 0) { - auto byte_offset_in_source_string = lineStart - 1; - uint8_t source_line_i = 1; - auto remaining_lines_to_grab = source_lines_count - 1; - - while (byte_offset_in_source_string > 0 && remaining_lines_to_grab > 0) { - unsigned int end_of_line_offset = byte_offset_in_source_string; - - // This should probably be code points instead of newlines - while (byte_offset_in_source_string > 0 && chars[byte_offset_in_source_string] != '\n') { - byte_offset_in_source_string--; - } - - // We are at the beginning of the line - source_lines[source_line_i] = {&chars[byte_offset_in_source_string], - end_of_line_offset - byte_offset_in_source_string + 1}; - - source_line_numbers[source_line_i] = line - source_line_i; - source_line_i++; - - remaining_lines_to_grab--; - - byte_offset_in_source_string -= byte_offset_in_source_string > 0; - } - } - } - - /* Finally, store the source "positions" info. - * Notes: - * - The retrieved column seem to point the "end column". To make sure we're current, we'll - *calculate the columns ourselves, since we've already found where the line starts. Note that in - *v8 it should be 0-based here (in contrast the 1-based column number in v8::StackFrame). - * - The static_casts are ugly, but comes from differences between JSC and v8's api, and should - *be OK since no source should be longer than "max int" chars. - * TODO: If expressionStart == expressionStop, then m_endColumn will be equal to m_startColumn. - *Should we handle this case? - */ - position->expression_start = expressionStart; - position->expression_stop = expressionStop; - position->line = WTF::OrdinalNumber::fromOneBasedInt(static_cast<int>(line)).zeroBasedInt(); - position->column_start = (expressionStart - lineStart) + columnOffset; - position->column_stop = position->column_start + (expressionStop - expressionStart); - position->line_start = lineStart; - position->line_stop = lineStop; - - return; -} -static void populateStackFrame(ZigStackTrace *trace, const JSC::StackFrame *stackFrame, - ZigStackFrame *frame, bool is_top) { - populateStackFrameMetadata(stackFrame, frame); - populateStackFramePosition(stackFrame, is_top ? trace->source_lines_ptr : nullptr, - is_top ? trace->source_lines_numbers : nullptr, - is_top ? trace->source_lines_to_collect : 0, &frame->position); -} -static void populateStackTrace(const WTF::Vector<JSC::StackFrame> &frames, ZigStackTrace *trace) { - uint8_t frame_i = 0; - size_t stack_frame_i = 0; - const size_t total_frame_count = frames.size(); - const uint8_t frame_count = - total_frame_count < trace->frames_len ? total_frame_count : trace->frames_len; - - while (frame_i < frame_count && stack_frame_i < total_frame_count) { - // Skip native frames - while (stack_frame_i < total_frame_count && !(&frames.at(stack_frame_i))->codeBlock() && - !(&frames.at(stack_frame_i))->isWasmFrame()) { - stack_frame_i++; - } - if (stack_frame_i >= total_frame_count) break; - - ZigStackFrame *frame = &trace->frames_ptr[frame_i]; - populateStackFrame(trace, &frames[stack_frame_i], frame, frame_i == 0); - stack_frame_i++; - frame_i++; - } - trace->frames_len = frame_i; -} -static void fromErrorInstance(ZigException *except, JSC::JSGlobalObject *global, - JSC::ErrorInstance *err, const Vector<JSC::StackFrame> *stackTrace, - JSC::JSValue val) { - JSC::JSObject *obj = JSC::jsDynamicCast<JSC::JSObject *>(global->vm(), val); - if (stackTrace != nullptr && stackTrace->size() > 0) { - populateStackTrace(*stackTrace, &except->stack); - } else if (err->stackTrace() != nullptr && err->stackTrace()->size() > 0) { - populateStackTrace(*err->stackTrace(), &except->stack); - } - - except->code = (unsigned char)err->errorType(); - if (err->isStackOverflowError()) { except->code = 253; } - if (err->isOutOfMemoryError()) { except->code = 8; } - - if (obj->hasProperty(global, global->vm().propertyNames->message)) { - except->message = Zig::toZigString( - obj->getDirect(global->vm(), global->vm().propertyNames->message).toWTFString(global)); - - } else { - except->message = Zig::toZigString(err->sanitizedMessageString(global)); - } - except->name = Zig::toZigString(err->sanitizedNameString(global)); - except->runtime_type = err->runtimeTypeForCause(); - - except->exception = err; -} - void exceptionFromString(ZigException *except, JSC::JSValue value, JSC::JSGlobalObject *global) { // Fallback case for when it's a user-defined ErrorLike-object that doesn't inherit from // ErrorInstance |