gnash-commit
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Gnash-commit] gnash ChangeLog doc/C/internals.xml


From: strk
Subject: Re: [Gnash-commit] gnash ChangeLog doc/C/internals.xml
Date: Mon, 5 Mar 2007 23:39:31 +0100

On Mon, Mar 05, 2007 at 09:35:27PM +0000, Ann Barcomb wrote:

>               virtual bool get_member(const tu_stringi& name, as_value* 
> val) {
>                   if ((name == "firstChild") || (name == "childNodes")) {
> -                     val->set_as_object_interface(this);
> +                     val->set_as_object(this);
>                       return true;
>                   }

We now have the concept of getter/setter members, which allows us to *not*
override get_member and set_member. Not overriding them has the advantage of
automatically getting case conversion and inheritance crawling for free.
Ideally, I'd make get_member/set_member non-virtual functions of as_object
to completely disable overriding them.

Example of use for the gettersetter can be found in Sound.cpp, LoadVars.cpp,
xmlnode.cpp and other files.
Our gen-files.sh script does NOT output any getter/setter because it's input
file (docs/C/NOTES) doesn't distinguish between methods and properties.

One thing which is still uncertail is wheter properties should be set
in the class exported interface (get<classname>Iterface) or attached
to *instances* of that class. Currently both work fine, and an example
of split is found in sprite_instance.cpp.


> +                // Register _global.String
> +                global.init_member("XML", cl.get());

A typo: "// Register _global.XML"
 
> +       main one of interest is <emphasis>is_function</emphasis>, 
> +          <emphasis>is_as_function</emphasis>, 
> <emphasis>is_string</emphasis>,
> +          and so on.  A list of these methods, which indicate if a argument
> +          is of a specified type, can be found in 
> +          <emphasis>as_value.h</emphasis>.  
>         <programlisting>
> -       if (fn.env->top(0).get_type() == as_value::STRING) {
> +       if (fn.env->top(0).is_string()) {
>            ...
>         }
>         </programlisting>
> +          Another option is to use <emphasis>typeOf</emphasis>, which will
> +          return a string describing the argument type.

I'd discourage anyone from using as_value::typeOf().  That function
is specifically there to implement a TYPOF ActionScript expression.
Also, sometime an ActionScript class method only want a specific type, in
that case it can call the as_value::to<type> method directly, and check
that the return is valid. This is because there are automatic type conversions.
Like, if a function wants a number, but it has given the string "10", 
is_number()
will return false, but to_number() will return 10.


>       <para>
>         The supported data types for an object are
> +          <emphasis>NULLTYPE</emphasis>
>         <emphasis>BOOLEAN</emphasis>, <emphasis>STRING</emphasis>,
>         <emphasis>NUMBER</emphasis>, <emphasis>OBJECT</emphasis>,
> -       <emphasis>C_FUNCTION</emphasis>, <emphasis>AS_FUNCTION</emphasis>.  
> Because
> +       <emphasis>C_FUNCTION</emphasis>, <emphasis>AS_FUNCTION</emphasis>,

I'd add that C_FUNCTION is being deprecated for as_value.

>       <para>
>         To add methods to the class, a new class needs to be
> +       instantiated as an object.  Each ActionScript object can
> +          have child methods, which are attached to the object in a
> +          manner similar to how the object itself is initialized using
> +          <emphasis>init_member</emphasis>.

What ? :)

>         <programlisting>
>           xml_obj = new xml_as_object;
> -         xml_obj->set_member("load", &amp;xml_load);
> +            xml_obj->init_member("load", new builtin_function(xml_load));
>         </programlisting>  
>       </para>

The only reason ti add members to *instances* rather then to the class itself
is for attaching getter/setter properties, if we find out that's the way to go.
In this case, yes, the <class>_ctor will need to attach a set of properties, 
which is better done with a separate function, see attachMovieClipProperties
in sprite_instance.cpp. (I've just  seen it's not even used, btw).

>         <programlisting>
>           void
> -         xml_new(const fn_call&amp; fn) {
> +            xml_new(const fn_call&amp; fn)
> +            {
>               as_value      inum;
> -             xml_as_object *xml_obj;
> +                XML *xml_obj;
>           
>               if (fn.nargs > 0) {
> -                 if (fn.env->top(0).get_type() == as_value::STRING) {
> -                     xml_obj = new xml_as_object;
> +                    as_object* obj = fn.env->top(0).to_object();

Use fn.arg(0), not fn.env->top(0) !

> +                    if (! obj ) {
> +                        xml_obj = new XML;
>                       tu_string datain = fn.env->top(0).to_tu_string();
> -                     xml_obj->obj.parseXML(datain);
> -                     xml_obj->obj.setupFrame(xml_obj, 
> xml_obj->obj.firstChild(), true);
> +                        xml_obj->parseXML(datain);
> +                        xml_obj->setupFrame(xml_obj, xml_obj->firstChild(), 
> true);
>                   } else {
> -                     xml_as_object *xml_obj = 
> (xml_as_object*)fn.env->top(0).to_object();
> -                     fn.result->set_as_object_interface(xml_obj);
> +                        assert(dynamic_cast&lt;XML*&gt;(obj));

Don't assert, or new XML(new Date) will abort Gnash.
Rather, check as you did after .to_object() above.


> +                        XML*        xml_obj = (XML*)obj;
> +                        fn.result->set_as_object(xml_obj);
>                       return;
>                   }
>               } else {
> -                 xml_obj = new xml_as_object;
> -                 xml_obj->set_member("load", &amp;xml_load);
> -                 xml_obj->set_member("loaded", &amp;xml_loaded);
> +                    xml_obj = new XML;
>               }
> -             fn.result->set_as_object_interface(xml_obj);
> +            
> +                fn.result->set_as_object(xml_obj);
>           }
> +
>         </programlisting>
>       </para>

Maybe XML was not the better example to put in the manual :)


>         <programlisting>
> -         xml_as_object *xml_obj = (xml_as_object*)fn.this_ptr;
> +         xml_as_object *xml_obj = static_cast &lt; xml_as_object* &gt; 
> (fn.this_ptr);

These are both bad. And both doing the same thing, btw.
What we want here is a run-time check.
In the latest versions I took the habit  of using an 'type* 
ensureType(as_object* obj)'
function to take care of checking and eventually raise an exception.
Calling *any* function with an unexpected 'this' pointer is *always* an invalid
call and ActionException is cought at appropriate places to simply make the
function return 'undefined.
See for example array.cpp, or string.cpp.

>           if (fn.nargs) {
> -             filespec = fn.env->bottom(fn.first_arg_bottom_index).to_string;
> +             filespec = 
> fn.env->bottom(fn.first_arg_bottom_index).to_string();

Hard to read (still XML ?) but I belive it means fn.arg(0).to_string();

...

I'm happy you started, as it's still a lot of work to do ;)

--strk;




reply via email to

[Prev in Thread] Current Thread [Next in Thread]