scorm-again 3.1.0 → 3.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cross-frame-api.js +579 -320
- package/dist/cross-frame-api.js.map +1 -1
- package/dist/cross-frame-api.min.js +1 -1
- package/dist/cross-frame-api.min.js.map +1 -1
- package/dist/cross-frame-lms.js +226 -163
- package/dist/cross-frame-lms.js.map +1 -1
- package/dist/cross-frame-lms.min.js +1 -1
- package/dist/cross-frame-lms.min.js.map +1 -1
- package/dist/esm/scorm-again.js +3 -21
- package/dist/esm/scorm-again.js.map +1 -1
- package/dist/esm/scorm-again.min.js +1 -1
- package/dist/esm/scorm-again.min.js.map +1 -1
- package/dist/esm/scorm12.js +1 -7
- package/dist/esm/scorm12.js.map +1 -1
- package/dist/esm/scorm12.min.js +1 -1
- package/dist/esm/scorm12.min.js.map +1 -1
- package/dist/esm/scorm2004.js +2 -14
- package/dist/esm/scorm2004.js.map +1 -1
- package/dist/esm/scorm2004.min.js +1 -1
- package/dist/esm/scorm2004.min.js.map +1 -1
- package/dist/scorm-again.js +32441 -20207
- package/dist/scorm-again.js.map +1 -1
- package/dist/scorm-again.min.js +1 -1
- package/dist/scorm-again.min.js.map +1 -1
- package/dist/scorm12.js +9080 -5233
- package/dist/scorm12.js.map +1 -1
- package/dist/scorm12.min.js +1 -1
- package/dist/scorm12.min.js.map +1 -1
- package/dist/scorm2004.js +29962 -18628
- package/dist/scorm2004.js.map +1 -1
- package/dist/scorm2004.min.js +1 -1
- package/dist/scorm2004.min.js.map +1 -1
- package/package.json +21 -21
package/dist/cross-frame-api.js
CHANGED
|
@@ -1,345 +1,604 @@
|
|
|
1
1
|
this.CrossFrameAPI = (function () {
|
|
2
2
|
'use strict';
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
function _define_property(obj, key, value) {
|
|
5
|
+
if (key in obj) {
|
|
6
|
+
Object.defineProperty(obj, key, {
|
|
7
|
+
value: value,
|
|
8
|
+
enumerable: true,
|
|
9
|
+
configurable: true,
|
|
10
|
+
writable: true
|
|
11
|
+
});
|
|
12
|
+
} else {
|
|
13
|
+
obj[key] = value;
|
|
14
|
+
}
|
|
15
|
+
return obj;
|
|
16
|
+
}
|
|
17
|
+
function _object_spread(target) {
|
|
18
|
+
for(var i = 1; i < arguments.length; i++){
|
|
19
|
+
var source = arguments[i] != null ? arguments[i] : {};
|
|
20
|
+
var ownKeys = Object.keys(source);
|
|
21
|
+
if (typeof Object.getOwnPropertySymbols === "function") {
|
|
22
|
+
ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function(sym) {
|
|
23
|
+
return Object.getOwnPropertyDescriptor(source, sym).enumerable;
|
|
24
|
+
}));
|
|
25
|
+
}
|
|
26
|
+
ownKeys.forEach(function(key) {
|
|
27
|
+
_define_property(target, key, source[key]);
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
return target;
|
|
31
|
+
}
|
|
32
|
+
function ownKeys(object, enumerableOnly) {
|
|
33
|
+
var keys = Object.keys(object);
|
|
34
|
+
if (Object.getOwnPropertySymbols) {
|
|
35
|
+
var symbols = Object.getOwnPropertySymbols(object);
|
|
36
|
+
keys.push.apply(keys, symbols);
|
|
37
|
+
}
|
|
38
|
+
return keys;
|
|
39
|
+
}
|
|
40
|
+
function _object_spread_props(target, source) {
|
|
41
|
+
source = source != null ? source : {};
|
|
42
|
+
if (Object.getOwnPropertyDescriptors) {
|
|
43
|
+
Object.defineProperties(target, Object.getOwnPropertyDescriptors(source));
|
|
44
|
+
} else {
|
|
45
|
+
ownKeys(Object(source)).forEach(function(key) {
|
|
46
|
+
Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
return target;
|
|
50
|
+
}
|
|
51
|
+
var global_errors = {
|
|
52
|
+
GENERAL: 101,
|
|
53
|
+
INITIALIZATION_FAILED: 101,
|
|
54
|
+
INITIALIZED: 101,
|
|
55
|
+
TERMINATED: 101,
|
|
56
|
+
TERMINATION_FAILURE: 101,
|
|
57
|
+
TERMINATION_BEFORE_INIT: 101,
|
|
58
|
+
MULTIPLE_TERMINATION: 101,
|
|
59
|
+
RETRIEVE_BEFORE_INIT: 101,
|
|
60
|
+
RETRIEVE_AFTER_TERM: 101,
|
|
61
|
+
STORE_BEFORE_INIT: 101,
|
|
62
|
+
STORE_AFTER_TERM: 101,
|
|
63
|
+
COMMIT_BEFORE_INIT: 101,
|
|
64
|
+
COMMIT_AFTER_TERM: 101,
|
|
65
|
+
ARGUMENT_ERROR: 101,
|
|
66
|
+
CHILDREN_ERROR: 101,
|
|
67
|
+
COUNT_ERROR: 101,
|
|
68
|
+
GENERAL_GET_FAILURE: 101,
|
|
69
|
+
GENERAL_SET_FAILURE: 101,
|
|
70
|
+
GENERAL_COMMIT_FAILURE: 101,
|
|
71
|
+
UNDEFINED_DATA_MODEL: 101,
|
|
72
|
+
UNIMPLEMENTED_ELEMENT: 101,
|
|
73
|
+
VALUE_NOT_INITIALIZED: 101,
|
|
74
|
+
INVALID_SET_VALUE: 101,
|
|
75
|
+
READ_ONLY_ELEMENT: 101,
|
|
76
|
+
WRITE_ONLY_ELEMENT: 101,
|
|
77
|
+
TYPE_MISMATCH: 101,
|
|
78
|
+
VALUE_OUT_OF_RANGE: 101,
|
|
79
|
+
DEPENDENCY_NOT_ESTABLISHED: 101
|
|
80
|
+
};
|
|
81
|
+
_object_spread_props(_object_spread({}, global_errors), {
|
|
82
|
+
RETRIEVE_BEFORE_INIT: 301,
|
|
83
|
+
STORE_BEFORE_INIT: 301,
|
|
84
|
+
COMMIT_BEFORE_INIT: 301,
|
|
85
|
+
ARGUMENT_ERROR: 201,
|
|
86
|
+
CHILDREN_ERROR: 202,
|
|
87
|
+
COUNT_ERROR: 203,
|
|
88
|
+
UNDEFINED_DATA_MODEL: 401,
|
|
89
|
+
UNIMPLEMENTED_ELEMENT: 401,
|
|
90
|
+
VALUE_NOT_INITIALIZED: 301,
|
|
91
|
+
INVALID_SET_VALUE: 402,
|
|
92
|
+
READ_ONLY_ELEMENT: 403,
|
|
93
|
+
WRITE_ONLY_ELEMENT: 404,
|
|
94
|
+
TYPE_MISMATCH: 405,
|
|
95
|
+
// SCORM 1.2 has no out-of-range error code; an out-of-range value is reported
|
|
96
|
+
// as 405 (incorrect data type), per the SCORM 1.2 RTE error table and the ADL
|
|
97
|
+
// 1.2 CTS (DataModelValidator.checkScoreDecimal failure -> CMICategory 405).
|
|
98
|
+
VALUE_OUT_OF_RANGE: 405,
|
|
99
|
+
DEPENDENCY_NOT_ESTABLISHED: 408
|
|
100
|
+
});
|
|
101
|
+
_object_spread_props(_object_spread({}, global_errors), {
|
|
102
|
+
INITIALIZATION_FAILED: 102,
|
|
103
|
+
INITIALIZED: 103,
|
|
104
|
+
TERMINATED: 104,
|
|
105
|
+
TERMINATION_FAILURE: 111,
|
|
106
|
+
TERMINATION_BEFORE_INIT: 112,
|
|
107
|
+
MULTIPLE_TERMINATION: 113,
|
|
108
|
+
MULTIPLE_TERMINATIONS: 113,
|
|
109
|
+
RETRIEVE_BEFORE_INIT: 122,
|
|
110
|
+
RETRIEVE_AFTER_TERM: 123,
|
|
111
|
+
STORE_BEFORE_INIT: 132,
|
|
112
|
+
STORE_AFTER_TERM: 133,
|
|
113
|
+
COMMIT_BEFORE_INIT: 142,
|
|
114
|
+
COMMIT_AFTER_TERM: 143,
|
|
115
|
+
ARGUMENT_ERROR: 201,
|
|
116
|
+
GENERAL_GET_FAILURE: 301,
|
|
117
|
+
GENERAL_SET_FAILURE: 351,
|
|
118
|
+
GENERAL_COMMIT_FAILURE: 391,
|
|
119
|
+
UNDEFINED_DATA_MODEL: 401,
|
|
120
|
+
UNIMPLEMENTED_ELEMENT: 402,
|
|
121
|
+
VALUE_NOT_INITIALIZED: 403,
|
|
122
|
+
READ_ONLY_ELEMENT: 404,
|
|
123
|
+
WRITE_ONLY_ELEMENT: 405,
|
|
124
|
+
TYPE_MISMATCH: 406,
|
|
125
|
+
VALUE_OUT_OF_RANGE: 407,
|
|
126
|
+
DEPENDENCY_NOT_ESTABLISHED: 408
|
|
127
|
+
});
|
|
6
128
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
129
|
+
function _array_like_to_array(arr, len) {
|
|
130
|
+
if (len == null || len > arr.length) len = arr.length;
|
|
131
|
+
for(var i = 0, arr2 = new Array(len); i < len; i++)arr2[i] = arr[i];
|
|
132
|
+
return arr2;
|
|
133
|
+
}
|
|
134
|
+
function _array_with_holes(arr) {
|
|
135
|
+
if (Array.isArray(arr)) return arr;
|
|
136
|
+
}
|
|
137
|
+
function _class_call_check(instance, Constructor) {
|
|
138
|
+
if (!(instance instanceof Constructor)) {
|
|
139
|
+
throw new TypeError("Cannot call a class as a function");
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
function _defineProperties(target, props) {
|
|
143
|
+
for(var i = 0; i < props.length; i++){
|
|
144
|
+
var descriptor = props[i];
|
|
145
|
+
descriptor.enumerable = descriptor.enumerable || false;
|
|
146
|
+
descriptor.configurable = true;
|
|
147
|
+
if ("value" in descriptor) descriptor.writable = true;
|
|
148
|
+
Object.defineProperty(target, descriptor.key, descriptor);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
function _create_class(Constructor, protoProps, staticProps) {
|
|
152
|
+
if (protoProps) _defineProperties(Constructor.prototype, protoProps);
|
|
153
|
+
if (staticProps) _defineProperties(Constructor, staticProps);
|
|
154
|
+
return Constructor;
|
|
155
|
+
}
|
|
156
|
+
function _instanceof(left, right) {
|
|
157
|
+
"@swc/helpers - instanceof";
|
|
158
|
+
if (right != null && typeof Symbol !== "undefined" && right[Symbol.hasInstance]) {
|
|
159
|
+
return !!right[Symbol.hasInstance](left);
|
|
160
|
+
} else {
|
|
161
|
+
return left instanceof right;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
function _iterable_to_array_limit(arr, i) {
|
|
165
|
+
var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"];
|
|
166
|
+
if (_i == null) return;
|
|
167
|
+
var _arr = [];
|
|
168
|
+
var _n = true;
|
|
169
|
+
var _d = false;
|
|
170
|
+
var _s, _e;
|
|
171
|
+
try {
|
|
172
|
+
for(_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true){
|
|
173
|
+
_arr.push(_s.value);
|
|
174
|
+
if (i && _arr.length === i) break;
|
|
175
|
+
}
|
|
176
|
+
} catch (err) {
|
|
177
|
+
_d = true;
|
|
178
|
+
_e = err;
|
|
179
|
+
} finally{
|
|
180
|
+
try {
|
|
181
|
+
if (!_n && _i["return"] != null) _i["return"]();
|
|
182
|
+
} finally{
|
|
183
|
+
if (_d) throw _e;
|
|
47
184
|
}
|
|
48
|
-
const methodName = prop;
|
|
49
|
-
const isGet = methodName.endsWith("GetValue");
|
|
50
|
-
const isSet = methodName.startsWith("LMSSet") || methodName.endsWith("SetValue");
|
|
51
|
-
const isInit = methodName === "Initialize" || methodName === "LMSInitialize";
|
|
52
|
-
const isFinish = methodName === "Terminate" || methodName === "LMSFinish";
|
|
53
|
-
const isCommit = methodName === "Commit" || methodName === "LMSCommit";
|
|
54
|
-
const isErrorString = methodName === "GetErrorString" || methodName === "LMSGetErrorString";
|
|
55
|
-
const isDiagnostic = methodName === "GetDiagnostic" || methodName === "LMSGetDiagnostic";
|
|
56
|
-
return function () {
|
|
57
|
-
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
|
|
58
|
-
args[_key] = arguments[_key];
|
|
59
|
-
}
|
|
60
|
-
if (!CrossFrameAPI._validateArgs(args)) {
|
|
61
|
-
console.error(`CrossFrameAPI: Invalid arguments for ${methodName}`);
|
|
62
|
-
return "";
|
|
63
|
-
}
|
|
64
|
-
if (isSet && args.length >= 2) {
|
|
65
|
-
const key = args[0];
|
|
66
|
-
target._cache.set(key, String(args[1]));
|
|
67
|
-
target._cacheTimestamps.set(key, Date.now());
|
|
68
|
-
target._lastError = "0";
|
|
69
|
-
}
|
|
70
|
-
const requestTime = Date.now();
|
|
71
|
-
target._post(methodName, args).then(res => {
|
|
72
|
-
if (isGet && args.length >= 1) {
|
|
73
|
-
const key = args[0];
|
|
74
|
-
const localModTime = target._cacheTimestamps.get(key) ?? 0;
|
|
75
|
-
if (localModTime < requestTime) {
|
|
76
|
-
target._cache.set(key, String(res));
|
|
77
|
-
target._cacheTimestamps.delete(key);
|
|
78
|
-
}
|
|
79
|
-
target._lastError = "0";
|
|
80
|
-
}
|
|
81
|
-
if (isErrorString && args.length >= 1) {
|
|
82
|
-
const code = String(args[0]);
|
|
83
|
-
target._cache.set(`error_${code}`, String(res));
|
|
84
|
-
}
|
|
85
|
-
if (isDiagnostic && args.length >= 1) {
|
|
86
|
-
const code = String(args[0]);
|
|
87
|
-
target._cache.set(`diag_${code}`, String(res));
|
|
88
|
-
}
|
|
89
|
-
if (methodName === "GetLastError" || methodName === "LMSGetLastError") {
|
|
90
|
-
target._lastError = String(res);
|
|
91
|
-
}
|
|
92
|
-
}).catch(err => target._capture(methodName, err));
|
|
93
|
-
if (isGet && args.length >= 1) {
|
|
94
|
-
return target._cache.get(args[0]) ?? "";
|
|
95
|
-
}
|
|
96
|
-
if (isErrorString && args.length >= 1) {
|
|
97
|
-
const code = String(args[0]);
|
|
98
|
-
return target._cache.get(`error_${code}`) ?? "";
|
|
99
|
-
}
|
|
100
|
-
if (isDiagnostic && args.length >= 1) {
|
|
101
|
-
const code = String(args[0]);
|
|
102
|
-
return target._cache.get(`diag_${code}`) ?? "";
|
|
103
|
-
}
|
|
104
|
-
if (isInit || isFinish || isCommit || isSet) {
|
|
105
|
-
const result = "true";
|
|
106
|
-
target._post("getFlattenedCMI", []).then(all => {
|
|
107
|
-
if (all && typeof all === "object") {
|
|
108
|
-
const entries = Object.entries(all);
|
|
109
|
-
entries.forEach(_ref => {
|
|
110
|
-
let [key, val] = _ref;
|
|
111
|
-
const localModTime = target._cacheTimestamps.get(key) ?? 0;
|
|
112
|
-
if (localModTime < requestTime) {
|
|
113
|
-
target._cache.set(key, val);
|
|
114
|
-
target._cacheTimestamps.delete(key);
|
|
115
|
-
}
|
|
116
|
-
});
|
|
117
|
-
}
|
|
118
|
-
target._lastError = "0";
|
|
119
|
-
}).catch(err => target._capture("getFlattenedCMI", err));
|
|
120
|
-
return result;
|
|
121
|
-
}
|
|
122
|
-
if (methodName === "GetLastError" || methodName === "LMSGetLastError") {
|
|
123
|
-
return target._lastError;
|
|
124
|
-
}
|
|
125
|
-
return "";
|
|
126
|
-
};
|
|
127
|
-
}
|
|
128
|
-
});
|
|
129
|
-
this._origin = targetOrigin;
|
|
130
|
-
this._targetWindow = targetWindow;
|
|
131
|
-
this._timeout = options.timeout ?? 5e3;
|
|
132
|
-
this._heartbeatInterval = options.heartbeatInterval ?? 3e4;
|
|
133
|
-
this._heartbeatTimeout = options.heartbeatTimeout ?? 6e4;
|
|
134
|
-
if (targetOrigin === "*") {
|
|
135
|
-
console.warn("CrossFrameAPI: Using wildcard origin ('*') allows any origin to receive messages. This is insecure for production use. Specify an explicit origin (e.g., 'https://lms.example.com') to restrict message recipients.");
|
|
136
185
|
}
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
186
|
+
return _arr;
|
|
187
|
+
}
|
|
188
|
+
function _non_iterable_rest() {
|
|
189
|
+
throw new TypeError("Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
|
|
190
|
+
}
|
|
191
|
+
function _sliced_to_array(arr, i) {
|
|
192
|
+
return _array_with_holes(arr) || _iterable_to_array_limit(arr, i) || _unsupported_iterable_to_array(arr, i) || _non_iterable_rest();
|
|
193
|
+
}
|
|
194
|
+
function _type_of(obj) {
|
|
195
|
+
"@swc/helpers - typeof";
|
|
196
|
+
return obj && typeof Symbol !== "undefined" && obj.constructor === Symbol ? "symbol" : typeof obj;
|
|
197
|
+
}
|
|
198
|
+
function _unsupported_iterable_to_array(o, minLen) {
|
|
199
|
+
if (!o) return;
|
|
200
|
+
if (typeof o === "string") return _array_like_to_array(o, minLen);
|
|
201
|
+
var n = Object.prototype.toString.call(o).slice(8, -1);
|
|
202
|
+
if (n === "Object" && o.constructor) n = o.constructor.name;
|
|
203
|
+
if (n === "Map" || n === "Set") return Array.from(n);
|
|
204
|
+
if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _array_like_to_array(o, minLen);
|
|
205
|
+
}
|
|
206
|
+
var __defProp = Object.defineProperty;
|
|
207
|
+
var __defNormalProp = function __defNormalProp(obj, key, value) {
|
|
208
|
+
return key in obj ? __defProp(obj, key, {
|
|
209
|
+
enumerable: true,
|
|
210
|
+
configurable: true,
|
|
211
|
+
writable: true,
|
|
212
|
+
value: value
|
|
213
|
+
}) : obj[key] = value;
|
|
214
|
+
};
|
|
215
|
+
var __publicField = function __publicField(obj, key, value) {
|
|
216
|
+
return __defNormalProp(obj, (typeof key === "undefined" ? "undefined" : _type_of(key)) !== "symbol" ? key + "" : key, value);
|
|
217
|
+
};
|
|
218
|
+
var CrossFrameAPI = /*#__PURE__*/ function() {
|
|
219
|
+
function CrossFrameAPI() {
|
|
220
|
+
var targetOrigin = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : "*", targetWindow = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : window.parent, options = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : {};
|
|
221
|
+
_class_call_check(this, CrossFrameAPI);
|
|
222
|
+
var _options_timeout, _options_heartbeatInterval, _options_heartbeatTimeout;
|
|
223
|
+
__publicField(this, "_cache", /* @__PURE__ */ new Map());
|
|
224
|
+
__publicField(this, "_cacheTimestamps", /* @__PURE__ */ new Map());
|
|
225
|
+
__publicField(this, "_lastError", "0");
|
|
226
|
+
__publicField(this, "_pending", /* @__PURE__ */ new Map());
|
|
227
|
+
__publicField(this, "_counter", 0);
|
|
228
|
+
__publicField(this, "_origin");
|
|
229
|
+
__publicField(this, "_targetWindow");
|
|
230
|
+
__publicField(this, "_timeout");
|
|
231
|
+
__publicField(this, "_heartbeatInterval");
|
|
232
|
+
__publicField(this, "_heartbeatTimeout");
|
|
233
|
+
__publicField(this, "_destroyed", false);
|
|
234
|
+
__publicField(this, "_connected", true);
|
|
235
|
+
__publicField(this, "_lastHeartbeatResponse", Date.now());
|
|
236
|
+
__publicField(this, "_heartbeatTimer");
|
|
237
|
+
__publicField(this, "_eventListeners", /* @__PURE__ */ new Map());
|
|
238
|
+
__publicField(this, "_boundOnMessage");
|
|
239
|
+
__publicField(this, "_handler", {
|
|
240
|
+
get: function get(target, prop, receiver) {
|
|
241
|
+
if (typeof prop !== "string" || prop in target) {
|
|
242
|
+
var v = Reflect.get(target, prop, receiver);
|
|
243
|
+
return typeof v === "function" ? v.bind(target) : v;
|
|
244
|
+
}
|
|
245
|
+
var methodName = prop;
|
|
246
|
+
var isGet = methodName.endsWith("GetValue");
|
|
247
|
+
var isSet = methodName.startsWith("LMSSet") || methodName.endsWith("SetValue");
|
|
248
|
+
var isInit = methodName === "Initialize" || methodName === "LMSInitialize";
|
|
249
|
+
var isFinish = methodName === "Terminate" || methodName === "LMSFinish";
|
|
250
|
+
var isCommit = methodName === "Commit" || methodName === "LMSCommit";
|
|
251
|
+
var isErrorString = methodName === "GetErrorString" || methodName === "LMSGetErrorString";
|
|
252
|
+
var isDiagnostic = methodName === "GetDiagnostic" || methodName === "LMSGetDiagnostic";
|
|
253
|
+
return function() {
|
|
254
|
+
for(var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++){
|
|
255
|
+
args[_key] = arguments[_key];
|
|
256
|
+
}
|
|
257
|
+
if (!CrossFrameAPI._validateArgs(args)) {
|
|
258
|
+
console.error("CrossFrameAPI: Invalid arguments for ".concat(methodName));
|
|
259
|
+
return "";
|
|
260
|
+
}
|
|
261
|
+
if (isSet && args.length >= 2) {
|
|
262
|
+
var key = args[0];
|
|
263
|
+
target._cache.set(key, String(args[1]));
|
|
264
|
+
target._cacheTimestamps.set(key, Date.now());
|
|
265
|
+
target._lastError = "0";
|
|
266
|
+
}
|
|
267
|
+
var requestTime = Date.now();
|
|
268
|
+
target._post(methodName, args).then(function(res) {
|
|
269
|
+
if (isGet && args.length >= 1) {
|
|
270
|
+
var _target__cacheTimestamps_get;
|
|
271
|
+
var key = args[0];
|
|
272
|
+
var localModTime = (_target__cacheTimestamps_get = target._cacheTimestamps.get(key)) !== null && _target__cacheTimestamps_get !== void 0 ? _target__cacheTimestamps_get : 0;
|
|
273
|
+
if (localModTime < requestTime) {
|
|
274
|
+
target._cache.set(key, String(res));
|
|
275
|
+
target._cacheTimestamps.delete(key);
|
|
276
|
+
}
|
|
277
|
+
target._lastError = "0";
|
|
278
|
+
}
|
|
279
|
+
if (isErrorString && args.length >= 1) {
|
|
280
|
+
var code = String(args[0]);
|
|
281
|
+
target._cache.set("error_".concat(code), String(res));
|
|
282
|
+
}
|
|
283
|
+
if (isDiagnostic && args.length >= 1) {
|
|
284
|
+
var code1 = String(args[0]);
|
|
285
|
+
target._cache.set("diag_".concat(code1), String(res));
|
|
286
|
+
}
|
|
287
|
+
if (methodName === "GetLastError" || methodName === "LMSGetLastError") {
|
|
288
|
+
target._lastError = String(res);
|
|
289
|
+
}
|
|
290
|
+
}).catch(function(err) {
|
|
291
|
+
return target._capture(methodName, err);
|
|
292
|
+
});
|
|
293
|
+
if (isGet && args.length >= 1) {
|
|
294
|
+
var _target__cache_get;
|
|
295
|
+
return (_target__cache_get = target._cache.get(args[0])) !== null && _target__cache_get !== void 0 ? _target__cache_get : "";
|
|
296
|
+
}
|
|
297
|
+
if (isErrorString && args.length >= 1) {
|
|
298
|
+
var _target__cache_get1;
|
|
299
|
+
var code = String(args[0]);
|
|
300
|
+
return (_target__cache_get1 = target._cache.get("error_".concat(code))) !== null && _target__cache_get1 !== void 0 ? _target__cache_get1 : "";
|
|
301
|
+
}
|
|
302
|
+
if (isDiagnostic && args.length >= 1) {
|
|
303
|
+
var _target__cache_get2;
|
|
304
|
+
var code1 = String(args[0]);
|
|
305
|
+
return (_target__cache_get2 = target._cache.get("diag_".concat(code1))) !== null && _target__cache_get2 !== void 0 ? _target__cache_get2 : "";
|
|
306
|
+
}
|
|
307
|
+
if (isInit || isFinish || isCommit || isSet) {
|
|
308
|
+
var result = "true";
|
|
309
|
+
target._post("getFlattenedCMI", []).then(function(all) {
|
|
310
|
+
if (all && (typeof all === "undefined" ? "undefined" : _type_of(all)) === "object") {
|
|
311
|
+
var entries = Object.entries(all);
|
|
312
|
+
entries.forEach(function(param) {
|
|
313
|
+
var _param = _sliced_to_array(param, 2), key = _param[0], val = _param[1];
|
|
314
|
+
var _target__cacheTimestamps_get;
|
|
315
|
+
var localModTime = (_target__cacheTimestamps_get = target._cacheTimestamps.get(key)) !== null && _target__cacheTimestamps_get !== void 0 ? _target__cacheTimestamps_get : 0;
|
|
316
|
+
if (localModTime < requestTime) {
|
|
317
|
+
target._cache.set(key, val);
|
|
318
|
+
target._cacheTimestamps.delete(key);
|
|
319
|
+
}
|
|
320
|
+
});
|
|
321
|
+
}
|
|
322
|
+
target._lastError = "0";
|
|
323
|
+
}).catch(function(err) {
|
|
324
|
+
return target._capture("getFlattenedCMI", err);
|
|
325
|
+
});
|
|
326
|
+
return result;
|
|
327
|
+
}
|
|
328
|
+
if (methodName === "GetLastError" || methodName === "LMSGetLastError") {
|
|
329
|
+
return target._lastError;
|
|
330
|
+
}
|
|
331
|
+
return "";
|
|
332
|
+
};
|
|
333
|
+
}
|
|
334
|
+
});
|
|
335
|
+
this._origin = targetOrigin;
|
|
336
|
+
this._targetWindow = targetWindow;
|
|
337
|
+
this._timeout = (_options_timeout = options.timeout) !== null && _options_timeout !== void 0 ? _options_timeout : 5e3;
|
|
338
|
+
this._heartbeatInterval = (_options_heartbeatInterval = options.heartbeatInterval) !== null && _options_heartbeatInterval !== void 0 ? _options_heartbeatInterval : 3e4;
|
|
339
|
+
this._heartbeatTimeout = (_options_heartbeatTimeout = options.heartbeatTimeout) !== null && _options_heartbeatTimeout !== void 0 ? _options_heartbeatTimeout : 6e4;
|
|
340
|
+
if (targetOrigin === "*") {
|
|
341
|
+
console.warn("CrossFrameAPI: Using wildcard origin ('*') allows any origin to receive messages. This is insecure for production use. Specify an explicit origin (e.g., 'https://lms.example.com') to restrict message recipients.");
|
|
342
|
+
}
|
|
343
|
+
this._boundOnMessage = this._onMessage.bind(this);
|
|
344
|
+
window.addEventListener("message", this._boundOnMessage);
|
|
345
|
+
this._startHeartbeat();
|
|
346
|
+
return new Proxy(this, this._handler);
|
|
154
347
|
}
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
/**
|
|
159
|
-
* Validates that args is an array and sanitizes it for safe use
|
|
160
|
-
*/
|
|
161
|
-
static _validateArgs(args) {
|
|
162
|
-
if (!Array.isArray(args)) return false;
|
|
163
|
-
return true;
|
|
164
|
-
}
|
|
165
|
-
/**
|
|
348
|
+
_create_class(CrossFrameAPI, [
|
|
349
|
+
{
|
|
350
|
+
/**
|
|
166
351
|
* Destroys this instance, removing event listeners and preventing further message processing.
|
|
167
352
|
* Once destroyed, the instance cannot be reused.
|
|
168
|
-
*/
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
353
|
+
*/ key: "destroy",
|
|
354
|
+
value: function destroy() {
|
|
355
|
+
if (this._destroyed) return;
|
|
356
|
+
this._destroyed = true;
|
|
357
|
+
window.removeEventListener("message", this._boundOnMessage);
|
|
358
|
+
if (this._heartbeatTimer) {
|
|
359
|
+
clearInterval(this._heartbeatTimer);
|
|
360
|
+
this._heartbeatTimer = void 0;
|
|
361
|
+
}
|
|
362
|
+
var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
|
|
363
|
+
try {
|
|
364
|
+
for(var _iterator = Array.from(this._pending.values())[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
|
|
365
|
+
var pending = _step.value;
|
|
366
|
+
clearTimeout(pending.timer);
|
|
367
|
+
pending.reject(new Error("CrossFrameAPI destroyed"));
|
|
368
|
+
}
|
|
369
|
+
} catch (err) {
|
|
370
|
+
_didIteratorError = true;
|
|
371
|
+
_iteratorError = err;
|
|
372
|
+
} finally{
|
|
373
|
+
try {
|
|
374
|
+
if (!_iteratorNormalCompletion && _iterator.return != null) {
|
|
375
|
+
_iterator.return();
|
|
376
|
+
}
|
|
377
|
+
} finally{
|
|
378
|
+
if (_didIteratorError) {
|
|
379
|
+
throw _iteratorError;
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
this._pending.clear();
|
|
384
|
+
this._cache.clear();
|
|
385
|
+
this._cacheTimestamps.clear();
|
|
386
|
+
this._eventListeners.clear();
|
|
387
|
+
}
|
|
388
|
+
},
|
|
389
|
+
{
|
|
390
|
+
/**
|
|
187
391
|
* Subscribes to a CrossFrame event.
|
|
188
392
|
* @param event - Event type to listen for
|
|
189
393
|
* @param callback - Function to call when event occurs
|
|
190
|
-
*/
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
394
|
+
*/ key: "on",
|
|
395
|
+
value: function on(event, callback) {
|
|
396
|
+
var _this__eventListeners_get;
|
|
397
|
+
if (!this._eventListeners.has(event)) {
|
|
398
|
+
this._eventListeners.set(event, /* @__PURE__ */ new Set());
|
|
399
|
+
}
|
|
400
|
+
(_this__eventListeners_get = this._eventListeners.get(event)) === null || _this__eventListeners_get === void 0 ? void 0 : _this__eventListeners_get.add(callback);
|
|
401
|
+
}
|
|
402
|
+
},
|
|
403
|
+
{
|
|
404
|
+
/**
|
|
198
405
|
* Unsubscribes from a CrossFrame event.
|
|
199
406
|
* @param event - Event type to stop listening for
|
|
200
407
|
* @param callback - Function to remove
|
|
201
|
-
*/
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
408
|
+
*/ key: "off",
|
|
409
|
+
value: function off(event, callback) {
|
|
410
|
+
var _this__eventListeners_get;
|
|
411
|
+
(_this__eventListeners_get = this._eventListeners.get(event)) === null || _this__eventListeners_get === void 0 ? void 0 : _this__eventListeners_get.delete(callback);
|
|
412
|
+
}
|
|
413
|
+
},
|
|
414
|
+
{
|
|
415
|
+
key: "connected",
|
|
416
|
+
get: /**
|
|
206
417
|
* Returns whether the connection to the LMS frame is currently active.
|
|
207
|
-
*/
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
418
|
+
*/ function get() {
|
|
419
|
+
return this._connected;
|
|
420
|
+
}
|
|
421
|
+
},
|
|
422
|
+
{
|
|
423
|
+
/**
|
|
212
424
|
* Emits an event to all registered listeners.
|
|
213
|
-
*/
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
425
|
+
*/ key: "_emit",
|
|
426
|
+
value: function _emit(event) {
|
|
427
|
+
var _this__eventListeners_get;
|
|
428
|
+
(_this__eventListeners_get = this._eventListeners.get(event.type)) === null || _this__eventListeners_get === void 0 ? void 0 : _this__eventListeners_get.forEach(function(cb) {
|
|
429
|
+
return cb(event);
|
|
430
|
+
});
|
|
431
|
+
}
|
|
432
|
+
},
|
|
433
|
+
{
|
|
434
|
+
/**
|
|
218
435
|
* Starts the heartbeat mechanism for connection detection.
|
|
219
|
-
*/
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
436
|
+
*/ key: "_startHeartbeat",
|
|
437
|
+
value: function _startHeartbeat() {
|
|
438
|
+
var _this = this;
|
|
439
|
+
if (this._heartbeatTimer) {
|
|
440
|
+
clearInterval(this._heartbeatTimer);
|
|
441
|
+
}
|
|
442
|
+
this._heartbeatTimer = setInterval(function() {
|
|
443
|
+
if (_this._destroyed) return;
|
|
444
|
+
var timeSinceLastResponse = Date.now() - _this._lastHeartbeatResponse;
|
|
445
|
+
if (timeSinceLastResponse > _this._heartbeatTimeout && _this._connected) {
|
|
446
|
+
_this._connected = false;
|
|
447
|
+
_this._emit({
|
|
448
|
+
type: "connectionLost"
|
|
449
|
+
});
|
|
450
|
+
}
|
|
451
|
+
_this._sendHeartbeat();
|
|
452
|
+
}, this._heartbeatInterval);
|
|
453
|
+
}
|
|
454
|
+
},
|
|
455
|
+
{
|
|
456
|
+
/**
|
|
237
457
|
* Sends a heartbeat ping to the LMS frame.
|
|
238
|
-
*/
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
458
|
+
*/ key: "_sendHeartbeat",
|
|
459
|
+
value: function _sendHeartbeat() {
|
|
460
|
+
var messageId = "hb-".concat(Date.now(), "-").concat(this._counter++);
|
|
461
|
+
var msg = {
|
|
462
|
+
messageId: messageId,
|
|
463
|
+
method: "__heartbeat__",
|
|
464
|
+
params: [],
|
|
465
|
+
isHeartbeat: true
|
|
466
|
+
};
|
|
467
|
+
this._targetWindow.postMessage(msg, this._origin);
|
|
468
|
+
}
|
|
469
|
+
},
|
|
470
|
+
{
|
|
471
|
+
/**
|
|
250
472
|
* Send a message to the LMS frame and return a promise for its response.
|
|
251
|
-
*/
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
473
|
+
*/ key: "_post",
|
|
474
|
+
value: function _post(method, params) {
|
|
475
|
+
var _this = this;
|
|
476
|
+
if (this._destroyed) {
|
|
477
|
+
return Promise.reject(new Error("CrossFrameAPI destroyed"));
|
|
478
|
+
}
|
|
479
|
+
var messageId = "cfapi-".concat(Date.now(), "-").concat(this._counter++);
|
|
480
|
+
var requestTime = Date.now();
|
|
481
|
+
var safeParams = params.map(function(p) {
|
|
482
|
+
if (typeof p === "function") {
|
|
483
|
+
console.warn("Dropping function param when posting SCORM call:", method);
|
|
484
|
+
return void 0;
|
|
485
|
+
}
|
|
486
|
+
return p;
|
|
487
|
+
});
|
|
488
|
+
return new Promise(function(resolve, reject) {
|
|
489
|
+
var timer = setTimeout(function() {
|
|
490
|
+
if (_this._pending.has(messageId)) {
|
|
491
|
+
_this._pending.delete(messageId);
|
|
492
|
+
reject(new Error("Timeout calling ".concat(method)));
|
|
493
|
+
}
|
|
494
|
+
}, _this._timeout);
|
|
495
|
+
_this._pending.set(messageId, {
|
|
496
|
+
resolve: resolve,
|
|
497
|
+
reject: reject,
|
|
498
|
+
timer: timer,
|
|
499
|
+
requestTime: requestTime,
|
|
500
|
+
method: method
|
|
501
|
+
});
|
|
502
|
+
var msg = {
|
|
503
|
+
messageId: messageId,
|
|
504
|
+
method: method,
|
|
505
|
+
params: safeParams
|
|
506
|
+
};
|
|
507
|
+
_this._targetWindow.postMessage(msg, _this._origin);
|
|
508
|
+
});
|
|
509
|
+
}
|
|
510
|
+
},
|
|
511
|
+
{
|
|
512
|
+
/**
|
|
288
513
|
* Handle incoming postMessage responses from the LMS frame.
|
|
289
|
-
*/
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
514
|
+
*/ key: "_onMessage",
|
|
515
|
+
value: function _onMessage(ev) {
|
|
516
|
+
if (this._destroyed) return;
|
|
517
|
+
if (this._origin !== "*" && ev.origin !== this._origin) {
|
|
518
|
+
return;
|
|
519
|
+
}
|
|
520
|
+
if (ev.source && ev.source !== this._targetWindow) {
|
|
521
|
+
return;
|
|
522
|
+
}
|
|
523
|
+
if (!CrossFrameAPI._isValidMessageResponse(ev.data)) return;
|
|
524
|
+
var data = ev.data;
|
|
525
|
+
if (data.isHeartbeat) {
|
|
526
|
+
this._lastHeartbeatResponse = Date.now();
|
|
527
|
+
if (!this._connected) {
|
|
528
|
+
this._connected = true;
|
|
529
|
+
this._emit({
|
|
530
|
+
type: "connectionRestored"
|
|
531
|
+
});
|
|
532
|
+
}
|
|
533
|
+
return;
|
|
534
|
+
}
|
|
535
|
+
var pending = this._pending.get(data.messageId);
|
|
536
|
+
if (!pending) return;
|
|
537
|
+
clearTimeout(pending.timer);
|
|
538
|
+
this._pending.delete(data.messageId);
|
|
539
|
+
if (data.error) {
|
|
540
|
+
if (data.error.message === "Rate limit exceeded") {
|
|
541
|
+
this._emit({
|
|
542
|
+
type: "rateLimited",
|
|
543
|
+
method: pending.method
|
|
544
|
+
});
|
|
545
|
+
}
|
|
546
|
+
pending.reject(data.error);
|
|
547
|
+
} else {
|
|
548
|
+
pending.resolve(data.result);
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
},
|
|
552
|
+
{
|
|
553
|
+
/**
|
|
327
554
|
* Capture and cache SCORM errors.
|
|
328
|
-
*/
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
555
|
+
*/ key: "_capture",
|
|
556
|
+
value: function _capture(method, err) {
|
|
557
|
+
var _ref;
|
|
558
|
+
var errorMessage = "Unknown error";
|
|
559
|
+
if (_instanceof(err, Error)) {
|
|
560
|
+
errorMessage = err.message;
|
|
561
|
+
} else if ((typeof err === "undefined" ? "undefined" : _type_of(err)) === "object" && err !== null && "message" in err) {
|
|
562
|
+
errorMessage = String(err.message);
|
|
563
|
+
}
|
|
564
|
+
console.error("CrossFrameAPI ".concat(method, " error:"), err);
|
|
565
|
+
var match = /(?:error code|code)?\s*(\d{3})\b/i.exec(errorMessage);
|
|
566
|
+
var code = (_ref = match === null || match === void 0 ? void 0 : match[1]) !== null && _ref !== void 0 ? _ref : String(global_errors.GENERAL);
|
|
567
|
+
this._lastError = code;
|
|
568
|
+
this._cache.set("error_".concat(code), errorMessage);
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
], [
|
|
572
|
+
{
|
|
573
|
+
key: "_isValidMessageResponse",
|
|
574
|
+
value: /**
|
|
575
|
+
* Type guard to validate MessageResponse structure
|
|
576
|
+
*/ function _isValidMessageResponse(data) {
|
|
577
|
+
if ((typeof data === "undefined" ? "undefined" : _type_of(data)) !== "object" || data === null) return false;
|
|
578
|
+
var resp = data;
|
|
579
|
+
if (typeof resp.messageId !== "string" || resp.messageId.length === 0) return false;
|
|
580
|
+
if (resp.error !== void 0) {
|
|
581
|
+
if (_type_of(resp.error) !== "object" || resp.error === null) return false;
|
|
582
|
+
var err = resp.error;
|
|
583
|
+
if (typeof err.message !== "string") return false;
|
|
584
|
+
if (err.code !== void 0 && typeof err.code !== "string") return false;
|
|
585
|
+
}
|
|
586
|
+
if (resp.isHeartbeat !== void 0 && typeof resp.isHeartbeat !== "boolean") return false;
|
|
587
|
+
return true;
|
|
588
|
+
}
|
|
589
|
+
},
|
|
590
|
+
{
|
|
591
|
+
key: "_validateArgs",
|
|
592
|
+
value: /**
|
|
593
|
+
* Validates that args is an array and sanitizes it for safe use
|
|
594
|
+
*/ function _validateArgs(args) {
|
|
595
|
+
if (!Array.isArray(args)) return false;
|
|
596
|
+
return true;
|
|
597
|
+
}
|
|
598
|
+
}
|
|
599
|
+
]);
|
|
600
|
+
return CrossFrameAPI;
|
|
601
|
+
}();
|
|
343
602
|
|
|
344
603
|
return CrossFrameAPI;
|
|
345
604
|
|