WIP macros

This commit is contained in:
Jarred Sumner
2021-09-19 03:43:17 -07:00
parent 9ae35ec581
commit 60b5fb95b1
19 changed files with 5788 additions and 5382 deletions

View File

@@ -4,6 +4,7 @@ pub usingnamespace @import("../../global.zig");
usingnamespace @import("./javascript.zig");
usingnamespace @import("./webcore/response.zig");
const Router = @import("./api/router.zig");
const JSExpr = @import("../../js_ast.zig").Macro.JSExpr;
const TaggedPointerTypes = @import("../../tagged_pointer.zig");
const TaggedPointerUnion = TaggedPointerTypes.TaggedPointerUnion;
@@ -839,6 +840,10 @@ pub fn NewClass(
}
pub fn customHasInstance(ctx: js.JSContextRef, obj: js.JSObjectRef, value: js.JSValueRef, exception: js.ExceptionRef) callconv(.C) bool {
if (comptime @typeInfo(ZigType) == .Struct and @hasDecl(ZigType, "isInstanceOf")) {
return ZigType.isInstanceOf(ctx, obj, value, exception);
}
return js.JSValueIsObjectOfClass(ctx, value, get().*);
}
@@ -1449,6 +1454,7 @@ pub fn NewClass(
if (!singleton)
def.hasInstance = customHasInstance;
return def;
}
};
@@ -1509,6 +1515,7 @@ pub const JSPrivateDataPtr = TaggedPointerUnion(.{
Headers,
Body,
Router,
JSExpr,
});
pub inline fn GetJSPrivateData(comptime Type: type, ref: js.JSObjectRef) ?*Type {

View File

@@ -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

View File

@@ -373,12 +373,30 @@ pub const JSModuleLoader = extern struct {
});
}
pub fn callExportedFunction(
globalObject: *JSGlobalObject,
specifier: ZigString,
function_name: ZigString,
arguments_ptr: [*]JSValue,
arguments_len: u8,
exception: *ZigException,
) JSValue {
return shim.cppFn("callExportedFunction", .{
globalObject,
specifier,
function_name,
arguments_ptr,
arguments_len,
exception,
});
}
// pub fn dependencyKeysIfEvaluated(this: *JSModuleLoader, globalObject: *JSGlobalObject, moduleRecord: *JSModuleRecord) *JSValue {
// return shim.cppFn("dependencyKeysIfEvaluated", .{ this, globalObject, moduleRecord });
// }
pub const Extern = [_][]const u8{
// "dependencyKeysIfEvaluated",
"callExportedFunction",
"evaluate",
"loadAndEvaluateModuleEntryPoint",
"loadAndEvaluateModule",
@@ -821,7 +839,7 @@ pub const JSGlobalObject = extern struct {
const cppFn = shim.cppFn;
pub fn ref(this: *JSGlobalObject) C_API.JSContextRef {
pub inline fn ref(this: *JSGlobalObject) C_API.JSContextRef {
return @ptrCast(C_API.JSContextRef, this);
}
pub const ctx = ref;

View File

@@ -1,4 +1,4 @@
//-- AUTOGENERATED FILE -- 1631749917
//-- AUTOGENERATED FILE -- 1632030969
// clang-format off
#pragma once

View File

@@ -1,4 +1,4 @@
//-- AUTOGENERATED FILE -- 1631749917
//-- AUTOGENERATED FILE -- 1632030969
// clang-format: off
#pragma once
@@ -100,10 +100,10 @@ typedef void* JSClassRef;
typedef bJSC__JSGlobalObject JSC__JSGlobalObject; // JSC::JSGlobalObject
typedef bJSC__JSFunction JSC__JSFunction; // JSC::JSFunction
typedef struct JSC__ArrayPrototype JSC__ArrayPrototype; // JSC::ArrayPrototype
typedef struct JSC__AsyncFunctionPrototype JSC__AsyncFunctionPrototype; // JSC::AsyncFunctionPrototype
typedef bJSC__Identifier JSC__Identifier; // JSC::Identifier
typedef bJSC__JSPromise JSC__JSPromise; // JSC::JSPromise
typedef ZigException ZigException;
typedef struct JSC__AsyncFunctionPrototype JSC__AsyncFunctionPrototype; // JSC::AsyncFunctionPrototype
typedef bJSC__JSPromise JSC__JSPromise; // JSC::JSPromise
typedef bJSC__Identifier JSC__Identifier; // JSC::Identifier
typedef struct JSC__SetIteratorPrototype JSC__SetIteratorPrototype; // JSC::SetIteratorPrototype
typedef bJSC__SourceCode JSC__SourceCode; // JSC::SourceCode
typedef bJSC__JSCell JSC__JSCell; // JSC::JSCell
@@ -139,8 +139,8 @@ typedef void* JSClassRef;
class JSObject;
class AsyncIteratorPrototype;
class AsyncGeneratorFunctionPrototype;
class Identifier;
class JSPromise;
class Identifier;
class RegExpPrototype;
class AsyncFunctionPrototype;
class CatchScope;
@@ -193,8 +193,8 @@ typedef void* JSClassRef;
using JSC__JSObject = JSC::JSObject;
using JSC__AsyncIteratorPrototype = JSC::AsyncIteratorPrototype;
using JSC__AsyncGeneratorFunctionPrototype = JSC::AsyncGeneratorFunctionPrototype;
using JSC__Identifier = JSC::Identifier;
using JSC__JSPromise = JSC::JSPromise;
using JSC__Identifier = JSC::Identifier;
using JSC__RegExpPrototype = JSC::RegExpPrototype;
using JSC__AsyncFunctionPrototype = JSC::AsyncFunctionPrototype;
using JSC__CatchScope = JSC::CatchScope;
@@ -267,6 +267,7 @@ CPP_DECL void Inspector__ScriptArguments__release(Inspector__ScriptArguments* ar
#pragma mark - JSC::JSModuleLoader
CPP_DECL JSC__JSValue JSC__JSModuleLoader__callExportedFunction(JSC__JSGlobalObject* arg0, ZigString arg1, ZigString arg2, JSC__JSValue* arg3, unsigned char arg4, ZigException* arg5);
CPP_DECL bool JSC__JSModuleLoader__checkSyntax(JSC__JSGlobalObject* arg0, const JSC__SourceCode* arg1, bool arg2);
CPP_DECL JSC__JSValue JSC__JSModuleLoader__evaluate(JSC__JSGlobalObject* arg0, const unsigned char* arg1, size_t arg2, const unsigned char* arg3, size_t arg4, JSC__JSValue JSValue5, JSC__JSValue* arg6);
CPP_DECL JSC__JSInternalPromise* JSC__JSModuleLoader__importModule(JSC__JSGlobalObject* arg0, const JSC__Identifier* arg1);

File diff suppressed because one or more lines are too long

View File

@@ -8,7 +8,7 @@ const NodeModuleBundle = @import("../../node_module_bundle.zig").NodeModuleBundl
const logger = @import("../../logger.zig");
const Api = @import("../../api/schema.zig").Api;
const options = @import("../../options.zig");
const Bundler = @import("../../bundler.zig").ServeBundler;
const Bundler = @import("../../bundler.zig").Bundler;
const js_printer = @import("../../js_printer.zig");
const hash_map = @import("../../hash_map.zig");
const http = @import("../../http.zig");

View File

@@ -7,7 +7,7 @@ const NodeModuleBundle = @import("../../node_module_bundle.zig").NodeModuleBundl
const logger = @import("../../logger.zig");
const Api = @import("../../api/schema.zig").Api;
const options = @import("../../options.zig");
const Bundler = @import("../../bundler.zig").ServeBundler;
const Bundler = @import("../../bundler.zig").Bundler;
const ServerEntryPoint = @import("../../bundler.zig").ServerEntryPoint;
const js_printer = @import("../../js_printer.zig");
const js_parser = @import("../../js_parser.zig");
@@ -359,22 +359,16 @@ pub const Bun = struct {
const bun_file_import_path = "/node_modules.server.bun";
pub const LazyClasses = [_]type{};
pub const Module = struct {
reload_pending: bool = false,
};
// If you read JavascriptCore/API/JSVirtualMachine.mm - https://github.com/WebKit/WebKit/blob/acff93fb303baa670c055cb24c2bad08691a01a0/Source/JavaScriptCore/API/JSVirtualMachine.mm#L101
// We can see that it's sort of like std.mem.Allocator but for JSGlobalContextRef, to support Automatic Reference Counting
// Its unavailable on Linux
pub const VirtualMachine = struct {
const RequireCacheType = std.AutoHashMap(u32, *Module);
global: *JSGlobalObject,
allocator: *std.mem.Allocator,
node_modules: ?*NodeModuleBundle = null,
bundler: Bundler,
watcher: ?*http.Watcher = null,
console: *ZigConsoleClient,
require_cache: RequireCacheType,
log: *logger.Log,
event_listeners: EventListenerMixin.Map,
main: string = "",
@@ -389,8 +383,8 @@ pub const VirtualMachine = struct {
transpiled_count: usize = 0,
resolved_count: usize = 0,
had_errors: bool = false,
pub var vm_loaded = false;
pub var vm: *VirtualMachine = undefined;
pub threadlocal var vm_loaded = false;
pub threadlocal var vm: *VirtualMachine = undefined;
pub fn init(
allocator: *std.mem.Allocator,
@@ -421,7 +415,6 @@ pub const VirtualMachine = struct {
.global = undefined,
.allocator = allocator,
.entry_point = ServerEntryPoint{},
.require_cache = RequireCacheType.init(allocator),
.event_listeners = EventListenerMixin.Map.init(allocator),
.bundler = bundler,
.console = console,