1 // Global.cpp: Global ActionScript class setup, for Gnash.
3 // Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010,
4 // 2011 Free Software Foundation, Inc
6 // This program is free software; you can redistribute it and/or modify
7 // it under the terms of the GNU General Public License as published by
8 // the Free Software Foundation; either version 3 of the License, or
9 // (at your option) any later version.
11 // This program is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
16 // You should have received a copy of the GNU General Public License
17 // along with this program; if not, write to the Free Software
18 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 #include "gnashconfig.h"
25 #include "Global_as.h"
30 #include <boost/lexical_cast.hpp>
31 #include <boost/assign/list_of.hpp>
33 #include "as_object.h"
34 #include "builtin_function.h"
35 #include "movie_root.h"
36 #include "PropFlags.h"
38 #include "as_function.h"
39 #include "NativeFunction.h"
40 #include "AsBroadcaster.h"
41 #include "Boolean_as.h"
46 #include "String_as.h"
47 #include "Selection_as.h"
48 #include "Number_as.h"
50 #include "Accessibility_as.h"
51 #include "ContextMenu_as.h"
52 #include "ContextMenuItem_as.h"
55 #include "Microphone_as.h"
57 #include "Camera_as.h"
59 #include "MovieClip_as.h"
60 #include "Function_as.h"
61 #include "flash/display/BitmapData_as.h"
62 #include "flash/filters/BitmapFilter_as.h"
63 #include "flash/geom/ColorTransform_as.h"
64 #include "LocalConnection_as.h"
65 #include "XMLSocket_as.h"
66 #include "SharedObject_as.h"
67 #include "NetConnection_as.h"
68 #include "NetStream_as.h"
69 #include "System_as.h"
70 #include "TextSnapshot_as.h"
71 #include "TextField_as.h"
72 #include "TextFormat_as.h"
73 #include "flash/text/TextRenderer_as.h"
75 #include "XMLNode_as.h"
76 #include "flash/external/ExternalInterface_as.h"
77 #include "MovieClipLoader.h"
78 #include "movie_definition.h"
80 #include "extension.h"
85 #include "ClassHierarchy.h"
86 #include "namedStrings.h"
87 #include "GnashNumeric.h" // for isfinite replacement
88 #include "flash_pkg.h"
91 #include "LoadVars_as.h"
93 #include "LoadableObject.h"
95 // Common code to warn and return if a required single arg is not present
96 // and to warn if there are extra args.
97 #define ASSERT_FN_ARGS_IS_1 \
99 IF_VERBOSE_ASCODING_ERRORS( \
100 log_aserror(_("%s needs one argument"), __FUNCTION__); \
104 IF_VERBOSE_ASCODING_ERRORS( \
106 log_aserror(_("%s has more than one argument"), __FUNCTION__); \
113 const ClassHierarchy::NativeClasses
& avm1Classes();
115 as_value
global_trace(const fn_call
& fn
);
116 as_value
global_isNaN(const fn_call
& fn
);
117 as_value
global_isfinite(const fn_call
& fn
);
118 as_value
global_unescape(const fn_call
& fn
);
119 as_value
global_escape(const fn_call
& fn
);
120 as_value
global_parsefloat(const fn_call
& fn
);
121 as_value
global_parseint(const fn_call
& fn
);
122 as_value
global_assetpropflags(const fn_call
& fn
);
123 as_value
global_assetuperror(const fn_call
& fn
);
124 as_value
global_asnative(const fn_call
& fn
);
125 as_value
global_asnew(const fn_call
& fn
);
126 as_value
global_assetnative(const fn_call
& fn
);
127 as_value
global_assetnativeaccessor(const fn_call
& fn
);
128 as_value
global_asconstructor(const fn_call
& fn
);
129 as_value
global_updateAfterEvent(const fn_call
& fn
);
130 as_value
global_setTimeout(const fn_call
& fn
);
131 as_value
global_clearInterval(const fn_call
& fn
);
132 as_value
global_setInterval(const fn_call
& fn
);
134 // These are present in the standalone, not sure about the plugin.
135 as_value
global_enableDebugConsole(const fn_call
& fn
);
136 as_value
global_showRedrawRegions(const fn_call
& fn
);
138 // This is a help function for the silly AsSetupError function.
139 as_value
local_errorConstructor(const fn_call
& fn
);
141 void registerNatives(as_object
& global
);
144 Global_as::Global_as(VM
& vm
)
147 _et(new Extension()),
148 _classes(this, _et
.get()),
149 _objectProto(new as_object(*this))
153 Global_as::~Global_as()
158 Global_as::createFunction(Global_as::ASFunction function
)
160 as_object
* proto
= createObject(*this);
161 builtin_function
* f
= new builtin_function(*this, function
);
163 proto
->init_member(NSV::PROP_CONSTRUCTOR
, f
);
165 f
->init_member(NSV::PROP_PROTOTYPE
, proto
);
168 gnash::getOwnProperty(*this, NSV::CLASS_FUNCTION
).to_function();
170 const int flags
= as_object::DefaultFlags
| PropFlags::onlySWF6Up
;
171 f
->init_member(NSV::PROP_uuPROTOuu
, getMember(*fun
,
172 NSV::PROP_PROTOTYPE
), flags
);
173 f
->init_member(NSV::PROP_CONSTRUCTOR
, fun
);
179 Global_as::createClass(Global_as::ASFunction ctor
, as_object
* prototype
)
181 as_object
* cl
= new builtin_function(*this, ctor
);
184 prototype
->init_member(NSV::PROP_CONSTRUCTOR
, cl
);
185 cl
->init_member(NSV::PROP_PROTOTYPE
, prototype
);
188 gnash::getOwnProperty(*this, NSV::CLASS_FUNCTION
).to_function();
191 const int flags
= as_object::DefaultFlags
| PropFlags::onlySWF6Up
;
192 cl
->init_member(NSV::PROP_uuPROTOuu
, getMember(*fun
,
193 NSV::PROP_PROTOTYPE
), flags
);
194 cl
->init_member(NSV::PROP_CONSTRUCTOR
, fun
);
200 /// Construct an Array.
202 /// This uses the _global Array class to initialize the "constructor" and
203 /// "__proto__" properties. If Array.prototype is undefined, those properties
206 Global_as::createArray()
208 as_object
* array
= new as_object(*this);
210 as_value ctor
= getMember(*this, NSV::CLASS_ARRAY
);
211 as_object
* obj
= toObject(ctor
, gnash::getVM(*this));
214 if (obj
->get_member(NSV::PROP_PROTOTYPE
, &proto
)) {
215 array
->init_member(NSV::PROP_CONSTRUCTOR
, ctor
);
216 array
->set_prototype(getMember(*obj
, NSV::PROP_PROTOTYPE
));
220 array
->init_member(NSV::PROP_LENGTH
, 0.0);
226 Global_as::markReachableResources() const
228 _classes
.markReachableResources();
229 _objectProto
->setReachable();
230 as_object::markReachableResources();
234 Global_as::registerClasses()
236 registerNatives(*this);
238 function_class_init(*this, NSV::CLASS_FUNCTION
);
239 initObjectClass(_objectProto
, *this, NSV::CLASS_OBJECT
);
241 string_class_init(*this, NSV::CLASS_STRING
);
242 array_class_init(*this, NSV::CLASS_ARRAY
);
244 // No idea why, but it seems there's a NULL _global.o
245 // defined at player startup...
246 // Probably due to the AS-based initialization
247 // Not enumerable but overridable and deletable.
249 as_value nullVal
; nullVal
.set_null();
250 init_member("o", nullVal
, PropFlags::dontEnum
);
255 // _global functions.
256 // These functions are only available in SWF6+, but this is just
257 // because SWF5 or lower did not have a "_global"
259 init_member("ASnative", createFunction(global_asnative
));
260 init_member("ASconstructor", createFunction(global_asconstructor
));
261 init_member("ASSetPropFlags", vm
.getNative(1, 0));
262 init_member("ASSetNative", vm
.getNative(4, 0));
263 init_member("ASSetNativeAccessor", vm
.getNative(4, 1));
264 init_member("AsSetupError", createFunction(global_assetuperror
));
265 init_member("updateAfterEvent", vm
.getNative(9, 0));
266 init_member("trace", vm
.getNative(100, 4));
268 init_member("setInterval", vm
.getNative(250, 0));
269 init_member("clearInterval", vm
.getNative(250, 1));
270 init_member("setTimeout", vm
.getNative(250, 2));
272 // This is an odd function with no properties. There ought to be
273 // a better way of implementing this. See also TextFormat.getTextExtent.
274 as_function
* edc
= createFunction(global_enableDebugConsole
);
275 edc
->clearProperties();
276 init_member("enableDebugConsole", edc
);
277 init_member("showRedrawRegions", vm
.getNative(1021, 1));
279 init_member("clearTimeout", getMember(*this, getURI(vm
, "clearInterval")));
281 _classes
.declareAll(avm1Classes());
284 const ObjectURI
& flash
= getURI(vm
, "flash");
285 flash_package_init(*this, flash
);
287 const int version
= vm
.getSWFVersion();
290 // This is surely not correct, but they are not available
292 init_member("escape", vm
.getNative(100, 0));
293 init_member("unescape", vm
.getNative(100, 1));
294 init_member("parseInt", vm
.getNative(100, 2));
295 init_member("parseFloat", vm
.getNative(100, 3));
296 init_member("isNaN", vm
.getNative(200, 18));
297 init_member("isFinite", vm
.getNative(200, 19));
299 init_member("NaN", as_value(NaN
));
300 init_member("Infinity", as_value(
301 std::numeric_limits
<double>::infinity()));
308 createObject(const Global_as
& gl
)
310 as_object
* obj
= new as_object(gl
);
315 //-----------------------
317 //-----------------------
318 // Scan the plugin directories for all plugins, and load them now.
319 // FIXME: this should actually be done dynamically, and only
320 // if a plugin defines a class that a movie actually wants to
323 Global_as::loadExtensions()
325 if (RcInitFile::getDefaultInstance().enableExtensions()) {
326 log_security(_("Extensions enabled, scanning plugin dir for load"));
327 _et
->scanAndLoad(*this);
330 log_security(_("Extensions disabled"));
335 Global_as::makeObject(as_object
& o
) const
337 o
.set_prototype(_objectProto
);
342 const ClassHierarchy::NativeClasses
&
345 typedef ClassHierarchy::NativeClass N
;
347 // Since we maintain separate lists for AVM1 and AVM2, these are all
348 // considered to be in the 'Global' namespace (AVM1 has no namespaces)
349 // An ObjectURI constructed without a namespace is in the global namespace.
350 static const ClassHierarchy::NativeClasses s
= boost::assign::list_of
352 (N(system_class_init
, NSV::CLASS_SYSTEM
, 1))
353 (N(stage_class_init
, NSV::CLASS_STAGE
, 1))
354 (N(movieclip_class_init
, NSV::CLASS_MOVIE_CLIP
, 3))
355 (N(textfield_class_init
, NSV::CLASS_TEXT_FIELD
, 3))
356 (N(math_class_init
, NSV::CLASS_MATH
, 4))
357 (N(boolean_class_init
, NSV::CLASS_BOOLEAN
, 5))
358 (N(button_class_init
, NSV::CLASS_BUTTON
, 5))
359 (N(color_class_init
, NSV::CLASS_COLOR
, 5))
360 (N(selection_class_init
, NSV::CLASS_SELECTION
, 5))
361 (N(sound_class_init
, NSV::CLASS_SOUND
, 5))
362 (N(xmlsocket_class_init
, NSV::CLASS_XMLSOCKET
, 5))
363 (N(date_class_init
, NSV::CLASS_DATE
, 5))
364 (N(xmlnode_class_init
, NSV::CLASS_XMLNODE
, 5))
365 (N(xml_class_init
, NSV::CLASS_XML
, 5))
366 (N(mouse_class_init
, NSV::CLASS_MOUSE
, 5))
367 (N(number_class_init
, NSV::CLASS_NUMBER
, 5))
368 (N(textformat_class_init
, NSV::CLASS_TEXT_FORMAT
, 5))
369 (N(key_class_init
, NSV::CLASS_KEY
, 5))
370 (N(AsBroadcaster::init
, NSV::CLASS_AS_BROADCASTER
, 5))
371 (N(textsnapshot_class_init
, NSV::CLASS_TEXT_SNAPSHOT
, 5))
372 (N(video_class_init
, NSV::CLASS_VIDEO
, 6))
373 (N(camera_class_init
, NSV::CLASS_CAMERA
, 5))
374 (N(microphone_class_init
, NSV::CLASS_MICROPHONE
, 5))
375 (N(sharedobject_class_init
, NSV::CLASS_SHARED_OBJECT
, 5))
376 (N(loadvars_class_init
, NSV::CLASS_LOAD_VARS
, 5))
377 (N(localconnection_class_init
, NSV::CLASS_LOCALCONNECTION
, 6))
378 (N(netconnection_class_init
, NSV::CLASS_NET_CONNECTION
, 6))
379 (N(netstream_class_init
, NSV::CLASS_NET_STREAM
, 6))
380 (N(contextmenu_class_init
, NSV::CLASS_CONTEXTMENU
, 5))
381 (N(contextmenuitem_class_init
, NSV::CLASS_CONTEXTMENUITEM
, 5))
382 (N(moviecliploader_class_init
, NSV::CLASS_MOVIE_CLIP_LOADER
, 5))
383 (N(Error_class_init
, NSV::CLASS_ERROR
, 5))
384 (N(accessibility_class_init
, NSV::CLASS_ACCESSIBILITY
, 5));
390 global_trace(const fn_call
& fn
)
396 // @@ what if we get extra args?
398 // @@ Nothing needs special treatment,
399 // as_value::to_string() will take care of everything
400 log_trace("%s", fn
.arg(0).to_string());
407 global_isNaN(const fn_call
& fn
)
411 return as_value(static_cast<bool>(isNaN(
412 toNumber(fn
.arg(0), getVM(fn
)))));
417 global_isfinite(const fn_call
& fn
)
421 return as_value(static_cast<bool>(isFinite(
422 toNumber(fn
.arg(0), getVM(fn
)))));
425 /// \brief Encode a string to URL-encoded format
426 /// converting all dodgy DisplayObjects to %AB hex sequences
428 /// Characters that need escaping are:
429 /// - ASCII control DisplayObjects: 0-31 and 127
430 /// - Non-ASCII chars: 128-255
431 /// - URL syntax DisplayObjects: $ & + , / : ; = ? @
432 /// - Unsafe DisplayObjects: SPACE " < > # % { } | \ ^ ~ [ ] `
433 /// Encoding is a % followed by two hexadecimal DisplayObjects, case insensitive.
434 /// See RFC1738 http://www.rfc-editor.org/rfc/rfc1738.txt,
435 /// Section 2.2 "URL Character Encoding Issues"
437 global_escape(const fn_call
& fn
)
441 std::string input
= fn
.arg(0).to_string();
443 return as_value(input
);
446 /// \brief Decode a string from URL-encoded format
447 /// converting all hexadecimal sequences to ASCII DisplayObjects.
449 /// A sequence to convert is % followed by two case-independent hexadecimal
450 /// digits, which is replaced by the equivalent ASCII DisplayObject.
451 /// See RFC1738 http://www.rfc-editor.org/rfc/rfc1738.txt,
452 /// Section 2.2 "URL Character Encoding Issues"
454 global_unescape(const fn_call
& fn
)
458 std::string input
= fn
.arg(0).to_string();
460 return as_value(input
);
463 // parseFloat (string)
465 global_parsefloat(const fn_call
& fn
)
469 std::istringstream
s(fn
.arg(0).to_string());
472 if (!(s
>> result
)) {
473 return as_value(NaN
);
476 return as_value(result
);
479 // parseInt(string[, base])
480 // The second argument, if supplied, is the base.
481 // If none is supplied, we have to work out the
482 // base from the string. Decimal, octal and hexadecimal are
483 // possible, according to the following rules:
484 // 1. If the string starts with 0x or 0X, the number is hex.
485 // 2. The 0x or 0X may be *followed* by '-' or '+' to indicate sign. A number
486 // with no sign is positive.
487 // 3. If the string starts with 0, -0 or +0 and contains only the DisplayObjects
489 // 4. If the string starts with *any* other sequence of DisplayObjects, including
490 // whitespace, it is decimal.
492 global_parseint(const fn_call
& fn
)
495 IF_VERBOSE_ASCODING_ERRORS(
496 log_aserror(_("%s needs at least one argument"), __FUNCTION__
);
501 IF_VERBOSE_ASCODING_ERRORS(
503 log_aserror(_("%s has more than two arguments"), __FUNCTION__
);
507 const std::string
& expr
= fn
.arg(0).to_string();
509 // A second argument specifies the base.
510 // Parsing still starts after any positive/negative
511 // sign or hex identifier (parseInt("0x123", 8) gives
512 // 83, not 0; parseInt(" 0x123", 8) is 0), which is
513 // why we do this here.
516 base
= toInt(fn
.arg(1), getVM(fn
));
518 // Bases from 2 to 36 are valid, otherwise return NaN
519 if (base
< 2 || base
> 36) return as_value(NaN
);
522 /// No radix specified, so try parsing as octal or hexadecimal
525 if (parseNonDecimalInt(expr
, d
, false)) return d
;
527 catch (const boost::bad_lexical_cast
&) {
528 return as_value(NaN
);
531 /// The number is not hex or octal, so we'll assume it's base-10.
536 std::string::const_iterator it
= expr
.begin();
538 // Check for expectional case "-0x" or "+0x", which
540 if ((expr
.length() > 2) && (*it
== '-' || *it
== '+') &&
541 *(it
+ 1) == '0' && std::toupper(*(it
+ 2)) == 'X') {
542 return as_value(NaN
);
545 // Try hexadecimal first
546 if (expr
.substr(0, 2) == "0x" || expr
.substr(0, 2) == "0X") it
+= 2;
548 // Skip leading whitespace
549 while(*it
== ' ' || *it
== '\n' || *it
== '\t' || *it
== '\r') {
552 if (it
== expr
.end()) return as_value(NaN
);
555 bool negative
= false;
556 if (*it
== '-' || *it
== '+') {
557 if (*it
== '-') negative
= true;
560 if (it
== expr
.end()) return as_value(NaN
);
563 // Now we have the base, parse the digits. The iterator should
564 // be pointing at the first digit.
566 const std::string digits
= "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
568 // Check to see if the first digit is valid, otherwise
570 std::string::size_type digit
= digits
.find(toupper(*it
));
572 if (digit
>= base
|| digit
== std::string::npos
) return as_value(NaN
);
574 // The first digit was valid, so continue from the present position
575 // until we reach the end of the string or an invalid DisplayObject,
576 // adding valid DisplayObjects to our result.
577 // Which DisplayObjects are invalid depends on the base.
578 double result
= digit
;
581 while (it
!= expr
.end() && (digit
= digits
.find(toupper(*it
))) < base
582 && digit
!= std::string::npos
) {
583 result
= result
* base
+ digit
;
587 // Now return the parsed string as an integer.
588 return negative
? as_value(-result
) : as_value(result
);
591 // ASSetPropFlags function
593 global_assetpropflags(const fn_call
& fn
)
596 IF_VERBOSE_ASCODING_ERRORS(
597 log_aserror(_("%s needs at least three arguments"), __FUNCTION__
);
602 IF_VERBOSE_ASCODING_ERRORS(
604 log_aserror(_("%s has more than four arguments"), "AsSetPropFlags");
609 as_object
* obj
= toObject(fn
.arg(0), getVM(fn
));
611 IF_VERBOSE_ASCODING_ERRORS(
612 log_aserror(_("Invalid call to ASSetPropFlags: "
613 "first argument is not an object: %s"),
619 // list of child names
621 const as_value
& props
= fn
.arg(1);
623 const int flagsMask
= PropFlags::dontEnum
|
624 PropFlags::dontDelete
|
625 PropFlags::readOnly
|
626 PropFlags::onlySWF6Up
|
627 PropFlags::ignoreSWF6
|
628 PropFlags::onlySWF7Up
|
629 PropFlags::onlySWF8Up
|
630 PropFlags::onlySWF9Up
;
632 // a number which represents three bitwise flags which
633 // are used to determine whether the list of child names should be hidden,
634 // un-hidden, protected from over-write, un-protected from over-write,
635 // protected from deletion and un-protected from deletion
636 const int setTrue
= int(toNumber(fn
.arg(2), getVM(fn
))) & flagsMask
;
638 // Is another integer bitmask that works like set_true,
639 // except it sets the attributes to false. The
640 // set_false bitmask is applied before set_true is applied
642 // ASSetPropFlags was exposed in Flash 5, however the fourth argument
643 // 'set_false' was not required as it always defaulted to the value '~0'.
644 const int setFalse
= (fn
.nargs
< 4 ? 0 : toInt(fn
.arg(3), getVM(fn
))) &
647 obj
->setPropFlags(props
, setFalse
, setTrue
);
652 // ASconstructor function
653 // See: http://osflash.org/flashcoders/undocumented/asnative?s=asnative
655 global_asconstructor(const fn_call
& fn
)
658 IF_VERBOSE_ASCODING_ERRORS(
659 std::ostringstream ss
; fn
.dump_args(ss
);
660 log_aserror(_("ASNative(%s): needs at least two arguments"),
666 const int sx
= toInt(fn
.arg(0), getVM(fn
));
667 const int sy
= toInt(fn
.arg(1), getVM(fn
));
669 if (sx
< 0 || sy
< 0) {
670 IF_VERBOSE_ASCODING_ERRORS(
671 std::ostringstream ss
; fn
.dump_args(ss
);
672 log_aserror(_("ASconstructor(%s): args must be 0 or above"),
678 const unsigned int x
= static_cast<unsigned int>(sx
);
679 const unsigned int y
= static_cast<unsigned int>(sy
);
682 as_function
* fun
= vm
.getNative(x
, y
);
684 log_debug(_("No ASnative(%d, %d) registered with the VM"), x
, y
);
688 Global_as
& gl
= getGlobal(fn
);
689 fun
->init_member(NSV::PROP_PROTOTYPE
, createObject(gl
));
691 return as_value(fun
);
696 // See: http://osflash.org/flashcoders/undocumented/asnative?s=asnative
698 global_asnative(const fn_call
& fn
)
701 IF_VERBOSE_ASCODING_ERRORS(
702 std::ostringstream ss
; fn
.dump_args(ss
);
703 log_aserror(_("ASNative(%s): needs at least two arguments"),
709 const int sx
= toInt(fn
.arg(0), getVM(fn
));
710 const int sy
= toInt(fn
.arg(1), getVM(fn
));
712 if (sx
< 0 || sy
< 0) {
713 IF_VERBOSE_ASCODING_ERRORS(
714 std::ostringstream ss
; fn
.dump_args(ss
);
715 log_aserror(_("ASnative(%s): args must be 0 or above"),
721 const unsigned int x
= static_cast<unsigned int>(sx
);
722 const unsigned int y
= static_cast<unsigned int>(sy
);
725 as_function
* fun
= vm
.getNative(x
, y
);
727 log_debug(_("No ASnative(%d, %d) registered with the VM"), x
, y
);
730 return as_value(fun
);
733 // Obsolete ASnew function (exists only as ASnative(2, 0))
735 global_asnew(const fn_call
& /*fn*/)
737 LOG_ONCE(log_unimpl("ASNative (2, 0) - old ASnew"));
741 /// ASSetNative(targetObject, major, properties, minor)
743 /// Sets a series of properties on targetObject using the native table.
744 /// The third argument is generally documented to be an array, but in fact
745 /// it is always converted to a string and parsed.
747 global_assetnative(const fn_call
& fn
)
753 as_object
* targetObject
= toObject(fn
.arg(0), getVM(fn
));
758 const int major
= toInt(fn
.arg(1), getVM(fn
));
759 if (major
< 0) return as_value();
761 const std::string
& props
= fn
.arg(2).to_string();
763 fn
.nargs
> 3 ? std::max
<boost::int32_t>(toInt(fn
.arg(3), getVM(fn
)), 0) : 0;
765 std::string::const_iterator pos
= props
.begin();
771 // pos is always the position after the last located property.
772 while (pos
!= props
.end()) {
774 // If there are no further commas, find the end of the string.
775 std::string::const_iterator comma
= std::find(pos
, props
.end(), ',');
777 const char num
= *pos
;
783 flag
= PropFlags::onlySWF6Up
;
787 flag
= PropFlags::onlySWF7Up
;
791 flag
= PropFlags::onlySWF8Up
;
795 flag
= PropFlags::onlySWF9Up
;
802 const std::string
& property
= std::string(pos
, comma
);
803 if (!property
.empty()) {
804 targetObject
->init_member(property
,
805 vm
.getNative(major
, minor
+ i
), flag
);
807 if (comma
== props
.end()) break;
814 // This is like ASSetNative, but attaches getter/setters.
816 global_assetnativeaccessor(const fn_call
& fn
)
822 as_object
* targetObject
= toObject(fn
.arg(0), getVM(fn
));
827 const int major
= toInt(fn
.arg(1), getVM(fn
));
828 if (major
< 0) return as_value();
830 const std::string
& props
= fn
.arg(2).to_string();
832 fn
.nargs
> 3 ? std::max
<boost::int32_t>(toInt(fn
.arg(3), getVM(fn
)), 0) : 0;
834 std::string::const_iterator pos
= props
.begin();
840 // pos is always the position after the last located property.
841 while (pos
!= props
.end()) {
843 // If there are no further commas, find the end of the string.
844 std::string::const_iterator comma
= std::find(pos
, props
.end(), ',');
846 const char num
= *pos
;
852 flag
= PropFlags::onlySWF6Up
;
856 flag
= PropFlags::onlySWF7Up
;
860 flag
= PropFlags::onlySWF8Up
;
864 flag
= PropFlags::onlySWF9Up
;
871 const std::string
& property
= std::string(pos
, comma
);
872 if (!property
.empty()) {
873 NativeFunction
* getset
= vm
.getNative(major
, minor
+ i
);
874 targetObject
->init_property(property
, *getset
, *getset
, flag
);
876 if (comma
== props
.end()) break;
883 // updateAfterEvent function
885 global_updateAfterEvent(const fn_call
& /*fn*/)
887 LOG_ONCE(log_unimpl("updateAfterEvent()"));
892 local_errorConstructor(const fn_call
& fn
)
894 as_object
* obj
= ensure
<ValidThis
>(fn
);
895 const as_value
& arg
= fn
.nargs
? fn
.arg(0) : as_value();
897 obj
->set_member(getURI(vm
, "message"), arg
);
902 /// Sets a range of Error subclasses.
904 global_assetuperror(const fn_call
& fn
)
906 if (!fn
.nargs
) return as_value();
908 // This should actually call String.split, but since our Array is
909 // wrong we may as well do it like this for now.
910 const std::string
& errors
= fn
.arg(0).to_string();
912 std::string::const_iterator pos
= errors
.begin();
914 Global_as
& gl
= getGlobal(fn
);
916 // pos is always the position after the last located error.
919 // If there are no further commas, find the end of the string.
920 std::string::const_iterator comma
= std::find(pos
, errors
.end(), ',');
922 const std::string
& err
= std::string(pos
, comma
);
926 as_function
* ctor
= getMember(gl
, NSV::CLASS_ERROR
).to_function();
929 as_object
* proto
= constructInstance(*ctor
, fn
.env(), args
);
931 // Not really sure what the point of this is.
932 gl
.createClass(local_errorConstructor
, proto
);
933 proto
->set_member(getURI(vm
, "name"), err
);
934 proto
->set_member(getURI(vm
, "message"), err
);
937 if (comma
== errors
.end()) break;
944 global_setInterval(const fn_call
& fn
)
947 IF_VERBOSE_ASCODING_ERRORS(
948 std::stringstream ss
; fn
.dump_args(ss
);
949 log_aserror("Invalid call to setInterval(%s) "
950 "- need at least 2 arguments",
956 unsigned timer_arg
= 1;
958 as_object
* obj
= toObject(fn
.arg(0), getVM(fn
));
961 IF_VERBOSE_ASCODING_ERRORS(
962 std::stringstream ss
; fn
.dump_args(ss
);
963 log_aserror("Invalid call to setInterval(%s) "
964 "- first argument is not an object or function",
970 ObjectURI methodName
;
972 // Get interval function
973 as_function
* as_func
= obj
->to_function();
975 methodName
= getURI(getVM(fn
), fn
.arg(1).to_string());
980 if (fn
.nargs
< timer_arg
+ 1) {
981 IF_VERBOSE_ASCODING_ERRORS(
982 std::stringstream ss
; fn
.dump_args(ss
);
983 log_aserror("Invalid call to setInterval(%s) "
984 "- missing timeout argument",
992 static_cast<unsigned long>(toNumber(fn
.arg(timer_arg
), getVM(fn
)));
993 // TODO: check validity of interval time number ?
997 for (unsigned i
= timer_arg
+ 1; i
< fn
.nargs
; ++i
) {
1001 std::auto_ptr
<Timer
> timer
;
1003 timer
.reset(new Timer(*as_func
, ms
, fn
.this_ptr
, args
));
1006 timer
.reset(new Timer(obj
, methodName
, ms
, args
));
1009 movie_root
& root
= getRoot(fn
);
1011 // TODO: check what should happen to overflows.
1012 const int id
= root
.addIntervalTimer(timer
);
1013 return as_value(id
);
1017 global_setTimeout(const fn_call
& fn
)
1020 IF_VERBOSE_ASCODING_ERRORS(
1021 std::stringstream ss
; fn
.dump_args(ss
);
1022 log_aserror("Invalid call to setTimeout(%s) "
1023 "- need at least 2 arguments",
1029 unsigned timer_arg
= 1;
1031 as_object
* obj
= toObject(fn
.arg(0), getVM(fn
));
1033 IF_VERBOSE_ASCODING_ERRORS(
1034 std::stringstream ss
; fn
.dump_args(ss
);
1035 log_aserror("Invalid call to setInterval(%s) "
1036 "- first argument is not an object or function",
1042 ObjectURI methodName
;
1044 // Get interval function
1045 as_function
* as_func
= obj
->to_function();
1047 methodName
= getURI(getVM(fn
), fn
.arg(1).to_string());
1052 if (fn
.nargs
< timer_arg
+ 1) {
1053 IF_VERBOSE_ASCODING_ERRORS(
1054 std::stringstream ss
; fn
.dump_args(ss
);
1055 log_aserror("Invalid call to setTimeout(%s): missing "
1056 "timeout argument", ss
.str());
1061 // Get interval time
1063 static_cast<unsigned long>(toNumber(fn
.arg(timer_arg
), getVM(fn
)));
1067 for (unsigned i
= timer_arg
+ 1; i
< fn
.nargs
; ++i
) {
1071 std::auto_ptr
<Timer
> timer
;
1073 timer
.reset(new Timer(*as_func
, ms
, fn
.this_ptr
, args
, true));
1076 timer
.reset(new Timer(obj
, methodName
, ms
, args
, true));
1079 movie_root
& root
= getRoot(fn
);
1081 // TODO: check what should happen to overflows.
1082 const int id
= root
.addIntervalTimer(timer
);
1083 return as_value(id
);
1087 global_clearInterval(const fn_call
& fn
)
1090 IF_VERBOSE_ASCODING_ERRORS(
1091 log_aserror("clearInterval requires one argument, got none");
1096 const boost::uint32_t id
= toInt(fn
.arg(0), getVM(fn
));
1098 movie_root
& root
= getRoot(fn
);
1099 return as_value(root
.clearIntervalTimer(id
));
1103 global_showRedrawRegions(const fn_call
& /*fn*/)
1105 LOG_ONCE(log_unimpl("_global.showRedrawRegions"));
1110 global_enableDebugConsole(const fn_call
& /*fn*/)
1112 LOG_ONCE(log_unimpl("_global.enableDebugConsole"));
1117 registerNatives(as_object
& global
)
1119 VM
& vm
= getVM(global
);
1121 // ASNew was dropped as an API function but exists
1123 vm
.registerNative(global_assetpropflags
, 1, 0);
1124 vm
.registerNative(global_asnew
, 2, 0);
1125 vm
.registerNative(global_assetnative
, 4, 0);
1126 vm
.registerNative(global_assetnativeaccessor
, 4, 1);
1127 vm
.registerNative(global_updateAfterEvent
, 9, 0);
1128 vm
.registerNative(global_escape
, 100, 0);
1129 vm
.registerNative(global_unescape
, 100, 1);
1130 vm
.registerNative(global_parseint
, 100, 2);
1131 vm
.registerNative(global_parsefloat
, 100, 3);
1132 vm
.registerNative(global_trace
, 100, 4);
1133 vm
.registerNative(global_isNaN
, 200, 18);
1134 vm
.registerNative(global_isfinite
, 200, 19);
1135 vm
.registerNative(global_setInterval
, 250, 0);
1136 vm
.registerNative(global_clearInterval
, 250, 1);
1137 vm
.registerNative(global_setTimeout
, 250, 2);
1139 vm
.registerNative(global_showRedrawRegions
, 1021, 1);
1141 registerObjectNative(global
);
1142 registerFunctionNative(global
);
1143 registerStringNative(global
);
1144 registerArrayNative(global
);
1145 registerNumberNative(global
);
1146 registerBooleanNative(global
);
1147 registerMovieClipNative(global
);
1148 registerSelectionNative(global
);
1149 registerColorNative(global
);
1150 registerMathNative(global
);
1151 registerSystemNative(global
);
1152 registerAccessibilityNative(global
);
1153 registerStageNative(global
);
1154 registerTextFieldNative(global
);
1155 registerButtonNative(global
);
1156 registerVideoNative(global
);
1157 registerMovieClipLoaderNative(global
);
1158 registerXMLSocketNative(global
);
1159 registerSharedObjectNative(global
);
1160 registerKeyNative(global
);
1161 registerNetStreamNative(global
);
1162 registerCameraNative(global
);
1163 registerMicrophoneNative(global
);
1164 registerTextSnapshotNative(global
);
1165 registerSoundNative(global
);
1166 registerLocalConnectionNative(global
);
1167 registerBitmapFilterNative(global
);
1168 registerColorTransformNative(global
);
1169 registerExternalInterfaceNative(global
);
1170 registerBitmapDataNative(global
);
1172 AsBroadcaster::registerNative(global
);
1173 registerTextFormatNative(global
);
1174 registerDateNative(global
);
1175 Mouse_as::registerNative(global
);
1177 // LoadableObject has natives shared between LoadVars and XML, so
1178 // should be registered first.
1179 registerLoadableNative(global
);
1180 registerXMLNative(global
);
1181 registerXMLNodeNative(global
);
1184 } // anonymous namespace
1185 } // namespace gnash