diff options
Diffstat (limited to 'src/bun.js/bindings/bindings.cpp')
-rw-r--r-- | src/bun.js/bindings/bindings.cpp | 177 |
1 files changed, 170 insertions, 7 deletions
diff --git a/src/bun.js/bindings/bindings.cpp b/src/bun.js/bindings/bindings.cpp index 4cb163f88..4c65cedf5 100644 --- a/src/bun.js/bindings/bindings.cpp +++ b/src/bun.js/bindings/bindings.cpp @@ -47,7 +47,7 @@ #include "wtf/text/StringImpl.h" #include "wtf/text/StringView.h" #include "wtf/text/WTFString.h" - +#include "JavaScriptCore/FunctionPrototype.h" #include "JSFetchHeaders.h" #include "FetchHeaders.h" #include "DOMURL.h" @@ -128,7 +128,7 @@ static void handlePromise(PromiseType* promise, JSC__JSGlobalObject* globalObjec } } -static bool canPerformFastPropertyEnumerationForObjectAssignBun(Structure* s) +static bool canPerformFastPropertyEnumerationForIterationBun(Structure* s) { if (s->typeInfo().overridesGetOwnPropertySlot()) return false; @@ -448,7 +448,6 @@ bool Bun__deepEquals(JSC__JSGlobalObject* globalObject, JSValue v1, JSValue v2, case JSFunctionType: { return false; } - default: { break; } @@ -547,14 +546,14 @@ bool Bun__deepEquals(JSC__JSGlobalObject* globalObject, JSValue v1, JSValue v2, } JSC::Structure* o1Structure = o1->structure(); - if (canPerformFastPropertyEnumerationForObjectAssignBun(o1Structure)) { + if (canPerformFastPropertyEnumerationForIterationBun(o1Structure)) { JSC::Structure* o2Structure = o2->structure(); - if (canPerformFastPropertyEnumerationForObjectAssignBun(o2Structure)) { + if (canPerformFastPropertyEnumerationForIterationBun(o2Structure)) { size_t count1 = 0; bool result = true; - if (o2Structure->maxOffset() != o1Structure->maxOffset()) { + if (o2Structure->inlineSize() + o2Structure->outOfLineSize() != o1Structure->inlineSize() + o1Structure->outOfLineSize()) { return false; } @@ -1819,7 +1818,15 @@ void JSC__JSValue__toZigString(JSC__JSValue JSValue0, ZigString* arg1, JSC__JSGl // return; // } - auto str = value.toWTFString(arg2); + auto* strValue = value.toStringOrNull(arg2); + + if (UNLIKELY(!strValue)) { + arg1->len = 0; + arg1->ptr = nullptr; + return; + } + + auto str = strValue->value(arg2); if (str.is8Bit()) { arg1->ptr = str.characters8(); @@ -3724,3 +3731,159 @@ bool JSC__JSValue__toBooleanSlow(JSC__JSValue JSValue0, JSC__JSGlobalObject* glo { return JSValue::decode(JSValue0).toBoolean(globalObject); } + +void JSC__JSValue__forEachProperty(JSC__JSValue JSValue0, JSC__JSGlobalObject* globalObject, void* arg2, void (*iter)(JSC__JSGlobalObject* arg0, void* ctx, ZigString* arg2, JSC__JSValue JSValue3, bool isSymbol)) +{ + JSC::JSValue value = JSC::JSValue::decode(JSValue0); + JSC::JSObject* object = value.getObject(); + if (!object) + return; + + JSC::VM& vm = globalObject->vm(); + auto scope = DECLARE_CATCH_SCOPE(vm); + + JSC::Structure* structure = object->structure(); + bool fast = canPerformFastPropertyEnumerationForIterationBun(structure); + if (fast) { + if (structure->outOfLineSize() == 0 && structure->inlineSize() == 0) { + fast = false; + if (JSValue proto = object->getPrototype(vm, globalObject)) { + if (structure = proto.structureOrNull()) { + fast = canPerformFastPropertyEnumerationForIterationBun(structure); + } + } + } + } + + if (fast) { + bool anyHits = false; + + structure->forEachProperty(vm, [&](const PropertyTableEntry& entry) -> bool { + if (entry.attributes() & PropertyAttribute::DontEnum) { + + if ((entry.attributes() & PropertyAttribute::Accessor) != 0) { + return true; + } + if (!(entry.attributes() & (PropertyAttribute::BuiltinOrFunction | PropertyAttribute::CustomAccessorOrValue))) { + return true; + } + + // ignore constructor + if (entry.key() == vm.propertyNames->constructor) { + return true; + } + } + + ZigString key = toZigString(entry.key()); + + JSC::JSValue propertyValue = object->getDirect(entry.offset()); + if (!propertyValue) { + propertyValue = object->get(globalObject, entry.key()); + } + + if (scope.exception()) + scope.clearException(); + + if (!propertyValue) + return true; + + anyHits = true; + JSC::EnsureStillAliveScope ensureStillAliveScope(propertyValue); + iter(globalObject, arg2, &key, JSC::JSValue::encode(propertyValue), entry.key()->isSymbol()); + return true; + }); + if (anyHits) { + if (scope.exception()) { + scope.clearException(); + return; + } + return; + } + } + + JSC::PropertyNameArray properties(vm, PropertyNameMode::StringsAndSymbols, PrivateSymbolMode::Exclude); + + { + auto scope = DECLARE_THROW_SCOPE(vm); + + JSObject* iterating = object; + unsigned prototypeCount = 0; + size_t count = 0; + + while (count == 0) { + iterating->methodTable()->getOwnPropertyNames(iterating, globalObject, properties, DontEnumPropertiesMode::Include); + RETURN_IF_EXCEPTION(scope, void()); + + for (auto& property : properties) { + if (UNLIKELY(property.isEmpty() || property.isNull())) + continue; + + // ignore constructor + if (property == vm.propertyNames->constructor) { + continue; + } + + JSC::PropertySlot slot(object, PropertySlot::InternalMethodType::Get); + if (!object->getPropertySlot(globalObject, property, slot)) + continue; + + if ((slot.attributes() & PropertyAttribute::Accessor) != 0) { + continue; + } + + if ((slot.attributes() & PropertyAttribute::DontEnum) != 0) { + if (property == vm.propertyNames->length || property == vm.propertyNames->name || property == vm.propertyNames->underscoreProto) + continue; + } + + ZigString key = toZigString(property.isSymbol() ? property.impl() : property.string()); + + JSC::JSValue propertyValue = jsUndefined(); + + if ((slot.attributes() & PropertyAttribute::DontEnum) != 0) { + if (slot.attributes() & PropertyAttribute::BuiltinOrFunction) { + propertyValue = slot.getValue(globalObject, property); + } else if (slot.isCustom()) { + propertyValue = slot.internalMethodType() == PropertySlot::InternalMethodType::Get || slot.internalMethodType() == PropertySlot::InternalMethodType::HasProperty ? slot.getValue(globalObject, property) : jsUndefined(); + } else if (slot.isValue()) { + propertyValue = slot.getValue(globalObject, property); + } else if (object->getOwnPropertySlot(object, globalObject, property, slot)) { + propertyValue = slot.getValue(globalObject, property); + } + } else { + propertyValue = slot.getValue(globalObject, property); + } + + if (scope.exception()) { + scope.clearException(); + propertyValue = jsUndefined(); + } + + JSC::EnsureStillAliveScope ensureStillAliveScope(propertyValue); + count++; + iter(globalObject, arg2, &key, JSC::JSValue::encode(propertyValue), property.isSymbol()); + } + // reuse memory + properties.data()->propertyNameVector().shrink(0); + + JSValue prototype = iterating->getPrototype(vm, globalObject); + RETURN_IF_EXCEPTION(scope, void()); + if (prototype.isNull() || prototype == JSValue(globalObject->functionPrototype()) || prototype == JSValue(globalObject->objectPrototype()) || prototype == JSValue(globalObject->objectPrototype())) + break; + + if (++prototypeCount > 1) { + break; + } + + iterating = asObject(prototype); + if (iterating->structure()->typeInfo().overridesAnyFormOfGetOwnPropertyNames()) + break; + } + } + properties.releaseData(); + + if (scope.exception()) { + scope.clearException(); + return; + } +} |