Replace second set of #defines with templates in JS_Define.h

Continuation of effort now that a test case is present on origin/master.

R=brucedawson@chromium.org

Review URL: https://codereview.chromium.org/945623002
diff --git a/fpdfsdk/include/javascript/JS_Define.h b/fpdfsdk/include/javascript/JS_Define.h
index 63b9fb7..04833bb 100644
--- a/fpdfsdk/include/javascript/JS_Define.h
+++ b/fpdfsdk/include/javascript/JS_Define.h
@@ -42,9 +42,8 @@
 #define JS_TRUE			(unsigned)1
 #define JS_FALSE		(unsigned)0
 
-
-#define CJS_PointsArray		CFX_ArrayTemplate<float>
-#define CJS_IntArray		CFX_ArrayTemplate<int>
+typedef CFX_ArrayTemplate<float> CJS_PointsArray;
+typedef CFX_ArrayTemplate<int> CJS_IntArray;
 
 /* ====================================== PUBLIC DEFINE SPEC ============================================== */
 #define JS_WIDESTRING(widestring) L###widestring
@@ -278,6 +277,90 @@
 
 /* ===================================== SPECIAL JS CLASS =============================================== */
 
+template <class Alt>
+void JSSpecialPropQuery(const char *, v8::Local<v8::String> property,const v8::PropertyCallbackInfo<v8::Integer>& info) {
+  v8::Isolate* isolate = info.GetIsolate();
+  v8::String::Utf8Value utf8_value(property);
+  CFX_WideString propname = CFX_WideString::FromUTF8(*utf8_value, utf8_value.length());
+  CJS_Object* pJSObj = reinterpret_cast<CJS_Object*>(JS_GetPrivate(isolate, info.Holder()));
+  Alt* pObj = reinterpret_cast<Alt*>(pJSObj->GetEmbedObject());
+  FX_BOOL bRet = pObj->QueryProperty(propname.c_str());
+  info.GetReturnValue().Set(bRet ? 4 : 0);
+}
+
+template <class Alt>
+void JSSpecialPropGet(const char* class_name,
+                      v8::Local<v8::String> property,
+                      const v8::PropertyCallbackInfo<v8::Value>& info) {
+  v8::Isolate* isolate = info.GetIsolate();
+  v8::Local<v8::Context> context = isolate->GetCurrentContext();
+  v8::Local<v8::Value> v = context->GetEmbedderData(1);
+  v8::Handle<v8::External> field = v8::Handle<v8::External>::Cast(v);
+  IFXJS_Runtime* pRuntime = (IFXJS_Runtime*)field->Value();
+  IFXJS_Context* pRuntimeContext = pRuntime->GetCurrentContext();
+  CJS_Object* pJSObj = reinterpret_cast<CJS_Object*>(JS_GetPrivate(isolate, info.Holder()));
+  Alt* pObj = reinterpret_cast<Alt*>(pJSObj->GetEmbedObject());
+  v8::String::Utf8Value utf8_value(property);
+  CFX_WideString propname = CFX_WideString::FromUTF8(*utf8_value, utf8_value.length());
+  JS_ErrorString sError;
+  CJS_PropValue value(isolate);
+  value.StartGetting();
+  if (!pObj->DoProperty(pRuntimeContext, propname.c_str(), value, sError)) {
+    CFX_ByteString cbName;
+    cbName.Format("%s.%s", class_name, L"GetProperty");
+    JS_Error(NULL,CFX_WideString::FromLocal(cbName), sError);
+    return;
+  }
+  info.GetReturnValue().Set((v8::Handle<v8::Value>)value);
+}
+
+template <class Alt>
+void JSSpecialPropPut(const char* class_name,
+                      v8::Local<v8::String> property,
+                      v8::Local<v8::Value> value,
+                      const v8::PropertyCallbackInfo<v8::Value>& info) {
+  v8::Isolate* isolate = info.GetIsolate();
+  v8::Local<v8::Context> context = isolate->GetCurrentContext();
+  v8::Local<v8::Value> v = context->GetEmbedderData(1);
+  v8::Handle<v8::External> field = v8::Handle<v8::External>::Cast(v);
+  IFXJS_Runtime* pRuntime = (IFXJS_Runtime*)field->Value();
+  IFXJS_Context* pRuntimeContext = pRuntime->GetCurrentContext();
+  CJS_Object* pJSObj = reinterpret_cast<CJS_Object*>(JS_GetPrivate(isolate, info.Holder()));
+  Alt* pObj = reinterpret_cast<Alt*>(pJSObj->GetEmbedObject());
+  v8::String::Utf8Value utf8_value(property);
+  CFX_WideString propname = CFX_WideString::FromUTF8(*utf8_value, utf8_value.length());
+  JS_ErrorString sError;
+  CJS_PropValue PropValue(CJS_Value(isolate,value,VT_unknown));
+  PropValue.StartSetting();
+  if (!pObj->DoProperty(pRuntimeContext, propname.c_str(), PropValue, sError)) {
+    CFX_ByteString cbName;
+    cbName.Format("%s.%s", class_name, "PutProperty");
+    JS_Error(NULL,CFX_WideString::FromLocal(cbName), sError);
+  }
+}
+
+template <class Alt>
+void JSSpecialPropDel(const char* class_name,
+                      v8::Local<v8::String> property,
+                      const v8::PropertyCallbackInfo<v8::Boolean>& info) {
+  v8::Isolate* isolate = info.GetIsolate();
+  v8::Local<v8::Context> context = isolate->GetCurrentContext();
+  v8::Local<v8::Value> v = context->GetEmbedderData(1);
+  v8::Handle<v8::External> field = v8::Handle<v8::External>::Cast(v);
+  IFXJS_Runtime* pRuntime = (IFXJS_Runtime*)field->Value();
+  IFXJS_Context* pRuntimeContext = pRuntime->GetCurrentContext();
+  CJS_Object* pJSObj = reinterpret_cast<CJS_Object*>(JS_GetPrivate(isolate, info.Holder()));
+  Alt* pObj = reinterpret_cast<Alt*>(pJSObj->GetEmbedObject());
+  v8::String::Utf8Value utf8_value(property);
+  CFX_WideString propname = CFX_WideString::FromUTF8(*utf8_value, utf8_value.length());
+  JS_ErrorString sError;
+  if (!pObj->DelProperty(pRuntimeContext, propname.c_str(), sError)) {
+    CFX_ByteString cbName;
+    cbName.Format("%s.%s", class_name, "DelProperty");
+    // Probably a missing call to JS_Error().
+  }
+}
+
 #define DECLARE_SPECIAL_JS_CLASS(js_class_name) \
 	static JSBool JSConstructor(IFXJS_Context* cc, JSFXObject obj, JSFXObject global);\
 	static JSBool JSDestructor(JSFXObject obj);\
