| Index: test/JsLatch.cpp | 
| =================================================================== | 
| new file mode 100644 | 
| --- /dev/null | 
| +++ b/test/JsLatch.cpp | 
| @@ -0,0 +1,70 @@ | 
| +/* | 
| + * This file is part of Adblock Plus <https://adblockplus.org/>, | 
| + * Copyright (C) 2006-2016 Eyeo GmbH | 
| + * | 
| + * Adblock Plus is free software: you can redistribute it and/or modify | 
| + * it under the terms of the GNU General Public License version 3 as | 
| + * published by the Free Software Foundation. | 
| + * | 
| + * Adblock Plus is distributed in the hope that it will be useful, | 
| + * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
| + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
| + * GNU General Public License for more details. | 
| + * | 
| + * You should have received a copy of the GNU General Public License | 
| + * along with Adblock Plus.  If not, see <http://www.gnu.org/licenses/>. | 
| + */ | 
| + | 
| +#include "JsLatch.h" | 
| + | 
| +namespace | 
| +{ | 
| +  /** | 
| +   */ | 
| +  v8::Handle<v8::Value> ArriveCallback(const v8::Arguments& arguments) | 
| +  { | 
| +    auto self = static_cast<JsTestingLatch *>( | 
| +      v8::Local<v8::External>::Cast(arguments.Holder()->GetInternalField(0))->Value()); | 
| +    if (self) | 
| +    { | 
| +      self->GetLatch().Arrive(); | 
| +    } | 
| +    return v8::Undefined(); | 
| +  } | 
| +} | 
| + | 
| +/** | 
| + * \par Implementation Notes | 
| + *    Internal field 0 of the JS object contains a copy of \c this. | 
| + */ | 
| +V8PersistentNG<v8::Object> JsTestingLatch::JsObjectInitializer(const std::string& propertyName) | 
| +{ | 
| +  V8ExecutionScope context(engine); | 
| +  // Object template | 
| +  auto jsObjectTemplate = v8::ObjectTemplate::New(); | 
| +  jsObjectTemplate->SetInternalFieldCount(1); | 
| +  jsObjectTemplate->Set(engine->ToV8String("Arrive"), v8::FunctionTemplate::New(ArriveCallback)); | 
| +  // Object | 
| +  auto localJsObject = jsObjectTemplate->NewInstance(); | 
| +  localJsObject->SetInternalField(0, v8::External::New(this)); | 
| +  // Property on global | 
| +  engine->GetGlobalObject()->Set(engine->ToV8String(propertyName), localJsObject); | 
| +  // Persistent | 
| +  return V8PersistentNG<v8::Object>(engine->GetIsolate(), localJsObject); | 
| +} | 
| + | 
| +JsTestingLatch::JsTestingLatch(JsEngineInternal* engine, const std::string& propertyName, int count) | 
| +  : engine(engine), latch(count), jsObject(JsObjectInitializer(propertyName)) | 
| +{} | 
| + | 
| +JsTestingLatch::~JsTestingLatch() | 
| +{ | 
| +  V8ExecutionScope context(engine); | 
| +  auto obj = jsObject.Get(engine->GetIsolate()); | 
| +  // ensure object still exists | 
| +  if (obj->IsObject()) | 
| +  { | 
| +    obj->SetInternalField(0, v8::External::New(nullptr)); | 
| +  } | 
| +  // Rather than changing the "Arrive" property, we handle a null pointer in the callback for it. | 
| +} | 
|  |