Source code drop for the Actionscript virtual machine in the Adobe Flash Player for December 2013
426 lines
17 KiB
ActionScript
426 lines
17 KiB
ActionScript
/* -*- c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 4 -*- */
|
|
/* vi: set ts=4 sw=4 expandtab: (add to ~/.vimrc: set modeline modelines=5) */
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
|
|
package
|
|
{
|
|
[native(cls="ArrayClass", gc="exact", instance="ArrayObject", methods="auto")]
|
|
public dynamic class Array extends Object
|
|
{
|
|
// option flags for sort and sortOn
|
|
public static const CASEINSENSITIVE:uint = 1;
|
|
public static const DESCENDING:uint = 2;
|
|
public static const UNIQUESORT:uint = 4;
|
|
public static const RETURNINDEXEDARRAY:uint = 8;
|
|
public static const NUMERIC:uint = 16;
|
|
|
|
// E262 {DontEnum, DontDelete}
|
|
public native function get length():uint
|
|
public native function set length(newLength:uint)
|
|
|
|
// Assigns this.length = newLength if latter fits; otherwise
|
|
// throws exception or assigns altLength (SWF version dependent).
|
|
//
|
|
// It is responsibility of caller to provide an appropriate
|
|
// altLength. Old behavior used altLength == uint(newLength),
|
|
// but it is better to clamp rather than wrap in such cases.
|
|
// More discussion on Bugzilla 658677, 661330, and 681399.
|
|
private function set_length(newLength:*, altLength:uint)
|
|
{
|
|
if (newLength is uint)
|
|
this.length = newLength;
|
|
else if (bugzilla(661330))
|
|
Error.throwError( RangeError, 2108, // kInvalidArrayLengthError
|
|
newLength );
|
|
else
|
|
this.length = altLength;
|
|
}
|
|
|
|
// Array.length = 1 per ES3
|
|
public static const length:int = 1
|
|
|
|
// ECMA 15.4.2.2
|
|
public function Array(...args)
|
|
{
|
|
var n:uint = args.length
|
|
if (n == 1 && (args[0] is Number))
|
|
{
|
|
var dlen:Number = args[0];
|
|
var ulen:uint = dlen
|
|
if (ulen != dlen)
|
|
Error.throwError( RangeError, 1005 /*kArrayIndexNotIntegerError*/, dlen );
|
|
length = ulen;
|
|
}
|
|
else
|
|
{
|
|
// FIXME why not just return args?
|
|
length = n
|
|
for (var i:uint=0; i < n; i++)
|
|
this[i] = args[i]
|
|
}
|
|
}
|
|
|
|
/**
|
|
15.4.4.5 Array.prototype.join (separator)
|
|
The elements of the array are converted to strings, and these strings are then concatenated, separated by
|
|
occurrences of the separator. If no separator is provided, a single comma is used as the separator.
|
|
The join method takes one argument, separator, and performs the following steps:
|
|
1. Call the [[Get]] method of this object with argument "length".
|
|
2. Call ToUint32(Result(1)).
|
|
3. If separator is undefined, let separator be the single-character string ",".
|
|
4. Call ToString(separator).
|
|
5. If Result(2) is zero, return the empty string.
|
|
6. Call the [[Get]] method of this object with argument "0".
|
|
7. If Result(6) is undefined or null, use the empty string; otherwise, call ToString(Result(6)).
|
|
8. Let R be Result(7).
|
|
9. Let k be 1.
|
|
10. If k equals Result(2), return R.
|
|
11. Let S be a string value produced by concatenating R and Result(4).
|
|
12. Call the [[Get]] method of this object with argument ToString(k).
|
|
13. If Result(12) is undefined or null, use the empty string; otherwise, call ToString(Result(12)).
|
|
14. Let R be a string value produced by concatenating S and Result(13).
|
|
15. Increase k by 1.
|
|
16. Go to step 10.
|
|
*/
|
|
|
|
private static function _join(o, sep):String
|
|
{
|
|
var s:String = (sep === undefined) ? "," : String(sep)
|
|
var out:String = ""
|
|
for (var i:uint = 0, n:uint=uint(o.length); i < n; i++)
|
|
{
|
|
var x = o[i]
|
|
if (x != null)
|
|
out += x
|
|
if (i+1 < n)
|
|
out += s
|
|
}
|
|
return out
|
|
}
|
|
AS3 function join(sep=void 0):String
|
|
{
|
|
return _join(this, sep)
|
|
}
|
|
prototype.join = function(sep=void 0):String
|
|
{
|
|
return _join(this, sep)
|
|
}
|
|
|
|
private static native function _pop(o)
|
|
AS3 native function pop()
|
|
prototype.pop = function()
|
|
{
|
|
return _pop(this)
|
|
}
|
|
|
|
/**
|
|
15.4.4.2 Array.prototype.toString ( )
|
|
The result of calling this function is the same as if the built-in join method were invoked for this object with no
|
|
argument.
|
|
The toString function is not generic; it throws a TypeError exception if its this value is not an Array object.
|
|
Therefore, it cannot be transferred to other kinds of objects for use as a method.
|
|
*/
|
|
|
|
prototype.toString = function():String
|
|
{
|
|
var a:Array = this // TypeError if not compatible
|
|
return _join(a, ",");
|
|
}
|
|
|
|
/**
|
|
15.4.4.3 Array.prototype.toLocaleString ( )
|
|
The elements of the array are converted to strings using their toLocaleString methods, and these strings are
|
|
then concatenated, separated by occurrences of a separator string that has been derived in an implementationdefined
|
|
locale-specific way. The result of calling this function is intended to be analogous to the result of
|
|
toString, except that the result of this function is intended to be locale-specific.
|
|
The result is calculated as follows:
|
|
1. Call the [[Get]] method of this object with argument "length".
|
|
2. Call ToUint32(Result(1)).
|
|
3. Let separator be the list-separator string appropriate for the host environment's current locale (this is derived in
|
|
an implementation-defined way).
|
|
4. Call ToString(separator).
|
|
5. If Result(2) is zero, return the empty string.
|
|
6. Call the [[Get]] method of this object with argument "0".
|
|
7. If Result(6) is undefined or null, use the empty string; otherwise, call ToObject(Result(6)).toLocaleString().
|
|
8. Let R be Result(7).
|
|
9. Let k be 1.
|
|
10. If k equals Result(2), return R.
|
|
11. Let S be a string value produced by concatenating R and Result(4).
|
|
12. Call the [[Get]] method of this object with argument ToString(k).
|
|
13. If Result(12) is undefined or null, use the empty string; otherwise, call ToObject(Result(12)).toLocaleString().
|
|
14. Let R be a string value produced by concatenating S and Result(13).
|
|
15. Increase k by 1.
|
|
16. Go to step 10.
|
|
The toLocaleString function is not generic; it throws a TypeError exception if its this value is not an Array
|
|
object. Therefore, it cannot be transferred to other kinds of objects for use as a method.
|
|
*/
|
|
|
|
prototype.toLocaleString = function():String
|
|
{
|
|
var a:Array = this // TypeError if not compatible
|
|
|
|
var out:String = ""
|
|
for (var i:uint = 0, n:uint=a.length; i < n; i++)
|
|
{
|
|
var x = a[i]
|
|
if (x != null)
|
|
out += x.toLocaleString()
|
|
if (i+1 < n)
|
|
out += ","
|
|
}
|
|
return out
|
|
}
|
|
|
|
/**
|
|
When the push method is called with zero or more arguments item1, item2, etc., the following steps are taken:
|
|
1. Call the [[Get]] method of this object with argument "length".
|
|
2. Let n be the result of calling ToUint32(Result(1)).
|
|
3. Get the next argument in the argument list; if there are no more arguments, go to step 7.
|
|
4. Call the [[Put]] method of this object with arguments ToString(n) and Result(3).
|
|
5. Increase n by 1.
|
|
6. Go to step 3.
|
|
7. Call the [[Put]] method of this object with arguments "length" and n.
|
|
8. Return n.
|
|
The length property of the push method is 1.
|
|
NOTE The push function is intentionally generic; it does not require that its this value be an Array object. Therefore it can be
|
|
transferred to other kinds of objects for use as a method. Whether the push function can be applied successfully to a host object
|
|
is implementation-dependent.
|
|
*/
|
|
AS3 native function push(...args):uint
|
|
prototype.push = function(...args):uint
|
|
{
|
|
var n:uint = uint(this.length)
|
|
for (var i:uint=0, argc:uint=args.length; i < argc; i++)
|
|
this[n++] = args[i]
|
|
this.length = n
|
|
return n
|
|
}
|
|
|
|
private static native function _reverse(o)
|
|
AS3 function reverse():Array
|
|
{
|
|
return _reverse(this) // return will cast to Array
|
|
}
|
|
prototype.reverse = function()
|
|
{
|
|
return _reverse(this)
|
|
}
|
|
|
|
private static native function _concat(o, args:Array):Array
|
|
AS3 function concat(...args):Array
|
|
{
|
|
return _concat(this, args)
|
|
}
|
|
prototype.concat = function(...args):Array
|
|
{
|
|
return _concat(this, args)
|
|
}
|
|
|
|
private static native function _shift(o)
|
|
AS3 function shift()
|
|
{
|
|
return _shift(this)
|
|
}
|
|
prototype.shift = function()
|
|
{
|
|
return _shift(this)
|
|
}
|
|
|
|
private static native function _slice(o, A:Number, B:Number):Array
|
|
AS3 function slice(A=0, B=0xffffffff):Array
|
|
{
|
|
return _slice(this, Number(A), Number(B))
|
|
}
|
|
prototype.slice = function(A=0, B=0xffffffff):Array
|
|
{
|
|
return _slice(this, Number(A), Number(B))
|
|
}
|
|
|
|
/**
|
|
15.4.4.13 Array.prototype.unshift ( [ item1 [ , item2 [ , ... ] ] ] )
|
|
The arguments are prepended to the start of the array, such that their order within the array is the same as the
|
|
order in which they appear in the argument list.
|
|
When the unshift method is called with zero or more arguments item1, item2, etc., the following steps are taken:
|
|
1. Call the [[Get]] method of this object with argument "length".
|
|
2. Call ToUint32(Result(1)).
|
|
3. Compute the number of arguments.
|
|
4. Let k be Result(2).
|
|
5. If k is zero, go to step 15.
|
|
6. Call ToString(k-1).
|
|
7. Call ToString(k+Result(3)-1).
|
|
8. If this object has a property named by Result(6), go to step 9; but if this object has no property named by
|
|
Result(6), then go to step 12.
|
|
9. Call the [[Get]] method of this object with argument Result(6).
|
|
10. Call the [[Put]] method of this object with arguments Result(7) and Result(9).
|
|
11. Go to step 13.
|
|
12. Call the [[Delete]] method of this object with argument Result(7).
|
|
13. Decrease k by 1.
|
|
14. Go to step 5.
|
|
15. Let k be 0.
|
|
16. Get the next argument in the part of the argument list that starts with item1; if there are no more arguments, go
|
|
to step 21.
|
|
17. Call ToString(k).
|
|
18. Call the [[Put]] method of this object with arguments Result(17) and Result(16).
|
|
19. Increase k by 1.
|
|
20. Go to step 16.
|
|
21. Call the [[Put]] method of this object with arguments "length" and (Result(2)+Result(3)).
|
|
22. Return (Result(2)+Result(3)).
|
|
The length property of the unshift method is 1.
|
|
NOTE The unshift function is intentionally generic; it does not require that its this value be an Array object. Therefore it can
|
|
be transferred to other kinds of objects for use as a method. Whether the unshift function can be applied successfully to a
|
|
host object is implementation-dependent.
|
|
*/
|
|
private static native function _unshift(o, args:Array):uint
|
|
native AS3 function unshift(...args):uint
|
|
prototype.unshift = function(...args):uint
|
|
{
|
|
if (this is Array)
|
|
return _unshift(this, args);
|
|
var len:uint = uint(this.length)
|
|
var argc:uint = args.length
|
|
var k:uint
|
|
for (k=len; k > 0; )
|
|
{
|
|
k--
|
|
var d:uint = k+argc
|
|
if (k in this)
|
|
this[d] = this[k]
|
|
else
|
|
delete this[d]
|
|
}
|
|
|
|
for (var i:uint = 0; i < argc; i++)
|
|
this[k++] = args[i]
|
|
|
|
len += argc
|
|
this.length = len
|
|
return len
|
|
}
|
|
|
|
private static native function _splice(o, args:Array):Array
|
|
|
|
// splice with zero args returns undefined. All other cases return Array.
|
|
AS3 function splice(...args)
|
|
{
|
|
if (!args.length)
|
|
return undefined;
|
|
|
|
return _splice(this, args)
|
|
}
|
|
prototype.splice = function(...args)
|
|
{
|
|
if (!args.length)
|
|
return undefined;
|
|
|
|
return _splice(this, args)
|
|
}
|
|
|
|
// sort can return an Array or a Number (unique sort option)
|
|
private static native function _sort(o, args:Array)
|
|
AS3 function sort(...args)
|
|
{
|
|
return _sort (this, args);
|
|
}
|
|
prototype.sort = function(...args)
|
|
{
|
|
return _sort (this, args);
|
|
}
|
|
|
|
private static native function _sortOn(o, names, options)
|
|
AS3 function sortOn(names, options=0, ...ignored)
|
|
{
|
|
// this is our own addition so we don't have to make names be optional
|
|
return _sortOn(this, names, options);
|
|
}
|
|
prototype.sortOn = function(names, options=0, ...ignored)
|
|
{
|
|
return _sortOn(this, names, options)
|
|
}
|
|
|
|
// Array extensions that are in Mozilla...
|
|
// http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array
|
|
//
|
|
// These all work on generic objects (array like objects) as well as arrays
|
|
|
|
private static native function _indexOf (o, searchElement, fromIndex:int):int;
|
|
AS3 function indexOf(searchElement, fromIndex=0):int
|
|
{
|
|
return _indexOf (this, searchElement, int(fromIndex));
|
|
}
|
|
prototype.indexOf = function(searchElement, fromIndex=0):int
|
|
{
|
|
return _indexOf (this, searchElement, int(fromIndex));
|
|
}
|
|
|
|
private static native function _lastIndexOf (o, searchElement, fromIndex:int=0):int;
|
|
AS3 function lastIndexOf(searchElement, fromIndex=0x7fffffff):int
|
|
{
|
|
return _lastIndexOf (this, searchElement, int(fromIndex));
|
|
}
|
|
prototype.lastIndexOf = function(searchElement, fromIndex=0x7fffffff):int
|
|
{
|
|
return _lastIndexOf (this, searchElement, int(fromIndex));
|
|
}
|
|
|
|
// Returns true if every element in this array satisfies the provided testing function.
|
|
private static native function _every(o, callback:Function, thisObject):Boolean;
|
|
AS3 function every(callback:Function, thisObject=null):Boolean
|
|
{
|
|
return _every (this, callback, thisObject);
|
|
}
|
|
prototype.every = function(callback:Function, thisObject=null):Boolean
|
|
{
|
|
return _every (this, callback, thisObject);
|
|
}
|
|
|
|
// Creates a new array with all elements that pass the test implemented by the provided function.
|
|
private static native function _filter(o, callback:Function, thisObject):Array;
|
|
AS3 function filter(callback:Function, thisObject=null):Array
|
|
{
|
|
return _filter (this, callback, thisObject);
|
|
}
|
|
prototype.filter = function(callback:Function, thisObject=null):Array
|
|
{
|
|
return _filter (this, callback, thisObject);
|
|
}
|
|
|
|
// Calls a function for each element in the array.
|
|
private static native function _forEach(o, callback:Function, thisObject):void;
|
|
AS3 function forEach(callback:Function, thisObject=null):void
|
|
{
|
|
_forEach (this, callback, thisObject);
|
|
}
|
|
prototype.forEach = function(callback:Function, thisObject=null):void
|
|
{
|
|
_forEach (this, callback, thisObject);
|
|
}
|
|
|
|
// Creates a new array with the results of calling a provided function on every element in this array.
|
|
private native static function _map(o, callback:Function, thisObject):Array;
|
|
AS3 function map(callback:Function, thisObject=null):Array
|
|
{
|
|
return _map (this, callback, thisObject);
|
|
}
|
|
prototype.map = function(callback:Function, thisObject=null):Array
|
|
{
|
|
return _map (this, callback, thisObject);
|
|
}
|
|
|
|
// Returns true if at least one element in this array satisfies the provided testing function.
|
|
private static native function _some(o, callback:Function, thisObject):Boolean;
|
|
AS3 function some(callback:Function, thisObject=null):Boolean
|
|
{
|
|
return _some (this, callback, thisObject);
|
|
}
|
|
prototype.some = function(callback:Function, thisObject=null):Boolean
|
|
{
|
|
return _some (this, callback, thisObject);
|
|
}
|
|
|
|
_dontEnumPrototype(prototype);
|
|
}
|
|
}
|