⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 jsicontext.cpp

📁 sloedgy open sip stack source code
💻 CPP
📖 第 1 页 / 共 4 页
字号:

 /****************License************************************************
  *
  * Copyright 2000-2003.  ScanSoft, Inc.    
  *
  * Use of this software is subject to notices and obligations set forth 
  * in the SpeechWorks Public License - Software Version 1.2 which is 
  * included with this software. 
  *
  * ScanSoft is a registered trademark of ScanSoft, Inc., and OpenSpeech, 
  * SpeechWorks and the SpeechWorks logo are registered trademarks or 
  * trademarks of SpeechWorks International, Inc. in the United States 
  * and other countries.
  *
  ***********************************************************************/
 

 /*****************************************************************************
  *****************************************************************************
  *
  *
  * JsiContext, class for managing JavaScript contexts 
  *
  * The JsiContext class represents a JavaScript context, a script
  * execution state. All JavaScript variables are maintained in a
  * context, and all scripts are executed in reference to a context
  * (for accessing variables and maintaining script side-effects). Each
  * context may have one or more scopes that are used to layer the
  * state information so that it is possible for clients to control the
  * lifetime of state information within the context.
  * SBjsiInterface, definition of the real SBjsi resource object
  *
  *****************************************************************************
  ****************************************************************************/
 
 
 // -----1=0-------2=0-------3=0-------4=0-------5=0-------6=0-------7=0-------8
 
 
