COM: Script Caching
COM: Script Caching
- Manage script lifetimes
- BasicIdeCtl synchronized with a BasicNoUIObj in the same thread
- Application evaluates function defined by script
- DesignMode controls script editing/evaluation for the application
- COM Sample Implementation
COM: Script Caching
For an explanation of how this sample works please refer to the
Script Caching solution.
Sample source: ScriptCaching-Com.zip

Load a script:
HRESULT ScriptManager::LoadScript(const wchar_t* script_name, ScriptNode*& script_node)
{
std::wstring name = script_name;
if (name[0] != L'\\')
{
// relative script path
if (!active_script_node_)
name = L"\\" + name;
else
{
bstr_t namex(name.c_str());
Combine(bstr_t(active_script_node_->ScriptName().c_str()), bstr_t(name.c_str()), &namex.GetBSTR());
name = namex;
}
}
script_node = 0;
// is the script already loaded
auto it = std::find_if(loaded_script_nodes_.begin(), loaded_script_nodes_.end(), [&name](auto script_nodex) { return script_nodex->ScriptName() == name; });
if (it != loaded_script_nodes_.end())
script_node = *it;
if (!script_node)
// not active or loaded
script_node = new ScriptNode(name.c_str());
// evaluate a script node
if (!script_node->IsLoaded())
{
// load the script, a syntax error will return a failed hr
HRESULT hr = script_node->Load(basicNoUIObj_, fast_);
if (FAILED(hr))
return hr; // syntax error
// add to front of the loaded list
loaded_script_nodes_.push_front(script_node);
// update tree view with new status
script_loaded_status_changed_(script_node->ScriptName(), true);
while (loaded_script_nodes_.size() > max_loaded_scripts)
{
// remove the back (oldest loaded script node)
auto oldest_script_node = loaded_script_nodes_.back();
if (oldest_script_node->IsActive())
break;
loaded_script_nodes_.pop_back();
oldest_script_node->Unload();
// update tree view with new status
script_loaded_status_changed_(oldest_script_node->ScriptName(), false);
}
}
else if (script_node != loaded_script_nodes_.front())
{
// move to the front of the loaded list
loaded_script_nodes_.remove(script_node);
loaded_script_nodes_.push_front(script_node);
}
return S_OK;
}
Evaluate a script:
HRESULT ScriptManager::EvaluateScript(ScriptNode* script_node, VARIANT& result, const VARIANT* default_value)
{
// script is active
ScriptNode* previous_active_script_node = active_script_node_;
active_script_node_ = script_node;
// a run-time error will be return failed hr
HRESULT hr = script_node->Evaluate(result, default_value);
// script is no longer active
active_script_node_ = previous_active_script_node;
return hr;
}
Sample script:
'#Language "WWB-COM"
Option Explicitwwbnet
Function Action3() As Variant
Return "Item3\Action3: " & LoadScript("\Item4\Action1.bas").Evaluate
End Function
Sample script:
'#Language "WWB-COM"
Option Explicit
Function Action1() As Variant
' measure Evaluate performance
Dim script As Script
Set script = LoadScript("Nop.bas")
Const count = 1000000
Dim t0 As Single
t0 = Timer
Dim i As Long
For i = 1 To count
script.Evaluate
Next
Dim t1 As Single
t1 = Timer
Return "Item4\Timer\Action1: " & Int(count/(t1-t0)) & " per second"
End Function
Copyright Polar Engineering, Inc.