Skip to content

Commit edf8cfa

Browse files
author
lixiangfei
committed
add source
0 parents  commit edf8cfa

File tree

5 files changed

+325
-0
lines changed

5 files changed

+325
-0
lines changed

src/index.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
import _ProxyPromise from '.proxyPromise'
2+
3+
4+
export const ProxyPromise = _ProxyPromise

src/proxyPromise.js

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
export default class ProxyPromise {
2+
3+
constructor() {
4+
let resolvePromise;
5+
let rejectPromise;
6+
7+
const promise = new Promise((resolve, reject) => {
8+
resolvePromise = resolve;
9+
rejectPromise = reject;
10+
});
11+
12+
const publicPromise = promise;
13+
publicPromise.resolve = resolvePromise;
14+
publicPromise.reject = rejectPromise;
15+
16+
return publicPromise;
17+
}
18+
19+
20+
/** @param {T=} value */
21+
resolve(value) {}
22+
23+
24+
/** @param {*=} reason */
25+
reject(reason) {}
26+
}

src/speedSampler.js

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
/*
2+
* Copyright (C) 2016 Bilibili. All Rights Reserved.
3+
*
4+
* @author zheng qian <[email protected]>
5+
*
6+
* Licensed under the Apache License, Version 2.0 (the "License");
7+
* you may not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
19+
// Utility class to calculate realtime network I/O speed
20+
class SpeedSampler {
21+
22+
constructor() {
23+
// milliseconds
24+
this._firstCheckpoint = 0;
25+
this._lastCheckpoint = 0;
26+
this._intervalBytes = 0;
27+
this._totalBytes = 0;
28+
this._lastSecondBytes = 0;
29+
30+
// compatibility detection
31+
if (self.performance && self.performance.now) {
32+
this._now = self.performance.now.bind(self.performance);
33+
} else {
34+
this._now = Date.now;
35+
}
36+
}
37+
38+
reset() {
39+
this._firstCheckpoint = this._lastCheckpoint = 0;
40+
this._totalBytes = this._intervalBytes = 0;
41+
this._lastSecondBytes = 0;
42+
}
43+
44+
addBytes(bytes) {
45+
if (this._firstCheckpoint === 0) {
46+
this._firstCheckpoint = this._now();
47+
this._lastCheckpoint = this._firstCheckpoint;
48+
this._intervalBytes += bytes;
49+
this._totalBytes += bytes;
50+
} else if (this._now() - this._lastCheckpoint < 1000) {
51+
this._intervalBytes += bytes;
52+
this._totalBytes += bytes;
53+
} else { // duration >= 1000
54+
this._lastSecondBytes = this._intervalBytes;
55+
this._intervalBytes = bytes;
56+
this._totalBytes += bytes;
57+
this._lastCheckpoint = this._now();
58+
}
59+
}
60+
61+
get currentKBps() {
62+
this.addBytes(0);
63+
64+
let durationSeconds = (this._now() - this._lastCheckpoint) / 1000;
65+
if (durationSeconds === 0) durationSeconds = 1;
66+
return (this._intervalBytes / durationSeconds) / 1024;
67+
}
68+
69+
get lastSecondKBps() {
70+
this.addBytes(0);
71+
72+
if (this._lastSecondBytes !== 0) {
73+
return this._lastSecondBytes / 1024;
74+
} else { // lastSecondBytes === 0
75+
if (this._now() - this._lastCheckpoint >= 500) {
76+
// if time interval since last checkpoint has exceeded 500ms
77+
// the speed is nearly accurate
78+
return this.currentKBps;
79+
} else {
80+
// We don't know
81+
return 0;
82+
}
83+
}
84+
}
85+
86+
get averageKBps() {
87+
let durationSeconds = (this._now() - this._firstCheckpoint) / 1000;
88+
return (this._totalBytes / durationSeconds) / 1024;
89+
}
90+
91+
}
92+
93+
export default SpeedSampler;

src/utils.js

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
export default class Utils{
2+
/**
3+
* Parses an XML date string.
4+
* @param {string} dateString
5+
* @return {?number} The parsed date in seconds on success; otherwise, return
6+
* null.
7+
*/
8+
static parseDate(dateString) {
9+
if (!dateString) {
10+
return null;
11+
}
12+
13+
// Times in the manifest should be in UTC. If they don't specify a timezone,
14+
// Date.parse() will use the local timezone instead of UTC. So manually add
15+
// the timezone if missing ('Z' indicates the UTC timezone).
16+
// Format: YYYY-MM-DDThh:mm:ss.ssssss
17+
if (/^\d+-\d+-\d+T\d+:\d+:\d+(\.\d+)?$/.test(dateString)) {
18+
// eslint-disable-next-line no-param-reassign
19+
dateString += 'Z';
20+
}
21+
22+
const result = Date.parse(dateString);
23+
return (!isNaN(result) ? Math.floor(result / 1000.0) : null);
24+
}
25+
26+
static parseDuration(durationString) {
27+
if (!durationString) {
28+
return null;
29+
}
30+
31+
const re = '^P(?:([0-9]*)Y)?(?:([0-9]*)M)?(?:([0-9]*)D)?' +
32+
'(?:T(?:([0-9]*)H)?(?:([0-9]*)M)?(?:([0-9.]*)S)?)?$';
33+
const matches = new RegExp(re).exec(durationString);
34+
35+
if (!matches) {
36+
return null;
37+
}
38+
39+
// Note: Number(null) == 0 but Number(undefined) == NaN.
40+
const years = Number(matches[1] || null);
41+
const months = Number(matches[2] || null);
42+
const days = Number(matches[3] || null);
43+
const hours = Number(matches[4] || null);
44+
const minutes = Number(matches[5] || null);
45+
const seconds = Number(matches[6] || null);
46+
47+
// Assume a year always has 365 days and a month always has 30 days.
48+
const d = (60 * 60 * 24 * 365) * years +
49+
(60 * 60 * 24 * 30) * months +
50+
(60 * 60 * 24) * days +
51+
(60 * 60) * hours +
52+
60 * minutes +
53+
seconds;
54+
return isFinite(d) ? d : null;
55+
}
56+
57+
58+
static parseRange(rangeString) {
59+
const matches = /([0-9]+)-([0-9]+)/.exec(rangeString);
60+
61+
if (!matches) {
62+
return null;
63+
}
64+
65+
const start = Number(matches[1]);
66+
if (!isFinite(start)) {
67+
return null;
68+
}
69+
70+
const end = Number(matches[2]);
71+
if (!isFinite(end)) {
72+
return null;
73+
}
74+
75+
return { start: start, end: end };
76+
}
77+
}

