Remove redundancy between CFX_KeyValue and JSGlobalData.

Split CFX_Value off of CFX_KeyValue and use it in JSGlobalData.
There's one superfluous field, but the re-use of the data type
enum is troubling without it.

Change-Id: I474bed7b32bfe8937e6849624c9545e4d170959d
Reviewed-on: https://pdfium-review.googlesource.com/c/45250
Reviewed-by: Lei Zhang <thestig@chromium.org>
Commit-Queue: Tom Sepez <tsepez@chromium.org>
diff --git a/fxjs/cfx_globaldata.cpp b/fxjs/cfx_globaldata.cpp
index db0d125..4038e9d 100644
--- a/fxjs/cfx_globaldata.cpp
+++ b/fxjs/cfx_globaldata.cpp
@@ -39,7 +39,7 @@
 }
 
 void MakeNameTypeString(const ByteString& name,
-                        CFX_KeyValue::DataType eType,
+                        CFX_Value::DataType eType,
                         CFX_BinaryBuf* result) {
   uint32_t dwNameLen = (uint32_t)name.GetLength();
   result->AppendBlock(&dwNameLen, sizeof(uint32_t));
@@ -53,31 +53,31 @@
                     const CFX_KeyValue& pData,
                     CFX_BinaryBuf* result) {
   switch (pData.nType) {
-    case CFX_KeyValue::DataType::NUMBER: {
+    case CFX_Value::DataType::NUMBER: {
       MakeNameTypeString(name, pData.nType, result);
       double dData = pData.dData;
       result->AppendBlock(&dData, sizeof(double));
       return true;
     }
-    case CFX_KeyValue::DataType::BOOLEAN: {
+    case CFX_Value::DataType::BOOLEAN: {
       MakeNameTypeString(name, pData.nType, result);
       uint16_t wData = static_cast<uint16_t>(pData.bData);
       result->AppendBlock(&wData, sizeof(uint16_t));
       return true;
     }
-    case CFX_KeyValue::DataType::STRING: {
+    case CFX_Value::DataType::STRING: {
       MakeNameTypeString(name, pData.nType, result);
       uint32_t dwDataLen = (uint32_t)pData.sData.GetLength();
       result->AppendBlock(&dwDataLen, sizeof(uint32_t));
       result->AppendString(pData.sData);
       return true;
     }
-    case CFX_KeyValue::DataType::NULLOBJ: {
+    case CFX_Value::DataType::NULLOBJ: {
       MakeNameTypeString(name, pData.nType, result);
       return true;
     }
     // Arrays don't get persisted per JS spec page 484.
-    case CFX_KeyValue::DataType::OBJECT:
+    case CFX_Value::DataType::OBJECT:
     default:
       break;
   }
@@ -145,13 +145,13 @@
 
   CFX_GlobalData::Element* pData = GetGlobalVariable(sPropName);
   if (pData) {
-    pData->data.nType = CFX_KeyValue::DataType::NUMBER;
+    pData->data.nType = CFX_Value::DataType::NUMBER;
     pData->data.dData = dData;
     return;
   }
   auto pNewData = pdfium::MakeUnique<CFX_GlobalData::Element>();
   pNewData->data.sKey = std::move(sPropName);
-  pNewData->data.nType = CFX_KeyValue::DataType::NUMBER;
+  pNewData->data.nType = CFX_Value::DataType::NUMBER;
   pNewData->data.dData = dData;
   m_arrayGlobalData.push_back(std::move(pNewData));
 }
@@ -163,13 +163,13 @@
 
   CFX_GlobalData::Element* pData = GetGlobalVariable(sPropName);
   if (pData) {
-    pData->data.nType = CFX_KeyValue::DataType::BOOLEAN;
+    pData->data.nType = CFX_Value::DataType::BOOLEAN;
     pData->data.bData = bData;
     return;
   }
   auto pNewData = pdfium::MakeUnique<CFX_GlobalData::Element>();
   pNewData->data.sKey = std::move(sPropName);
-  pNewData->data.nType = CFX_KeyValue::DataType::BOOLEAN;
+  pNewData->data.nType = CFX_Value::DataType::BOOLEAN;
   pNewData->data.bData = bData;
   m_arrayGlobalData.push_back(std::move(pNewData));
 }
@@ -181,13 +181,13 @@
 
   CFX_GlobalData::Element* pData = GetGlobalVariable(sPropName);
   if (pData) {
-    pData->data.nType = CFX_KeyValue::DataType::STRING;
+    pData->data.nType = CFX_Value::DataType::STRING;
     pData->data.sData = sData;
     return;
   }
   auto pNewData = pdfium::MakeUnique<CFX_GlobalData::Element>();
   pNewData->data.sKey = std::move(sPropName);
-  pNewData->data.nType = CFX_KeyValue::DataType::STRING;
+  pNewData->data.nType = CFX_Value::DataType::STRING;
   pNewData->data.sData = sData;
   m_arrayGlobalData.push_back(std::move(pNewData));
 }
@@ -199,13 +199,13 @@
 
   CFX_GlobalData::Element* pData = GetGlobalVariable(sPropName);
   if (pData) {
-    pData->data.nType = CFX_KeyValue::DataType::OBJECT;
+    pData->data.nType = CFX_Value::DataType::OBJECT;
     pData->data.objData = std::move(array);
     return;
   }
   auto pNewData = pdfium::MakeUnique<CFX_GlobalData::Element>();
   pNewData->data.sKey = std::move(sPropName);
-  pNewData->data.nType = CFX_KeyValue::DataType::OBJECT;
+  pNewData->data.nType = CFX_Value::DataType::OBJECT;
   pNewData->data.objData = std::move(array);
   m_arrayGlobalData.push_back(std::move(pNewData));
 }
@@ -216,12 +216,12 @@
 
   CFX_GlobalData::Element* pData = GetGlobalVariable(sPropName);
   if (pData) {
-    pData->data.nType = CFX_KeyValue::DataType::NULLOBJ;
+    pData->data.nType = CFX_Value::DataType::NULLOBJ;
     return;
   }
   auto pNewData = pdfium::MakeUnique<CFX_GlobalData::Element>();
   pNewData->data.sKey = std::move(sPropName);
-  pNewData->data.nType = CFX_KeyValue::DataType::NULLOBJ;
+  pNewData->data.nType = CFX_Value::DataType::NULLOBJ;
   m_arrayGlobalData.push_back(std::move(pNewData));
 }
 
