Commit Graph

32 Commits

Author SHA1 Message Date
Nathan Adams 85b9ffe102 core: Merge both test macros into a generic test_method 2019-11-29 13:12:00 -08:00
David Wendt 9ec85c3892 Add tests for SWF6 numerical coercions. 2019-11-28 21:32:10 -05:00
David Wendt f856243247 Primitive coercions should not yield an object just because valueOf is undefined. 2019-11-28 20:53:32 -05:00
David Wendt ec3ac4e5d6 `undefined` coerces to `0.0` on SWF6 2019-11-28 20:53:32 -05:00
David Wendt 16259ad74a Calling uncallable values does not actually cause a runtime error in Flash; it just returns null.
This was discovered almost by accident: @Dinnerbone noticed that `_global == null`, and surmised that `valueOf` was the culprit. However, this doesn't really make sense: `_global` is a bare object, so it shouldn't have a `valueOf` (and in practice, it doesn't).

The ultimate cause of such an odd comparison is as such:

1. Flash coerces the `_global` object to a numerical primitive by calling `valueOf`.
2. `_global.valueOf` is undefined. Flash handles calls to any uncallable value by literally just having it return `undefined`. In other words, all values are implicitly callable as empty functions.
3. `undefined` is then compared to `null`. These two values *are* equal under abstract equality (`==`). Hence, `_global == null`.

For comparison, modern ECMAScript engines throw errors on calls to uncallable values; and won't attempt to use an invalid `valueOf` to coerce objects. So none of this applies to, say, standard JavaScript in your browser.
2019-11-28 20:53:31 -05:00
Nathan Adams 581d0940b2 NaN == NaN without coercion 2019-11-28 20:43:59 -05:00
Nathan Adams f33229a2a1 `_global` == null && `_global` == undefined 2019-11-28 20:43:58 -05:00
David Wendt 129d50bfa6 Implement ECMAScript compliant type coercions.
This includes ECMA-262 2ed `ToNumber`, `ToPrimitive` (Number), `ToString`, and abstract equality and less-than implementations. Note that `ToPrimitive` is only the "number hint" variant, and Flash specifically *never* calls `toString` like how ECMA-262 specifies.

Several builtins inherit numerical coercion - I'm not 100% sure if that's correct.

The following ActionScript opcodes now perform ECMA-262 style coercions:

`ActionAdd2` (uses `valueOf` / "ToPrimitive hint Number")
`ActionDecrement` (uses `valueOf`)
`ActionEquals2` (uses `valueOf`)
`ActionGetMember` (member names, uses `toString`)
`ActionIncrement` (uses `valueOf`)
`ActionLess2` (uses `valueOf`)
`ActionGreater` (uses `valueOf`)
`ActionSetMember` (member names, uses `toString`)
`ActionStringEquals` (uses `toString`)
`ActionStringGreater` (uses `toString`)
`ActionStringLess` (uses `toString`)
`ActionToNumber` (uses `valueOf`)
`ActionToString` (uses `toString`)
`ActionTrace` (uses `toString`)

The following functions now gained user-specified coercions via `toString`:
`_global.number` (uses `valueOf`)
`_global.is_nan` (uses `valueOf`)
Every function in `Math` (uses `valueOf`)
2019-11-28 20:23:39 -05:00
David Wendt d25bdbacf8 Separate `Object` into an interface trait and a standard implementation. Host object implementations may bypass `ScriptObject` and directly interface with the AVM using this trait.
Note that host objects that do so will *not* have access to their standard representation from within member functions - you will need to extend the interface to accomodate for them. This is due to long-standing limitations with type IDs and downcasting with types that bear lifetimes - it's entirely an unsafe operation and exposing such a facility to safe Rust is unsound. However, this will at least let us separate out several things from ScriptObject that don't need to be there for the time being.
2019-11-26 14:51:05 -05:00
David Wendt f347992eeb Add `as_usize` method to `Value` 2019-11-26 14:51:05 -05:00
David Wendt 207a157f20 Add missing usize conversion 2019-11-26 14:51:05 -05:00
David Wendt 2aa5b62b44 Make most code that might touch user-defined functions falliable. 2019-11-20 14:30:32 -05:00
David Wendt a2ee7f9e3a Replace `Option<Value<'gc>>` with a dedicated `ReturnValue<'gc>` type with associated methods.
This type explicitly signals if an immediate value is to be returned, if a value is to be returned on the stack, or if no return value is to be generated. Holders of a `ReturnValue` can also use `and_then` to schedule a `StackContinuation` to be executed when and if that value is ready.

`StackContinuations` now yield `ReturnValues` as well, so they have a moderate level of composability. For example, if you need to get a property from an object and push it on the stack, you can return the result of calling `get` directly and the machinery ensures it eventually gets there.
2019-11-20 14:30:31 -05:00
Mike Welsh dddfb42e1e core: Merge ActionContext into UpdateContext 2019-10-27 13:49:47 -07:00
Nathan Adams 348e7f6adb chore: Impl From<numeric> for Value, better dev ergonomics 2019-10-21 17:14:00 +02:00
Nathan Adams 83b7d679ed chore: Impl From<GcCell<'gc, Object<'gc>>> for Value, better dev ergonomics 2019-10-21 13:00:52 +02:00
Nathan Adams fa5616a4f9 chore: Impl From<bool> for Value, better dev ergonomics 2019-10-21 12:55:17 +02:00
Nathan Adams f24ab37810 chore: Impl From<&str> for Value, better dev ergonomics 2019-10-21 12:33:49 +02:00
Nathan Adams 796c641b3b chore: Impl From<String> for Value, better dev ergonomics 2019-10-21 12:30:59 +02:00
Mike Welsh 84cb00b44b chore: Fix clippy lint in Value::as_bool 2019-10-21 02:11:50 -07:00
Will Brindle 019ea79551 core: return true for objects as boolean 2019-10-20 10:00:18 +01:00
Will Brindle 3fa198d8f2 core: Add extra test cases for Number function and resolve the issues they highlight 2019-10-19 10:29:26 +01:00
Will Brindle 463d0fc352 core: implement isNaN and Number functions. Involves updating to_number function in Value. Note: this varies a little from the ECMA spec such as not allowing spaces in numbers (i.e. ' 5' => NaN). No definitive reference for this but was found experimentally. Same with not supporting 'Infinity' 2019-10-19 10:29:26 +01:00
Will Brindle 38c66b5b8d core: implement Boolean function 2019-10-19 10:29:26 +01:00
David Wendt 83c832ce86 Distinguish between Native and ActionScript functions. 2019-10-06 13:02:31 -07:00
Mike Welsh 82c1116c42 chore: cargo fmt 2019-09-16 20:37:11 -07:00
David Wendt 130d9736bc Allow builtins access to the AVM1 state directly. 2019-09-16 20:04:30 -07:00
Nathan Adams a4cdbc4f70 Added `Math` unit tests, first avm tests :) 2019-09-02 22:19:09 +02:00
Nathan Adams 200129452a Pass along `ActionContext` to functions 2019-09-02 19:28:38 +02:00
Nathan Adams 002272d7b5 Functions return `[type Function]` when converted to strings 2019-08-31 18:28:28 +02:00
Nathan Adams 7a18ece455 `DisplayObject`s all have a AVM1 `Value`. Added `toString()` default method for Objects (but not functions) 2019-08-31 17:54:15 +02:00
Nathan Adams bd63a82e9e Split off `Value` into its own file, for slightly less code clutter 2019-08-31 14:29:46 +02:00