src/xmlutils.js

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
2+
/** @license
3+
* Copyright 2016 Google LLC
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
export default class XmlUtils {
7+
8+
static findChild(elem, name) {
9+
const children = XmlUtils.findChildren(elem, name);
10+
if (children.length !== 1) {
11+
return null;
12+
}
13+
return children[0];
14+
}
15+
16+
static findChildNS(elem, ns, name) {
17+
const children = XmlUtils.findChildrenNS(elem, ns, name);
18+
if (children.length !== 1) {
19+
return null;
20+
}
21+
return children[0];
22+
}
23+
24+
static findChildren(elem, name) {
25+
return Array.from(elem.childNodes).filter((child) => {
26+
return child instanceof Element && child.tagName === name;
27+
});
28+
}
29+
30+
static findChildrenNS(elem, ns, name) {
31+
return Array.from(elem.childNodes).filter((child) => {
32+
return child instanceof Element && child.localName === name &&
33+
child.namespaceURI === ns;
34+
});
35+
}
36+
37+
static getAttributeNS(elem, ns, name) {
38+
return elem.hasAttributeNS(ns, name) ? elem.getAttributeNS(ns, name) : null;
39+
}
40+
41+
static getContents(elem) {
42+
const isText = (child) => {
43+
return child.nodeType === Node.TEXT_NODE ||
44+
child.nodeType === Node.CDATA_SECTION_NODE;
45+
};
46+
if (!Array.from(elem.childNodes).every(isText)) {
47+
return null;
48+
}
49+
50+
// Read merged text content from all text nodes.
51+
return elem.textContent.trim();
52+
}
53+
54+
55+
static parseAttr(elem, name, parseFunction, defaultValue = null) {
56+
let parsedValue = null;
57+
58+
const value = elem.getAttribute(name);
59+
if (value != null) {
60+
parsedValue = parseFunction(value);
61+
}
62+
return parsedValue == null ? defaultValue : parsedValue;
63+
}
64+
65+
static parseInt(intString) {
66+
const n = Number(intString);
67+
return (n % 1 === 0) ? n : null;
68+
}
69+
70+
static parsePositiveInt(intString) {
71+
const n = Number(intString);
72+
return (n % 1 === 0) && (n > 0) ? n : null;
73+
}
74+
75+
static parseNonNegativeInt(intString) {
76+
const n = Number(intString);
77+
return (n % 1 === 0) && (n >= 0) ? n : null;
78+
}
79+
80+
static parseFloat(floatString) {
81+
const n = Number(floatString);
82+
return !isNaN(n) ? n : null;
83+
}
84+
85+
static evalDivision(exprString) {
86+
let res;
87+
let n;
88+
if ((res = exprString.match(/^(\d+)\/(\d+)$/))) {
89+
n = Number(res[1]) / Number(res[2]);
90+
} else {
91+
n = Number(exprString);
92+
}
93+
return !isNaN(n) ? n : null;
94+
}
95+
96+
static parseXmlString(xmlString, expectedRootElemName) {
97+
const parser = new DOMParser();
98+
let rootElem = null;
99+
let xml = null;
100+
try {
101+
xml = parser.parseFromString(xmlString, 'text/xml');
102+
} catch (exception) {}
103+
if (xml) {
104+
// The top-level element in the loaded xml should have the
105+
// same type as the element linking.
106+
if (xml.documentElement.tagName === expectedRootElemName) {
107+
rootElem = xml.documentElement;
108+
}
109+
}
110+
if (rootElem && rootElem.getElementsByTagName('parsererror').length > 0) {
111+
return null;
112+
} // It had a parser error in it.
113+
114+
return rootElem;
115+
}
116+
117+
118+
static parseXml(xmlString, expectedRootElemName) {
119+
try {
120+
return XmlUtils.parseXmlString(xmlString, expectedRootElemName);
121+
} catch (exception) {
122+
return null;
123+
}
124+
}
125+
}

0 commit comments

Comments
 (0)