efront 4.5.0 → 4.5.4

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.
@@ -1,5 +1,4 @@
1
1
  var acmebase = `https://acme-v02.api.letsencrypt.org/`;
2
- // <!-- acmebase=`https://acme-staging-v02.api.letsencrypt.org/` -->
3
2
  var data1 = data.enrich(parseYML(`
4
3
  ${acmebase}:
5
4
  directory: get directory
@@ -21,20 +20,13 @@ var base64url = function (params) {
21
20
  };
22
21
  var accountApi = await data1.getApi('get-account');
23
22
  var orderApi = await data1.getApi('get-order');
24
-
25
- var request = async function (id, params) {
26
- var api = await data1.getApi(id);
27
- if (/^(get|head)$/i.test(api.method)) return data1.from(id, params);
23
+ var wrapParams = async function (url, params, usejwk = false) {
28
24
  var protected = {
29
- url: api.base + api.path,
25
+ url
30
26
  };
31
- var rest;
32
- [protected.url, rest] = data.prepareURL(protected.url, params);
33
- var restparams = {};
34
- rest.forEach(k => { restparams[k] = params[k]; delete params[k]; });
35
27
  var jwk = await subtle.exportKey("jwk", publicKey);
36
28
  protected.alg = jwk.alg;
37
- if (/new-account|revert-cert/i.test(id)) {
29
+ if (usejwk) {
38
30
  protected.jwk = {
39
31
  e: jwk.e,
40
32
  kty: jwk.kty,
@@ -45,17 +37,124 @@ var request = async function (id, params) {
45
37
  protected.kid = acme2.kid;
46
38
  }
47
39
  protected.nonce = await data1.from("new-nonce");
48
- var payload = isEmpty(params) ? '' : base64url(params);
49
40
  protected = base64url(protected);
41
+ var payload = isHandled(params) ? base64url(params) : '';
50
42
  var params = {
51
43
  protected,
52
44
  payload,
53
45
  signature: toBase64(new Uint8Array(await subtle.sign({ name: RSASSA_PKCS1_v1_5, saltLength: 32 }, privateKey, new Uint8Array(encodeUTF8([protected, '.', payload].join(''))))), true)
54
46
  };
47
+ return params;
48
+ }
49
+ var request = async function (id, params) {
50
+ var api = await data1.getApi(id);
51
+ if (/^(get|head)$/i.test(api.method)) return data1.from(id, params);
52
+ var [url, rest] = data.prepareURL(api.base + api.path, params);
53
+ var restparams = {};
54
+ rest.forEach(k => { restparams[k] = params[k]; delete params[k]; });
55
+ var params = await wrapParams(url, params, /new-account|revert-cert/i.test(id));
55
56
  extend(params, restparams);
56
57
  var account = await data1.from(id, params);
57
58
  return account;
58
59
  };
60
+ var ASN1 = function (type) {
61
+ var length = 0;
62
+ var bytesarr = [];
63
+ for (var cx = 1, dx = arguments.length; cx < dx; cx++) {
64
+ var bytes = arguments[cx];
65
+ if (bytes.constructor !== Array) {
66
+ bytes = Array.apply(null, bytes);
67
+ }
68
+ bytesarr.push(bytes);
69
+ length += bytes.length;
70
+ }
71
+ var asn1 = [type];
72
+ if (length === (2 << 8 | 36)) console.log(arguments)
73
+ if (length > 127) {
74
+ var nums = [];
75
+ while (length > 0) {
76
+ nums.unshift(length & 0xff);
77
+ length = length >>> 8;
78
+ }
79
+ asn1.push(0x80 | nums.length, ...nums);
80
+ }
81
+ else {
82
+ asn1.push(length);
83
+ }
84
+ asn1 = asn1.concat(...bytesarr);
85
+ return asn1;
86
+ };
87
+ var packUint = function (bytes) {
88
+ if (bytes[0] & 0x80) {
89
+ return ASN1(0x02, [0], bytes);
90
+ }
91
+ return ASN1(0x02, bytes);
92
+ };
93
+ var packBits = function (bytes) {
94
+ return ASN1(0x03, [0x00], bytes);
95
+ };
96
+ var packPublicKey = function (jwk) {
97
+ var n = packUint(fromBase64(jwk.n));
98
+ var e = packUint(fromBase64(jwk.e));
99
+ var p = ASN1(0x30, n, e);
100
+ return ASN1(0x30, ASN1(0x30,
101
+ ASN1(0x06, [0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01]),
102
+ ASN1(0x05),
103
+ ), packBits(p));
104
+ };
105
+ var packCSR = function (asn1pubkey, domains) {
106
+ return ASN1(0x30,
107
+ packUint([0x00]),
108
+ ASN1(0x30, ASN1(0x31, ASN1(0x30,
109
+ ASN1(0x06, [0x55, 0x04, 0x03]),
110
+ ASN1(0x0c, encodeUTF8(domains[0]))
111
+ ))),
112
+ asn1pubkey,
113
+ ASN1(0xa0, ASN1(0x30,
114
+ ASN1(0x06, [0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x0e]),
115
+ ASN1(0x31, ASN1(0x30, ASN1(0x30,
116
+ ASN1(0x06, [0x55, 0x1d, 0x11]),
117
+ ASN1(0x04, ASN1(0x30,
118
+ ...domains.map(d => ASN1(0x82, encodeUTF8(d)))
119
+ ))
120
+ )))
121
+ ))
122
+ )
123
+ }
124
+
125
+ var createCSR = async function (domains, private_key) {
126
+ var privateKey = await subtle.importKey("pkcs8", new Uint8Array(fromBase64(private_key)), {
127
+ name: RSASSA_PKCS1_v1_5,
128
+ hash: "SHA-256",
129
+ }, true, ["sign"]);
130
+ var jwk = await subtle.exportKey("jwk", privateKey);
131
+ var pubkey = packPublicKey(jwk);
132
+ var request = packCSR(pubkey, domains);
133
+ var sign = new Uint8Array(await subtle.sign({ name: RSASSA_PKCS1_v1_5, saltLength: 32 }, privateKey, new Uint8Array(request)));
134
+ var sty = ASN1(0x30,
135
+ ASN1(0x06, [0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b]),
136
+ ASN1(0x05)
137
+ );
138
+ return ASN1(0x30, request,
139
+ sty,
140
+ packBits(sign)
141
+ );
142
+ };
143
+ var makeKeyPair = async function (modulusLength = 2048) {
144
+ //https://www.w3.org/TR/WebCryptoAPI/ 第20章 只有RSASSA-PKCS1-v1_5的jwk的alg才是rs256
145
+ var k = await subtle.generateKey({
146
+ name: RSASSA_PKCS1_v1_5,
147
+ modulusLength,
148
+ publicExponent: new Uint8Array([1, 0, 1]),
149
+ hash: "SHA-256",
150
+ }, true, ["sign", "verify"]);
151
+ var { publicKey, privateKey } = k;
152
+ var private_key = await subtle.exportKey("pkcs8", privateKey);
153
+ var public_key = await subtle.exportKey("spki", publicKey);
154
+ private_key = toBase64(new Uint8Array(private_key));
155
+ public_key = toBase64(new Uint8Array(public_key));
156
+ return [private_key, public_key];
157
+ };
59
158
  var subtle = this.crypto?.subtle;
60
159
  var acme2 = new class {
61
160
  email = '';
@@ -69,19 +168,14 @@ var acme2 = new class {
69
168
  get enabled() {
70
169
  return !!subtle;
71
170
  }
171
+ async requestURL(url, params) {
172
+ params = await wrapParams(url, params);
173
+ var res = data.postURL(url, params);
174
+ if (res.loading) res.loading.setRequestHeader("Content-Type", "application/jose+json");
175
+ return res;
176
+ }
72
177
  async initUnique() {
73
- //https://www.w3.org/TR/WebCryptoAPI/ 第20章 只有RSASSA-PKCS1-v1_5的jwk的alg才是rs256
74
- var k = await subtle.generateKey({
75
- name: RSASSA_PKCS1_v1_5,
76
- modulusLength: 4096,
77
- publicExponent: new Uint8Array([1, 0, 1]),
78
- hash: "SHA-256",
79
- }, true, ["sign", "verify"]);
80
- var { publicKey, privateKey } = k;
81
- private_key = await subtle.exportKey("pkcs8", privateKey);
82
- public_key = await subtle.exportKey("spki", publicKey);
83
- private_key = toBase64(new Uint8Array(private_key));
84
- public_key = toBase64(new Uint8Array(public_key));
178
+ [private_key, public_key] = await makeKeyPair(4096);
85
179
  var unique = [private_key, public_key].join(',');
86
180
  await acme2.makeUnique(unique);
87
181
  }
@@ -145,40 +239,51 @@ var acme2 = new class {
145
239
  this.kid = account;
146
240
  var a = data.getUrlParamsForApi(accountApi, account);
147
241
  this.aid = a.aid;
242
+ alert('创建成功!', 'success');
148
243
  return account;
149
244
  }
150
245
  async newOrder(params) {
246
+ if (!this.orders) this.orders = [];
247
+ if (this.orders.length > 20) return alert("请删除一些订单后再试!", "error");
151
248
  var params = {
152
249
  "identifiers": params.domain.trim().split(/[,;+,;\r\n\u2029\u2028\s]+/).map(n => {
153
- if (/^\d+(\.\d+){3}$|^\[[\da-f\:]+\]$|^[\da-f\:]+$/i.test(n)) return { type: "ipv4", value: n };
250
+ if (/^\d+(\.\d+){3}$/.test(n)) return { type: "ipv4", value: n };
154
251
  return { type: "dns", value: n };
155
252
  })
156
253
  };
157
254
  var order = await request("new-order", params);
158
255
  this.domain = params.domain;
159
- if (!this.orders) this.orders = [];
160
- if (this.orders.indexOf(order) < 0) this.orders.unshift(order);
256
+ var i = this.orders.indexOf(order);
257
+ if (i >= 0) this.orders.splice(i, 1);
258
+ this.orders = [order].concat(this.orders);
161
259
  return order;
162
260
  }
163
261
  parseOrder(o) {
164
262
  if (typeof o !== 'string') return o;
165
263
  var order = data.getUrlParamsForApi(orderApi, o);
264
+ order.url = o;
166
265
  order.name = order.oid;
167
266
  return order;
168
267
  }
169
268
  async getOrder(o) {
170
- var r = await data.from(orderApi, o);
269
+ var r = await data.fromURL(o.url);
171
270
  if (r.expires) r.expires = new Date(r.expires);
172
271
  return r;
173
272
  }
174
273
  async thumbprint() {
175
274
  var jwk = await subtle.exportKey('jwk', publicKey);
176
275
  jwk = `{"e":"${jwk.e}","kty":"${jwk.kty}","n":"${jwk.n}"}`;
177
- console.log(JSON.parse(jwk))
178
276
  var thumb = await subtle.digest("SHA-256", new Uint8Array(encodeUTF8(jwk)));
179
277
  thumb = toBase64(new Uint8Array(thumb), true);
180
278
  return thumb;
181
279
  }
280
+ async createKeyPair() {
281
+ return makeKeyPair(2048);
282
+ }
283
+ async createCSR(domains, private_key) {
284
+ var csr = await createCSR(domains, private_key);
285
+ return toBase64(csr, true);
286
+ }
182
287
  async audit(url) {
183
288
  return data.fromURL(url);
184
289
  }
@@ -2,21 +2,29 @@ function send(type, key, value, origin) {
2
2
  return data.from(origin ? "edit" : "add", {
3
3
  type,
4
4
  key: encode62.timeencode(key),
5
- value: encode62.timeencode(JSON.stringify(value)),
6
- }).loading_promise;
5
+ value: isHandled(value) ? encode62.timeencode(JSON.stringify(value)) : '',
6
+ }, e => e ? JSAM.parse(encode62.timedecode(e)) : '').loading_promise;
7
7
  }
8
8
  function pedit(title, type, params, idkey = params.fields[0].key) {
9
+ var pdata = params.data;
9
10
  return frame$edit(title, {
10
11
  submit(a, fields) {
11
12
  a = submit(fields, a);
12
- return send(type, a[idkey], a, params.data);
13
+ return send(type, a[idkey], a, pdata);
13
14
  },
14
-
15
15
  }, params);
16
16
  }
17
17
  pedit.create = function (type, key, value) {
18
18
  return send(type, key, value, false);
19
19
  }
20
- pedit.update = function (type, key, value) {
20
+ var query = pedit.query = function (type, key) {
21
+ return send(type, key, null, true);
22
+ }
23
+ var update = pedit.update = function (type, key, value) {
21
24
  return send(type, key, value, true);
25
+ }
26
+ pedit.merge = async function (type, key, params) {
27
+ var data = await query(type, key);
28
+ extendIfNeeded(params, data);
29
+ return update(type, key, params);
22
30
  }
@@ -1,5 +1,10 @@
1
-
2
- function main() {
1
+ function load(type) {
2
+ return data.from("list", { type }, a => JSAM.parse(encode62.timedecode(a || '')));
3
+ }
4
+ function remove(type, key) {
5
+ return data.from("edit", { type, key: encode62.timeencode(key), value: encode62.timeencode("") }).loading_promise;
6
+ }
7
+ function plist() {
3
8
  var title, type, fields, edit_ref, options, idkey, buttons;
4
9
  var parse = function (a) {
5
10
  switch (typeof a) {
@@ -33,10 +38,10 @@ function main() {
33
38
  if (!idkey) idkey = fields[0].key;
34
39
  return frame$list(title, {
35
40
  load() {
36
- return data.from("list", { type }, a => JSAM.parse(encode62.timedecode(a || '')));
41
+ return load(type);
37
42
  },
38
43
  remove(o) {
39
- return data.from("edit", { type, key: encode62.timeencode(o[idkey]), value: encode62.timeencode("") }).loading_promise;
44
+ return remove(type, o[idkey]);
40
45
  },
41
46
  fields,
42
47
  buttons,
@@ -48,4 +53,6 @@ function main() {
48
53
  move.setPosition(p, [.5, .5]);
49
54
  return p;
50
55
  });
51
- }
56
+ }
57
+ plist.load = load;
58
+ plist.remove = remove;
@@ -240,6 +240,7 @@ a&,
240
240
  opacity: 0;
241
241
  box-shadow: none;
242
242
  background: none;
243
+ display: none;
243
244
  }
244
245
  }
245
246
 
@@ -15,14 +15,21 @@ var change = lazy(async function (src) {
15
15
  }
16
16
  zimoli.global(src, this);
17
17
  }
18
- else if (isString(src) || +src < 0) zimoli.go(src, this.params, this);
18
+ else if (isString(src) || +src < 0) {
19
+ watch(this, 'params', onparams);
20
+ onparams.call(this, this.params);
21
+ }
19
22
  });
20
23
  var gosrc = function (src) {
24
+ if (!isHandled(this.$src) && !isHandled(src)) return;
21
25
  if (src !== this.$src) {
22
26
  this.$src = src;
23
27
  change.call(this, src);
24
28
  }
25
29
  };
30
+ var onparams = lazy(function (params) {
31
+ zimoli.go(this.$src, params, this);
32
+ });
26
33
  function container(element) {
27
34
  var comment = document.createComment('container');
28
35
  comment.$struct = element.$struct;
@@ -176,15 +176,15 @@ function getParamsFromUrl(url, s = "?") {
176
176
  function getUrlParamsForApi(api, url) {
177
177
  var r = /([\s\S]*?)/.source;
178
178
  var cap = [];
179
- var base = api.url.replace(/[\?\#][\s\S]*$/, '')
179
+ var reg = api.url.replace(/[\?\#][\s\S]*$/, '')
180
180
  .replace(/[\.\*\+\-\[\]\{\}\(\)\\\/\!<\>\^]/g, '\\$&')
181
181
  .replace(/\:\w+/g, function (a) {
182
182
  cap.push(a.slice(1));
183
183
  return r;
184
184
  });
185
- if (/\/$/.test(base)) base += "?";
185
+ if (/\/$/.test(reg)) reg += "?";
186
186
  var params = {};
187
- url = url.replace(/[\?#]*$/g, function (match) {
187
+ url = url.replace(/[\?#][\s\S]*$/g, function (match) {
188
188
  match.split(/[&#\?]+/).forEach(function (s) {
189
189
  if (!s) return;
190
190
  var [k, v] = s.split("=");
@@ -192,8 +192,9 @@ function getUrlParamsForApi(api, url) {
192
192
  });
193
193
  return '';
194
194
  });
195
- if (api.base) url = url.slice(api.base.length);
196
- url.replace(new RegExp(`^${base}$`, 'ig'), function () {
195
+ if (api.base === url.slice(0, api.base.length)) url = url.slice(api.base.length), reg = new RegExp(`^${reg}$`);
196
+ else reg = new RegExp(reg + '$');
197
+ url.replace(reg, function () {
197
198
  var args = arguments;
198
199
  cap.forEach(function (a, cx) {
199
200
  params[a] = args[cx + 1];
@@ -302,7 +303,7 @@ function parseConfig(api) {
302
303
  });
303
304
  url.replace(/[\#][\s\S]*$/, '').replace(/([\:\\]\:|\:\w+)/g, function (p) {
304
305
  p = p.slice(1);
305
- if (!required[p] && p !== ':') {
306
+ if (p !== ':' && required.indexOf(p) < 0) {
306
307
  required.push(p);
307
308
  }
308
309
  });
@@ -534,7 +535,7 @@ var privates = {
534
535
  params = this.repare(api, params);
535
536
  return this.loadIgnoreConfig(api.method, url, params, api);
536
537
  }
537
- return Promise.resolve();
538
+ return Promise.reject(ABORTED);
538
539
  },
539
540
  repare(api, params) {
540
541
  var { required, autotrim, prepared } = api;
@@ -601,7 +602,7 @@ var privates = {
601
602
  var temp = JSON.stringify(params);
602
603
  var currentTime = +new Date;
603
604
  var loading = promise && promise.loading;
604
- if (!promise || currentTime - promise.time > 60 || temp !== promise.params || promise.search !== search) {
605
+ if (!promise || currentTime - promise.time > 60 || temp !== promise.params || promise.search !== search || promise.uri !== uri) {
605
606
  var promise = new Promise(function (ok, oh) {
606
607
  if (headers) {
607
608
  headers = seekFromSource(headers, api.base);
@@ -617,6 +618,7 @@ var privates = {
617
618
  }
618
619
  });
619
620
  });
621
+ promise.uri = uri;
620
622
  promise.loading = loading;
621
623
  promise.search = search;
622
624
  promise.params = temp;
@@ -625,7 +627,11 @@ var privates = {
625
627
  }
626
628
  var p = promise.then(function (response) {
627
629
  if (/\*$/.test(coinmethod)) return response;
628
- var data = parseData(response);
630
+ var type = loading.getResponseHeader?.("content-type");
631
+ var data = response;
632
+ if (/text\/plain|json|[xyt]ml/i.test(type)) {
633
+ data = parseData(data);
634
+ }
629
635
  var checked = error_check(data);
630
636
  var apiMap = api && api.root;
631
637
  var trans = api ? api.transpile : getTranspile(url);
@@ -678,6 +684,7 @@ var loadInstance = function (storage, id) {
678
684
  };
679
685
 
680
686
  function responseCrash(e, data) {
687
+ if (e === ABORTED || e === OUTDATE) return;
681
688
  data.is_errored = true;
682
689
  data.is_loading = false;
683
690
  data.error_message = getErrorMessage(e);
@@ -734,8 +741,9 @@ var unbindInstance = function (instanceId, callback) {
734
741
  };
735
742
  var OUTDATE = new Error(i18n`请求被覆盖`);
736
743
  var ABORTED = new Error(i18n`请求已取消`);
737
- var wrapRequest = function (p, req) {
738
-
744
+ var oncatch = function (e) {
745
+ if (e === OUTDATE || e === ABORTED) return;
746
+ throw e;
739
747
  };
740
748
  var data = {
741
749
  prepareURL,
@@ -853,86 +861,57 @@ var data = {
853
861
  });
854
862
  },
855
863
  fromApi(api, params, parse) {
856
- var id = parse instanceof Function ? getInstanceId() : 0;
857
864
  var p = privates.fromApi(api, params);
858
- if (id) this.removeInstance(id);
859
- var url = api.url;
860
- var response = this.getInstance(id || url);
861
- if (!isObject(response)) response = new LoadingArray;
862
- this.responseLoading(response);
863
- response.loading = p.loading;
864
- p = response.loading_promise = p.then((data) => {
865
- response.loading = null;
866
- if (id) {
867
- data = parse(data);
868
- this.setInstance(id, data, false);
869
- this.removeInstance(id);
870
- } else {
871
- this.setInstance(url, data);
872
- }
873
- this.responseLoaded(response);
874
- return data;
875
- });
876
- p.catch((e) => {
877
- this.responseCrash(e, response);
878
- });
879
- return response;
880
-
865
+ p.id = api.id;
866
+ return this.createResponse(p, parse);
867
+ },
868
+ postURL(url, data, parse) {
869
+ var p = privates.loadIgnoreConfig("post", url, data);
870
+ p.id = "post " + url;
871
+ return this.createResponse(p, parse);
881
872
  },
882
873
  fromURL(url, parse) {
883
- var id = parse instanceof Function ? getInstanceId() : 0;
884
874
  var p = privates.loadIgnoreConfig('get', url);
875
+ p.id = "get " + url;
876
+ return this.createResponse(p, parse);
877
+ },
878
+ createResponse(p, parse) {
879
+ var id = parse instanceof Function ? getInstanceId() : 0;
885
880
  if (id) this.removeInstance(id);
886
- var response = this.getInstance(id || url);
881
+ var pid = p.id;
882
+ var response = this.getInstance(id || pid);
887
883
  if (!isObject(response)) response = new LoadingArray;
888
884
  this.responseLoading(response);
889
885
  response.loading = p.loading;
890
- p = response.loading_promise = p.then((data) => {
886
+ response.loading_promise = p;
887
+ p = p.then((data) => {
891
888
  response.loading = null;
892
889
  if (id) {
893
890
  data = parse(data);
894
891
  this.setInstance(id, data, false);
895
892
  this.removeInstance(id);
896
893
  } else {
897
- this.setInstance(url, data);
894
+ this.setInstance(pid, data);
898
895
  }
899
896
  this.responseLoaded(response);
900
897
  return data;
901
- });
902
- p.catch((e) => {
898
+ }, (e) => {
903
899
  this.responseCrash(e, response);
904
- });
905
-
900
+ })
901
+ if (parse) response.loading_promise = p;
906
902
  return response;
907
903
  },
908
904
  asyncInstance(sid, params, parse) {
909
905
  // 不同参数的请求互不影响
910
906
  if (typeof sid !== "string") throw new Error(i18n`serviceId 只能是字符串`);
911
- var id = parse instanceof Function || params ? getInstanceId() : 0;
912
- if (id) this.removeInstance(id);
913
- var response = this.getInstance(id || sid);
914
- if (!isObject(response)) response = new LoadingArray;
915
- this.responseLoading(response);
916
- var p = response.loading_promise = privates.getApi(sid).then((api) => {
907
+ var p = privates.getApi(sid).then((api) => {
917
908
  params = privates.pack(sid, params);
918
909
  var p = privates.fromApi(api, params);
919
- response.loading = p.loading;
910
+ p.loading = response.loading = p.loading;
920
911
  return p;
921
- }).then((data) => {
922
- response.loading = null;
923
- if (id) {
924
- data = parse instanceof Function ? parse(data) : data;
925
- this.setInstance(id, data, false);
926
- this.removeInstance(id);
927
- } else {
928
- this.setInstance(sid, data);
929
- }
930
- this.responseLoaded(response);
931
- return data;
932
- });
933
- p.catch((e) => {
934
- this.responseCrash(e, response);
935
- });
912
+ }, oncatch);
913
+ p.id = sid;
914
+ var response = this.createResponse(p, parse);
936
915
  return response;
937
916
  },
938
917
 
@@ -957,77 +936,35 @@ var data = {
957
936
  });
958
937
  var id = "." + sid;
959
938
  var instance = this.getInstance(id);
960
- if (!isObject(instance)) instance = new LoadingArray;
961
-
962
- var promise1 = instance.loading_promise;
963
- if (promise1) {
964
- var params = promise1.params;
965
- if (shallowEqual(params1, params)) {
966
- return instance;
967
- }
968
- }
969
- this.responseLoading(instance);
970
- promise1 = instance.loading_promise = new Promise(function (ok) {
971
- if (!instance.loading) {
972
- instance.loading = false;
973
- }
974
- setTimeout(ok, timeout);
939
+ var loading_promise = instance && instance.loading_promise;
940
+ var p = Promise.resolve().then(function () {
941
+ if (loading_promise) return wait(timeout);
942
+ return wait(60);
975
943
  }).then(function () {
976
- if (promise1 !== instance.loading_promise) throw OUTDATE;
944
+ if (p !== instance.loading_promise) throw OUTDATE;
977
945
  return privates.getApi(sid);
978
946
  }).then((api) => {
979
- if (promise1 !== instance.loading_promise) throw OUTDATE;
947
+ if (p !== instance.loading_promise) throw OUTDATE;
948
+ if ("params" in instance && shallowEqual(instance.params, params1)) throw ABORTED;
949
+ instance.params = params1;
980
950
  if (instance.loading) {
981
951
  instance.loading.abort();
982
952
  }
983
- var params2 = privates.pack(sid, params1);
984
- if (!privates.validApi(api, params2)) throw ABORTED;
985
- let url = api.url;
986
- var base = api.base;
987
- if (base) url = base + api.path;
988
- var { method, uri, params, selector } = privates.prepare(api.method, url, params2);
989
- var promise = new Promise(function (ok, oh) {
990
- var headers = api.headers;
991
- if (headers) {
992
- headers = seekFromSource(headers, api.base);
993
- }
994
- instance.loading = cross(method, uri, headers).send(params).done(xhr => {
995
- if (instance.loading !== xhr) return oh(ABORTED);
996
- instance.loading = null;
997
- ok(xhr.responseText || xhr.response);
998
- }).error(xhr => {
999
- if (instance.loading !== xhr) return oh(ABORTED);
1000
- instance.loading = null;
1001
- try {
1002
- var e = getErrorMessage(parseData(xhr.response || xhr.responseText || xhr.statusText || xhr.status));
1003
- oh({ status: xhr.status, error: e, api, params: params2, toString: getErrorMessage })
1004
- } catch (error) {
1005
- oh(error);
1006
- }
1007
- });
1008
- }).then(function (response) {
1009
- return transpile(seekResponse(parseData(response), selector), api.transpile, api.root);
1010
- });
1011
- return promise;
953
+ var r = privates.fromApi(api, params1);
954
+ instance.loading = r.loading;
955
+ return r;
1012
956
  }).then((data) => {
1013
- if (instance.loading_promise !== promise1) throw ABORTED;
1014
- if (id) {
1015
- data = parse instanceof Function ? parse(data) : data;
1016
- this.setInstance(id, data, false);
1017
- } else {
1018
- this.setInstance(sid, data);
1019
- }
1020
- this.responseLoaded(instance);
957
+ if (instance.loading_promise !== p) throw ABORTED;
958
+ if (isFunction(parse)) data = parse(data);
1021
959
  return data;
1022
- }).catch(function (e) {
1023
- if (e === OUTDATE || e === ABORTED) return;
1024
- throw e;
960
+ }, oncatch);
961
+ p.id = id;
962
+ var instance = this.createResponse(p);
963
+ p.catch(function () { }).then(() => {
964
+ return wait(timeout);
965
+ }).then(() => {
966
+ if (instance.loading_promise === p) delete instance.loading_promise;
1025
967
  });
1026
- promise1.params = params;
1027
- promise1.catch((e) => {
1028
- this.responseCrash(e, instance);
1029
- });
1030
-
1031
968
  return instance;
1032
969
  },
1033
970
  /**
@@ -463,9 +463,9 @@ function ylist(container, generator, $Y) {
463
463
  * @param {Element|null} focused
464
464
  * @param {boolean} animate
465
465
  */
466
- list.setFocus = function (focused, animate) {
466
+ list.setFocus = function (focused, animate = true) {
467
467
  if (isElement(focused) && (focused.hasAttribute("disabled") || focused.hasAttribute("line"))) return;
468
- if (isFinite(focused)) {
468
+ if (focused === (focused | 0)) {
469
469
  var index = focused;
470
470
  focused = list.getIndexedElement(index);
471
471
  if (!focused) {