@@ -289,138 +372,25 @@
 	static JSMethodSpec	JS_Class_Methods[];\
 	static int Init(IJS_Runtime* pRuntime, FXJSOBJTYPE eObjType);\
 	static const wchar_t* m_pClassName;\
-	static void queryprop_##js_class_name##_static(JS_PROPQUERY_ARGS);\
-	static void getprop_##js_class_name##_static(JS_NAMED_PROPGET_ARGS);\
-	static void putprop_##js_class_name##_static(JS_NAMED_PROPPUT_ARGS);\
-	static void delprop_##js_class_name##_static(JS_PROPDEL_ARGS)
+	static void queryprop_##js_class_name##_static(v8::Local<v8::String> property,const v8::PropertyCallbackInfo<v8::Integer>& info);\
+	static void getprop_##js_class_name##_static(v8::Local<v8::String> property, const v8::PropertyCallbackInfo<v8::Value>& info);\
+	static void putprop_##js_class_name##_static(v8::Local<v8::String> property,v8::Local<v8::Value> value,const v8::PropertyCallbackInfo<v8::Value>& info);\
+	static void delprop_##js_class_name##_static(v8::Local<v8::String> property,const v8::PropertyCallbackInfo<v8::Boolean>& info)
 
 #define IMPLEMENT_SPECIAL_JS_CLASS(js_class_name, class_alternate, class_name) \
 const wchar_t * js_class_name::m_pClassName = JS_WIDESTRING(class_name);\
