JSValue readTerminal()

in src/bun.js/bindings/webcore/SerializedScriptValue.cpp [4474:4930]


    JSValue readTerminal()
    {
        SerializationTag tag = readTag();
        // if (!isTypeExposedToGlobalObject(*m_globalObject, tag))
        //     return JSValue();

        // read bun types
        if (auto value = StructuredCloneableDeserialize::fromTagDeserialize(tag, m_lexicalGlobalObject, m_ptr, m_end)) {
            JSValue deserialized = JSValue::decode(value.value());
            if (deserialized.isEmpty()) {
                fail();
                return JSValue();
            }
            return deserialized;
        }

        switch (tag) {
        case UndefinedTag:
            return jsUndefined();
        case NullTag:
            return jsNull();
        case IntTag: {
            int32_t i;
            if (!read(i))
                return JSValue();
            return jsNumber(i);
        }
        case ZeroTag:
            return jsNumber(0);
        case OneTag:
            return jsNumber(1);
        case FalseTag:
            return jsBoolean(false);
        case TrueTag:
            return jsBoolean(true);
        case FalseObjectTag: {
            BooleanObject* obj = BooleanObject::create(m_lexicalGlobalObject->vm(), m_globalObject->booleanObjectStructure());
            obj->setInternalValue(m_lexicalGlobalObject->vm(), jsBoolean(false));
            m_gcBuffer.appendWithCrashOnOverflow(obj);
            return obj;
        }
        case TrueObjectTag: {
            BooleanObject* obj = BooleanObject::create(m_lexicalGlobalObject->vm(), m_globalObject->booleanObjectStructure());
            obj->setInternalValue(m_lexicalGlobalObject->vm(), jsBoolean(true));
            m_gcBuffer.appendWithCrashOnOverflow(obj);
            return obj;
        }
        case DoubleTag: {
            double d;
            if (!read(d))
                return JSValue();
            return jsNumber(purifyNaN(d));
        }
        case BigIntTag:
            return readBigInt();
        case NumberObjectTag: {
            double d;
            if (!read(d))
                return JSValue();
            NumberObject* obj = constructNumber(m_globalObject, jsNumber(purifyNaN(d)));
            m_gcBuffer.appendWithCrashOnOverflow(obj);
            return obj;
        }
        case BigIntObjectTag: {
            JSValue bigInt = readBigInt();
            if (!bigInt)
                return JSValue();
            ASSERT(bigInt.isBigInt());
            BigIntObject* obj = BigIntObject::create(m_lexicalGlobalObject->vm(), m_globalObject, bigInt);
            m_gcBuffer.appendWithCrashOnOverflow(obj);
            return obj;
        }
        case DateTag: {
            double d;
            if (!read(d))
                return JSValue();
            return DateInstance::create(m_lexicalGlobalObject->vm(), m_globalObject->dateStructure(), d);
        }
        // case FileTag: {
        //     RefPtr<File> file;
        //     if (!readFile(file))
        //         return JSValue();
        //     if (!m_canCreateDOMObject)
        //         return jsNull();
        //     return toJS(m_lexicalGlobalObject, jsCast<JSDOMGlobalObject*>(m_globalObject), file.get());
        // }
        // case FileListTag: {
        //     unsigned length = 0;
        //     if (!read(length))
        //         return JSValue();
        //     ASSERT(m_globalObject->inherits<JSDOMGlobalObject>());
        //     Vector<Ref<File>> files;
        //     for (unsigned i = 0; i < length; i++) {
        //         RefPtr<File> file;
        //         if (!readFile(file))
        //             return JSValue();
        //         if (m_canCreateDOMObject)
        //             files.append(file.releaseNonNull());
        //     }
        //     if (!m_canCreateDOMObject)
        //         return jsNull();
        //     return getJSValue(FileList::create(WTFMove(files)).get());
        // }
        // case ImageDataTag: {
        //     uint32_t width;
        //     if (!read(width))
        //         return JSValue();
        //     if (width == ImageDataPoolTag) {
        //         auto index = readImageDataIndex();
        //         if (!index || *index >= m_imageDataPool.size()) {
        //             fail();
        //             return JSValue();
        //         }
        //         return getJSValue(m_imageDataPool[*index]);
        //     }
        //     uint32_t height;
        //     if (!read(height))
        //         return JSValue();
        //     uint32_t length;
        //     if (!read(length))
        //         return JSValue();
        //     if (static_cast<uint32_t>(m_end - m_ptr) < length) {
        //         fail();
        //         return JSValue();
        //     }
        //     auto bufferStart = m_ptr;
        //     m_ptr += length;

        //     auto resultColorSpace = PredefinedColorSpace::SRGB;
        //     if (m_version > 7) {
        //         if (!read(resultColorSpace))
        //             return JSValue();
        //     }

        //     if (length && (IntSize(width, height).area() * 4) != length) {
        //         fail();
        //         return JSValue();
        //     }

        //     if (!m_isDOMGlobalObject)
        //         return jsNull();

        //     auto result = ImageData::createUninitialized(width, height, resultColorSpace);
        //     if (result.hasException()) {
        //         fail();
        //         return JSValue();
        //     }
        //     if (length)
        //         memcpy(result.returnValue()->data().data(), bufferStart, length);
        //     else
        //         result.returnValue()->data().zeroFill();
        //     m_imageDataPool.append(result.returnValue().copyRef());
        //     return getJSValue(result.releaseReturnValue());
        // }
        // case BlobTag: {
        //     CachedStringRef url;
        //     if (!readStringData(url))
        //         return JSValue();
        //     CachedStringRef type;
        //     if (!readStringData(type))
        //         return JSValue();
        //     uint64_t size = 0;
        //     if (!read(size))
        //         return JSValue();
        //     uint64_t memoryCost = 0;
        //     if (m_version >= 11 && !read(memoryCost))
        //         return JSValue();
        //     if (!m_canCreateDOMObject)
        //         return jsNull();
        //     return getJSValue(Blob::deserialize(executionContext(m_lexicalGlobalObject), URL { url->string() }, type->string(), size, memoryCost, blobFilePathForBlobURL(url->string())).get());
        // }
        case StringTag: {
            CachedStringRef cachedString;
            if (!readStringData(cachedString))
                return JSValue();
            return cachedString->jsString(m_lexicalGlobalObject);
        }
        case EmptyStringTag:
            return jsEmptyString(m_lexicalGlobalObject->vm());
        case StringObjectTag: {
            CachedStringRef cachedString;
            if (!readStringData(cachedString))
                return JSValue();
            StringObject* obj = constructString(m_lexicalGlobalObject->vm(), m_globalObject, cachedString->jsString(m_lexicalGlobalObject));
            m_gcBuffer.appendWithCrashOnOverflow(obj);
            return obj;
        }
        case EmptyStringObjectTag: {
            VM& vm = m_lexicalGlobalObject->vm();
            StringObject* obj = constructString(vm, m_globalObject, jsEmptyString(vm));
            m_gcBuffer.appendWithCrashOnOverflow(obj);
            return obj;
        }
        case RegExpTag: {
            CachedStringRef pattern;
            if (!readStringData(pattern))
                return JSValue();
            CachedStringRef flags;
            if (!readStringData(flags))
                return JSValue();
            auto reFlags = Yarr::parseFlags(flags->string());
            ASSERT(reFlags.has_value());
            VM& vm = m_lexicalGlobalObject->vm();
            RegExp* regExp = RegExp::create(vm, pattern->string(), reFlags.value());
            return RegExpObject::create(vm, m_globalObject->regExpStructure(), regExp);
        }
        case ErrorInstanceTag: {
            SerializableErrorType serializedErrorType;
            if (!read(serializedErrorType)) {
                fail();
                return JSValue();
            }
            String message;
            if (!readNullableString(message)) {
                fail();
                return JSValue();
            }
            uint32_t line;
            if (!read(line)) {
                fail();
                return JSValue();
            }
            uint32_t column;
            if (!read(column)) {
                fail();
                return JSValue();
            }
            String sourceURL;
            if (!readNullableString(sourceURL)) {
                fail();
                return JSValue();
            }
            String stackString;
            if (!readNullableString(stackString)) {
                fail();
                return JSValue();
            }
            return ErrorInstance::create(m_lexicalGlobalObject, WTFMove(message), toErrorType(serializedErrorType), { line, column }, WTFMove(sourceURL), WTFMove(stackString));
        }
        case ObjectReferenceTag: {
            auto index = readConstantPoolIndex(m_gcBuffer);
            if (!index) {
                fail();
                return JSValue();
            }
            return m_gcBuffer.at(*index);
        }
        case MessagePortReferenceTag: {
            uint32_t index;
            bool indexSuccessfullyRead = read(index);
            if (!indexSuccessfullyRead || index >= m_messagePorts.size()) {
                fail();
                return JSValue();
            }
            return getJSValue(m_messagePorts[index].get());
        }
#if ENABLE(WEBASSEMBLY)
        case WasmModuleTag: {
            if (m_version >= 12) {
                // https://webassembly.github.io/spec/web-api/index.html#serialization
                CachedStringRef agentClusterID;
                bool agentClusterIDSuccessfullyRead = readStringData(agentClusterID);
                if (!agentClusterIDSuccessfullyRead || agentClusterID->string() != agentClusterIDFromGlobalObject(*m_globalObject)) {
                    fail();
                    return JSValue();
                }
            }
            uint32_t index;
            bool indexSuccessfullyRead = read(index);
            if (!indexSuccessfullyRead || !m_wasmModules || index >= m_wasmModules->size()) {
                fail();
                return JSValue();
            }
            return JSC::JSWebAssemblyModule::create(m_lexicalGlobalObject->vm(), m_globalObject->webAssemblyModuleStructure(), Ref { *m_wasmModules->at(index) });
        }
        case WasmMemoryTag: {
            if (m_version >= 12) {
                CachedStringRef agentClusterID;
                bool agentClusterIDSuccessfullyRead = readStringData(agentClusterID);
                if (!agentClusterIDSuccessfullyRead || agentClusterID->string() != agentClusterIDFromGlobalObject(*m_globalObject)) {
                    fail();
                    return JSValue();
                }
            }
            uint32_t index;
            bool indexSuccessfullyRead = read(index);
            if (!indexSuccessfullyRead || !m_wasmMemoryHandles || index >= m_wasmMemoryHandles->size() || !JSC::Options::useSharedArrayBuffer()) {
                fail();
                return JSValue();
            }

            auto& vm = m_lexicalGlobalObject->vm();
            auto scope = DECLARE_THROW_SCOPE(vm);
            JSWebAssemblyMemory* result = JSC::JSWebAssemblyMemory::tryCreate(m_lexicalGlobalObject, vm, m_globalObject->webAssemblyMemoryStructure());
            // Since we are cloning a JSWebAssemblyMemory, it's impossible for that
            // module to not have been a valid module. Therefore, createStub should
            // not throw.
            scope.releaseAssertNoException();

            RefPtr<Wasm::Memory> memory;
            auto handler = [&vm, result](Wasm::Memory::GrowSuccess, PageCount oldPageCount, PageCount newPageCount) { result->growSuccessCallback(vm, oldPageCount, newPageCount); };
            if (RefPtr<SharedArrayBufferContents> contents = m_wasmMemoryHandles->at(index)) {
                if (!contents->memoryHandle()) {
                    fail();
                    return JSValue();
                }
                memory = Wasm::Memory::create(vm, contents.releaseNonNull(), WTFMove(handler));
            } else {
                // zero size & max-size.
                memory = Wasm::Memory::createZeroSized(vm, JSC::MemorySharingMode::Shared, WTFMove(handler));
            }

            result->adopt(memory.releaseNonNull());
            m_gcBuffer.appendWithCrashOnOverflow(result);
            return result;
        }
#endif
        case ArrayBufferTag: {
            RefPtr<ArrayBuffer> arrayBuffer;
            if (!readArrayBuffer(arrayBuffer)) {
                fail();
                return JSValue();
            }
            Structure* structure = m_globalObject->arrayBufferStructure(arrayBuffer->sharingMode());
            // A crazy RuntimeFlags mismatch could mean that we are not equipped to handle shared
            // array buffers while the sender is. In that case, we would see a null structure here.
            if (UNLIKELY(!structure)) {
                fail();
                return JSValue();
            }
            JSValue result = JSArrayBuffer::create(m_lexicalGlobalObject->vm(), structure, WTFMove(arrayBuffer));
            m_gcBuffer.appendWithCrashOnOverflow(result);
            return result;
        }
        case ResizableArrayBufferTag: {
            RefPtr<ArrayBuffer> arrayBuffer;
            if (!readResizableNonSharedArrayBuffer(arrayBuffer)) {
                fail();
                return JSValue();
            }
            Structure* structure = m_globalObject->arrayBufferStructure(arrayBuffer->sharingMode());
            // A crazy RuntimeFlags mismatch could mean that we are not equipped to handle shared
            // array buffers while the sender is. In that case, we would see a null structure here.
            if (UNLIKELY(!structure)) {
                fail();
                return JSValue();
            }
            JSValue result = JSArrayBuffer::create(m_lexicalGlobalObject->vm(), structure, WTFMove(arrayBuffer));
            m_gcBuffer.appendWithCrashOnOverflow(result);
            return result;
        }
        case ArrayBufferTransferTag: {
            uint32_t index;
            bool indexSuccessfullyRead = read(index);
            if (!indexSuccessfullyRead || index >= m_arrayBuffers.size()) {
                fail();
                return JSValue();
            }

            if (!m_arrayBuffers[index])
                m_arrayBuffers[index] = ArrayBuffer::create(WTFMove(m_arrayBufferContents->at(index)));

            return getJSValue(m_arrayBuffers[index].get());
        }
        case SharedArrayBufferTag: {
            // https://html.spec.whatwg.org/multipage/structured-data.html#structureddeserialize
            uint32_t index = UINT_MAX;
            bool indexSuccessfullyRead = read(index);
            if (!indexSuccessfullyRead || !m_sharedBuffers || index >= m_sharedBuffers->size() || !JSC::Options::useSharedArrayBuffer()) {
                fail();
                return JSValue();
            }

            RELEASE_ASSERT(m_sharedBuffers->at(index));
            auto buffer = ArrayBuffer::create(WTFMove(m_sharedBuffers->at(index)));
            JSValue result = getJSValue(buffer.get());
            m_gcBuffer.appendWithCrashOnOverflow(result);
            return result;
        }
        case ArrayBufferViewTag: {
            JSValue arrayBufferView;
            if (!readArrayBufferView(m_lexicalGlobalObject->vm(), arrayBufferView)) {
                fail();
                return JSValue();
            }
            m_gcBuffer.appendWithCrashOnOverflow(arrayBufferView);
            return arrayBufferView;
        }
#if ENABLE(WEB_CRYPTO)
        case CryptoKeyTag: {
            Vector<uint8_t> wrappedKey;
            if (!read(wrappedKey)) {
                fail();
                return JSValue();
            }
            Vector<uint8_t> serializedKey;
            if (!unwrapCryptoKey(m_lexicalGlobalObject, wrappedKey, serializedKey)) {
                fail();
                return JSValue();
            }
            JSValue cryptoKey;
            // Vector<RefPtr<MessagePort>> dummyMessagePorts;
            // CloneDeserializer rawKeyDeserializer(m_lexicalGlobalObject, m_globalObject, dummyMessagePorts, nullptr, {}, serializedKey);
            CloneDeserializer rawKeyDeserializer(m_lexicalGlobalObject, m_globalObject, {}, nullptr, serializedKey);
            if (!rawKeyDeserializer.readCryptoKey(cryptoKey)) {
                fail();
                return JSValue();
            }
            m_gcBuffer.appendWithCrashOnOverflow(cryptoKey);
            return cryptoKey;
        }
#endif
        // case DOMPointReadOnlyTag:
        //     return readDOMPoint<DOMPointReadOnly>();
        // case DOMPointTag:
        //     return readDOMPoint<DOMPoint>();
        // case DOMRectReadOnlyTag:
        //     return readDOMRect<DOMRectReadOnly>();
        // case DOMRectTag:
        //     return readDOMRect<DOMRect>();
        // case DOMMatrixReadOnlyTag:
        //     return readDOMMatrix<DOMMatrixReadOnly>();
        // case DOMMatrixTag:
        //     return readDOMMatrix<DOMMatrix>();
        // case DOMQuadTag:
        //     return readDOMQuad();
        // case ImageBitmapTransferTag:
        //     return readTransferredImageBitmap();
#if ENABLE(WEB_RTC)
        case RTCCertificateTag:
            return readRTCCertificate();

#endif
            // case ImageBitmapTag:
            //     return readImageBitmap();
#if ENABLE(OFFSCREEN_CANVAS_IN_WORKERS)
        case OffscreenCanvasTransferTag:
            return readOffscreenCanvas();
#endif
#if ENABLE(WEB_RTC)
        case RTCDataChannelTransferTag:
            return readRTCDataChannel();
#endif
#if ENABLE(WEB_CODECS)
        case WebCodecsEncodedVideoChunkTag:
            return readWebCodecsEncodedVideoChunk();
        case WebCodecsVideoFrameTag:
            return readWebCodecsVideoFrame();
#endif
        case DOMExceptionTag:
            return readDOMException();

        default:
            m_ptr--; // Push the tag back
            return JSValue();
        }
    }