|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783 |
- /* eslint-disable camelcase, no-unused-vars, no-empty, no-constant-condition */
- const DNA1 = 826363460;
- const ENDB = 1111772741;
-
- /* Note: Blender coordinates treat the Z axis as the vertical an Y as depth. */
-
- // web worker not functional in this version
- let USE_WEBWORKER = false;
-
- let worker = null;
-
- // FR = new FileReader(),
-
- const return_object = {
- loadBlendFromArrayBuffer: function (array_buffer) {
- return_object.ready = false;
- if (USE_WEBWORKER) {
- worker.postMessage(array_buffer, array_buffer);
- } else {
- worker.onmessage({
- data: array_buffer,
- });
- }
- },
- // loadBlendFromBlob: function (blob) {
- // FR.onload = function () {
- // return_object.loadBlendFromArrayBuffer(this.result);
- // };
- // FR.readAsArrayBuffer(blob);
- // },
- ready: true,
- onParseReady: function () {},
- };
-
- function worker_code () {
- 'use strict';
-
- let data = null,
- _data = null,
- BIG_ENDIAN = false,
- pointer_size = 0,
- struct_names = [],
- offset = 0,
- working_blend_file = null,
- current_SDNA_template = null,
- templates = {},
- finished_objects = [],
- FILE = null,
- ERROR = null,
- AB = null;
-
- const self = this;
-
- function parseFile (msg) {
-
- if (typeof msg.data == 'object') {
- // reset global variables
- AB = null;
- data = null;
- BIG_ENDIAN = false;
- pointer_size = 0;
- struct_names = [];
- offset = 0;
- working_blend_file = null;
- finished_objects = [];
- current_SDNA_template = null;
-
-
- // set data
- _data = msg.data;
-
- AB = _data.slice();
-
- data = new DataView(_data);
-
-
- FILE = new BLENDER_FILE(AB);
-
- // start parsing
- readFile();
-
- // export parsed data
- self.postMessage(FILE, ERROR);
- }
- }
-
- /*
- Export object for a parsed __blender_file__.
- */
-
- var BLENDER_FILE = function (AB) {
- this.AB = AB;
- // this.double = new Float64Array(AB);
- this.byte = new Uint8Array(AB);
-
- this.dv = new DataView(AB);
-
- this.objects = {};
- this.memory_lookup = {},
- this.object_array = [];
-
- this.template = null;
- };
-
- BLENDER_FILE.prototype = {
- addObject: function (obj) {
- this.object_array.push(obj);
- if (!this.objects[obj.blender_name]) this.objects[obj.blender_name] = [];
- this.objects[obj.blender_name].push(obj);
- },
-
- getPointer: function (offset) {
- const pointerLow = this.dv.getUint32(offset, this.template.endianess);
- if (this.template.pointer_size > 4) {
- const pointerHigh = this.dv.getUint32(offset + 4, this.template.endianess);
- if (this.template.endianess) {
- return (pointerLow) + 'l|h' + pointerHigh;
- } else {
- return (pointerHigh) + 'h|l' + pointerLow;
- }
- } else {
- return pointerLow;
- }
- },
- };
-
- self.onmessage = parseFile;
- // this.onmessage = parseFile;
-
- /*
- These functions map offsets in the blender __blender_file__ to basic types (byte,short,int,float) through TypedArrays;
- This allows the underlying binary data to be changed.
- */
-
- function float64Prop (offset, Blender_Array_Length, length) {
- return {
- get: function () {
- return (Blender_Array_Length > 1) ?
- new Float64Array(this.__blender_file__.AB, this.__data_address__ + offset, length) :
- this.__blender_file__.dv.getFloat64(this.__data_address__ + offset, this.__blender_file__.template.endianess);
- },
- set: function (float) {
- if (Blender_Array_Length > 1) {} else {
- this.__blender_file__.dv.setFloat64(this.__data_address__ + offset, float, this.__blender_file__.template.endianess);
- }
- },
- };
- }
-
- function floatProp (offset, Blender_Array_Length, length) {
- return {
- get: function () {
- return (Blender_Array_Length > 1) ?
- new Float32Array(this.__blender_file__.AB, this.__data_address__ + offset, length) :
- this.__blender_file__.dv.getFloat32(this.__data_address__ + offset, this.__blender_file__.template.endianess);
- },
- set: function (float) {
- if (Blender_Array_Length > 1) {} else {
- this.__blender_file__.dv.setFloat32(this.__data_address__ + offset, float, this.__blender_file__.template.endianess);
- }
- },
- };
- }
-
- function intProp (offset, Blender_Array_Length, length) {
- return {
- get: function () {
- return (Blender_Array_Length > 1) ?
- new Int32Array(this.__blender_file__.AB, this.__data_address__ + offset, length) :
- this.__blender_file__.dv.getInt32(this.__data_address__ + offset, this.__blender_file__.template.endianess);
- },
- set: function (float) {
- if (Blender_Array_Length > 1) {} else {
- this.__blender_file__.dv.setInt32(this.__data_address__ + offset, float, this.__blender_file__.template.endianess);
- }
- },
- };
- }
-
- function uIntProp (offset, Blender_Array_Length, length) {
- return {
- get: function () {
- return (Blender_Array_Length > 1) ?
- new Uint32Array(this.__blender_file__.AB, this.__data_address__ + offset, length) :
- this.__blender_file__.dv.getUint32(this.__data_address__ + offset, this.__blender_file__.template.endianess);
- },
- set: function (float) {
- if (Blender_Array_Length > 1) {} else {
- this.__blender_file__.dv.setUint32(this.__data_address__ + offset, float, this.__blender_file__.template.endianess);
- }
- },
- };
- }
-
- function shortProp (offset, Blender_Array_Length, length) {
- return {
- get: function () {
- return (Blender_Array_Length > 1) ?
- new Int16Array(this.__blender_file__.AB, this.__data_address__ + offset, length) :
- this.__blender_file__.dv.getInt16(this.__data_address__ + offset, this.__blender_file__.template.endianess);
- },
- set: function (float) {
- if (Blender_Array_Length > 1) {} else {
- this.__blender_file__.dv.setInt16(this.__data_address__ + offset, float, this.__blender_file__.template.endianess);
- }
- },
- };
- }
-
- const uShortProp = (offset, Blender_Array_Length, length) => {
- return {
- get: function () {
- return (Blender_Array_Length > 1) ?
- new Uint16Array(this.__blender_file__.AB, this.__data_address__ + offset, length) :
- this.__blender_file__.dv.getUint16(this.__data_address__ + offset, this.__blender_file__.template.endianess);
- },
- set: function (float) {
- if (Blender_Array_Length > 1) {
- } else {
- this.__blender_file__.dv.setUint16(this.__data_address__ + offset, float, this.__blender_file__.template.endianess);
- }
- },
- };
- };
-
- function charProp (offset, Blender_Array_Length, length) {
- return {
- get: function () {
- if (Blender_Array_Length > 1) {
- let start = this.__data_address__ + offset;
- let end = start;
- let buffer_guard = 0;
-
- while (this.__blender_file__.byte[end] != 0 && buffer_guard++ < length) end++;
-
- return toString(this.__blender_file__.AB, start, end);
- }
- return this.__blender_file__.byte[(this.__data_address__ + offset)];
- },
- set: function (byte) {
- if (Blender_Array_Length > 1) {
- const string = byte + '';
- let i = 0;
- const l = string.length;
- while (i < length) {
- if (i < l) {
- this.__blender_file__.byte[(this.__data_address__ + offset + i)] = string.charCodeAt(i) | 0;
- } else {
- this.__blender_file__.byte[(this.__data_address__ + offset + i)] = 0;
- }
- i++;
- }
- } else {
- this.__blender_file__.byte[(this.__data_address__ + offset)] = byte | 0;
- }
- },
- };
- }
-
- function pointerProp2 (offset) {
- return {
- get: function () {
- let pointer = this.__blender_file__.getPointer(this.__data_address__ + offset, this.__blender_file__);
- const link = this.__blender_file__.memory_lookup[pointer];
-
- const results = [];
-
- if (link) {
- const address = link.__data_address__;
- let j = 0;
- while (true) {
- pointer = this.__blender_file__.getPointer(address + j * 8, this.__blender_file__);
- let obj = this.__blender_file__.memory_lookup[pointer];
- if (!obj) break;
- results.push(obj);
- j++;
- }
-
- }
-
- return results;
- },
- set: function () {},
- };
- }
-
- function pointerProp (offset, Blender_Array_Length, length) {
- return {
- get: function () {
- if (Blender_Array_Length > 1) {
- let array = [];
- let j = 0;
- let off = offset;
- while (j < Blender_Array_Length) {
- let pointer = this.__blender_file__.getPointer(this.__data_address__ + off, this.__blender_file__);
-
- array.push(this.__blender_file__.memory_lookup[pointer]);
- off += length;
- j++;
- }
-
- return array;
- } else {
- let pointer = this.__blender_file__.getPointer(this.__data_address__ + offset, this.__blender_file__);
- return this.__blender_file__.memory_lookup[pointer];
- }
- },
- set: function () {},
- };
- }
-
- function compileProp (obj, name, type, offset, array_size, IS_POINTER, pointer_size, length) {
-
- if (!IS_POINTER) {
- switch (type) {
- case 'double':
- Object.defineProperty(obj, name, float64Prop(offset, array_size, length >> 3));
- break;
- case 'float':
- Object.defineProperty(obj, name, floatProp(offset, array_size, length >> 2));
- break;
- case 'int':
- Object.defineProperty(obj, name, intProp(offset, array_size, length >> 2));
- break;
- case 'short':
- case 'ushort':
- Object.defineProperty(obj, name, shortProp(offset, array_size, length >> 1));
- break;
- case 'char':
- case 'uchar':
- Object.defineProperty(obj, name, charProp(offset, array_size, length));
- break;
- default:
- // compile list to
- obj[name] = {};
- obj.__list__.push(name, type, length, offset, array_size, IS_POINTER);
- }
- obj._length += length;
- offset += length;
- } else {
- Object.defineProperty(obj, name, pointerProp(offset, array_size, pointer_size));
- offset += pointer_size * array_size;
- }
-
- return offset;
- }
-
- // Store final DNA structs
- const MASTER_SDNA_SCHEMA = function (version) {
- this.version = version;
- this.SDNA_SET = false;
- this.byte_size = 0;
- this.struct_index = 0;
- this.structs = {};
- this.SDNA = {};
- this.endianess = false;
- };
-
- MASTER_SDNA_SCHEMA.prototype = {
- getSDNAStructureConstructor: function (name, struct) {
- if (struct) {
- const blen_struct = Function('function ' + name + '(){}; return ' + name)();
-
- blen_struct.prototype = new BLENDER_STRUCTURE();
- blen_struct.prototype.blender_name = name;
- blen_struct.prototype.__pointers = [];
- blen_struct.prototype.__list__ = [];
-
- let offset = 0;
- // Create properties of struct
- for (let i = 0; i < struct.length; i += 3) {
- let _name = struct[i];
- const n = _name,
- type = struct[i + 1];
- let length = struct[i + 2],
- array_length = 0,
- match = null,
- Blender_Array_Length = 1,
- Suparray_match = 1,
- PointerToArray = false,
- Pointer_Match = 0;
- const DNA = this.SDNA[name] = {
- constructor: blen_struct,
- };
-
-
- let original_name = _name;
-
- // mini type parser
- if ((match = _name.match(/(\*?)(\*?)(\w+)(\[(\w*)\])?(\[(\w*)\])?/))) {
-
- // base name
- _name = match[3];
-
- // pointer type
- if (match[1]) {
- Pointer_Match = 10;
- blen_struct.prototype.__pointers.push(_name);
- }
-
- if (match[2]) {
- PointerToArray = true;
- }
-
- // arrays
- if (match[4]) {
- if (match[6]) {
- Suparray_match = parseInt(match[5]);
- Blender_Array_Length = parseInt(match[7]);
- } else {
- Blender_Array_Length = parseInt(match[5]);
- }
- }
- array_length = Blender_Array_Length * length;
- length = array_length * Suparray_match;
- }
-
- DNA[n] = {
- type: type,
- length: length,
- isArray: (Blender_Array_Length > 0),
- };
-
- if (PointerToArray) {
- Object.defineProperty(blen_struct.prototype, _name, pointerProp2(offset));
- offset += pointer_size;
- } else if (Suparray_match > 1) {
- const array_names = new Array(Suparray_match);
-
- // construct sub_array object that will return the correct structs
- for (let j = 0; j < Suparray_match; j++) {
- let array_name_ = `__${_name}[${j}]__`;
- array_names[j] = array_name_;
-
- offset = compileProp(blen_struct.prototype, array_name_, type, offset, Blender_Array_Length, Pointer_Match, pointer_size, array_length);
- }
-
- Object.defineProperty(blen_struct.prototype, _name, {
- get: (function (array_names) {
- return function () {
- const array = [];
- for (let i = 0; i < array_names.length; i++) {
- array.push(this[array_names[i]]);
- }
- return array;
- };
- })(array_names),
- });
- } else {
- offset = compileProp(blen_struct.prototype, _name, type, offset, Blender_Array_Length, Pointer_Match, pointer_size, length);
- }
- }
-
- return this.SDNA[name].constructor;
-
- } else {
- if (!this.SDNA[name]) {
- return null;
- }
- return this.SDNA[name].constructor;
- }
- },
- };
-
- var BLENDER_STRUCTURE = function () {
- this.__blender_file__ = null;
- this.__list__ = null;
- this.__super_array_list__ = null;
- this.blender_name = '';
- this.__pointers = null;
- this.address = null;
- this.length = 0;
- this.__data_address__ = 0;
- this.blender_name = '';
- this._length = 0;
- };
-
-
- /*
- Returns a pre-constructed BLENDER_STRUCTURE or creates a new BLENDER_STRUCTURE to match the DNA struct type
- */
- const pointer_function = (pointer) => () => {
- return FILE.memory_lookup[pointer];
- };
-
- function getPointer (offset) {
- const pointerLow = data.getUint32(offset, BIG_ENDIAN);
- if (pointer_size > 4) {
- const pointerHigh = data.getUint32(offset + 4, BIG_ENDIAN);
-
- if (BIG_ENDIAN) {
- return (pointerLow) + '' + pointerHigh;
- } else {
- return (pointerHigh) + '' + pointerLow;
- }
- } else {
- return pointerLow;
- }
- }
-
- BLENDER_STRUCTURE.prototype = {
- setData: function (pointer, _data_offset, data_block_length, BLENDER_FILE) {
- if (this.__list__ === null) return this;
- BLENDER_FILE.addObject(this);
-
- this.__blender_file__ = BLENDER_FILE;
-
- const struct = this.__list__;
- let j = 0,
- i = 0,
- obj, name = '',
- type, length, Blender_Array_Length, Pointer_Match, offset, constructor;
-
- this.__data_address__ = _data_offset;
-
- if (struct === null) return this;
-
- for (i = 0; i < struct.length; i += 6) {
- obj = null;
- name = struct[i];
- type = struct[i + 1];
- Blender_Array_Length = struct[i + 4];
- Pointer_Match = struct[i + 5];
- offset = this.__data_address__ + struct[i + 3];
-
- if (Blender_Array_Length > 1) {
- this[name] = [];
- j = 0;
- while (j < Blender_Array_Length) {
- if (current_SDNA_template.getSDNAStructureConstructor(type)) {
- constructor = current_SDNA_template.getSDNAStructureConstructor(type);
- this[name].push((new constructor()).setData(0, offset, offset + length / Blender_Array_Length, BLENDER_FILE));
- } else this[name].push(null);
- offset += length / Blender_Array_Length;
- j++;
- }
- } else {
- if (current_SDNA_template.getSDNAStructureConstructor(type)) {
- constructor = current_SDNA_template.getSDNAStructureConstructor(type);
- this[name] = (new constructor()).setData(0, offset, length + offset, BLENDER_FILE);
- } else this[name] = null;
- }
- }
- // break connection to configuration list
- this.__list__ = null;
- return this;
- },
-
- get aname () {
- if (this.id) return this.id.name.slice(2);
- else return undefined;
- },
- };
-
- function toString (buffer, _in, _out) {
- return String.fromCharCode.apply(String, new Uint8Array(buffer, _in, _out - _in));
- }
-
- // Begin parsing blender __blender_file__
-
- function readFile () {
- let count = 0;
- let offset2 = 0;
- const root = 0;
- const i = 0;
- let data_offset = 0;
- let sdna_index = 0;
- let code = '';
- let block_length = 0;
- let curr_count = 0;
- let curr_count2 = 0;
-
- FILE.memory_lookup = {};
- struct_names = [];
- offset = 0;
-
- // Make sure we have a .blend __blender_file__. All blend files have the first 12bytes
- // set with BLENDER-v### in Utf-8
- if (toString(_data, offset, 7) !== 'BLENDER') return ERROR = 'File supplied is not a .blend compatible Blender file.';
-
- // otherwise get templete from save version.
-
- offset += 7;
- pointer_size = ((toString(_data, offset++, offset)) == '_') ? 4 : 8;
- BIG_ENDIAN = toString(_data, offset++, offset) !== 'V';
- const version = toString(_data, offset, offset + 3);
-
-
- // create new master template if none exist for current blender version;
- if (!templates[version]) {
- templates[version] = new MASTER_SDNA_SCHEMA(version);
- }
-
- current_SDNA_template = templates[version];
-
- FILE.template = current_SDNA_template;
-
- offset += 3;
-
- // Set SDNA structs if template hasn't been set.
- // Todo: Move the following block into the MASTER_SDNA_SCHEMA object.
- //* Like so:*/ current_SDNA_template.set(AB);
-
- if (!current_SDNA_template.SDNA_SET) {
- current_SDNA_template.endianess = BIG_ENDIAN;
- current_SDNA_template.pointer_size = pointer_size;
- // find DNA1 data block
- offset2 = offset;
-
- while (true) {
- sdna_index = data.getInt32(offset2 + pointer_size + 8, BIG_ENDIAN);
- // eslint-disable-next-line no-control-regex
- code = toString(_data, offset2, offset2 + 4).replace(/\u0000/g, '');
- block_length = data.getInt32(offset2 + 4, true);
- offset2 += 16 + (pointer_size);
- if (code === 'DNA1') {
- // DNA found; This is the core of the __blender_file__ and contains all the structure for the various data types used in Blender.
- count = 0;
- let types = [],
- fields = [],
- names = [],
- lengths = [],
- name = '',
- curr_name = '';
-
- // skip SDNA and NAME identifiers
- offset2 += 8;
-
- // Number of structs.
- count = data.getInt32(offset2, true);
- offset2 += 4;
-
- curr_count = 0;
-
- // Build up list of names for structs
- while (curr_count < count) {
- curr_name = '';
- while (data.getInt8(offset2) !== 0) {
- curr_name += toString(_data, offset2, offset2 + 1);
- offset2++;
- }
- names.push(curr_name);
- offset2++;
- curr_count++;
- }
-
-
- // Adjust for 4byte alignment
- if ((offset2 % 4) > 0) offset2 = (4 - (offset2 % 4)) + offset2;
- offset2 += 4;
-
- // Number of struct types
- count = data.getInt32(offset2, true);
- offset2 += 4;
- curr_count = 0;
-
- // Build up list of types
- while (curr_count < count) {
- curr_name = '';
- while (data.getInt8(offset2) !== 0) {
- curr_name += toString(_data, offset2, offset2 + 1);
- offset2++;
- }
- types.push(curr_name);
- offset2++;
- curr_count++;
- }
-
- // Adjust for 4byte alignment
- if ((offset2 % 4) > 0) offset2 = (4 - (offset2 % 4)) + offset2;
- offset2 += 4;
- curr_count = 0;
-
- // Build up list of byte lengths for types
- while (curr_count < count) {
- lengths.push(data.getInt16(offset2, BIG_ENDIAN));
- offset2 += 2;
- curr_count++;
- }
-
- // Adjust for 4byte alignment
- if ((offset2 % 4) > 0) offset2 = (4 - (offset2 % 4)) + offset2;
- offset2 += 4;
-
- // Number of structures
- const structure_count = data.getInt32(offset2, BIG_ENDIAN);
- offset2 += 4;
- curr_count = 0;
-
- // Create constructor objects from list of SDNA structs
- while (curr_count < structure_count) {
- const struct_name = types[data.getInt16(offset2, BIG_ENDIAN)];
- offset2 += 2;
- const obj = [];
- count = data.getInt16(offset2, BIG_ENDIAN);
- offset2 += 2;
- curr_count2 = 0;
- struct_names.push(struct_name);
-
- // Fill an array with name, type, and length for each SDNA struct property
- while (curr_count2 < count) {
- obj.push(names[data.getInt16(offset2 + 2, BIG_ENDIAN)], types[data.getInt16(offset2, BIG_ENDIAN)], lengths[data.getInt16(offset2, BIG_ENDIAN)]);
- offset2 += 4;
- curr_count2++;
- }
-
- // Create a SDNA constructor by passing [type,name,lenth] array as second argument
- current_SDNA_template.getSDNAStructureConstructor(struct_name, obj);
- curr_count++;
- }
- current_SDNA_template.SDNA_SET = true;
- current_SDNA_template.SDNA_NAMES = struct_names;
- break;
- }
- offset2 += block_length;
- }
- }
-
- // parse the rest of the data, starting back at the top.
-
- // TODO: turn into "on-demand" parsing.
-
- while (true) {
- if ((offset % 4) > 0) {
- offset = (4 - (offset % 4)) + offset;
- }
-
- data_offset = offset;
- sdna_index = data.getInt32(offset + pointer_size + 8, BIG_ENDIAN);
- let code_uint = data.getUint32(offset, BIG_ENDIAN);
- offset2 = offset + 16 + (pointer_size);
- offset += data.getInt32(offset + 4, true) + 16 + (pointer_size);
-
- if (code_uint === DNA1); // skip - already processed at this point
- else if (code_uint === ENDB) break; // end of __blender_file__ found
- else {
- // Create a Blender object using a constructor template from current_SDNA_template
- const data_start = data_offset + pointer_size + 16;
-
- // Get a SDNA constructor by name;
- const constructor = current_SDNA_template.getSDNAStructureConstructor(current_SDNA_template.SDNA_NAMES[sdna_index]);
-
- const size = data.getInt32(data_offset + 4, BIG_ENDIAN);
-
- count = data.getInt32(data_offset + 12 + pointer_size, BIG_ENDIAN);
-
- if (count > 0) {
- let obj = new constructor();
-
- const length = constructor.prototype._length;
-
-
- const address = FILE.getPointer(data_offset + 8);
-
- obj.address = address + '';
-
- obj.setData(address, data_start, data_start + size, FILE);
-
- if (count > 1) {
- let array = [];
- array.push(obj);
- for (let u = 1; u < count; u++) {
- obj = new constructor();
- obj.setData(address, data_start + length * u, data_start + (length * u) + length, FILE);
- array.push(obj);
- }
- FILE.memory_lookup[address] = array;
- } else {
- FILE.memory_lookup[address] = obj;
- }
- }
- }
- }
- }
- }
-
- worker = new worker_code();
-
- worker.postMessage = function (message) {
- return_object.onParseReady(message);
- };
-
- export default return_object;
|