-	void js_class_name::queryprop_##js_class_name##_static(JS_PROPQUERY_ARGS)\
-{\
-	v8::Isolate* isolate = info.GetIsolate();\
-	v8::String::Utf8Value utf8_value(property);\
-	CFX_WideString propname = CFX_WideString::FromUTF8(*utf8_value, utf8_value.length());\
-	CJS_Object* pJSObj = (CJS_Object*)JS_GetPrivate(isolate,info.Holder());\
-	ASSERT(pJSObj != NULL);\
-	class_alternate* pObj = (class_alternate*)pJSObj->GetEmbedObject();\
-	ASSERT(pObj != NULL);\
-	FX_BOOL bRet = FALSE;\
-	bRet = pObj->QueryProperty(propname.c_str());\
-	if (bRet)\
-	{\
-		info.GetReturnValue().Set(0x004);\
-		return ;\
-	}\
-	else\
-	{\
-		info.GetReturnValue().Set(0);\
-		return ;\
-	}\
-	return ;\
+void js_class_name::queryprop_##js_class_name##_static(v8::Local<v8::String> property,const v8::PropertyCallbackInfo<v8::Integer>& info) { \
+  JSSpecialPropQuery<class_alternate>(#class_name, property, info);     \
 }\
-	void js_class_name::getprop_##js_class_name##_static(JS_NAMED_PROPGET_ARGS)\
-{\
-	v8::Isolate* isolate = info.GetIsolate();\
-	v8::Local<v8::Context> context = isolate->GetCurrentContext();\
-	v8::Local<v8::Value> v = context->GetEmbedderData(1);\
-	ASSERT(!v.IsEmpty());\
-	if(v.IsEmpty()) return;\
-	v8::Handle<v8::External> field = v8::Handle<v8::External>::Cast(v);\
-	IFXJS_Runtime* pRuntime = (IFXJS_Runtime*)field->Value();\
-	IFXJS_Context* cc = pRuntime->GetCurrentContext();\
-	v8::String::Utf8Value utf8_value(property);\
-	CFX_WideString propname = CFX_WideString::FromUTF8(*utf8_value, utf8_value.length());\
-	CJS_PropValue value(isolate);\
-	value.StartGetting();\
-	CJS_Object* pJSObj = (CJS_Object*)JS_GetPrivate(isolate,info.Holder());\
-	ASSERT(pJSObj != NULL);\
-	class_alternate* pObj = (class_alternate*)pJSObj->GetEmbedObject();\
-	ASSERT(pObj != NULL);\
-	JS_ErrorString sError;\
-	FX_BOOL bRet = FALSE;\
-	bRet = pObj->DoProperty(cc, propname.c_str(), value, sError);\
-	if (bRet)\
-	{\
-		info.GetReturnValue().Set((v8::Handle<v8::Value>)value);\
-		return ;\
-	}\
-	else\
-	{\
-		CFX_ByteString cbName;\
-		cbName.Format("%s.%s", #class_name, L"GetProperty");\
-		JS_Error(NULL,CFX_WideString::FromLocal(cbName), sError);\
-		return ;\
-	}\
-	JS_Error(NULL,L"GetProperty", L"Embeded object not found!");\
-	return ;\
+void js_class_name::getprop_##js_class_name##_static(v8::Local<v8::String> property, const v8::PropertyCallbackInfo<v8::Value>& info) { \
+  JSSpecialPropGet<class_alternate>(#class_name, property, info); \
+}                                                                       \
+void js_class_name::putprop_##js_class_name##_static(v8::Local<v8::String> property,v8::Local<v8::Value> value,const v8::PropertyCallbackInfo<v8::Value>& info) {\
+  JSSpecialPropPut<class_alternate>(#class_name, property, value, info); \
 }\
-	void js_class_name::putprop_##js_class_name##_static(JS_NAMED_PROPPUT_ARGS)\
-{\
-	v8::Isolate* isolate = info.GetIsolate();\
-	v8::Local<v8::Context> context = isolate->GetCurrentContext();\
-	v8::Local<v8::Value> v = context->GetEmbedderData(1);\
-	ASSERT(!v.IsEmpty());\
-	if(v.IsEmpty()) return;\
-	v8::Handle<v8::External> field = v8::Handle<v8::External>::Cast(v);\
-	IFXJS_Runtime* pRuntime = (IFXJS_Runtime*)field->Value();\
-	IFXJS_Context* cc = pRuntime->GetCurrentContext();\
-	v8::String::Utf8Value utf8_value(property);\
-	CFX_WideString propname = CFX_WideString::FromUTF8(*utf8_value, utf8_value.length());\
-	CJS_PropValue PropValue(CJS_Value(isolate,value,VT_unknown));\
-	PropValue.StartSetting();\
-	CJS_Object* pJSObj = (CJS_Object*)JS_GetPrivate(isolate,info.Holder());\
-	if(!pJSObj) return;\
-	class_alternate* pObj = (class_alternate*)pJSObj->GetEmbedObject();\
-	ASSERT(pObj != NULL);\
-	JS_ErrorString sError;\
-	FX_BOOL bRet = FALSE;\
-	bRet = pObj->DoProperty(cc, propname.c_str(), PropValue, sError);\
-	if (bRet)\
-	{\
-		return ;\
-	}\
-	else\
-	{\
-		CFX_ByteString cbName;\
-		cbName.Format("%s.%s", #class_name, "PutProperty");\
-		JS_Error(NULL,CFX_WideString::FromLocal(cbName), sError);\
-		return ;\
-	}\
-	JS_Error(NULL,L"PutProperty", L"Embeded object not found!");\
-	return ;\
-}\
-	void js_class_name::delprop_##js_class_name##_static(JS_PROPDEL_ARGS)\
-{\
-	v8::Isolate* isolate = info.GetIsolate();\
-	v8::Local<v8::Context> context = isolate->GetCurrentContext();\
-	v8::Local<v8::Value> v = context->GetEmbedderData(1);\
-	ASSERT(!v.IsEmpty());\
-	if(v.IsEmpty()) return;\
-	v8::Handle<v8::External> field = v8::Handle<v8::External>::Cast(v);\
-	IFXJS_Runtime* pRuntime = (IFXJS_Runtime*)field->Value();\
-	IFXJS_Context* cc = pRuntime->GetCurrentContext();\
-	v8::String::Utf8Value utf8_value(property);\
-	CFX_WideString propname = CFX_WideString::FromUTF8(*utf8_value, utf8_value.length());\
-	CJS_Object* pJSObj = (CJS_Object*)JS_GetPrivate(isolate,info.Holder());\
-	ASSERT(pJSObj != NULL);\
-	class_alternate* pObj = (class_alternate*)pJSObj->GetEmbedObject();\
-	ASSERT(pObj != NULL);\
-	JS_ErrorString sError;\
-	FX_BOOL bRet = FALSE;\
-	bRet = pObj->DelProperty(cc, propname.c_str(), sError);\
-	if (bRet)\
-	{\
-		return ;\
-	}\
-	else\
-	{\
-		CFX_ByteString cbName;\
-		cbName.Format("%s.%s", #class_name, "DelProperty");\
-		return ;\
-	}\
-	return ;\
-}\
+void js_class_name::delprop_##js_class_name##_static(v8::Local<v8::String> property,const v8::PropertyCallbackInfo<v8::Boolean>& info) { \
+  JSSpecialPropDel<class_alternate>(#class_name, property, info); \
+} \
 JSBool js_class_name::JSConstructor(IFXJS_Context* cc, JSFXObject  obj,JSFXObject  global)\
 {\
 	CJS_Object* pObj = FX_NEW js_class_name(obj);\
diff --git a/fpdfsdk/include/jsapi/fxjs_v8.h b/fpdfsdk/include/jsapi/fxjs_v8.h
index e08196d..b6ea60b 100644
--- a/fpdfsdk/include/jsapi/fxjs_v8.h
+++ b/fpdfsdk/include/jsapi/fxjs_v8.h
@@ -1,7 +1,7 @@
 // Copyright 2014 PDFium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
- 
+
 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
 
 #ifndef FXJSAPI_H
@@ -30,8 +30,8 @@
 
 struct FXJSErr
 {
-	const wchar_t* message;	
-    const wchar_t* srcline;	
+	const wchar_t* message;
+    const wchar_t* srcline;
     unsigned linnum;
 };
 
@@ -41,23 +41,9 @@
 class IFXJS_Context;
 class IFXJS_Runtime;
 
+typedef unsigned (*LP_CONSTRUCTOR)(IFXJS_Context* cc, v8::Handle<v8::Object> obj, v8::Handle<v8::Object> global);
+typedef unsigned (*LP_DESTRUCTOR)(v8::Handle<v8::Object> obj);
 
-#ifndef JSCRIPT_ARGS
-#define JSCRIPT_ARGS
-
-#define JS_CONSTRUCTOR_ARGS		IFXJS_Context* cc, v8::Handle<v8::Object> obj, v8::Handle<v8::Object> global
-#define JS_DESTRUCTOR_ARGS		v8::Handle<v8::Object> obj
-
-#define JS_PROPQUERY_ARGS		v8::Local<v8::String> property,const v8::PropertyCallbackInfo<v8::Integer>& info
-#define JS_NAMED_PROPGET_ARGS	        v8::Local<v8::String> property, const v8::PropertyCallbackInfo<v8::Value>& info
-
-#define JS_NAMED_PROPPUT_ARGS	v8::Local<v8::String> property,v8::Local<v8::Value> value,const v8::PropertyCallbackInfo<v8::Value>& info
-#define JS_PROPDEL_ARGS			v8::Local<v8::String> property,const v8::PropertyCallbackInfo<v8::Boolean>& info
-
-typedef unsigned (*LP_CONSTRUCTOR)(JS_CONSTRUCTOR_ARGS);
-typedef unsigned (*LP_DESTRUCTOR)(JS_DESTRUCTOR_ARGS);
-
-#endif
 
 int								JS_DefineObj(IJS_Runtime* pJSRuntime, const wchar_t* sObjName, FXJSOBJTYPE eObjType, LP_CONSTRUCTOR pConstructor, LP_DESTRUCTOR pDestructor, unsigned bApplyNew);
 int								JS_DefineObjMethod(IJS_Runtime* pJSRuntime, int nObjDefnID, const wchar_t* sMethodName, v8::FunctionCallback pMethodCall, unsigned nParamNum);
@@ -69,7 +55,7 @@
 
 void							JS_InitialRuntime(IJS_Runtime* pJSRuntime,IFXJS_Runtime* pFXRuntime, IFXJS_Context* context, v8::Persistent<v8::Context>& v8PersistentContext);
 void							JS_ReleaseRuntime(IJS_Runtime* pJSRuntime, v8::Persistent<v8::Context>& v8PersistentContext);
-void							JS_Initial(); 
+void							JS_Initial();
 void							JS_Release();
 int								JS_Parse(IJS_Runtime* pJSRuntime, IFXJS_Context* pJSContext, const wchar_t* script, long length, FXJSErr* perror);
 int								JS_Execute(IJS_Runtime* pJSRuntime, IFXJS_Context* pJSContext, const wchar_t* script, long length, FXJSErr* perror);