Fixes variable bound AVM1 text field.

This commit is contained in:
Yury Delendik 2014-11-29 14:33:04 -06:00
Родитель e63d1bafe2
Коммит 4c8029c229
7 изменённых файлов: 95 добавлений и 25 удалений

Просмотреть файл

@ -34,7 +34,9 @@ module Shumway.AVM1 {
}
export interface IAVM1RuntimeUtils {
hasProperty(obj, name);
getProperty(obj, name);
setProperty(obj, name, value);
}
export class AVM1Context {

17
src/avm1/flash.d.ts поставляемый
Просмотреть файл

@ -51,6 +51,7 @@ declare module Shumway.AVM2.AS.flash {
_mouseDown: boolean;
_children: DisplayObject [];
_depth: number;
_symbol: DisplaySymbol;
getBounds(obj: DisplayObject): flash.geom.Rectangle;
play();
stop();
@ -129,9 +130,7 @@ declare module Shumway.AVM2.AS.flash {
constructor();
}
class SimpleButton extends DisplayObject {
_symbol: {
data: {buttonActions: Shumway.Timeline.AVM1ButtonAction[]}
}
_symbol: ButtonSymbol;
}
class Stage extends DisplayObject {
@ -144,8 +143,12 @@ declare module Shumway.AVM2.AS.flash {
stageHeight: number;
}
class BitmapSymbol {}
class SpriteSymbol {
class DisplaySymbol {}
class BitmapSymbol extends DisplaySymbol {}
class ButtonSymbol extends DisplaySymbol {
data: { buttonActions: Shumway.Timeline.AVM1ButtonAction[] }
}
class SpriteSymbol extends DisplaySymbol {
avm1Name: string;
avm1SymbolClass;
}
@ -276,10 +279,14 @@ declare module Shumway.AVM2.AS.flash {
textWidth: number;
textHeight: number;
defaultTextFormat: TextFormat;
_symbol: TextSymbol;
}
class TextFormat extends ASNative {
constructor(...args);
}
class TextSymbol extends display.DisplaySymbol {
variableName: string;
}
}
module ui {
class ContextMenu extends ASNative {}

Просмотреть файл

@ -197,10 +197,27 @@ module Shumway.AVM1 {
this.errorsIgnored = 0;
this.deferScriptExecution = true;
this.pendingScripts = [];
var context = this;
this.utils = {
hasProperty(obj, name) {
var result: boolean;
context.enterContext(function () {
result = as2HasProperty(obj, name);
}, obj);
return result;
},
getProperty(obj, name) {
var resolved = avm1ResolveProperty(obj, name, false);
return resolved ? resolved.link.asGetPublicProperty(name) : undefined;
var result;
context.enterContext(function () {
result = as2GetProperty(obj, name);
}, obj);
return result;
},
setProperty(obj, name, value) {
context.enterContext(function () {
as2SetProperty(obj, name, value);
}, obj);
}
};
}
@ -554,6 +571,11 @@ module Shumway.AVM1 {
// versions 6 and below ignore identifier case
if (isNumeric(name) ||
as2GetCurrentSwfVersion() > 6) {
if (normalize) {
__resolvePropertyResult.link = obj;
__resolvePropertyResult.name = name;
return __resolvePropertyResult;
}
return null;
}
@ -596,18 +618,26 @@ module Shumway.AVM1 {
return null;
}
function as2ResolveProperty(obj, name: string, normalize: boolean): string {
var resolved = avm1ResolveProperty(obj, name, normalize);
return resolved ? resolved.name : null;
}
function as2HasProperty(obj, name: string): boolean {
return !!avm1ResolveProperty(obj, name, false);
}
function as2ResolveProperty(obj, name: string, normalize: boolean): string {
var result = avm1ResolveProperty(obj, name, normalize);
return result ? result.name : null;
function as2GetProperty(obj, name: string): any {
var resolved = avm1ResolveProperty(obj, name, false);
return resolved ? resolved.link.asGetPublicProperty(resolved.name) : undefined;
}
function as2GetProperty(obj, name: string): any {
var result = avm1ResolveProperty(obj, name, false);
return result ? result.link.asGetPublicProperty(name) : undefined;
function as2SetProperty(obj, name: string, value: any): any {
var resolved = avm1ResolveProperty(obj, name, true);
if (!resolved) {
return; // probably obj is undefined or null
}
resolved.link.asSetPublicProperty(resolved.name, value);
}
function as2CastError(ex) {

Просмотреть файл

@ -39,13 +39,20 @@ module Shumway.AVM1.Lib {
return wrapped;
}
_variable: string;
private _variable: string;
private _exitFrameHandler: (event: flash.events.Event) => void;
public initAVM1Instance(as2Object: flash.text.TextField, context: AVM1Context) {
super.initAVM1Instance(as2Object, context);
public initAVM1Instance(as3Object: flash.text.TextField, context: AVM1Context) {
super.initAVM1Instance(as3Object, context);
this._variable = '';
this._exitFrameHandler = null;
initDefaultListeners(this);
if (as3Object._symbol) {
this.variable = as3Object._symbol.variableName || '';
}
}
public get _alpha() {
@ -351,14 +358,33 @@ module Shumway.AVM1.Lib {
if (name === this._variable) {
return;
}
this._variable = name;
var instance = this.as3Object;
var hasPath = name.indexOf('.') >= 0 || name.indexOf(':') >= 0;
if (this._exitFrameHandler && !name) {
instance.removeEventListener('exitFrame', this._exitFrameHandler);
this._exitFrameHandler = null;
}
this._variable = name;
if (!this._exitFrameHandler && name) {
this._exitFrameHandler = this._onAS3ObjectExitFrame.bind(this);
instance.addEventListener('exitFrame', this._exitFrameHandler);
}
}
private _onAS3ObjectExitFrame() {
this._syncTextFieldValue(this.as3Object, this._variable);
}
private _syncTextFieldValue(instance, name) {
var clip;
var hasPath = name.indexOf('.') >= 0 || name.indexOf(':') >= 0;
var avm1ContextUtils = this.context.utils;
if (hasPath) {
var targetPath = name.split(/[.:\/]/g);
name = targetPath.pop();
if (targetPath[0] == '_root' || targetPath[0] === '') {
if (instance.root === null) {
return; // text field is not part of the stage yet
}
clip = getAVM1Object(instance.root, this.context);
targetPath.shift();
if (targetPath[0] === '') {
@ -369,20 +395,20 @@ module Shumway.AVM1.Lib {
}
while (targetPath.length > 0) {
var childName = targetPath.shift();
clip = clip.asGetPublicProperty(childName) || clip[childName];
clip = avm1ContextUtils.getProperty(clip, childName);
if (!clip) {
throw new Error('Cannot find ' + childName + ' variable');
return; // cannot find child clip
}
}
} else {
clip = getAVM1Object(instance._parent, this.context);
}
if (!clip.asHasProperty(undefined, name, 0)) {
clip.asSetPublicProperty(name, instance.text);
// Sets default values as defined in SWF if this property was not found.
if (!avm1ContextUtils.hasProperty(clip, name)) {
avm1ContextUtils.setProperty(clip, name, instance.text);
}
instance.addEventListener('advanceFrame', function () {
instance.text = '' + clip.asGetPublicProperty(name);
});
instance.text = '' + avm1ContextUtils.getProperty(clip, name);
}
public get _visible() {

Двоичные данные
test/swfs/avm1/text-bind/text-bind-1.fla Normal file

Двоичный файл не отображается.

Двоичные данные
test/swfs/avm1/text-bind/text-bind-1.swf Normal file

Двоичный файл не отображается.

Просмотреть файл

@ -447,6 +447,11 @@
"swf": "/examples/textfield/align.swf",
"type": "eq"
},
{ "id": "text-bind-ref",
"frames": [3],
"swf": "swfs/avm1/text-bind/text-bind-1.swf",
"type": "eq"
},
{ "id": "as3-loader",
"stas": "swfs/trace.stas",
"filenames": [