165 lines
5.6 KiB
C++
165 lines
5.6 KiB
C++
///////////////////////////////////////////////////////////////////////////////
|
|
// Name: wx/private/jsscriptwrapper.h
|
|
// Purpose: JS Script Wrapper for wxWebView
|
|
// Author: Jose Lorenzo
|
|
// Created: 2017-08-12
|
|
// Copyright: (c) 2017 Jose Lorenzo <josee.loren@gmail.com>
|
|
// Licence: wxWindows licence
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
#ifndef _WX_PRIVATE_JSSCRIPTWRAPPER_H_
|
|
#define _WX_PRIVATE_JSSCRIPTWRAPPER_H_
|
|
|
|
#include "wx/regex.h"
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// Helper for wxWebView::RunScript()
|
|
// ----------------------------------------------------------------------------
|
|
|
|
// This class provides GetWrappedCode(), GetOutputCode() and GetCleanUpCode()
|
|
// functions that should be executed in the backend-appropriate way by each
|
|
// wxWebView implementation in order to actually execute the user-provided
|
|
// JavaScript code, retrieve its result (if it executed successfully) and
|
|
// perform the cleanup at the end.
|
|
class wxJSScriptWrapper
|
|
{
|
|
public:
|
|
wxJSScriptWrapper(const wxString& js, int* runScriptCount)
|
|
: m_escapedCode(js)
|
|
{
|
|
// We assign the return value of JavaScript snippet we execute to the
|
|
// variable with this name in order to be able to access it later if
|
|
// needed.
|
|
//
|
|
// Note that we use a different name for it for each call to
|
|
// RunScript() (which creates a new wxJSScriptWrapper every time) to
|
|
// avoid any possible conflict between different calls.
|
|
m_outputVarName = wxString::Format("__wxOut%i", (*runScriptCount)++);
|
|
|
|
// Adds one escape level if there is a single quote, double quotes or
|
|
// escape characters
|
|
wxRegEx escapeDoubleQuotes("(\\\\*)(['\"\n\r\v\t\b\f])");
|
|
escapeDoubleQuotes.Replace(&m_escapedCode,"\\1\\1\\\\\\2");
|
|
}
|
|
|
|
// Get the code to execute, its returned value will be either boolean true,
|
|
// if it executed successfully, or the exception message if an error
|
|
// occurred.
|
|
//
|
|
// Execute GetOutputCode() later to get the real output after successful
|
|
// execution of this code.
|
|
wxString GetWrappedCode() const
|
|
{
|
|
return wxString::Format("try { var %s = eval(\"%s\"); true; } \
|
|
catch (e) { e.name + \": \" + e.message; }", m_outputVarName, m_escapedCode);
|
|
}
|
|
|
|
// Get code returning the result of the last successful execution of the
|
|
// code returned by GetWrappedCode().
|
|
wxString GetOutputCode() const
|
|
{
|
|
#if wxUSE_WEBVIEW && wxUSE_WEBVIEW_WEBKIT && defined(__WXOSX__)
|
|
return wxString::Format("if (typeof %s == 'object') \
|
|
JSON.stringify(%s); \
|
|
else if (typeof %s == 'undefined') \
|
|
'undefined'; \
|
|
else \
|
|
%s;",
|
|
m_outputVarName, m_outputVarName, m_outputVarName, m_outputVarName);
|
|
#elif wxUSE_WEBVIEW && wxUSE_WEBVIEW_IE
|
|
return wxString::Format("try {(%s == null || typeof %s != 'object') ? String(%s) : JSON.stringify(%s);} \
|
|
catch (e) { \
|
|
try \
|
|
{ \
|
|
function __wx$stringifyJSON(obj) \
|
|
{ \
|
|
var objElements = []; \
|
|
if (!(obj instanceof Object)) \
|
|
return typeof obj === \"string\" \
|
|
? \'\"\' + obj + \'\"\' : \'\' + obj; \
|
|
else if (obj instanceof Array) \
|
|
{ \
|
|
if (obj[0] === undefined) \
|
|
return \'[]\'; \
|
|
else \
|
|
{ \
|
|
var arr = []; \
|
|
for (var i = 0; i < obj.length; i++) \
|
|
arr.push(__wx$stringifyJSON(obj[i])); \
|
|
return \'[\' + arr + \']\'; \
|
|
} \
|
|
} \
|
|
else if (typeof obj === \"object\") \
|
|
{ \
|
|
if (obj instanceof Date) \
|
|
{ \
|
|
if (!Date.prototype.toISOString) \
|
|
{ \
|
|
(function() \
|
|
{ \
|
|
function pad(number) \
|
|
{ \
|
|
if (number < 10) \
|
|
return '0' + number; \
|
|
return number; \
|
|
} \
|
|
\
|
|
Date.prototype.toISOString = function() \
|
|
{ \
|
|
return this.getUTCFullYear() + \
|
|
'-' + pad(this.getUTCMonth() + 1) + \
|
|
'-' + pad(this.getUTCDate()) + \
|
|
'T' + pad(this.getUTCHours()) + \
|
|
':' + pad(this.getUTCMinutes()) + \
|
|
':' + pad(this.getUTCSeconds()) + \
|
|
'.' + (this.getUTCMilliseconds() / 1000).toFixed(3).slice(2, 5) + \
|
|
'Z\"'; \
|
|
}; \
|
|
\
|
|
}()); \
|
|
} \
|
|
return '\"' + obj.toISOString(); + '\"' \
|
|
} \
|
|
for (var key in obj) \
|
|
{ \
|
|
if (typeof obj[key] === \"function\") \
|
|
return \'{}\'; \
|
|
else \
|
|
objElements.push(\'\"\' \
|
|
+ key + \'\":\' + \
|
|
__wx$stringifyJSON(obj[key])); \
|
|
} \
|
|
return \'{\' + objElements + \'}\'; \
|
|
} \
|
|
} \
|
|
\
|
|
__wx$stringifyJSON(%s); \
|
|
} \
|
|
catch (e) { e.name + \": \" + e.message; }}",
|
|
m_outputVarName, m_outputVarName, m_outputVarName, m_outputVarName, m_outputVarName);
|
|
#else
|
|
return m_outputVarName;
|
|
#endif
|
|
}
|
|
|
|
// Execute the code returned by this function to let the output of the code
|
|
// we executed be garbage-collected.
|
|
wxString GetCleanUpCode() const
|
|
{
|
|
return wxString::Format("%s = undefined;", m_outputVarName);
|
|
}
|
|
|
|
wxString GetOutputJSVariable() const
|
|
{
|
|
return m_outputVarName;
|
|
}
|
|
|
|
private:
|
|
wxString m_escapedCode;
|
|
wxString m_outputVarName;
|
|
|
|
wxDECLARE_NO_COPY_CLASS(wxJSScriptWrapper);
|
|
};
|
|
|
|
#endif // _WX_PRIVATE_JSSCRIPTWRAPPER_H_
|