[ Web Proxy ]
URL:
Viewing: https://raw.githubusercontent.com/ClearFoundry/ClearScript/master/ClearScriptV8/V8Value.h [Back]  [Original]

// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.

#pragma once

//-----------------------------------------------------------------------------
// V8BigInt
//-----------------------------------------------------------------------------

class V8BigInt final
{
public:

    V8BigInt(int signBit, std::vector&& words):
        m_SignBit(signBit),
        m_Words(std::move(words))
    {
    }

    V8BigInt(const V8BigInt& that):
        m_SignBit(that.m_SignBit),
        m_Words(that.m_Words)
    {
    }

    V8BigInt(V8BigInt&& that) noexcept:
        m_SignBit(that.m_SignBit),
        m_Words(std::move(that.m_Words))
    {
    }

    const V8BigInt& operator=(const V8BigInt& that)
    {
        if (&that != this)
        {
            m_SignBit = that.m_SignBit;
            m_Words = that.m_Words;
        }

        return *this;
    }

    const V8BigInt& operator=(V8BigInt&& that) noexcept
    {
        if (&that != this)
        {
            m_SignBit = that.m_SignBit;
            m_Words = std::move(that.m_Words);
        }

        return *this;
    }

    int GetSignBit() const
    {
        return m_SignBit;
    }

    const std::vector& GetWords() const
    {
        return m_Words;
    }

private:

    int m_SignBit;
    std::vector m_Words;
};

//-----------------------------------------------------------------------------
// V8Value
//-----------------------------------------------------------------------------

class V8Value
{
public:

    enum NonexistentInitializer
    {
        Nonexistent
    };

    enum UndefinedInitializer
    {
        Undefined
    };

    enum NullInitializer
    {
        Null
    };

    enum DateTimeInitializer
    {
        DateTime
    };

    enum class Type: uint8_t
    {
        // IMPORTANT: maintain bitwise equivalence with managed enum V8.SplitProxy.V8Value.Type
        Nonexistent,
        Undefined,
        Null,
        Boolean,
        Number,
        String,
        DateTime,
        BigInt,
        V8Object,
        HostObject
    };

    enum class Subtype: uint8_t
    {
        // IMPORTANT: maintain bitwise equivalence with managed enum V8.SplitProxy.V8Value.Subtype
        None,
        Function,
        Iterator,
        Promise,
        Array,
        ArrayBuffer,
        DataView,
        Uint8Array,
        Uint8ClampedArray,
        Int8Array,
        Uint16Array,
        Int16Array,
        Uint32Array,
        Int32Array,
        BigUint64Array,
        BigInt64Array,
        Float32Array,
        Float64Array
    };

    enum class Flags : uint16_t
    {
        // IMPORTANT: maintain bitwise equivalence with managed enum V8.SplitProxy.V8Value.Flags
        None = 0,
        Shared = 0x0001,
        Fast = 0x0001,
        Async = 0x0002,
        Generator = 0x0004,
        Pending = 0x0008,
        Rejected = 0x0010,
        Iterable = 0x0020,
        AsyncIterable = 0x0040,
        Disposable = 0x0080,
        AsyncDisposable = 0x0100
    };

    struct WireData;
    struct Decoded;
    struct FastArg;
    struct FastResult;
    struct FastScriptArg;
    struct FastScriptResult;

    explicit V8Value(NonexistentInitializer):
        m_Type(Type::Nonexistent)
    {
    }

    explicit V8Value(UndefinedInitializer):
        m_Type(Type::Undefined)
    {
    }

    explicit V8Value(NullInitializer):
        m_Type(Type::Null)
    {
    }

    explicit V8Value(bool value):
        m_Type(Type::Boolean)
    {
        m_Data.BooleanValue = value;
    }

    explicit V8Value(double value):
        m_Type(Type::Number)
    {
        m_Data.DoubleValue = value;
    }

    explicit V8Value(const StdString* pString):
        m_Type(Type::String)
    {
        m_Data.pString = pString;
    }

    V8Value(DateTimeInitializer, double value):
        m_Type(Type::DateTime)
    {
        m_Data.DoubleValue = value;
    }

    explicit V8Value(const V8BigInt* pBigInt):
        m_Type(Type::BigInt)
    {
        m_Data.pBigInt = pBigInt;
    }

    V8Value(V8ObjectHolder* pV8ObjectHolder, Subtype subtype, Flags flags):
        m_Type(Type::V8Object),
        m_Subtype(subtype),
        m_Flags(flags)
    {
        m_Data.pV8ObjectHolder = pV8ObjectHolder;
    }

    explicit V8Value(HostObjectHolder* pHostObjectHolder):
        m_Type(Type::HostObject),
        m_Subtype(::ToEnum(pHostObjectHolder->GetSubtype())),
        m_Flags(::ToEnum(pHostObjectHolder->GetFlags()))
    {
        m_Data.pHostObjectHolder = pHostObjectHolder;
    }

    V8Value(const V8Value& that)
    {
        Copy(that);
    }

    V8Value(V8Value&& that) noexcept
    {
        Move(that);
    }

    explicit V8Value(const FastResult& result)
    {
        InitializeFromFastResult(result);
    }

    explicit V8Value(void*) = delete;

    const V8Value& operator=(const V8Value& that)
    {
        Dispose();
        Copy(that);
        return *this;
    }

