diff options
Diffstat (limited to 'src/bun.js')
| -rw-r--r-- | src/bun.js/bindings/JSStringDecoder.cpp | 116 | 
1 files changed, 104 insertions, 12 deletions
| diff --git a/src/bun.js/bindings/JSStringDecoder.cpp b/src/bun.js/bindings/JSStringDecoder.cpp index c73378fdf..96fbc3a57 100644 --- a/src/bun.js/bindings/JSStringDecoder.cpp +++ b/src/bun.js/bindings/JSStringDecoder.cpp @@ -21,6 +21,46 @@ static JSC_DECLARE_CUSTOM_GETTER(jsStringDecoder_lastChar);  static JSC_DECLARE_CUSTOM_GETTER(jsStringDecoder_lastNeed);  static JSC_DECLARE_CUSTOM_GETTER(jsStringDecoder_lastTotal); +static inline EncodedJSValue jsStringDecoderCast(JSGlobalObject* globalObject, JSValue stringDecoderValue) +{ +    if (LIKELY(jsDynamicCast<JSStringDecoder*>(stringDecoderValue))) +        return JSValue::encode(stringDecoderValue); + +    auto& vm = globalObject->vm(); +    auto throwScope = DECLARE_THROW_SCOPE(vm); + +    if (stringDecoderValue.isEmpty() || stringDecoderValue.isUndefinedOrNull()) { +        return JSC::JSValue::encode(jsUndefined()); +    } + +    if (!stringDecoderValue.isObject()) { +        return throwThisTypeError(*globalObject, throwScope, JSStringDecoder::info()->className, "write"); +    } + +    JSC::JSObject* thisObject = JSC::asObject(stringDecoderValue); +    JSStringDecoder* castedThis = nullptr; +    auto clientData = WebCore::clientData(vm); +    if (JSValue existingDecoderValue = thisObject->getIfPropertyExists(globalObject, clientData->builtinNames().decodePrivateName())) { +        castedThis = jsDynamicCast<JSStringDecoder*>(existingDecoderValue); +    } + +    if (!castedThis) { +        BufferEncodingType encoding = BufferEncodingType::utf8; +        if (JSValue encodingValue = thisObject->getIfPropertyExists(globalObject, clientData->builtinNames().encodingPrivateName())) { +            if (encodingValue.isString()) { +                std::optional<BufferEncodingType> opt = parseEnumeration<BufferEncodingType>(*globalObject, encodingValue); +                if (opt.has_value()) { +                    encoding = opt.value(); +                } +            } +        } +        castedThis = JSStringDecoder::create(globalObject->vm(), globalObject, reinterpret_cast<Zig::GlobalObject*>(globalObject)->JSStringDecoderStructure(), encoding); +        thisObject->putDirect(vm, clientData->builtinNames().decodePrivateName(), castedThis, 0); +    } + +    return JSValue::encode(castedThis); +} +  void JSStringDecoder::finishCreation(JSC::VM& vm, JSC::JSGlobalObject* globalObject)  {      Base::finishCreation(vm); @@ -299,7 +339,7 @@ JSC::GCClient::IsoSubspace* JSStringDecoder::subspaceForImpl(JSC::VM& vm)  STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(JSStringDecoderPrototype, JSStringDecoderPrototype::Base); -static inline JSC::EncodedJSValue jsStringDecoderPrototypeFunction_writeBody(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame, typename IDLOperation<JSStringDecoder>::ClassParameter castedThis) +static inline JSC::EncodedJSValue jsStringDecoderPrototypeFunction_writeBody(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame, JSStringDecoder* castedThis)  {      auto& vm = JSC::getVM(lexicalGlobalObject);      auto throwScope = DECLARE_THROW_SCOPE(vm); @@ -324,7 +364,7 @@ static inline JSC::EncodedJSValue jsStringDecoderPrototypeFunction_writeBody(JSC      }      RELEASE_AND_RETURN(throwScope, JSC::JSValue::encode(castedThis->write(vm, lexicalGlobalObject, reinterpret_cast<uint8_t*>(view->vector()), view->byteLength())));  } -static inline JSC::EncodedJSValue jsStringDecoderPrototypeFunction_endBody(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame, typename IDLOperation<JSStringDecoder>::ClassParameter castedThis) +static inline JSC::EncodedJSValue jsStringDecoderPrototypeFunction_endBody(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame, JSStringDecoder* castedThis)  {      auto& vm = JSC::getVM(lexicalGlobalObject);      auto throwScope = DECLARE_THROW_SCOPE(vm); @@ -340,7 +380,7 @@ static inline JSC::EncodedJSValue jsStringDecoderPrototypeFunction_endBody(JSC::      }      RELEASE_AND_RETURN(throwScope, JSC::JSValue::encode(castedThis->end(vm, lexicalGlobalObject, reinterpret_cast<uint8_t*>(view->vector()), view->byteLength())));  } -static inline JSC::EncodedJSValue jsStringDecoderPrototypeFunction_textBody(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame, typename IDLOperation<JSStringDecoder>::ClassParameter castedThis) +static inline JSC::EncodedJSValue jsStringDecoderPrototypeFunction_textBody(JSC::JSGlobalObject* lexicalGlobalObject, JSC::CallFrame* callFrame, JSStringDecoder* castedThis)  {      auto& vm = JSC::getVM(lexicalGlobalObject);      auto throwScope = DECLARE_THROW_SCOPE(vm); @@ -366,24 +406,44 @@ static inline JSC::EncodedJSValue jsStringDecoderPrototypeFunction_textBody(JSC:  static JSC_DEFINE_HOST_FUNCTION(jsStringDecoderPrototypeFunction_write,      (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame))  { -    return IDLOperation<JSStringDecoder>::call<jsStringDecoderPrototypeFunction_writeBody>(*globalObject, *callFrame, "write"); +    JSValue stringDecoderValue = JSValue::decode(jsStringDecoderCast(globalObject, callFrame->thisValue())); +    if (stringDecoderValue.isEmpty() || !stringDecoderValue.isCell()) { +        return JSValue::encode(stringDecoderValue); +    } +    JSStringDecoder* castedThis = jsCast<JSStringDecoder*>(stringDecoderValue); +    return jsStringDecoderPrototypeFunction_writeBody(globalObject, callFrame, castedThis);  }  static JSC_DEFINE_HOST_FUNCTION(jsStringDecoderPrototypeFunction_end,      (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame))  { -    return IDLOperation<JSStringDecoder>::call<jsStringDecoderPrototypeFunction_endBody>(*globalObject, *callFrame, "end"); +    JSValue stringDecoderValue = JSValue::decode(jsStringDecoderCast(globalObject, callFrame->thisValue())); +    if (stringDecoderValue.isEmpty() || !stringDecoderValue.isCell()) { +        return JSValue::encode(stringDecoderValue); +    } +    JSStringDecoder* castedThis = jsCast<JSStringDecoder*>(stringDecoderValue); +    return jsStringDecoderPrototypeFunction_endBody(globalObject, callFrame, castedThis);  }  static JSC_DEFINE_HOST_FUNCTION(jsStringDecoderPrototypeFunction_text,      (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame))  { -    return IDLOperation<JSStringDecoder>::call<jsStringDecoderPrototypeFunction_textBody>(*globalObject, *callFrame, "text"); +    JSValue stringDecoderValue = JSValue::decode(jsStringDecoderCast(globalObject, callFrame->thisValue())); +    if (stringDecoderValue.isEmpty() || !stringDecoderValue.isCell()) { +        return JSValue::encode(stringDecoderValue); +    } +    JSStringDecoder* castedThis = jsCast<JSStringDecoder*>(stringDecoderValue); + +    return jsStringDecoderPrototypeFunction_textBody(globalObject, callFrame, castedThis);  }  static JSC_DEFINE_CUSTOM_GETTER(jsStringDecoder_lastChar, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, PropertyName attributeName))  {      auto& vm = JSC::getVM(lexicalGlobalObject); +    JSValue stringDecoderValue = JSValue::decode(jsStringDecoderCast(lexicalGlobalObject, JSValue::decode(thisValue))); +    if (stringDecoderValue.isEmpty() || !stringDecoderValue.isCell()) { +        return JSValue::encode(stringDecoderValue); +    } +    JSStringDecoder* thisObject = jsCast<JSStringDecoder*>(stringDecoderValue);      auto throwScope = DECLARE_THROW_SCOPE(vm); -    JSStringDecoder* thisObject = jsCast<JSStringDecoder*>(JSValue::decode(thisValue));      auto buffer = ArrayBuffer::createFromBytes(thisObject->m_lastChar, 4, nullptr);      auto* globalObject = reinterpret_cast<Zig::GlobalObject*>(lexicalGlobalObject);      JSC::JSUint8Array* uint8Array = JSC::JSUint8Array::create(lexicalGlobalObject, globalObject->JSBufferSubclassStructure(), WTFMove(buffer), 0, 4); @@ -392,15 +452,23 @@ static JSC_DEFINE_CUSTOM_GETTER(jsStringDecoder_lastChar, (JSGlobalObject * lexi  static JSC_DEFINE_CUSTOM_GETTER(jsStringDecoder_lastNeed, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, PropertyName attributeName))  {      auto& vm = JSC::getVM(lexicalGlobalObject); +    JSValue stringDecoderValue = JSValue::decode(jsStringDecoderCast(lexicalGlobalObject, JSValue::decode(thisValue))); +    if (stringDecoderValue.isEmpty() || !stringDecoderValue.isCell()) { +        return JSValue::encode(stringDecoderValue); +    } +    JSStringDecoder* thisObject = jsCast<JSStringDecoder*>(stringDecoderValue);      auto throwScope = DECLARE_THROW_SCOPE(vm); -    JSStringDecoder* thisObject = jsCast<JSStringDecoder*>(JSValue::decode(thisValue));      RELEASE_AND_RETURN(throwScope, JSC::JSValue::encode(JSC::jsNumber(thisObject->m_lastNeed)));  }  static JSC_DEFINE_CUSTOM_GETTER(jsStringDecoder_lastTotal, (JSGlobalObject * lexicalGlobalObject, EncodedJSValue thisValue, PropertyName attributeName))  {      auto& vm = JSC::getVM(lexicalGlobalObject); +    JSValue stringDecoderValue = JSValue::decode(jsStringDecoderCast(lexicalGlobalObject, JSValue::decode(thisValue))); +    if (stringDecoderValue.isEmpty() || !stringDecoderValue.isCell()) { +        return JSValue::encode(stringDecoderValue); +    } +    JSStringDecoder* thisObject = jsCast<JSStringDecoder*>(stringDecoderValue);      auto throwScope = DECLARE_THROW_SCOPE(vm); -    JSStringDecoder* thisObject = jsCast<JSStringDecoder*>(JSValue::decode(thisValue));      RELEASE_AND_RETURN(throwScope, JSC::JSValue::encode(JSC::jsNumber(thisObject->m_lastTotal)));  } @@ -452,13 +520,37 @@ JSC::EncodedJSValue JSStringDecoderConstructor::construct(JSC::JSGlobalObject* l              }          }      } -    JSStringDecoder* stringDecoder = JSStringDecoder::create( -        vm, lexicalGlobalObject, reinterpret_cast<Zig::GlobalObject*>(lexicalGlobalObject)->JSStringDecoderStructure(), encoding); -    return JSC::JSValue::encode(stringDecoder); +    JSValue thisValue = callFrame->newTarget(); +    auto* globalObject = JSC::jsCast<Zig::GlobalObject*>(lexicalGlobalObject); +    JSObject* newTarget = asObject(thisValue); +    auto* constructor = globalObject->JSStringDecoder(); +    Structure* structure = globalObject->JSStringDecoderStructure(); + +    JSStringDecoder* jsObject = JSStringDecoder::create( +        vm, lexicalGlobalObject, structure, encoding); + +    // StringDecodeer is a Weird one +    // This is a hack to make express' body-parser work +    // It does something weird with the prototype +    // Not exactly a subclass +    if (constructor != newTarget && callFrame->thisValue().isObject()) { +        auto clientData = WebCore::clientData(vm); +        JSObject* thisObject = asObject(callFrame->thisValue()); + +        thisObject->putDirect(vm, clientData->builtinNames().decodePrivateName(), jsObject, JSC::PropertyAttribute::DontEnum | 0); +        return JSC::JSValue::encode(thisObject); +    } + +    return JSC::JSValue::encode(jsObject);  }  void JSStringDecoderConstructor::initializeProperties(VM& vm, JSC::JSGlobalObject* globalObject, JSStringDecoderPrototype* prototype)  { +    putDirect(vm, vm.propertyNames->length, jsNumber(1), JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontEnum); +    JSString* nameString = jsNontrivialString(vm, "StringDecoder"_s); +    m_originalName.set(vm, this, nameString); +    putDirect(vm, vm.propertyNames->name, nameString, JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontEnum); +    putDirect(vm, vm.propertyNames->prototype, prototype, JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontEnum | JSC::PropertyAttribute::DontDelete);  }  const ClassInfo JSStringDecoderConstructor::s_info = { "StringDecoder"_s, &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSStringDecoderConstructor) }; | 
