Пример #1
0
static bool respond_to_p(JSContext* js_context, JSObject* obj, char* name)
{
  VALUE ruby_context = (VALUE)JS_GetContextPrivate(js_context);

  JohnsonContext* context;
  Data_Get_Struct(ruby_context, JohnsonContext, context);

  VALUE self = (VALUE)JS_GetInstancePrivate(
    context->js, obj, JS_GET_CLASS(context->js, obj), NULL);

  if (!self) return false;

  return autovivified_p(ruby_context, self, name)
    || const_p(self, name)
    || global_p(name)
    || attribute_p(self, name)
    || method_p(self, name)
    || has_key_p(self, name);
}
Пример #2
0
/*
 * local function to read an expression
 */
static LVAL _readexpr(tpLspObject pLSP,FILE *f)
{
   int ch,ch1,ch2,i;
   LVAL p;
   char *s;
   double dval;
   long lval;


   spaceat(ch,f);
   if( ch == EOF )
   {
      return NIL;
   }
   if( ch == pLSP->cClose )
   {
      return NIL;
   }

   if( ch == pLSP->cOpen )/* Read a cons node. */
      return readcons(pLSP,f);

   /**** Note: XLISP allows 1E++10 as a symbol. This is dangerous.
         We do not change XLISP (so far), but here I exclude all symbol
         names starting with numeral. */
   if( const_p1(ch) )/* Read a symbol. */
   {
      for( i = 0 ; const_p(ch) ; i++ ){
        if( storech(pLSP,i,ch) )return NIL;
        ch = getC(pLSP,f);
        }
      UNGETC(ch);
      /* Recognize NIL and nil symbols. */
      if( !strcmp(BUFFER,"NIL") || !strcmp(BUFFER,"nil") )
         return NIL;
      p = newsymbol();
      s = StrDup( BUFFER );
      if( null(p) || s == NULL )return NIL;
      setsymbol(p,s);
      return p;
   }
   if( ch == '\"' ){
     ch = GETC(f);
     storech(pLSP,0,0); /* inititalize the buffer */
     if( ch != '\"' )goto SimpleString;
     ch = GETC(f);
     if( ch != '\"' ){
       UNGETC(ch);
       ch = '\"';/* ch should hold the first character of the string that is " now */
       goto SimpleString;
       }
     ch = GETC(f);     
     /* multi line string */
     for( i = 0 ; ch != EOF ; i++ ){
       if( ch == '\"' ){
         ch1 = GETC(f);
         ch2 = GETC(f);
         if( ch1 == '\"' && ch2 == '\"' )break;
         UNGETC(ch2);
         UNGETC(ch1);
         }
       if( ch == '\\' ){
         ch = GETC(f);
         s = escapers;
         while( *s ){
           if( *s++ == ch ){
             ch = *s;
             break;
             }
           if( *s )s++;
           }
         }
       if( storech(pLSP,i,ch) )return NIL;
       ch = GETC(f);
       }
     p = newstring();
     s = StrDup( BUFFER );
     if( null(p) || s == NULL )return NIL;
     setstring(p,s);
     return p;
     }

   if( ch == '\"' ){/* Read a string. */
     ch = GETC(f);/* Eat the " character. */
SimpleString:
     for( i = 0 ; ch != '\"' && ch != EOF ; i++ ){
       if( ch == '\\' ){
         ch = GETC(f);
         s = escapers;
         while( *s ){
           if( *s++ == ch ){
             ch = *s;
             break;
             }
           if( *s )s++;
           }
         }
       if( ch == '\n' )return NIL;
       if( storech(pLSP,i,ch) )return NIL;
       ch = GETC(f);
       }
      p = newstring();
      s = StrDup( BUFFER );
      if( null(p) || s == NULL )
      {
         return NIL;
      }
      setstring(p,s);
      return p;
   }
   if( numeral1(ch) )
   {
      for( i = 0 ; isinset(ch,"0123456789+-eE.") ; i++ )
      {
         if( storech(pLSP,i,ch) )return NIL;
         ch = getC(pLSP,f);
      }
      UNGETC(ch);
      cnumeric(BUFFER,&i,&dval,&lval);
      switch( i )
      {
      case 0:
         return NIL;
      case 1:
         /* A float number is coming. */
         p = newfloat();
         if( null(p) )
         {
            return NIL;
         }
         setfloat(p,dval);
         return p;
      case 2:
         /* An integer is coming. */
         p = newint();
         if( null(p) )
         {
            return NIL;
         }
         setint(p,lval);
         return p;
      default:
         return NIL;
      }
   }
   return NIL;
}
Пример #3
0
static JSBool get(JSContext* js_context, JSObject* obj, jsval id, jsval* retval)
{
  // pull out our Ruby context, which is embedded in js_context
  
  VALUE ruby_context = (VALUE)JS_GetContextPrivate(js_context);
  
  // get our struct, which is embedded in ruby_context
  
  JohnsonContext* context;
  JohnsonRuntime* runtime;
  Data_Get_Struct(ruby_context, JohnsonContext, context);

  VALUE ruby_runtime = (VALUE)JS_GetRuntimePrivate(JS_GetRuntime(js_context));
  Data_Get_Struct(ruby_runtime, JohnsonRuntime, runtime);

  PREPARE_JROOTS(js_context, 1);
  JROOT(id);
    
  // get the Ruby object that backs this proxy
  
  VALUE self = (VALUE)JS_GetInstancePrivate(context->js, obj, JS_GET_CLASS(context->js, obj), NULL);
  
  // Short-circuit for numeric indexes
  
  if (JSVAL_IS_INT(id))
  {
    if (indexable_p(self)) {
      VALUE idx = INT2FIX(JSVAL_TO_INT(id));
      JCHECK(call_ruby_from_js(runtime, retval, self, rb_intern("[]"), 1, idx));
    }
    
    JRETURN;
  }
  
  char* name = JS_GetStringBytes(JSVAL_TO_STRING(id));
  VALUE ruby_id = rb_intern(name);

  // FIXME: we should probably just JS_DefineProperty this, and it shouldn't be enumerable
  
  if (!strcasecmp("__iterator__", name)) {
    JCHECK(evaluate_js_property_expression(runtime, "Johnson.Generator.create", retval));
  }
  
  // if the Ruby object has a dynamic js property with a key
  // matching the property we're looking for, pull the value out of
  // that map.
  
  else if (autovivified_p(ruby_context, self, name))
  {
    JCHECK(call_ruby_from_js(runtime, retval, Johnson_SpiderMonkey_JSLandProxy(),
      rb_intern("autovivified"), 2, self, rb_str_new2(name)));
  }

  // if the Ruby object is a Module or Class and has a matching
  // const defined, return the converted result of const_get
  
  else if (const_p(self, name))
  {
    JCHECK(call_ruby_from_js(runtime, retval, self, rb_intern("const_get"),
      1, ID2SYM(ruby_id)));
  }  

  // otherwise, if it's a global, return the global
  else if (global_p(name))
  {
    JCHECK(convert_to_js(runtime, rb_gv_get(name), retval));
  }
  
  // otherwise, if the Ruby object has a an attribute method matching
  // the property we're trying to get, call it and return the converted result
  
  else if (attribute_p(self, name))
  {
    JCHECK(call_ruby_from_js(runtime, retval, self, ruby_id, 0));
  }

  // otherwise, if the Ruby object quacks sorta like a hash (it responds to
  // "[]" and "key?"), index it by key and return the converted result
  
  else if (has_key_p(self, name))
  {
    JCHECK(call_ruby_from_js(runtime, retval, self, rb_intern("[]"), 1, rb_str_new2(name)));
  }
  
  // otherwise, it's a method being accessed as a property, which means
  // we need to return a lambda
  
  // FIXME: this should really wrap the Method  for 'name' in a JS class
  // rather than generating a wrapper Proc
  
  else if (method_p(self, name))
  {
    JCHECK(call_ruby_from_js(runtime, retval, self, rb_intern("method"), 1, rb_str_new2(name)));
  }

  // else it's undefined (JS_VOID) by default
  JRETURN;
}