    const V8Value& operator=(V8Value&& that) noexcept
    {
        Dispose();
        Move(that);
        return *this;
    }

    bool IsNonexistent() const
    {
        return m_Type == Type::Nonexistent;
    }

    bool IsUndefined() const
    {
        return m_Type == Type::Undefined;
    }

    bool IsNull() const
    {
        return m_Type == Type::Null;
    }

    bool AsBoolean(bool& result) const
    {
        if (m_Type == Type::Boolean)
        {
            result = m_Data.BooleanValue;
            return true;
        }

        return false;
    }

    bool AsNumber(double& result) const
    {
        if (m_Type == Type::Number)
        {
            result = m_Data.DoubleValue;
            return true;
        }

        return false;
    }

    bool AsString(const StdString*& pString) const
    {
        if (m_Type == Type::String)
        {
            pString = m_Data.pString;
            return true;
        }

        return false;
    }

    bool AsDateTime(double& result) const
    {
        if (m_Type == Type::DateTime)
        {
            result = m_Data.DoubleValue;
            return true;
        }

        return false;
    }

    bool AsBigInt(const V8BigInt*& pBigInt) const
    {
        if (m_Type == Type::BigInt)
        {
            pBigInt = m_Data.pBigInt;
            return true;
        }

        return false;
    }

    bool AsV8Object(V8ObjectHolder*& pV8ObjectHolder, Subtype& subtype, Flags& flags) const
    {
        if (m_Type == Type::V8Object)
        {
            pV8ObjectHolder = m_Data.pV8ObjectHolder;
            subtype = m_Subtype;
            flags = m_Flags;
            return true;
        }

        return false;
    }

    bool AsHostObject(HostObjectHolder*& pHostObjectHolder, Subtype& subtype, Flags& flags) const
    {
        if (m_Type == Type::HostObject)
        {
            pHostObjectHolder = m_Data.pHostObjectHolder;
            subtype = m_Subtype;
            flags = m_Flags;
            return true;
        }

        return false;
    }

    Type GetType() const
    {
        return m_Type;
    }

    void Decode(Decoded& decoded) const;

    ~V8Value()
    {
        Dispose();
    }

private:

    union Data
    {
        bool BooleanValue;
        double DoubleValue;
        const StdString* pString;
        V8ObjectHolder* pV8ObjectHolder;
        HostObjectHolder* pHostObjectHolder;
        const V8BigInt* pBigInt;
    };

    void Copy(const V8Value& that)
    {
        m_Type = that.m_Type;
        m_Subtype = that.m_Subtype;
        m_Flags = that.m_Flags;

        if (m_Type == Type::Boolean)
        {
            m_Data.BooleanValue = that.m_Data.BooleanValue;
        }
        else if (m_Type == Type::Number)
        {
            m_Data.DoubleValue = that.m_Data.DoubleValue;
        }
        else if (m_Type == Type::String)
        {
            m_Data.pString = new StdString(*that.m_Data.pString);
        }
        else if (m_Type == Type::DateTime)
        {
            m_Data.DoubleValue = that.m_Data.DoubleValue;
        }
        else if (m_Type == Type::BigInt)
        {
            m_Data.pBigInt = new V8BigInt(*that.m_Data.pBigInt);
        }
        else if (m_Type == Type::V8Object)
        {
            m_Data.pV8ObjectHolder = that.m_Data.pV8ObjectHolder->Clone();
        }
        else if (m_Type == Type::HostObject)
        {
            m_Data.pHostObjectHolder = that.m_Data.pHostObjectHolder->Clone();
        }
    }

    void Move(V8Value& that)
    {
        m_Type = that.m_Type;
        m_Subtype = that.m_Subtype;
        m_Flags = that.m_Flags;
        m_Data = that.m_Data;
        that.m_Type = Type::Nonexistent;
    }

    void InitializeFromFastResult(const FastResult& result);

    void Dispose()
    {
        if (m_Type == Type::String)
        {
            delete m_Data.pString;
        }
        else if (m_Type == Type::BigInt)
        {
            delete m_Data.pBigInt;
        }
        else if (m_Type == Type::V8Object)
        {
            delete m_Data.pV8ObjectHolder;
        }
        else if (m_Type == Type::HostObject)
        {
            delete m_Data.pHostObjectHolder;
        }
    }

    Type m_Type;
    Subtype m_Subtype;
    Flags m_Flags;
    int32_t m_Padding;
    Data m_Data;
};

static_assert(sizeof(V8Value) == 16, "The managed SplitProxy code assumes that sizeof(V8Value) is 16 on all platforms.");

//-----------------------------------------------------------------------------
// DefaultInitializedV8Value
//-----------------------------------------------------------------------------

template 
class DefaultInitializedV8Value final: public V8Value
{
public:

    using V8Value::V8Value;

    DefaultInitializedV8Value():
        V8Value(ms_Initializer)
    {
        static_assert(sizeof(DefaultInitializedV8Value) == sizeof(V8Value));
    }

    using V8Value::operator=;

private:

    static const TInitializer ms_Initializer {};
};

using NonexistentV8Value = DefaultInitializedV8Value;
using UndefinedV8Value = DefaultInitializedV8Value;
using NullV8Value = DefaultInitializedV8Value;

Web Proxy Viewer  |  New URL  |  Original Page