Ticket #2416: Remove_ValueCloner_v1.0.diff

File Remove_ValueCloner_v1.0.diff, 4.2 KB (added by Yves, 10 years ago)

Removes ValueCloner and replaces it with a much simple implementation using StructuredClones

  • source/scriptinterface/ScriptInterface.cpp

     
    12441244    JS_MaybeGC(m->m_cx);
    12451245}
    12461246
    1247 class ValueCloner
    1248 {
    1249 public:
    1250     ValueCloner(ScriptInterface& from, ScriptInterface& to) :
    1251         scriptInterfaceFrom(from), cxFrom(from.GetContext()), cxTo(to.GetContext()), m_RooterFrom(from), m_RooterTo(to)
    1252     {
    1253     }
    1254 
    1255     // Return the cloned object (or an already-computed object if we've cloned val before)
    1256     jsval GetOrClone(jsval val)
    1257     {
    1258         if (!JSVAL_IS_GCTHING(val) || JSVAL_IS_NULL(val))
    1259             return val;
    1260 
    1261         std::map<void*, jsval>::iterator it = m_Mapping.find(JSVAL_TO_GCTHING(val));
    1262         if (it != m_Mapping.end())
    1263             return it->second;
    1264 
    1265         m_RooterFrom.Push(val); // root it so our mapping doesn't get invalidated
    1266 
    1267         return Clone(val);
    1268     }
    1269 
    1270 private:
    1271 
    1272 #define CLONE_REQUIRE(expr, msg) if (!(expr)) { debug_warn(L"Internal error in CloneValueFromOtherContext: " msg); return JSVAL_VOID; }
    1273 
    1274     // Clone a new value (and root it and add it to the mapping)
    1275     jsval Clone(jsval val)
    1276     {
    1277         if (JSVAL_IS_DOUBLE(val))
    1278         {
    1279             jsval rval;
    1280             CLONE_REQUIRE(JS_NewNumberValue(cxTo, JSVAL_TO_DOUBLE(val), &rval), L"JS_NewNumberValue");
    1281             m_RooterTo.Push(rval);
    1282             return rval;
    1283         }
    1284 
    1285         if (JSVAL_IS_STRING(val))
    1286         {
    1287             size_t len;
    1288             const jschar* chars = JS_GetStringCharsAndLength(cxFrom, JSVAL_TO_STRING(val), &len);
    1289             CLONE_REQUIRE(chars, L"JS_GetStringCharsAndLength");
    1290             JSString* str = JS_NewUCStringCopyN(cxTo, chars, len);
    1291             CLONE_REQUIRE(str, L"JS_NewUCStringCopyN");
    1292             jsval rval = STRING_TO_JSVAL(str);
    1293             m_Mapping[JSVAL_TO_GCTHING(val)] = rval;
    1294             m_RooterTo.Push(rval);
    1295             return rval;
    1296         }
    1297 
    1298         ENSURE(JSVAL_IS_OBJECT(val));
    1299 
    1300         JSObject* newObj;
    1301         if (JS_IsArrayObject(cxFrom, JSVAL_TO_OBJECT(val)))
    1302         {
    1303             jsuint length;
    1304             CLONE_REQUIRE(JS_GetArrayLength(cxFrom, JSVAL_TO_OBJECT(val), &length), L"JS_GetArrayLength");
    1305             newObj = JS_NewArrayObject(cxTo, length, NULL);
    1306             CLONE_REQUIRE(newObj, L"JS_NewArrayObject");
    1307         }
    1308         else
    1309         {
    1310             newObj = JS_NewObject(cxTo, NULL, NULL, NULL);
    1311             CLONE_REQUIRE(newObj, L"JS_NewObject");
    1312         }
    1313 
    1314         m_Mapping[JSVAL_TO_GCTHING(val)] = OBJECT_TO_JSVAL(newObj);
    1315         m_RooterTo.Push(newObj);
    1316 
    1317         AutoJSIdArray ida (cxFrom, JS_Enumerate(cxFrom, JSVAL_TO_OBJECT(val)));
    1318         CLONE_REQUIRE(ida.get(), L"JS_Enumerate");
    1319 
    1320         AutoGCRooter idaRooter(scriptInterfaceFrom);
    1321         idaRooter.Push(ida.get());
    1322 
    1323         for (size_t i = 0; i < ida.length(); ++i)
    1324         {
    1325             jsid id = ida[i];
    1326             jsval idval, propval;
    1327             CLONE_REQUIRE(JS_IdToValue(cxFrom, id, &idval), L"JS_IdToValue");
    1328             CLONE_REQUIRE(JS_GetPropertyById(cxFrom, JSVAL_TO_OBJECT(val), id, &propval), L"JS_GetPropertyById");
    1329             jsval newPropval = GetOrClone(propval);
    1330 
    1331             if (JSVAL_IS_INT(idval))
    1332             {
    1333                 // int jsids are portable across runtimes
    1334                 CLONE_REQUIRE(JS_SetPropertyById(cxTo, newObj, id, &newPropval), L"JS_SetPropertyById");
    1335             }
    1336             else if (JSVAL_IS_STRING(idval))
    1337             {
    1338                 // string jsids are runtime-specific, so we need to copy the string content
    1339                 JSString* idstr = JS_ValueToString(cxFrom, idval);
    1340                 CLONE_REQUIRE(idstr, L"JS_ValueToString (id)");
    1341                 size_t len;
    1342                 const jschar* chars = JS_GetStringCharsAndLength(cxFrom, idstr, &len);
    1343                 CLONE_REQUIRE(idstr, L"JS_GetStringCharsAndLength (id)");
    1344                 CLONE_REQUIRE(JS_SetUCProperty(cxTo, newObj, chars, len, &newPropval), L"JS_SetUCProperty");
    1345             }
    1346             else
    1347             {
    1348                 // this apparently could be an XML object; ignore it
    1349             }
    1350         }
    1351 
    1352         return OBJECT_TO_JSVAL(newObj);
    1353     }
    1354 
    1355     ScriptInterface& scriptInterfaceFrom;
    1356     JSContext* cxFrom;
    1357     JSContext* cxTo;
    1358     std::map<void*, jsval> m_Mapping;
    1359     AutoGCRooter m_RooterFrom;
    1360     AutoGCRooter m_RooterTo;
    1361 };
    1362 
    13631247jsval ScriptInterface::CloneValueFromOtherContext(ScriptInterface& otherContext, jsval val)
    13641248{
    13651249    PROFILE("CloneValueFromOtherContext");
    1366 
    1367     ValueCloner cloner(otherContext, *this);
    1368     return cloner.GetOrClone(val);
     1250    shared_ptr<StructuredClone> structuredClone = otherContext.WriteStructuredClone(val);
     1251    jsval clone = ReadStructuredClone(structuredClone);
     1252    return clone;
    13691253}
    13701254
    13711255ScriptInterface::StructuredClone::StructuredClone() :