@@ -317,12 +317,12 @@
     ByteString sEntry = ByteString(p, dwNameLen);
     p += sizeof(char) * dwNameLen;
 
-    CFX_KeyValue::DataType wDataType =
-        static_cast<CFX_KeyValue::DataType>(*((uint16_t*)p));
+    CFX_Value::DataType wDataType =
+        static_cast<CFX_Value::DataType>(*((uint16_t*)p));
     p += sizeof(uint16_t);
 
     switch (wDataType) {
-      case CFX_KeyValue::DataType::NUMBER: {
+      case CFX_Value::DataType::NUMBER: {
         double dData = 0;
         switch (wVersion) {
           case 1: {
@@ -338,13 +338,13 @@
         SetGlobalVariableNumber(sEntry, dData);
         SetGlobalVariablePersistent(sEntry, true);
       } break;
-      case CFX_KeyValue::DataType::BOOLEAN: {
+      case CFX_Value::DataType::BOOLEAN: {
         uint16_t wData = *((uint16_t*)p);
         p += sizeof(uint16_t);
         SetGlobalVariableBoolean(sEntry, (bool)(wData == 1));
         SetGlobalVariablePersistent(sEntry, true);
       } break;
-      case CFX_KeyValue::DataType::STRING: {
+      case CFX_Value::DataType::STRING: {
         uint32_t dwLength = *((uint32_t*)p);
         p += sizeof(uint32_t);
         if (p + dwLength > buffer.end())
@@ -354,11 +354,11 @@
         SetGlobalVariablePersistent(sEntry, true);
         p += sizeof(char) * dwLength;
       } break;
-      case CFX_KeyValue::DataType::NULLOBJ: {
+      case CFX_Value::DataType::NULLOBJ: {
         SetGlobalVariableNull(sEntry);
         SetGlobalVariablePersistent(sEntry, true);
       } break;
-      case CFX_KeyValue::DataType::OBJECT:
+      case CFX_Value::DataType::OBJECT:
       default:
         // Arrays aren't allowed in these buffers, nor are unrecoginzed tags.
         return false;
diff --git a/fxjs/cfx_globaldata_unittest.cpp b/fxjs/cfx_globaldata_unittest.cpp
index 8f6cbce..1c2e681 100644
--- a/fxjs/cfx_globaldata_unittest.cpp
+++ b/fxjs/cfx_globaldata_unittest.cpp
@@ -73,25 +73,25 @@
   auto* element = pInstance->GetAt(0);
   ASSERT_TRUE(element);
   EXPECT_EQ("double", element->data.sKey);
-  EXPECT_EQ(CFX_KeyValue::DataType::NUMBER, element->data.nType);
+  EXPECT_EQ(CFX_Value::DataType::NUMBER, element->data.nType);
   EXPECT_EQ(2.0, element->data.dData);
 
   element = pInstance->GetAt(1);
   ASSERT_TRUE(element);
   EXPECT_EQ("string", element->data.sKey);
-  EXPECT_EQ(CFX_KeyValue::DataType::STRING, element->data.nType);
+  EXPECT_EQ(CFX_Value::DataType::STRING, element->data.nType);
   EXPECT_EQ("clams", element->data.sData);
 
   element = pInstance->GetAt(2);
   ASSERT_TRUE(element);
   EXPECT_EQ("boolean", element->data.sKey);
-  EXPECT_EQ(CFX_KeyValue::DataType::BOOLEAN, element->data.nType);
+  EXPECT_EQ(CFX_Value::DataType::BOOLEAN, element->data.nType);
   EXPECT_EQ(true, element->data.bData);
 
   element = pInstance->GetAt(3);
   ASSERT_TRUE(element);
   EXPECT_EQ("null", element->data.sKey);
-  EXPECT_EQ(CFX_KeyValue::DataType::NULLOBJ, element->data.nType);
+  EXPECT_EQ(CFX_Value::DataType::NULLOBJ, element->data.nType);
 
   // Arrays don't get persisted.
   element = pInstance->GetAt(4);
@@ -115,25 +115,25 @@
   auto* element = pInstance->GetAt(0);
   ASSERT_TRUE(element);
   EXPECT_EQ("double", element->data.sKey);
-  EXPECT_EQ(CFX_KeyValue::DataType::NUMBER, element->data.nType);
+  EXPECT_EQ(CFX_Value::DataType::NUMBER, element->data.nType);
   EXPECT_EQ(2.0, element->data.dData);
 
   element = pInstance->GetAt(1);
   ASSERT_TRUE(element);
   EXPECT_EQ("string", element->data.sKey);
-  EXPECT_EQ(CFX_KeyValue::DataType::STRING, element->data.nType);
+  EXPECT_EQ(CFX_Value::DataType::STRING, element->data.nType);
   EXPECT_EQ("clams", element->data.sData);
 
   element = pInstance->GetAt(2);
   ASSERT_TRUE(element);
   EXPECT_EQ("boolean", element->data.sKey);
-  EXPECT_EQ(CFX_KeyValue::DataType::BOOLEAN, element->data.nType);
+  EXPECT_EQ(CFX_Value::DataType::BOOLEAN, element->data.nType);
   EXPECT_EQ(true, element->data.bData);
 
   element = pInstance->GetAt(3);
   ASSERT_TRUE(element);
   EXPECT_EQ("null", element->data.sKey);
-  EXPECT_EQ(CFX_KeyValue::DataType::NULLOBJ, element->data.nType);
+  EXPECT_EQ(CFX_Value::DataType::NULLOBJ, element->data.nType);
 
   ASSERT_TRUE(pInstance->Release());
 }
diff --git a/fxjs/cfx_keyvalue.cpp b/fxjs/cfx_keyvalue.cpp
index 5a4a5fb..d1c7fae 100644
--- a/fxjs/cfx_keyvalue.cpp
+++ b/fxjs/cfx_keyvalue.cpp
@@ -6,6 +6,10 @@
 
 #include "fxjs/cfx_keyvalue.h"
 
+CFX_Value::CFX_Value() = default;
+
+CFX_Value::~CFX_Value() = default;
+
 CFX_KeyValue::CFX_KeyValue() = default;
 
 CFX_KeyValue::~CFX_KeyValue() = default;
diff --git a/fxjs/cfx_keyvalue.h b/fxjs/cfx_keyvalue.h
index 8facfb8..59c31cb 100644
--- a/fxjs/cfx_keyvalue.h
+++ b/fxjs/cfx_keyvalue.h
@@ -10,7 +10,7 @@
 #include "core/fxcrt/fx_string.h"
 #include "fxjs/cfx_globalarray.h"
 
-class CFX_KeyValue {
+class CFX_Value {
  public:
   enum class DataType : uint8_t {
     NUMBER = 0,
@@ -20,15 +20,22 @@
     NULLOBJ
   };
 
-  CFX_KeyValue();
-  ~CFX_KeyValue();
+  CFX_Value();
+  ~CFX_Value();
 
-  ByteString sKey;
-  CFX_KeyValue::DataType nType;
+  DataType nType = DataType::NULLOBJ;
   bool bData;
   double dData;
   ByteString sData;
   CFX_GlobalArray objData;
 };
 
+class CFX_KeyValue : public CFX_Value {
+ public:
+  CFX_KeyValue();
+  ~CFX_KeyValue();
+
+  ByteString sKey;
+};
+
 #endif  // FXJS_CFX_KEYVALUE_H_
diff --git a/fxjs/cjs_global.cpp b/fxjs/cjs_global.cpp
index fd3a9ac..35619c0 100644
--- a/fxjs/cjs_global.cpp
+++ b/fxjs/cjs_global.cpp
@@ -123,17 +123,9 @@
 
 }  // namespace
 
-CJS_Global::JSGlobalData::JSGlobalData()
-    : nType(CFX_KeyValue::DataType::NUMBER),
-      dData(0),
-      bData(false),
-      sData(""),
-      bPersistent(false),
-      bDeleted(false) {}
+CJS_Global::JSGlobalData::JSGlobalData() = default;
 
-CJS_Global::JSGlobalData::~JSGlobalData() {
-  pData.Reset();
-}
+CJS_Global::JSGlobalData::~JSGlobalData() = default;
 
 const JSMethodSpec CJS_Global::MethodSpecs[] = {
     {"setPersistent", setPersistent_static}};
@@ -256,17 +248,17 @@
     return CJS_Result::Success();
 
   switch (pData->nType) {
-    case CFX_KeyValue::DataType::NUMBER:
+    case CFX_Value::DataType::NUMBER:
       return CJS_Result::Success(pRuntime->NewNumber(pData->dData));
-    case CFX_KeyValue::DataType::BOOLEAN:
+    case CFX_Value::DataType::BOOLEAN:
       return CJS_Result::Success(pRuntime->NewBoolean(pData->bData));
-    case CFX_KeyValue::DataType::STRING:
+    case CFX_Value::DataType::STRING:
       return CJS_Result::Success(pRuntime->NewString(
           WideString::FromLocal(pData->sData.AsStringView()).AsStringView()));
-    case CFX_KeyValue::DataType::OBJECT:
+    case CFX_Value::DataType::OBJECT:
       return CJS_Result::Success(
           v8::Local<v8::Object>::New(pRuntime->GetIsolate(), pData->pData));
-    case CFX_KeyValue::DataType::NULLOBJ:
+    case CFX_Value::DataType::NULLOBJ:
       return CJS_Result::Success(pRuntime->NewNull());
     default:
       break;
@@ -279,27 +271,27 @@
                                    v8::Local<v8::Value> vp) {
   ByteString sPropName = WideString(propname).ToDefANSI();
   if (vp->IsNumber()) {
-    return SetGlobalVariables(sPropName, CFX_KeyValue::DataType::NUMBER,
+    return SetGlobalVariables(sPropName, CFX_Value::DataType::NUMBER,
                               pRuntime->ToDouble(vp), false, "",
                               v8::Local<v8::Object>(), false);
   }
   if (vp->IsBoolean()) {
-    return SetGlobalVariables(sPropName, CFX_KeyValue::DataType::BOOLEAN, 0,
+    return SetGlobalVariables(sPropName, CFX_Value::DataType::BOOLEAN, 0,
                               pRuntime->ToBoolean(vp), "",
                               v8::Local<v8::Object>(), false);
   }
   if (vp->IsString()) {
-    return SetGlobalVariables(sPropName, CFX_KeyValue::DataType::STRING, 0,
-                              false, pRuntime->ToWideString(vp).ToDefANSI(),
+    return SetGlobalVariables(sPropName, CFX_Value::DataType::STRING, 0, false,
+                              pRuntime->ToWideString(vp).ToDefANSI(),
                               v8::Local<v8::Object>(), false);
   }
   if (vp->IsObject()) {
-    return SetGlobalVariables(sPropName, CFX_KeyValue::DataType::OBJECT, 0,
-                              false, "", pRuntime->ToObject(vp), false);
+    return SetGlobalVariables(sPropName, CFX_Value::DataType::OBJECT, 0, false,
+                              "", pRuntime->ToObject(vp), false);
   }
   if (vp->IsNull()) {
-    return SetGlobalVariables(sPropName, CFX_KeyValue::DataType::NULLOBJ, 0,
-                              false, "", v8::Local<v8::Object>(), false);
+    return SetGlobalVariables(sPropName, CFX_Value::DataType::NULLOBJ, 0, false,
+                              "", v8::Local<v8::Object>(), false);
   }
   if (vp->IsUndefined()) {
     DelProperty(pRuntime, propname);
@@ -330,41 +322,41 @@
   for (int i = 0, sz = m_pGlobalData->GetSize(); i < sz; i++) {
     CFX_GlobalData::Element* pData = m_pGlobalData->GetAt(i);
     switch (pData->data.nType) {
-      case CFX_KeyValue::DataType::NUMBER:
-        SetGlobalVariables(pData->data.sKey, CFX_KeyValue::DataType::NUMBER,
+      case CFX_Value::DataType::NUMBER:
+        SetGlobalVariables(pData->data.sKey, CFX_Value::DataType::NUMBER,
                            pData->data.dData, false, "",
                            v8::Local<v8::Object>(), pData->bPersistent == 1);
         pRuntime->PutObjectProperty(ToV8Object(), pData->data.sKey.UTF8Decode(),
                                     pRuntime->NewNumber(pData->data.dData));
         break;
-      case CFX_KeyValue::DataType::BOOLEAN:
-        SetGlobalVariables(pData->data.sKey, CFX_KeyValue::DataType::BOOLEAN, 0,
+      case CFX_Value::DataType::BOOLEAN:
+        SetGlobalVariables(pData->data.sKey, CFX_Value::DataType::BOOLEAN, 0,
                            pData->data.bData == 1, "", v8::Local<v8::Object>(),
                            pData->bPersistent == 1);
         pRuntime->PutObjectProperty(
             ToV8Object(), pData->data.sKey.UTF8Decode(),
             pRuntime->NewBoolean(pData->data.bData == 1));
         break;
-      case CFX_KeyValue::DataType::STRING:
-        SetGlobalVariables(pData->data.sKey, CFX_KeyValue::DataType::STRING, 0,
+      case CFX_Value::DataType::STRING:
+        SetGlobalVariables(pData->data.sKey, CFX_Value::DataType::STRING, 0,
                            false, pData->data.sData, v8::Local<v8::Object>(),
                            pData->bPersistent == 1);
         pRuntime->PutObjectProperty(
             ToV8Object(), pData->data.sKey.UTF8Decode(),
             pRuntime->NewString(pData->data.sData.UTF8Decode().AsStringView()));
         break;
-      case CFX_KeyValue::DataType::OBJECT: {
+      case CFX_Value::DataType::OBJECT: {
         v8::Local<v8::Object> pObj = pRuntime->NewObject();
         if (!pObj.IsEmpty()) {
           PutObjectProperty(pObj, &pData->data);
-          SetGlobalVariables(pData->data.sKey, CFX_KeyValue::DataType::OBJECT,
-                             0, false, "", pObj, pData->bPersistent == 1);
+          SetGlobalVariables(pData->data.sKey, CFX_Value::DataType::OBJECT, 0,
+                             false, "", pObj, pData->bPersistent == 1);
           pRuntime->PutObjectProperty(ToV8Object(),
                                       pData->data.sKey.UTF8Decode(), pObj);
         }
       } break;
-      case CFX_KeyValue::DataType::NULLOBJ:
-        SetGlobalVariables(pData->data.sKey, CFX_KeyValue::DataType::NULLOBJ, 0,
+      case CFX_Value::DataType::NULLOBJ:
+        SetGlobalVariables(pData->data.sKey, CFX_Value::DataType::NULLOBJ, 0,
                            false, "", v8::Local<v8::Object>(),
                            pData->bPersistent == 1);
         pRuntime->PutObjectProperty(ToV8Object(), pData->data.sKey.UTF8Decode(),
@@ -383,19 +375,19 @@
       continue;
     }
     switch (pData->nType) {
-      case CFX_KeyValue::DataType::NUMBER:
+      case CFX_Value::DataType::NUMBER:
         m_pGlobalData->SetGlobalVariableNumber(name, pData->dData);
         m_pGlobalData->SetGlobalVariablePersistent(name, pData->bPersistent);
         break;
-      case CFX_KeyValue::DataType::BOOLEAN:
+      case CFX_Value::DataType::BOOLEAN:
         m_pGlobalData->SetGlobalVariableBoolean(name, pData->bData);
         m_pGlobalData->SetGlobalVariablePersistent(name, pData->bPersistent);
         break;
-      case CFX_KeyValue::DataType::STRING:
+      case CFX_Value::DataType::STRING:
         m_pGlobalData->SetGlobalVariableString(name, pData->sData);
         m_pGlobalData->SetGlobalVariablePersistent(name, pData->bPersistent);
         break;
-      case CFX_KeyValue::DataType::OBJECT: {
+      case CFX_Value::DataType::OBJECT: {
         CFX_GlobalArray array;
         v8::Local<v8::Object> obj =
             v8::Local<v8::Object>::New(GetIsolate(), pData->pData);
@@ -403,7 +395,7 @@
         m_pGlobalData->SetGlobalVariableObject(name, std::move(array));
         m_pGlobalData->SetGlobalVariablePersistent(name, pData->bPersistent);
       } break;
-      case CFX_KeyValue::DataType::NULLOBJ:
+      case CFX_Value::DataType::NULLOBJ:
         m_pGlobalData->SetGlobalVariableNull(name);
         m_pGlobalData->SetGlobalVariablePersistent(name, pData->bPersistent);
         break;
@@ -420,7 +412,7 @@
     v8::Local<v8::Value> v = pRuntime->GetObjectProperty(pObj, ws);
     if (v->IsNumber()) {
       auto pObjElement = pdfium::MakeUnique<CFX_KeyValue>();
-      pObjElement->nType = CFX_KeyValue::DataType::NUMBER;
+      pObjElement->nType = CFX_Value::DataType::NUMBER;
       pObjElement->sKey = sKey;
       pObjElement->dData = pRuntime->ToDouble(v);
       pArray->Add(std::move(pObjElement));
@@ -428,7 +420,7 @@
     }
     if (v->IsBoolean()) {
       auto pObjElement = pdfium::MakeUnique<CFX_KeyValue>();
-      pObjElement->nType = CFX_KeyValue::DataType::BOOLEAN;
+      pObjElement->nType = CFX_Value::DataType::BOOLEAN;
       pObjElement->sKey = sKey;
       pObjElement->dData = pRuntime->ToBoolean(v);
       pArray->Add(std::move(pObjElement));
@@ -437,7 +429,7 @@
     if (v->IsString()) {
       ByteString sValue = pRuntime->ToWideString(v).ToDefANSI();
       auto pObjElement = pdfium::MakeUnique<CFX_KeyValue>();
-      pObjElement->nType = CFX_KeyValue::DataType::STRING;
+      pObjElement->nType = CFX_Value::DataType::STRING;
       pObjElement->sKey = sKey;
       pObjElement->sData = sValue;
       pArray->Add(std::move(pObjElement));
@@ -445,7 +437,7 @@
     }
     if (v->IsObject()) {
       auto pObjElement = pdfium::MakeUnique<CFX_KeyValue>();
-      pObjElement->nType = CFX_KeyValue::DataType::OBJECT;
+      pObjElement->nType = CFX_Value::DataType::OBJECT;
       pObjElement->sKey = sKey;
       ObjectToArray(pRuntime, pRuntime->ToObject(v), &pObjElement->objData);
       pArray->Add(std::move(pObjElement));
@@ -453,7 +445,7 @@
     }
     if (v->IsNull()) {
       auto pObjElement = pdfium::MakeUnique<CFX_KeyValue>();
-      pObjElement->nType = CFX_KeyValue::DataType::NULLOBJ;
+      pObjElement->nType = CFX_Value::DataType::NULLOBJ;
       pObjElement->sKey = sKey;
       pArray->Add(std::move(pObjElement));
     }
@@ -469,20 +461,20 @@
   for (int i = 0, sz = pData->objData.Count(); i < sz; i++) {
     CFX_KeyValue* pObjData = pData->objData.GetAt(i);
     switch (pObjData->nType) {
-      case CFX_KeyValue::DataType::NUMBER:
+      case CFX_Value::DataType::NUMBER:
         pRuntime->PutObjectProperty(pObj, pObjData->sKey.UTF8Decode(),
                                     pRuntime->NewNumber(pObjData->dData));
         break;
-      case CFX_KeyValue::DataType::BOOLEAN:
+      case CFX_Value::DataType::BOOLEAN:
         pRuntime->PutObjectProperty(pObj, pObjData->sKey.UTF8Decode(),
                                     pRuntime->NewBoolean(pObjData->bData == 1));
         break;
-      case CFX_KeyValue::DataType::STRING:
+      case CFX_Value::DataType::STRING:
         pRuntime->PutObjectProperty(
             pObj, pObjData->sKey.UTF8Decode(),
             pRuntime->NewString(pObjData->sData.UTF8Decode().AsStringView()));
         break;
-      case CFX_KeyValue::DataType::OBJECT: {
+      case CFX_Value::DataType::OBJECT: {
         v8::Local<v8::Object> pNewObj = pRuntime->NewObject();
         if (!pNewObj.IsEmpty()) {
           PutObjectProperty(pNewObj, pObjData);
@@ -490,7 +482,7 @@
                                       pNewObj);
         }
       } break;
-      case CFX_KeyValue::DataType::NULLOBJ:
+      case CFX_Value::DataType::NULLOBJ:
         pRuntime->PutObjectProperty(pObj, pObjData->sKey.UTF8Decode(),
                                     pRuntime->NewNull());
         break;
@@ -503,7 +495,7 @@
 }
 
 CJS_Result CJS_Global::SetGlobalVariables(const ByteString& propname,
-                                          CFX_KeyValue::DataType nType,
+                                          CFX_Value::DataType nType,
                                           double dData,
                                           bool bData,
                                           const ByteString& sData,
@@ -523,19 +515,19 @@
     }
     pTemp->bDeleted = false;
     switch (nType) {
-      case CFX_KeyValue::DataType::NUMBER:
+      case CFX_Value::DataType::NUMBER:
         pTemp->dData = dData;
         break;
-      case CFX_KeyValue::DataType::BOOLEAN:
+      case CFX_Value::DataType::BOOLEAN:
         pTemp->bData = bData;
         break;
-      case CFX_KeyValue::DataType::STRING:
+      case CFX_Value::DataType::STRING:
         pTemp->sData = sData;
         break;
-      case CFX_KeyValue::DataType::OBJECT:
+      case CFX_Value::DataType::OBJECT:
         pTemp->pData.Reset(pData->GetIsolate(), pData);
         break;
-      case CFX_KeyValue::DataType::NULLOBJ:
+      case CFX_Value::DataType::NULLOBJ:
         break;
       default:
         return CJS_Result::Failure(JSMessage::kObjectTypeError);
@@ -545,28 +537,28 @@
 
   auto pNewData = pdfium::MakeUnique<JSGlobalData>();
   switch (nType) {
-    case CFX_KeyValue::DataType::NUMBER:
-      pNewData->nType = CFX_KeyValue::DataType::NUMBER;
+    case CFX_Value::DataType::NUMBER:
+      pNewData->nType = CFX_Value::DataType::NUMBER;
       pNewData->dData = dData;
       pNewData->bPersistent = bDefaultPersistent;
       break;
-    case CFX_KeyValue::DataType::BOOLEAN:
-      pNewData->nType = CFX_KeyValue::DataType::BOOLEAN;
+    case CFX_Value::DataType::BOOLEAN:
+      pNewData->nType = CFX_Value::DataType::BOOLEAN;
       pNewData->bData = bData;
       pNewData->bPersistent = bDefaultPersistent;
       break;
-    case CFX_KeyValue::DataType::STRING:
-      pNewData->nType = CFX_KeyValue::DataType::STRING;
+    case CFX_Value::DataType::STRING:
+      pNewData->nType = CFX_Value::DataType::STRING;
       pNewData->sData = sData;
       pNewData->bPersistent = bDefaultPersistent;
       break;
-    case CFX_KeyValue::DataType::OBJECT:
-      pNewData->nType = CFX_KeyValue::DataType::OBJECT;
+    case CFX_Value::DataType::OBJECT:
+      pNewData->nType = CFX_Value::DataType::OBJECT;
       pNewData->pData.Reset(pData->GetIsolate(), pData);
       pNewData->bPersistent = bDefaultPersistent;
       break;
-    case CFX_KeyValue::DataType::NULLOBJ:
-      pNewData->nType = CFX_KeyValue::DataType::NULLOBJ;
+    case CFX_Value::DataType::NULLOBJ:
+      pNewData->nType = CFX_Value::DataType::NULLOBJ;
       pNewData->bPersistent = bDefaultPersistent;
       break;
     default:
diff --git a/fxjs/cjs_global.h b/fxjs/cjs_global.h
index bc73153..6491bbf 100644
--- a/fxjs/cjs_global.h
+++ b/fxjs/cjs_global.h
@@ -51,17 +51,14 @@
                          v8::Local<v8::Value> vp);
 
  private:
-  struct JSGlobalData {
+  struct JSGlobalData : public CFX_Value {
+   public:
     JSGlobalData();
     ~JSGlobalData();
 
-    CFX_KeyValue::DataType nType;
-    double dData;
-    bool bData;
-    ByteString sData;
     v8::Global<v8::Object> pData;
-    bool bPersistent;
-    bool bDeleted;
+    bool bPersistent = false;
+    bool bDeleted = false;
   };
 
   static int ObjDefnID;
@@ -71,7 +68,7 @@
   void CommitGlobalPersisitentVariables(CJS_Runtime* pRuntime);
   void DestroyGlobalPersisitentVariables();
   CJS_Result SetGlobalVariables(const ByteString& propname,
-                                CFX_KeyValue::DataType nType,
+                                CFX_Value::DataType nType,
                                 double dData,
                                 bool bData,
                                 const ByteString& sData,