@astronautlabs/amf
Version:
Action Message Format (AMF0/3)
616 lines • 21.2 kB
JavaScript
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
import { BitstreamElement, Field, Variant, ReservedLow, VariantMarker } from "@astronautlabs/bitstream";
import * as AMF3 from './amf3';
export var TypeMarker;
(function (TypeMarker) {
TypeMarker[TypeMarker["Number"] = 0] = "Number";
TypeMarker[TypeMarker["Boolean"] = 1] = "Boolean";
TypeMarker[TypeMarker["String"] = 2] = "String";
TypeMarker[TypeMarker["Object"] = 3] = "Object";
TypeMarker[TypeMarker["MovieClip"] = 4] = "MovieClip";
TypeMarker[TypeMarker["Null"] = 5] = "Null";
TypeMarker[TypeMarker["Undefined"] = 6] = "Undefined";
TypeMarker[TypeMarker["Reference"] = 7] = "Reference";
TypeMarker[TypeMarker["EcmaArray"] = 8] = "EcmaArray";
TypeMarker[TypeMarker["ObjectEnd"] = 9] = "ObjectEnd";
TypeMarker[TypeMarker["StrictArray"] = 10] = "StrictArray";
TypeMarker[TypeMarker["Date"] = 11] = "Date";
TypeMarker[TypeMarker["LongString"] = 12] = "LongString";
TypeMarker[TypeMarker["Unsupported"] = 13] = "Unsupported";
TypeMarker[TypeMarker["RecordSet"] = 14] = "RecordSet";
TypeMarker[TypeMarker["XmlDocument"] = 15] = "XmlDocument";
TypeMarker[TypeMarker["TypedObject"] = 16] = "TypedObject";
TypeMarker[TypeMarker["AvmPlus"] = 17] = "AvmPlus"; // x
})(TypeMarker || (TypeMarker = {}));
export class Value extends BitstreamElement {
get referenceTable() {
if (!this._referenceTable) {
if (this.context) {
if (this.context.__references) {
this._referenceTable = this.context.__references;
}
else {
this.context.__references = this._referenceTable = [];
}
}
}
return this._referenceTable;
}
get value() { return undefined; }
set value(value) {
throw new Error(`Cannot set value [${this.constructor.name}]`);
}
static get undefined() {
return new UndefinedValue();
}
static get true() {
return this.boolean(true);
}
static get false() {
return this.boolean(false);
}
static boolean(value) {
return new BooleanValue().with({ value });
}
static number(value) {
return new NumberValue().with({ value });
}
static string(value) {
if (value.length > 0xFFFF)
return new LongStringValue().with({ value });
else
return new StringValue().with({ value });
}
static xmlDocument(value) {
return new XmlDocumentValue().with({ value });
}
static object(value, className) {
if (value === null || value === void 0 || typeof value !== 'object')
throw new Error(`Invalid value for object: ${value}`);
if (className)
return new TypedObjectValue().with({ value, className });
else
return new ObjectValue().with({ value });
}
static get null() {
return new NullValue();
}
static date(value) {
return new DateValue().with({ value });
}
static array(value) {
return new StrictArrayValue().with({ value });
}
static associativeArray(value) {
if (value instanceof Map)
return new EcmaArrayValue().with({ value });
else
return new EcmaArrayValue().with({ value: new Map(Object.keys(value).map(key => [key, value[key]])) });
}
static any(value) {
if (value instanceof Value)
return value;
if (value === void 0)
return this.undefined;
if (value === true)
return this.true;
if (value === false)
return this.false;
if (value === null)
return this.null;
if (typeof value === 'number')
return this.number(value);
if (typeof value === 'string')
return this.string(value);
if (value instanceof Date)
return this.date(value);
if (value instanceof Map)
return this.associativeArray(value);
if (Array.isArray(value))
return this.array(value);
if (typeof value === 'object')
return this.object(value);
}
static avmPlus(value) {
return new AvmPlusValue().with({ value });
}
static amf3(value) {
return this.avmPlus(value);
}
}
__decorate([
Field(8 * 1),
__metadata("design:type", Number)
], Value.prototype, "marker", void 0);
export class ObjectProperty extends BitstreamElement {
get key() { return this._key; }
set key(value) {
if (typeof value !== 'string')
throw new Error(`Key must be a string`);
this._key = value;
this.keyLength = value.length;
}
}
__decorate([
Field(8 * 2, { writtenValue: (i) => Buffer.from(i.key).length }),
__metadata("design:type", Number)
], ObjectProperty.prototype, "keyLength", void 0);
__decorate([
Field((i) => i.keyLength, { string: { encoding: 'utf-8' } }),
__metadata("design:type", String),
__metadata("design:paramtypes", [Object])
], ObjectProperty.prototype, "key", null);
__decorate([
Field(),
__metadata("design:type", Value)
], ObjectProperty.prototype, "value", void 0);
export class ObjectPropertyArraySerializer {
*read(reader, type, parent, field) {
let properties = [];
let readOperation;
let hasMore = true;
while (hasMore) {
readOperation = ObjectProperty.read(reader);
while (true) {
let propResult = readOperation.next();
if (propResult.done === false) {
yield propResult.value;
}
else {
let prop = propResult.value;
if (prop.value instanceof ObjectEndValue)
hasMore = false;
else
properties.push(prop);
break;
}
}
}
return properties;
}
write(writer, type, parent, field, value) {
for (let prop of value)
prop.write(writer);
new ObjectProperty()
.with({ key: "", value: new ObjectEndValue() })
.write(writer);
}
}
let NumberValue = class NumberValue extends Value {
constructor() {
super(...arguments);
this.marker = TypeMarker.Number;
}
get value() { return this.$value; }
set value(value) { this.$value = value; }
};
__decorate([
Field(8 * 8, { number: { format: 'float' } }),
__metadata("design:type", Number)
], NumberValue.prototype, "$value", void 0);
NumberValue = __decorate([
Variant(i => i.marker === TypeMarker.Number)
], NumberValue);
export { NumberValue };
let BooleanValue = class BooleanValue extends Value {
constructor() {
super(...arguments);
this.marker = TypeMarker.Boolean;
}
get value() { return this.$value; }
set value(value) { this.$value = value; }
};
__decorate([
Field(8 * 1),
__metadata("design:type", Boolean)
], BooleanValue.prototype, "$value", void 0);
BooleanValue = __decorate([
Variant(i => i.marker === TypeMarker.Boolean)
], BooleanValue);
export { BooleanValue };
let StringValue = class StringValue extends Value {
constructor() {
super(...arguments);
this.marker = TypeMarker.String;
this.length = 0;
}
get value() { return this.$value; }
set value(value) {
if (typeof value !== 'string')
throw new Error(`Value must be a string`);
this.$value = value;
this.length = value.length;
}
};
__decorate([
Field(8 * 2, { writtenValue: (i) => Buffer.from(i.value).length }),
__metadata("design:type", Number)
], StringValue.prototype, "length", void 0);
__decorate([
Field((i) => i.length, { string: { encoding: 'utf-8' } }),
__metadata("design:type", String)
], StringValue.prototype, "$value", void 0);
StringValue = __decorate([
Variant(i => i.marker === TypeMarker.String)
], StringValue);
export { StringValue };
let ComplexValue = class ComplexValue extends Value {
write(bitstream, options) {
var _a, _b, _c;
this.context = (_a = options === null || options === void 0 ? void 0 : options.context) !== null && _a !== void 0 ? _a : {};
let json = JSON.stringify(this);
if (!this.context.id)
this.context.id = Math.floor(Math.random() * 1000);
let index = (_c = (_b = this.referenceTable) === null || _b === void 0 ? void 0 : _b.findIndex) === null || _c === void 0 ? void 0 : _c.call(_b, x => JSON.stringify(x) === json);
if (index >= 0) {
new ReferenceValue().with({ index }).write(bitstream, options);
}
else {
super.write(bitstream, options);
}
}
onSerializeFinished() {
this.referenceTable.push(this);
}
onParseFinished() {
this.referenceTable.push(this);
}
};
ComplexValue = __decorate([
Variant(i => [TypeMarker.Object, TypeMarker.TypedObject, TypeMarker.StrictArray, TypeMarker.EcmaArray].includes(i.marker))
], ComplexValue);
export { ComplexValue };
function symbol() {
return Symbol('');
}
let ObjectValue = class ObjectValue extends ComplexValue {
constructor() {
super(...arguments);
this.marker = TypeMarker.Object;
}
get properties() {
return this._properties;
}
set properties(value) {
this._properties = value;
this.buildValue();
}
buildValue() {
this._value = this.properties.reduce((o, p) => (o[p.key] = p.value.value, o), {});
}
get value() {
return this._value;
}
set value(value) {
this._value = value;
this._properties = Object
.keys(value !== null && value !== void 0 ? value : {})
.map(key => new ObjectProperty().with({
key,
value: Value.any(value[key])
}));
}
};
__decorate([
VariantMarker(),
__metadata("design:type", Object)
], ObjectValue.prototype, "$objectVariantMarker", void 0);
__decorate([
Field(0, {
array: { type: ObjectProperty },
serializer: new ObjectPropertyArraySerializer()
}),
__metadata("design:type", Array),
__metadata("design:paramtypes", [Object])
], ObjectValue.prototype, "properties", null);
ObjectValue = __decorate([
Variant(i => [TypeMarker.Object, TypeMarker.TypedObject].includes(i.marker))
], ObjectValue);
export { ObjectValue };
let TypedObjectValue = class TypedObjectValue extends ObjectValue {
constructor() {
super(...arguments);
this.marker = TypeMarker.TypedObject;
}
get className() {
return this._className;
}
set className(value) {
if (typeof value !== 'string')
throw new TypeError(`Class name must be a string`);
this._className = value;
this.classNameLength = value.length;
}
};
__decorate([
Field(8 * 2, { writtenValue: (i) => Buffer.from(i.className).length }),
__metadata("design:type", Number)
], TypedObjectValue.prototype, "classNameLength", void 0);
__decorate([
Field((i) => i.classNameLength, { string: { encoding: 'utf-8' } }),
__metadata("design:type", String),
__metadata("design:paramtypes", [Object])
], TypedObjectValue.prototype, "className", null);
TypedObjectValue = __decorate([
Variant(i => i.marker === TypeMarker.TypedObject)
], TypedObjectValue);
export { TypedObjectValue };
let NullValue = class NullValue extends Value {
constructor() {
super(...arguments);
this.marker = TypeMarker.Null;
}
};
NullValue = __decorate([
Variant(i => i.marker === TypeMarker.Null)
], NullValue);
export { NullValue };
let UndefinedValue = class UndefinedValue extends Value {
constructor() {
super(...arguments);
this.marker = TypeMarker.Undefined;
}
};
UndefinedValue = __decorate([
Variant(i => i.marker === TypeMarker.Undefined)
], UndefinedValue);
export { UndefinedValue };
let ReferenceValue = class ReferenceValue extends Value {
constructor() {
super(...arguments);
this.marker = TypeMarker.Reference;
}
get reference() {
var _a;
return (_a = this.referenceTable) === null || _a === void 0 ? void 0 : _a[this.index];
}
get value() {
var _a;
return (_a = this.reference) === null || _a === void 0 ? void 0 : _a.value;
}
};
__decorate([
Field(8 * 2),
__metadata("design:type", Number)
], ReferenceValue.prototype, "index", void 0);
ReferenceValue = __decorate([
Variant(i => i.marker === TypeMarker.Reference)
], ReferenceValue);
export { ReferenceValue };
let EcmaArrayValue = class EcmaArrayValue extends ComplexValue {
constructor() {
super(...arguments);
this.marker = TypeMarker.EcmaArray;
this.endKey = '';
this.endMarker = TypeMarker.ObjectEnd;
}
get properties() {
return this._properties;
}
set properties(value) {
this._properties = value;
this._value = new Map(value.map(prop => [prop.key, prop.value.value]));
}
get value() {
return this._value;
}
set value(value) {
this._value = value;
this._properties = Array.from(value.entries()).map(([key, value]) => new ObjectProperty().with({ key, value: Value.any(value) }));
this._count = this._properties.length;
}
};
__decorate([
Field(8 * 4, { writtenValue: (i) => i._properties.length }),
__metadata("design:type", Number)
], EcmaArrayValue.prototype, "_count", void 0);
__decorate([
Field((i) => i._count, { array: { type: ObjectProperty } }),
__metadata("design:type", Array),
__metadata("design:paramtypes", [Object])
], EcmaArrayValue.prototype, "properties", null);
__decorate([
Field((i) => 0, { string: { encoding: 'utf-8' }, writtenValue: '' }),
__metadata("design:type", Object)
], EcmaArrayValue.prototype, "endKey", void 0);
__decorate([
Field(8, { writtenValue: TypeMarker.ObjectEnd }),
__metadata("design:type", Object)
], EcmaArrayValue.prototype, "endMarker", void 0);
EcmaArrayValue = __decorate([
Variant(i => i.marker === TypeMarker.EcmaArray)
], EcmaArrayValue);
export { EcmaArrayValue };
let ObjectEndValue = class ObjectEndValue extends Value {
constructor() {
super(...arguments);
this.marker = TypeMarker.ObjectEnd;
}
};
ObjectEndValue = __decorate([
Variant(i => i.marker === TypeMarker.ObjectEnd)
], ObjectEndValue);
export { ObjectEndValue };
let StrictArrayValue = class StrictArrayValue extends ComplexValue {
constructor() {
super(...arguments);
this.marker = TypeMarker.StrictArray;
}
get values() {
return this._values;
}
set values(value) {
this._values = value;
this._value = value.map(z => z.value);
}
get value() {
return this._value;
}
static elementValues(value) {
return value.values;
}
set value(value) {
if (!Array.isArray(value))
throw new Error(`Value must be an array`);
this._value = value;
this.values = value.map(z => Value.any(z));
this.count = value.length;
}
};
__decorate([
Field(8 * 4),
__metadata("design:type", Number)
], StrictArrayValue.prototype, "count", void 0);
__decorate([
Field((i) => i.count, { array: { type: Value } }),
__metadata("design:type", Array),
__metadata("design:paramtypes", [Object])
], StrictArrayValue.prototype, "values", null);
StrictArrayValue = __decorate([
Variant(i => i.marker === TypeMarker.StrictArray)
], StrictArrayValue);
export { StrictArrayValue };
let DateValue = class DateValue extends Value {
constructor() {
super(...arguments);
this.marker = TypeMarker.Date;
}
get $value() {
return this._value;
}
set $value(value) {
this._value = Math.floor(value);
}
get value() {
return new Date(this.$value);
}
set value(value) {
this.$value = value.getTime();
}
};
__decorate([
Field(8 * 8, { number: { format: 'float' } }),
__metadata("design:type", Number),
__metadata("design:paramtypes", [Object])
], DateValue.prototype, "$value", null);
__decorate([
ReservedLow(8 * 2, { writtenValue: 0x0000 }),
__metadata("design:type", Number)
], DateValue.prototype, "timeZone", void 0);
DateValue = __decorate([
Variant(i => i.marker === TypeMarker.Date)
], DateValue);
export { DateValue };
let LongStringValue = class LongStringValue extends Value {
constructor() {
super(...arguments);
this.marker = TypeMarker.LongString;
}
get value() { return this.$value; }
set value(value) {
if (typeof value !== 'string')
throw new TypeError(`Value must be a string`);
this.$value = value;
this._length = value.length;
}
};
__decorate([
Field(8 * 4, { writtenValue: (i) => Buffer.from(i.value).length }),
__metadata("design:type", Number)
], LongStringValue.prototype, "_length", void 0);
__decorate([
Field((i) => i._length, { string: { encoding: 'utf-8' } }),
__metadata("design:type", String)
], LongStringValue.prototype, "$value", void 0);
LongStringValue = __decorate([
Variant(i => i.marker === TypeMarker.LongString)
], LongStringValue);
export { LongStringValue };
let UnsupportedValue = class UnsupportedValue extends Value {
constructor() {
super(...arguments);
this.marker = TypeMarker.Unsupported;
}
};
UnsupportedValue = __decorate([
Variant(i => i.marker === TypeMarker.Unsupported)
], UnsupportedValue);
export { UnsupportedValue };
let RecordSetValue = class RecordSetValue extends Value {
constructor() {
super(...arguments);
this.marker = TypeMarker.RecordSet;
}
};
RecordSetValue = __decorate([
Variant(i => i.marker === TypeMarker.RecordSet)
], RecordSetValue);
export { RecordSetValue };
let MovieClipValue = class MovieClipValue extends Value {
constructor() {
super(...arguments);
this.marker = TypeMarker.MovieClip;
}
};
MovieClipValue = __decorate([
Variant(i => i.marker === TypeMarker.MovieClip)
], MovieClipValue);
export { MovieClipValue };
let XmlDocumentValue = class XmlDocumentValue extends Value {
constructor() {
super(...arguments);
this.marker = TypeMarker.XmlDocument;
}
get value() { return this.$value; }
set value(value) {
if (typeof value !== 'string')
throw new TypeError(`Value must be a string`);
this.$value = value;
this._length = value.length;
}
};
__decorate([
Field(8 * 4, { writtenValue: (i) => Buffer.from(i.value).length }),
__metadata("design:type", Number)
], XmlDocumentValue.prototype, "_length", void 0);
__decorate([
Field((i) => i._length, { string: { encoding: 'utf-8' } }),
__metadata("design:type", String)
], XmlDocumentValue.prototype, "$value", void 0);
XmlDocumentValue = __decorate([
Variant(i => i.marker === TypeMarker.XmlDocument)
], XmlDocumentValue);
export { XmlDocumentValue };
let AvmPlusValue = class AvmPlusValue extends Value {
constructor() {
super(...arguments);
this.marker = TypeMarker.AvmPlus;
}
get value() {
var _a;
return (_a = this.$value) === null || _a === void 0 ? void 0 : _a.value;
}
set value(value) {
this.$value = AMF3.Value.any(value);
}
static unwrap(v) {
return v.$value;
}
};
__decorate([
Field(),
__metadata("design:type", AMF3.Value)
], AvmPlusValue.prototype, "$value", void 0);
AvmPlusValue = __decorate([
Variant(i => i.marker === TypeMarker.AvmPlus)
], AvmPlusValue);
export { AvmPlusValue };
//# sourceMappingURL=amf0.js.map