#include <vxibuildopts.h>
#if P_VXI

 #include "SBjsiInternal.h"
 
 #include "JsiRuntime.hpp"            // For the JsiRuntime class
 #include "JsiContext.hpp"            // Defines this class
 
 #include <string.h>                  // For strlen( )
 #include <deque>                       // for deque 
 
 #include "SBjsiLog.h"                // For logging
 #include "SBjsiString.hpp"          // For SBjsiString
 #include "JsiCharCvt.hpp"            // For jschar <-> VXIchar conversion
 
 // SpiderMonkey class that describes our scope objects which we use
 // as contexts
 static JSClass SCOPE_CLASS = {
     "__SBjsiScope", JSCLASS_HAS_PRIVATE,
     JS_PropertyStub,  JS_PropertyStub, JS_PropertyStub, JsiContext::SCOPE_CLASS_SetProperty,
     JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub,  
     JsiContext::ScopeFinalize, JSCLASS_NO_OPTIONAL_MEMBERS
 };
 
 // SpiderMonkey class that describes our content objects which we use
 // to point at VXIContent objects
 static JSClass CONTENT_CLASS = {
     "__SBjsiContent", JSCLASS_HAS_PRIVATE,
     JS_PropertyStub,  JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
     JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub,  
     JsiContext::ContentFinalize, JSCLASS_NO_OPTIONAL_MEMBERS
 };
 
 // SpiderMonkey class that describes our objects which we create from
 // a VXIMap, just very simple objects
 static JSClass MAP_CLASS = {
     "__SBjsiMap", 0,
     JS_PropertyStub,  JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
     JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub,  
     JS_FinalizeStub, JSCLASS_NO_OPTIONAL_MEMBERS
 };
 
 // Names for JS objects we protect from garbage collection, only used
 // for SpiderMonkey debugging purposes
 static const char GLOBAL_SCOPE_NAME[]  = "__SBjsiGlobalScope";
 static const wchar_t GLOBAL_SCOPE_NAME_W[]  = L"__SBjsiGlobalScope";
 static const char SCRIPT_OBJECT_NAME[] = "__SBjsiScriptObject";
 static const char PROTECTED_JSVAL_NAME[] = "__SBjsiProtectedJsval";
 
 // Global variable we use for temporaries
 static const char GLOBAL_TEMP_VAR[] = "__SBjsiTempVar";
 static const wchar_t GLOBAL_TEMP_VAR_W[] = L"__SBjsiTempVar";
 
 
 // -----1=0-------2=0-------3=0-------4=0-------5=0-------6=0-------7=0-------8
 
 
 #define GET_VXICHAR_FROM_JSCHAR(out, in) \
   JscharToVXIchar convert_##out(in); \
   const VXIchar *out = convert_##out.c_str( )
 
 #define GET_JSCHAR_FROM_VXICHAR(out, outlen, in) \
   VXIcharToJschar convert_##out(in); \
   const jschar *out = convert_##out.c_str( ); \
   size_t outlen = convert_##out.length( )
 
 
 // -----1=0-------2=0-------3=0-------4=0-------5=0-------6=0-------7=0-------8
 
 
 // Wrapper class around jsval that automatically protects the held
 // jsval from garbage collection
 class JsiProtectedJsval {
  public:
   // Constructor and destructor
   JsiProtectedJsval (JSContext *c) : context(c), val(JSVAL_VOID) { }
   ~JsiProtectedJsval( ) { Clear( ); }
 
   // Clear the value
   VXIjsiResult Clear( ) { 
     VXIjsiResult rc;
     rc = ((( JSVAL_IS_GCTHING(val) ) && ( ! JS_RemoveRoot (context, &val) )) ?
     VXIjsi_RESULT_FATAL_ERROR : VXIjsi_RESULT_SUCCESS);
     val = JSVAL_VOID;
     return rc;
   }
   
   // Set the value
   VXIjsiResult Set (jsval v) {
     VXIjsiResult rc = Clear( );
     val = v;
     if (( JSVAL_IS_GCTHING(val) ) &&
   ( ! JS_AddNamedRoot (context, &val, PROTECTED_JSVAL_NAME) )){
       rc = VXIjsi_RESULT_OUT_OF_MEMORY; // blown away by GC already!
     }
     return rc;
   }
 
   // Accessor
   const jsval Get( ) const { return val; }
 
  private:
   // Disabled copy constructor and assignment operator
   JsiProtectedJsval (const JsiProtectedJsval &v);
   JsiProtectedJsval &operator=(const JsiProtectedJsval &v);
 
  private:
   JSContext  *context;
   jsval      val;
 };
 
 
 // -----1=0-------2=0-------3=0-------4=0-------5=0-------6=0-------7=0-------8
 
 
 // Scope chain class, used to keep the scope chain independantly of
 // the actual user visible scope chain to avoid crashes from invalid
 // or malicious scripts (push a scope called "session", then overwrite
 // that variable with an integer named "session", then try to do more
 // work in that scope)
 class JsiScopeChainNode {
  public:
   // Constructor and destructor
   JsiScopeChainNode (JSContext *context, JsiScopeChainNode *p, 
          const VXIchar *n) :
     pushAliasFlag(false), name(n), parent(p), child(NULL), jsVal(context) { }
   ~JsiScopeChainNode( ) { }
 
   // Creation method
   VXIjsiResult Create (JSObject *scopeObj) { 
     return jsVal.Set (OBJECT_TO_JSVAL(scopeObj)); }
 
   // Accessors
   const SBjsiString & GetName( )   const { return name; }
   jsval                GetJsval( )  { return jsVal.Get( ); }
   JSObject           * GetJsobj( )  { return JSVAL_TO_OBJECT(jsVal.Get( )); }
   JsiScopeChainNode  * GetParent( ) { return parent; }
   JsiScopeChainNode  * GetChild( )  { return child; }
 
   // Set the child scope
   void SetChild (JsiScopeChainNode *c) { child = c; }
 
   // Release this scope and all under it
   VXIjsiResult Release( );
   
   // Alias functions
   VXIjsiResult PushAlias(JsiScopeChainNode *_alias) 
   { 
     VXIjsiResult rc = VXIjsi_RESULT_SUCCESS;
     if( _alias )
     {
       aliasList.push_front(_alias);
     }
     else
       rc = VXIjsi_RESULT_FAILURE;
     return rc;
   } 
   
   JsiScopeChainNode* PopAlias(void) 
   {
     JsiScopeChainNode *a = NULL;
     if( !aliasList.empty() )
     {
       a = aliasList.front();
       aliasList.pop_front();  
     }
     return a;
   }
   bool HasAlias(void) { return !aliasList.empty(); }
   const SBjsiString & GetAliasName(void) const
   {
     if( !aliasList.empty() )
       return aliasList.front()->GetName();
     return GetName();
   }
   
   void SetAliasScopeFlag(void) { pushAliasFlag = true; }
   bool IsSetAliasScopeFlag(void) { return pushAliasFlag; }
   void ResetAliasScopeFlag(void) { pushAliasFlag = false; }
   
  private:
   SBjsiString        name;      // Name of this scope
   JsiScopeChainNode  *parent;    // Parent scope
   JsiScopeChainNode  *child;     // Child scope, may be NULL
   JsiProtectedJsval   jsVal;     // JS object for the scope
   // alias list
   std::deque<JsiScopeChainNode*> aliasList;
   bool               pushAliasFlag;
 };
 
 
 VXIjsiResult JsiScopeChainNode::Release( )
 {
   JsiScopeChainNode *node = this, *next = NULL, *alias = NULL;
   while (node) {
     // if node is an alias, just pop the alias and continue
     if( node->HasAlias() )
     {
       alias = node->PopAlias();
       if( alias ) alias->jsVal.Clear( );
       continue;
     }
     // Release the lock on the underlying object
     node->jsVal.Clear( );
 
     // Clear pointers for safety and advance to child scopes
     next = node->child;
     node->parent = NULL;
     node->child = NULL;
     node = next;
 
     // NOTE: the deletion of this node and the child nodes is handled
     // by the ScopeFinalize( ) method that is called when the JS
     // object is garbage collected
   }
 
   return VXIjsi_RESULT_SUCCESS;
 }
 
 
 // To support VXML 2.0 SPEC, that added the read-only attribute to a namespace.
 // Therefore any attempt to modify, create any variable in this namespace will result
 // in java script semantic error.  This is the callback that will be called
 // every time set property function is called.  It will check for read-only flag
 // of the current scope to determine if it is read-only, if so return false.
 JSBool JsiContext::SCOPE_CLASS_SetProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
 {
   uintN attrp;
   JSBool foundp;
   JsiScopeChainNode * prdata = (JsiScopeChainNode *) JS_GetPrivate(cx, obj);
   if( prdata )
   {
     // return true, if pushing alias scope
     if (prdata->IsSetAliasScopeFlag() )
       return JS_TRUE;
     GET_JSCHAR_FROM_VXICHAR(tmpname, tmpnamelen, prdata->GetName().c_str());
     JSObject *pobj = (prdata->GetParent() ? prdata->GetParent()->GetJsobj() : prdata->GetJsobj());
     if( JS_GetUCPropertyAttributes(cx, pobj,
                            tmpname, tmpnamelen,
                            &attrp, &foundp) )
     {
       if( foundp && (attrp & JSPROP_READONLY) )
       {
         return JS_FALSE;
       }
     }
   }
   return JS_TRUE;
 }
 
 VXIjsiResult JsiContext::CheckWriteable(JSContext *cx, JSObject *obj, const VXIchar* varname)
 {
   VXIjsiResult rc = VXIjsi_RESULT_SUCCESS;
   uintN attrp;
   JSBool foundp;
   JsiScopeChainNode * prdata = (JsiScopeChainNode *) JS_GetPrivate(cx, obj);
   // evaluate var name to get the root, i.e a.b.c, then the root is a
   // if there is no root i.e, a then we don't need to evaluate
   if( wcschr (varname, L'.') )
   {
     //VXIchar* rootvar, *state = NULL;
     VXIchar* rootvar = NULL;
     VXIchar _varname[1024];
     wcscpy(_varname, varname);
 #ifdef WIN32
     rootvar = wcstok(_varname, L".");
 #else
     rootvar = wcstok(_varname, L".", &state);
 #endif
     if( rootvar )
     {
       JsiProtectedJsval val (context);
       VXIjsiResult rc = EvaluateScript (rootvar, &val);
       JSObject *classobj = JSVAL_TO_OBJECT(val.Get());
       // if this object is scope class then get the private data,
       // otherwise just ignore it
       if( rc == VXIjsi_RESULT_SUCCESS && JS_InstanceOf (cx, classobj, &SCOPE_CLASS, NULL) )
       {
         prdata = (JsiScopeChainNode *) JS_GetPrivate(cx, classobj);
       }
       val.Clear( );
     }
   }    
   
   if( prdata )
   {
     // get scope from the current parent
     JSObject* pscope = (prdata->GetParent() ? prdata->GetParent()->GetJsobj() : prdata->GetJsobj());
 
     // retrieve read-only attribute 
     GET_JSCHAR_FROM_VXICHAR(tmpname, tmpnamelen, prdata->GetName().c_str());
     if( JS_GetUCPropertyAttributes(cx, pscope,
                            tmpname, tmpnamelen,
                            &attrp, &foundp) )
     {
       if( foundp && (attrp & JSPROP_READONLY) )
       {
         return rc = VXIjsi_RESULT_NON_FATAL_ERROR;
       }
     }
   }
   return rc;
 }
 
 // -----1=0-------2=0-------3=0-------4=0-------5=0-------6=0-------7=0-------8
 
 
 // Constructor, only does initialization that cannot fail
 JsiContext::JsiContext( ) : SBjsiLogger (MODULE_SBJSI, NULL, 0),
   version(JSVERSION_DEFAULT), runtime(NULL), context(NULL),
   contextRefs(0), scopeChain(NULL), currentScope(NULL), logEnabled(true),
   maxBranches(0L), numBranches(0L), exception(NULL)
 {
 }
 
 
 // Destructor
 JsiContext::~JsiContext( )
 {
   Diag (SBJSI_LOG_CONTEXT, L"JsiContext::~JsiContext", 
   L"start 0x%p, JS context 0x%p", this, context);
     
   if ( exception )
     VXIValueDestroy (&exception);
 
   if ( context ) {
     // Lock the context for access
 #ifdef JS_THREADSAFE
     JS_ResumeRequest (context, contextRefs);
 #else
     if ( ! AccessBegin( ) )
       return;
 #endif
 
     // Destroy the scope chain, which automatically unroots the global
     // scope to allow garbage collection of everything
     if ( scopeChain )
       scopeChain->Release( );
 
     // Release the lock, must be done before destroying the context
 #ifdef JS_THREADSAFE
     JS_EndRequest (context);
 #else
     AccessEnd( );
 #endif
 
     // Destroy the context, is set to NULL
     runtime->DestroyContext (&context);
   }
 
   Diag (SBJSI_LOG_CONTEXT, L"JsiContext::~JsiContext", L"end 0x%p", this);
 }
 
 
 // Creation method
 VXIjsiResult JsiContext::Create (JsiRuntime        *rt, 
          long               contextSize, 
          long               mb,
          VXIlogInterface   *l,
          VXIunsigned        diagTagBase)
 {
   if (( rt == NULL ) || ( contextSize < 1 ) || ( mb < 1 ) ||
       ( l == NULL ))
     return VXIjsi_RESULT_INVALID_ARGUMENT;
 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -