mapbox-gl
Version:
A WebGL interactive maps library
1,675 lines (1,433 loc) • 11 MB
JavaScript
/* Mapbox GL JS is Copyright © 2020 Mapbox and subject to the Mapbox Terms of Service ((https://www.mapbox.com/legal/tos/). */
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
typeof define === 'function' && define.amd ? define(factory) :
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.mapboxgl = factory());
})(this, (function () { 'use strict';
/* eslint-disable */
var shared, worker, mapboxgl;
// define gets called three times: one for each chunk. we rely on the order
// they're imported to know which is which
function define(_, chunk) {
if (!shared) {
shared = chunk;
} else if (!worker) {
worker = chunk;
} else {
var workerBundleString = "self.onerror = function() { console.error('An error occurred while parsing the WebWorker bundle. This is most likely due to improper transpilation by Babel; please see https://docs.mapbox.com/mapbox-gl-js/guides/install/#transpiling'); }; var sharedChunk = {}; (" + shared + ")(sharedChunk); (" + worker + ")(sharedChunk); self.onerror = null;"
var sharedChunk = {};
shared(sharedChunk);
mapboxgl = chunk(sharedChunk);
if (typeof window !== 'undefined' && window && window.URL && window.URL.createObjectURL) {
mapboxgl.workerUrl = window.URL.createObjectURL(new Blob([workerBundleString], { type: 'text/javascript' }));
}
}
}
define(['exports'], (function (exports) { 'use strict';
//
/* eslint-env browser */
// shim window for the case of requiring the browser bundle in Node
var window$1 = ((typeof self !== 'undefined' ? self : ({} )) );
var name = "mapbox-gl";
var description = "A WebGL interactive maps library";
var version = "2.15.0";
var main = "dist/mapbox-gl.js";
var style = "dist/mapbox-gl.css";
var license = "SEE LICENSE IN LICENSE.txt";
var type = "module";
var repository = {
type: "git",
url: "git://github.com/mapbox/mapbox-gl-js.git"
};
var dependencies = {
"@mapbox/geojson-rewind": "^0.5.2",
"@mapbox/jsonlint-lines-primitives": "^2.0.2",
"@mapbox/mapbox-gl-supported": "^2.0.1",
"@mapbox/point-geometry": "^0.1.0",
"@mapbox/tiny-sdf": "^2.0.6",
"@mapbox/unitbezier": "^0.0.1",
"@mapbox/vector-tile": "^1.3.1",
"@mapbox/whoots-js": "^3.1.0",
csscolorparser: "~1.0.3",
earcut: "^2.2.4",
"geojson-vt": "^3.2.1",
"gl-matrix": "^3.4.3",
"grid-index": "^1.1.0",
kdbush: "^4.0.1",
"murmurhash-js": "^1.0.0",
pbf: "^3.2.1",
potpack: "^2.0.0",
quickselect: "^2.0.0",
rw: "^1.3.3",
supercluster: "^8.0.0",
tinyqueue: "^2.0.3",
"vt-pbf": "^3.1.3"
};
var devDependencies = {
"@babel/core": "^7.20.5",
"@babel/eslint-parser": "^7.18.9",
"@mapbox/flow-remove-types": "^2.0.0",
"@mapbox/mvt-fixtures": "^3.10.0",
"@octokit/rest": "^19.0.4",
"@rollup/plugin-commonjs": "^25.0.0",
"@rollup/plugin-json": "^6.0.0",
"@rollup/plugin-node-resolve": "^15.0.0",
"@rollup/plugin-replace": "^5.0.0",
"@rollup/plugin-strip": "^3.0.0",
"@rollup/plugin-terser": "^0.4.1",
address: "^1.2.0",
browserify: "^17.0.0",
chalk: "^5.0.1",
chokidar: "^3.5.3",
"cross-env": "^7.0.3",
cssnano: "^6.0.0",
d3: "^7.6.1",
"d3-queue": "^3.0.7",
diff: "^5.1.0",
ejs: "^3.1.8",
envify: "^4.1.0",
eslint: "^7.32.0",
"eslint-config-mourner": "^3.0.0",
"eslint-plugin-flowtype": "^7.0.0",
"eslint-plugin-html": "^7.1.0",
"eslint-plugin-import": "^2.26.0",
"eslint-plugin-jsdoc": "^39.6.4",
"flow-bin": "0.191.0",
gl: "6.0.2",
glob: "^10.0.0",
"is-builtin-module": "^3.2.0",
jsdom: "^15.2.1",
"json-stringify-pretty-compact": "^4.0.0",
"lodash.template": "^4.5.0",
"mapbox-gl-styles": "^2.0.2",
minimist: "^1.2.6",
"mock-geolocation": "^1.0.11",
"node-notifier": "^10.0.1",
"npm-font-open-sans": "^1.1.0",
"npm-run-all": "^4.1.5",
nyc: "^15.1.0",
pixelmatch: "^5.3.0",
postcss: "^8.4.16",
"postcss-cli": "^10.1.0",
"postcss-inline-svg": "^6.0.0",
"pretty-bytes": "^6.0.0",
"puppeteer-core": "^19.7.0",
"qrcode-terminal": "^0.12.0",
rollup: "^3.21.7",
"rollup-plugin-sourcemaps": "^0.6.3",
"rollup-plugin-unassert": "^0.6.0",
"selenium-webdriver": "^4.8.0",
"serve-static": "^1.15.0",
"shuffle-seed": "^1.1.6",
sinon: "^15.0.0",
st: "^3.0.0",
stylelint: "^14.11.0",
"stylelint-config-standard": "^29.0.0",
tap: "~16.3.2",
tape: "^5.6.1",
"tape-filter": "^1.0.4",
testem: "^3.10.1"
};
var browser = {
"./src/shaders/index.js": "./src/shaders/shaders.js",
"./src/util/window.js": "./src/util/browser/window.js",
"./src/util/web_worker.js": "./src/util/browser/web_worker.js"
};
var scripts = {
"build-dev": "rollup -c --environment BUILD:dev",
"watch-dev": "rollup -c --environment BUILD:dev --watch",
"build-bench": "rollup -c --environment BUILD:bench,MINIFY:true",
"build-prod": "rollup -c --environment BUILD:production",
"build-prod-min": "rollup -c --environment BUILD:production,MINIFY:true",
"build-csp": "rollup -c rollup.config.csp.js",
"build-test-suite": "rollup -c test/integration/rollup.config.test.js",
"build-flow-types": "mkdir -p dist && cp build/mapbox-gl.js.flow dist/mapbox-gl.js.flow && cp build/mapbox-gl.js.flow dist/mapbox-gl-dev.js.flow",
"build-css": "postcss -o dist/mapbox-gl.css src/css/mapbox-gl.css",
"build-style-spec": "cd src/style-spec && npm run build && cd ../.. && mkdir -p dist/style-spec && cp src/style-spec/dist/* dist/style-spec",
"watch-css": "postcss --watch -o dist/mapbox-gl.css src/css/mapbox-gl.css",
"build-token": "node build/generate-access-token-script.js",
"build-benchmarks": "BENCHMARK_VERSION=${BENCHMARK_VERSION:-\"$(git rev-parse --abbrev-ref HEAD) $(git rev-parse --short=7 HEAD)\"} rollup -c bench/versions/rollup_config_benchmarks.js",
"watch-benchmarks": "BENCHMARK_VERSION=${BENCHMARK_VERSION:-\"$(git rev-parse --abbrev-ref HEAD) $(git rev-parse --short=7 HEAD)\"} rollup -c bench/rollup_config_benchmarks.js -w",
"start-server": "st --no-cache -H 0.0.0.0 --port 9966 --index index.html .",
start: "run-p build-token watch-css watch-dev watch-benchmarks start-server",
"start-debug": "run-p build-token watch-css watch-dev start-server",
"start-bench": "run-p build-token watch-benchmarks start-server",
"start-release": "run-s build-token build-prod-min build-css print-release-url start-server",
lint: "eslint --cache --ignore-path .gitignore src test bench debug/*.html",
"lint-css": "stylelint 'src/css/mapbox-gl.css'",
test: "run-s lint lint-css test-flow test-unit",
"test-suite": "run-s test-render test-query test-expressions",
"test-suite-clean": "find test/integration/{render,query, expressions}-tests -mindepth 2 -type d -exec test -e \"{}/actual.png\" \\; -not \\( -exec test -e \"{}/style.json\" \\; \\) -print | xargs -t rm -r",
"test-unit": "build/run-tap --reporter classic --no-coverage test/unit",
"test-build": "build/run-tap --no-coverage test/build/**/*.test.js",
"test-browser": "build/run-tap --jobs=1 --reporter spec --no-coverage -- test/browser/**/*.test.js",
"watch-render": "cross-env SUITE_NAME=render testem -f test/integration/testem/testem.js",
"watch-query": "SUITE_NAME=query testem -f test/integration/testem/testem.js",
"test-render": "cross-env SUITE_NAME=render testem ci -f test/integration/testem/testem.js",
"test-render-firefox": "cross-env BROWSER=Firefox SUITE_NAME=render testem ci -f test/integration/testem/testem.js",
"test-render-safari": "cross-env BROWSER=Safari SUITE_NAME=render testem ci -f test/integration/testem/testem.js",
"test-render-prod": "BUILD=production SUITE_NAME=render testem ci -f test/integration/testem/testem.js",
"test-render-csp": "BUILD=csp SUITE_NAME=render testem ci -f test/integration/testem/testem.js",
"test-query": "SUITE_NAME=query testem ci -f test/integration/testem/testem.js",
"test-expressions": "build/run-node test/expression.test.js",
"test-flow": "build/run-node build/generate-flow-typed-style-spec && flow .",
"test-cov": "nyc --require=@mapbox/flow-remove-types/register --reporter=text-summary --reporter=lcov --cache run-s test-unit test-expressions test-query test-render",
"test-style-spec": "cd src/style-spec && npm test",
prepublishOnly: "run-s build-flow-types build-dev build-prod-min build-prod build-csp build-css build-style-spec",
"print-release-url": "node build/print-release-url.js",
"check-bundle-size": "node build/check-bundle-size.js",
codegen: "build/run-node build/generate-style-code.js && build/run-node build/generate-struct-arrays.js"
};
var files = [
"build/",
"dist/mapbox-gl*",
"dist/style-spec/",
"dist/package.json",
"flow-typed/*.js",
"src/",
".flowconfig",
"LICENSE.txt"
];
var _package = {
name: name,
description: description,
version: version,
main: main,
style: style,
license: license,
type: type,
repository: repository,
dependencies: dependencies,
devDependencies: devDependencies,
browser: browser,
scripts: scripts,
files: files
};
// strict
let mapboxHTTPURLRegex;
const config = {
API_URL: 'https://api.mapbox.com',
get API_URL_REGEX () {
if (mapboxHTTPURLRegex == null) {
const prodMapboxHTTPURLRegex = /^((https?:)?\/\/)?([^\/]+\.)?mapbox\.c(n|om)(\/|\?|$)/i;
try {
mapboxHTTPURLRegex = (process.env.API_URL_REGEX != null) ? new RegExp(process.env.API_URL_REGEX) : prodMapboxHTTPURLRegex;
} catch (e) {
mapboxHTTPURLRegex = prodMapboxHTTPURLRegex;
}
}
return mapboxHTTPURLRegex;
},
get API_TILEJSON_REGEX() {
// https://docs.mapbox.com/api/maps/mapbox-tiling-service/#retrieve-tilejson-metadata
return /^((https?:)?\/\/)?([^\/]+\.)?mapbox\.c(n|om)(\/v[0-9]*\/.*\.json.*$)/i;
},
get API_SPRITE_REGEX() {
// https://docs.mapbox.com/api/maps/styles/#retrieve-a-sprite-image-or-json
return /^((https?:)?\/\/)?([^\/]+\.)?mapbox\.c(n|om)(\/styles\/v[0-9]*\/)(.*\/sprite.*\..*$)/i;
},
get API_FONTS_REGEX() {
// https://docs.mapbox.com/api/maps/fonts/#retrieve-font-glyph-ranges
return /^((https?:)?\/\/)?([^\/]+\.)?mapbox\.c(n|om)(\/fonts\/v[0-9]*\/)(.*\.pbf.*$)/i;
},
get API_STYLE_REGEX() {
// https://docs.mapbox.com/api/maps/styles/#retrieve-a-style
return /^((https?:)?\/\/)?([^\/]+\.)?mapbox\.c(n|om)(\/styles\/v[0-9]*\/)(.*$)/i;
},
get API_CDN_URL_REGEX() {
return /^((https?:)?\/\/)?api\.mapbox\.c(n|om)(\/mapbox-gl-js\/)(.*$)/i;
},
get EVENTS_URL() {
if (!config.API_URL) { return null; }
try {
const url = new URL(config.API_URL);
if (url.hostname === 'api.mapbox.cn') {
return 'https://events.mapbox.cn/events/v2';
} else if (url.hostname === 'api.mapbox.com') {
return 'https://events.mapbox.com/events/v2';
} else {
return null;
}
} catch (e) {
return null;
}
},
SESSION_PATH: '/map-sessions/v1',
FEEDBACK_URL: 'https://apps.mapbox.com/feedback',
TILE_URL_VERSION: 'v4',
RASTER_URL_PREFIX: 'raster/v1',
REQUIRE_ACCESS_TOKEN: true,
ACCESS_TOKEN: null,
MAX_PARALLEL_IMAGE_REQUESTS: 16
};
// strict
const exported$1 = {
supported: false,
testSupport
};
let glForTesting;
let webpCheckComplete = false;
let webpImgTest;
let webpImgTestOnloadComplete = false;
if (window$1.document) {
webpImgTest = window$1.document.createElement('img');
webpImgTest.onload = function() {
if (glForTesting) testWebpTextureUpload(glForTesting);
glForTesting = null;
webpImgTestOnloadComplete = true;
};
webpImgTest.onerror = function() {
webpCheckComplete = true;
glForTesting = null;
};
webpImgTest.src = 'data:image/webp;base64,UklGRh4AAABXRUJQVlA4TBEAAAAvAQAAAAfQ//73v/+BiOh/AAA=';
}
function testSupport(gl ) {
if (webpCheckComplete || !webpImgTest) return;
// HTMLImageElement.complete is set when an image is done loading it's source
// regardless of whether the load was successful or not.
// It's possible for an error to set HTMLImageElement.complete to true which would trigger
// testWebpTextureUpload and mistakenly set exported.supported to true in browsers which don't support webp
// To avoid this, we set a flag in the image's onload handler and only call testWebpTextureUpload
// after a successful image load event.
if (webpImgTestOnloadComplete) {
testWebpTextureUpload(gl);
} else {
glForTesting = gl;
}
}
function testWebpTextureUpload(gl ) {
// Edge 18 supports WebP but not uploading a WebP image to a gl texture
// Test support for this before allowing WebP images.
// https://github.com/mapbox/mapbox-gl-js/issues/7671
const texture = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, texture);
try {
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, webpImgTest);
// The error does not get triggered in Edge if the context is lost
if (gl.isContextLost()) return;
exported$1.supported = true;
} catch (e) {
// Catch "Unspecified Error." in Edge 18.
}
gl.deleteTexture(texture);
webpCheckComplete = true;
}
//
/***** START WARNING REMOVAL OR MODIFICATION OF THE
* FOLLOWING CODE VIOLATES THE MAPBOX TERMS OF SERVICE ******
* The following code is used to access Mapbox's APIs. Removal or modification
* of this code can result in higher fees and/or
* termination of your account with Mapbox.
*
* Under the Mapbox Terms of Service, you may not use this code to access Mapbox
* Mapping APIs other than through Mapbox SDKs.
*
* The Mapping APIs documentation is available at https://docs.mapbox.com/api/maps/#maps
* and the Mapbox Terms of Service are available at https://www.mapbox.com/tos/
******************************************************************************/
const SKU_ID = '01';
function createSkuToken() {
// SKU_ID and TOKEN_VERSION are specified by an internal schema and should not change
const TOKEN_VERSION = '1';
const base62chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
// sessionRandomizer is a randomized 10-digit base-62 number
let sessionRandomizer = '';
for (let i = 0; i < 10; i++) {
sessionRandomizer += base62chars[Math.floor(Math.random() * 62)];
}
const expiration = 12 * 60 * 60 * 1000; // 12 hours
const token = [TOKEN_VERSION, SKU_ID, sessionRandomizer].join('');
const tokenExpiresAt = Date.now() + expiration;
return {token, tokenExpiresAt};
}
/***** END WARNING - REMOVAL OR MODIFICATION OF THE
PRECEDING CODE VIOLATES THE MAPBOX TERMS OF SERVICE ******/
var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
function getDefaultExportFromCjs (x) {
return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
}
function getDefaultExportFromNamespaceIfPresent (n) {
return n && Object.prototype.hasOwnProperty.call(n, 'default') ? n['default'] : n;
}
function getDefaultExportFromNamespaceIfNotNamed (n) {
return n && Object.prototype.hasOwnProperty.call(n, 'default') && Object.keys(n).length === 1 ? n['default'] : n;
}
function getAugmentedNamespace(n) {
if (n.__esModule) return n;
var f = n.default;
if (typeof f == "function") {
var a = function a () {
if (this instanceof a) {
var args = [null];
args.push.apply(args, arguments);
var Ctor = Function.bind.apply(f, args);
return new Ctor();
}
return f.apply(this, arguments);
};
a.prototype = f.prototype;
} else a = {};
Object.defineProperty(a, '__esModule', {value: true});
Object.keys(n).forEach(function (k) {
var d = Object.getOwnPropertyDescriptor(n, k);
Object.defineProperty(a, k, d.get ? d : {
enumerable: true,
get: function () {
return n[k];
}
});
});
return a;
}
'use strict';
var unitbezier = UnitBezier;
function UnitBezier(p1x, p1y, p2x, p2y) {
// Calculate the polynomial coefficients, implicit first and last control points are (0,0) and (1,1).
this.cx = 3.0 * p1x;
this.bx = 3.0 * (p2x - p1x) - this.cx;
this.ax = 1.0 - this.cx - this.bx;
this.cy = 3.0 * p1y;
this.by = 3.0 * (p2y - p1y) - this.cy;
this.ay = 1.0 - this.cy - this.by;
this.p1x = p1x;
this.p1y = p1y;
this.p2x = p2x;
this.p2y = p2y;
}
UnitBezier.prototype = {
sampleCurveX: function (t) {
// `ax t^3 + bx t^2 + cx t' expanded using Horner's rule.
return ((this.ax * t + this.bx) * t + this.cx) * t;
},
sampleCurveY: function (t) {
return ((this.ay * t + this.by) * t + this.cy) * t;
},
sampleCurveDerivativeX: function (t) {
return (3.0 * this.ax * t + 2.0 * this.bx) * t + this.cx;
},
solveCurveX: function (x, epsilon) {
if (epsilon === undefined) epsilon = 1e-6;
if (x < 0.0) return 0.0;
if (x > 1.0) return 1.0;
var t = x;
// First try a few iterations of Newton's method - normally very fast.
for (var i = 0; i < 8; i++) {
var x2 = this.sampleCurveX(t) - x;
if (Math.abs(x2) < epsilon) return t;
var d2 = this.sampleCurveDerivativeX(t);
if (Math.abs(d2) < 1e-6) break;
t = t - x2 / d2;
}
// Fall back to the bisection method for reliability.
var t0 = 0.0;
var t1 = 1.0;
t = x;
for (i = 0; i < 20; i++) {
x2 = this.sampleCurveX(t);
if (Math.abs(x2 - x) < epsilon) break;
if (x > x2) {
t0 = t;
} else {
t1 = t;
}
t = (t1 - t0) * 0.5 + t0;
}
return t;
},
solve: function (x, epsilon) {
return this.sampleCurveY(this.solveCurveX(x, epsilon));
}
};
var UnitBezier$1 = /*@__PURE__*/getDefaultExportFromCjs(unitbezier);
'use strict';
var pointGeometry = Point$1;
/**
* A standalone point geometry with useful accessor, comparison, and
* modification methods.
*
* @class Point
* @param {Number} x the x-coordinate. this could be longitude or screen
* pixels, or any other sort of unit.
* @param {Number} y the y-coordinate. this could be latitude or screen
* pixels, or any other sort of unit.
* @example
* var point = new Point(-77, 38);
*/
function Point$1(x, y) {
this.x = x;
this.y = y;
}
Point$1.prototype = {
/**
* Clone this point, returning a new point that can be modified
* without affecting the old one.
* @return {Point} the clone
*/
clone: function() { return new Point$1(this.x, this.y); },
/**
* Add this point's x & y coordinates to another point,
* yielding a new point.
* @param {Point} p the other point
* @return {Point} output point
*/
add: function(p) { return this.clone()._add(p); },
/**
* Subtract this point's x & y coordinates to from point,
* yielding a new point.
* @param {Point} p the other point
* @return {Point} output point
*/
sub: function(p) { return this.clone()._sub(p); },
/**
* Multiply this point's x & y coordinates by point,
* yielding a new point.
* @param {Point} p the other point
* @return {Point} output point
*/
multByPoint: function(p) { return this.clone()._multByPoint(p); },
/**
* Divide this point's x & y coordinates by point,
* yielding a new point.
* @param {Point} p the other point
* @return {Point} output point
*/
divByPoint: function(p) { return this.clone()._divByPoint(p); },
/**
* Multiply this point's x & y coordinates by a factor,
* yielding a new point.
* @param {Point} k factor
* @return {Point} output point
*/
mult: function(k) { return this.clone()._mult(k); },
/**
* Divide this point's x & y coordinates by a factor,
* yielding a new point.
* @param {Point} k factor
* @return {Point} output point
*/
div: function(k) { return this.clone()._div(k); },
/**
* Rotate this point around the 0, 0 origin by an angle a,
* given in radians
* @param {Number} a angle to rotate around, in radians
* @return {Point} output point
*/
rotate: function(a) { return this.clone()._rotate(a); },
/**
* Rotate this point around p point by an angle a,
* given in radians
* @param {Number} a angle to rotate around, in radians
* @param {Point} p Point to rotate around
* @return {Point} output point
*/
rotateAround: function(a,p) { return this.clone()._rotateAround(a,p); },
/**
* Multiply this point by a 4x1 transformation matrix
* @param {Array<Number>} m transformation matrix
* @return {Point} output point
*/
matMult: function(m) { return this.clone()._matMult(m); },
/**
* Calculate this point but as a unit vector from 0, 0, meaning
* that the distance from the resulting point to the 0, 0
* coordinate will be equal to 1 and the angle from the resulting
* point to the 0, 0 coordinate will be the same as before.
* @return {Point} unit vector point
*/
unit: function() { return this.clone()._unit(); },
/**
* Compute a perpendicular point, where the new y coordinate
* is the old x coordinate and the new x coordinate is the old y
* coordinate multiplied by -1
* @return {Point} perpendicular point
*/
perp: function() { return this.clone()._perp(); },
/**
* Return a version of this point with the x & y coordinates
* rounded to integers.
* @return {Point} rounded point
*/
round: function() { return this.clone()._round(); },
/**
* Return the magitude of this point: this is the Euclidean
* distance from the 0, 0 coordinate to this point's x and y
* coordinates.
* @return {Number} magnitude
*/
mag: function() {
return Math.sqrt(this.x * this.x + this.y * this.y);
},
/**
* Judge whether this point is equal to another point, returning
* true or false.
* @param {Point} other the other point
* @return {boolean} whether the points are equal
*/
equals: function(other) {
return this.x === other.x &&
this.y === other.y;
},
/**
* Calculate the distance from this point to another point
* @param {Point} p the other point
* @return {Number} distance
*/
dist: function(p) {
return Math.sqrt(this.distSqr(p));
},
/**
* Calculate the distance from this point to another point,
* without the square root step. Useful if you're comparing
* relative distances.
* @param {Point} p the other point
* @return {Number} distance
*/
distSqr: function(p) {
var dx = p.x - this.x,
dy = p.y - this.y;
return dx * dx + dy * dy;
},
/**
* Get the angle from the 0, 0 coordinate to this point, in radians
* coordinates.
* @return {Number} angle
*/
angle: function() {
return Math.atan2(this.y, this.x);
},
/**
* Get the angle from this point to another point, in radians
* @param {Point} b the other point
* @return {Number} angle
*/
angleTo: function(b) {
return Math.atan2(this.y - b.y, this.x - b.x);
},
/**
* Get the angle between this point and another point, in radians
* @param {Point} b the other point
* @return {Number} angle
*/
angleWith: function(b) {
return this.angleWithSep(b.x, b.y);
},
/*
* Find the angle of the two vectors, solving the formula for
* the cross product a x b = |a||b|sin(θ) for θ.
* @param {Number} x the x-coordinate
* @param {Number} y the y-coordinate
* @return {Number} the angle in radians
*/
angleWithSep: function(x, y) {
return Math.atan2(
this.x * y - this.y * x,
this.x * x + this.y * y);
},
_matMult: function(m) {
var x = m[0] * this.x + m[1] * this.y,
y = m[2] * this.x + m[3] * this.y;
this.x = x;
this.y = y;
return this;
},
_add: function(p) {
this.x += p.x;
this.y += p.y;
return this;
},
_sub: function(p) {
this.x -= p.x;
this.y -= p.y;
return this;
},
_mult: function(k) {
this.x *= k;
this.y *= k;
return this;
},
_div: function(k) {
this.x /= k;
this.y /= k;
return this;
},
_multByPoint: function(p) {
this.x *= p.x;
this.y *= p.y;
return this;
},
_divByPoint: function(p) {
this.x /= p.x;
this.y /= p.y;
return this;
},
_unit: function() {
this._div(this.mag());
return this;
},
_perp: function() {
var y = this.y;
this.y = this.x;
this.x = -y;
return this;
},
_rotate: function(angle) {
var cos = Math.cos(angle),
sin = Math.sin(angle),
x = cos * this.x - sin * this.y,
y = sin * this.x + cos * this.y;
this.x = x;
this.y = y;
return this;
},
_rotateAround: function(angle, p) {
var cos = Math.cos(angle),
sin = Math.sin(angle),
x = p.x + cos * (this.x - p.x) - sin * (this.y - p.y),
y = p.y + sin * (this.x - p.x) + cos * (this.y - p.y);
this.x = x;
this.y = y;
return this;
},
_round: function() {
this.x = Math.round(this.x);
this.y = Math.round(this.y);
return this;
}
};
/**
* Construct a point from an array if necessary, otherwise if the input
* is already a Point, or an unknown type, return it unchanged
* @param {Array<Number>|Point|*} a any kind of input value
* @return {Point} constructed point, or passed-through value.
* @example
* // this
* var point = Point.convert([0, 1]);
* // is equivalent to
* var point = new Point(0, 1);
*/
Point$1.convert = function (a) {
if (a instanceof Point$1) {
return a;
}
if (Array.isArray(a)) {
return new Point$1(a[0], a[1]);
}
return a;
};
var Point$2 = /*@__PURE__*/getDefaultExportFromCjs(pointGeometry);
var assert$2 = {exports: {}};
/*
object-assign
(c) Sindre Sorhus
@license MIT
*/
'use strict';
/* eslint-disable no-unused-vars */
var getOwnPropertySymbols = Object.getOwnPropertySymbols;
var hasOwnProperty = Object.prototype.hasOwnProperty;
var propIsEnumerable = Object.prototype.propertyIsEnumerable;
function toObject(val) {
if (val === null || val === undefined) {
throw new TypeError('Object.assign cannot be called with null or undefined');
}
return Object(val);
}
function shouldUseNative() {
try {
if (!Object.assign) {
return false;
}
// Detect buggy property enumeration order in older V8 versions.
// https://bugs.chromium.org/p/v8/issues/detail?id=4118
var test1 = new String('abc'); // eslint-disable-line no-new-wrappers
test1[5] = 'de';
if (Object.getOwnPropertyNames(test1)[0] === '5') {
return false;
}
// https://bugs.chromium.org/p/v8/issues/detail?id=3056
var test2 = {};
for (var i = 0; i < 10; i++) {
test2['_' + String.fromCharCode(i)] = i;
}
var order2 = Object.getOwnPropertyNames(test2).map(function (n) {
return test2[n];
});
if (order2.join('') !== '0123456789') {
return false;
}
// https://bugs.chromium.org/p/v8/issues/detail?id=3056
var test3 = {};
'abcdefghijklmnopqrst'.split('').forEach(function (letter) {
test3[letter] = letter;
});
if (Object.keys(Object.assign({}, test3)).join('') !==
'abcdefghijklmnopqrst') {
return false;
}
return true;
} catch (err) {
// We don't expect any of the above to throw, but better to be safe.
return false;
}
}
var objectAssign$1 = shouldUseNative() ? Object.assign : function (target, source) {
var from;
var to = toObject(target);
var symbols;
for (var s = 1; s < arguments.length; s++) {
from = Object(arguments[s]);
for (var key in from) {
if (hasOwnProperty.call(from, key)) {
to[key] = from[key];
}
}
if (getOwnPropertySymbols) {
symbols = getOwnPropertySymbols(from);
for (var i = 0; i < symbols.length; i++) {
if (propIsEnumerable.call(from, symbols[i])) {
to[symbols[i]] = from[symbols[i]];
}
}
}
}
return to;
};
var index = /*@__PURE__*/getDefaultExportFromCjs(objectAssign$1);
var util$2 = {};
var isBufferBrowser = function isBuffer(arg) {
return arg && typeof arg === 'object'
&& typeof arg.copy === 'function'
&& typeof arg.fill === 'function'
&& typeof arg.readUInt8 === 'function';
};
var isBufferBrowser$1 = /*@__PURE__*/getDefaultExportFromCjs(isBufferBrowser);
var inherits_browser$2 = {exports: {}};
var inherits_browser = inherits_browser$2.exports;
if (typeof Object.create === 'function') {
// implementation from standard node.js 'util' module
inherits_browser$2.exports = function inherits(ctor, superCtor) {
ctor.super_ = superCtor;
ctor.prototype = Object.create(superCtor.prototype, {
constructor: {
value: ctor,
enumerable: false,
writable: true,
configurable: true
}
});
};
} else {
// old school shim for old browsers
inherits_browser$2.exports = function inherits(ctor, superCtor) {
ctor.super_ = superCtor;
var TempCtor = function () {};
TempCtor.prototype = superCtor.prototype;
ctor.prototype = new TempCtor();
ctor.prototype.constructor = ctor;
};
}
var inherits_browserExports = inherits_browser$2.exports;
var inherits_browser$1 = /*@__PURE__*/getDefaultExportFromCjs(inherits_browserExports);
(function (exports) {
// Copyright Joyent, Inc. and other Node contributors.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to permit
// persons to whom the Software is furnished to do so, subject to the
// following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
// USE OR OTHER DEALINGS IN THE SOFTWARE.
var formatRegExp = /%[sdj%]/g;
exports.format = function(f) {
if (!isString(f)) {
var objects = [];
for (var i = 0; i < arguments.length; i++) {
objects.push(inspect(arguments[i]));
}
return objects.join(' ');
}
var i = 1;
var args = arguments;
var len = args.length;
var str = String(f).replace(formatRegExp, function(x) {
if (x === '%%') return '%';
if (i >= len) return x;
switch (x) {
case '%s': return String(args[i++]);
case '%d': return Number(args[i++]);
case '%j':
try {
return JSON.stringify(args[i++]);
} catch (_) {
return '[Circular]';
}
default:
return x;
}
});
for (var x = args[i]; i < len; x = args[++i]) {
if (isNull(x) || !isObject(x)) {
str += ' ' + x;
} else {
str += ' ' + inspect(x);
}
}
return str;
};
// Mark that a method should not be used.
// Returns a modified function which warns once by default.
// If --no-deprecation is set, then it is a no-op.
exports.deprecate = function(fn, msg) {
// Allow for deprecating things in the process of starting up.
if (isUndefined(global.process)) {
return function() {
return exports.deprecate(fn, msg).apply(this, arguments);
};
}
if (process.noDeprecation === true) {
return fn;
}
var warned = false;
function deprecated() {
if (!warned) {
if (process.throwDeprecation) {
throw new Error(msg);
} else if (process.traceDeprecation) {
console.trace(msg);
} else {
console.error(msg);
}
warned = true;
}
return fn.apply(this, arguments);
}
return deprecated;
};
var debugs = {};
var debugEnviron;
exports.debuglog = function(set) {
if (isUndefined(debugEnviron))
debugEnviron = process.env.NODE_DEBUG || '';
set = set.toUpperCase();
if (!debugs[set]) {
if (new RegExp('\\b' + set + '\\b', 'i').test(debugEnviron)) {
var pid = process.pid;
debugs[set] = function() {
var msg = exports.format.apply(exports, arguments);
console.error('%s %d: %s', set, pid, msg);
};
} else {
debugs[set] = function() {};
}
}
return debugs[set];
};
/**
* Echos the value of a value. Trys to print the value out
* in the best way possible given the different types.
*
* @param {Object} obj The object to print out.
* @param {Object} opts Optional options object that alters the output.
*/
/* legacy: obj, showHidden, depth, colors*/
function inspect(obj, opts) {
// default options
var ctx = {
seen: [],
stylize: stylizeNoColor
};
// legacy...
if (arguments.length >= 3) ctx.depth = arguments[2];
if (arguments.length >= 4) ctx.colors = arguments[3];
if (isBoolean(opts)) {
// legacy...
ctx.showHidden = opts;
} else if (opts) {
// got an "options" object
exports._extend(ctx, opts);
}
// set default options
if (isUndefined(ctx.showHidden)) ctx.showHidden = false;
if (isUndefined(ctx.depth)) ctx.depth = 2;
if (isUndefined(ctx.colors)) ctx.colors = false;
if (isUndefined(ctx.customInspect)) ctx.customInspect = true;
if (ctx.colors) ctx.stylize = stylizeWithColor;
return formatValue(ctx, obj, ctx.depth);
}
exports.inspect = inspect;
// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics
inspect.colors = {
'bold' : [1, 22],
'italic' : [3, 23],
'underline' : [4, 24],
'inverse' : [7, 27],
'white' : [37, 39],
'grey' : [90, 39],
'black' : [30, 39],
'blue' : [34, 39],
'cyan' : [36, 39],
'green' : [32, 39],
'magenta' : [35, 39],
'red' : [31, 39],
'yellow' : [33, 39]
};
// Don't use 'blue' not visible on cmd.exe
inspect.styles = {
'special': 'cyan',
'number': 'yellow',
'boolean': 'yellow',
'undefined': 'grey',
'null': 'bold',
'string': 'green',
'date': 'magenta',
// "name": intentionally not styling
'regexp': 'red'
};
function stylizeWithColor(str, styleType) {
var style = inspect.styles[styleType];
if (style) {
return '\u001b[' + inspect.colors[style][0] + 'm' + str +
'\u001b[' + inspect.colors[style][1] + 'm';
} else {
return str;
}
}
function stylizeNoColor(str, styleType) {
return str;
}
function arrayToHash(array) {
var hash = {};
array.forEach(function(val, idx) {
hash[val] = true;
});
return hash;
}
function formatValue(ctx, value, recurseTimes) {
// Provide a hook for user-specified inspect functions.
// Check that value is an object with an inspect function on it
if (ctx.customInspect &&
value &&
isFunction(value.inspect) &&
// Filter out the util module, it's inspect function is special
value.inspect !== exports.inspect &&
// Also filter out any prototype objects using the circular check.
!(value.constructor && value.constructor.prototype === value)) {
var ret = value.inspect(recurseTimes, ctx);
if (!isString(ret)) {
ret = formatValue(ctx, ret, recurseTimes);
}
return ret;
}
// Primitive types cannot have properties
var primitive = formatPrimitive(ctx, value);
if (primitive) {
return primitive;
}
// Look up the keys of the object.
var keys = Object.keys(value);
var visibleKeys = arrayToHash(keys);
if (ctx.showHidden) {
keys = Object.getOwnPropertyNames(value);
}
// IE doesn't make error fields non-enumerable
// http://msdn.microsoft.com/en-us/library/ie/dww52sbt(v=vs.94).aspx
if (isError(value)
&& (keys.indexOf('message') >= 0 || keys.indexOf('description') >= 0)) {
return formatError(value);
}
// Some type of object without properties can be shortcutted.
if (keys.length === 0) {
if (isFunction(value)) {
var name = value.name ? ': ' + value.name : '';
return ctx.stylize('[Function' + name + ']', 'special');
}
if (isRegExp(value)) {
return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');
}
if (isDate(value)) {
return ctx.stylize(Date.prototype.toString.call(value), 'date');
}
if (isError(value)) {
return formatError(value);
}
}
var base = '', array = false, braces = ['{', '}'];
// Make Array say that they are Array
if (isArray(value)) {
array = true;
braces = ['[', ']'];
}
// Make functions say that they are functions
if (isFunction(value)) {
var n = value.name ? ': ' + value.name : '';
base = ' [Function' + n + ']';
}
// Make RegExps say that they are RegExps
if (isRegExp(value)) {
base = ' ' + RegExp.prototype.toString.call(value);
}
// Make dates with properties first say the date
if (isDate(value)) {
base = ' ' + Date.prototype.toUTCString.call(value);
}
// Make error with message first say the error
if (isError(value)) {
base = ' ' + formatError(value);
}
if (keys.length === 0 && (!array || value.length == 0)) {
return braces[0] + base + braces[1];
}
if (recurseTimes < 0) {
if (isRegExp(value)) {
return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');
} else {
return ctx.stylize('[Object]', 'special');
}
}
ctx.seen.push(value);
var output;
if (array) {
output = formatArray(ctx, value, recurseTimes, visibleKeys, keys);
} else {
output = keys.map(function(key) {
return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array);
});
}
ctx.seen.pop();
return reduceToSingleString(output, base, braces);
}
function formatPrimitive(ctx, value) {
if (isUndefined(value))
return ctx.stylize('undefined', 'undefined');
if (isString(value)) {
var simple = '\'' + JSON.stringify(value).replace(/^"|"$/g, '')
.replace(/'/g, "\\'")
.replace(/\\"/g, '"') + '\'';
return ctx.stylize(simple, 'string');
}
if (isNumber(value))
return ctx.stylize('' + value, 'number');
if (isBoolean(value))
return ctx.stylize('' + value, 'boolean');
// For some reason typeof null is "object", so special case here.
if (isNull(value))
return ctx.stylize('null', 'null');
}
function formatError(value) {
return '[' + Error.prototype.toString.call(value) + ']';
}
function formatArray(ctx, value, recurseTimes, visibleKeys, keys) {
var output = [];
for (var i = 0, l = value.length; i < l; ++i) {
if (hasOwnProperty(value, String(i))) {
output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,
String(i), true));
} else {
output.push('');
}
}
keys.forEach(function(key) {
if (!key.match(/^\d+$/)) {
output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,
key, true));
}
});
return output;
}
function formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) {
var name, str, desc;
desc = Object.getOwnPropertyDescriptor(value, key) || { value: value[key] };
if (desc.get) {
if (desc.set) {
str = ctx.stylize('[Getter/Setter]', 'special');
} else {
str = ctx.stylize('[Getter]', 'special');
}
} else {
if (desc.set) {
str = ctx.stylize('[Setter]', 'special');
}
}
if (!hasOwnProperty(visibleKeys, key)) {
name = '[' + key + ']';
}
if (!str) {
if (ctx.seen.indexOf(desc.value) < 0) {
if (isNull(recurseTimes)) {
str = formatValue(ctx, desc.value, null);
} else {
str = formatValue(ctx, desc.value, recurseTimes - 1);
}
if (str.indexOf('\n') > -1) {
if (array) {
str = str.split('\n').map(function(line) {
return ' ' + line;
}).join('\n').substr(2);
} else {
str = '\n' + str.split('\n').map(function(line) {
return ' ' + line;
}).join('\n');
}
}
} else {
str = ctx.stylize('[Circular]', 'special');
}
}
if (isUndefined(name)) {
if (array && key.match(/^\d+$/)) {
return str;
}
name = JSON.stringify('' + key);
if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) {
name = name.substr(1, name.length - 2);
name = ctx.stylize(name, 'name');
} else {
name = name.replace(/'/g, "\\'")
.replace(/\\"/g, '"')
.replace(/(^"|"$)/g, "'");
name = ctx.stylize(name, 'string');
}
}
return name + ': ' + str;
}
function reduceToSingleString(output, base, braces) {
var numLinesEst = 0;
var length = output.reduce(function(prev, cur) {
numLinesEst++;
if (cur.indexOf('\n') >= 0) numLinesEst++;
return prev + cur.replace(/\u001b\[\d\d?m/g, '').length + 1;
}, 0);
if (length > 60) {
return braces[0] +
(base === '' ? '' : base + '\n ') +
' ' +
output.join(',\n ') +
' ' +
braces[1];
}
return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];
}
// NOTE: These type checking functions intentionally don't use `instanceof`
// because it is fragile and can be easily faked with `Object.create()`.
function isArray(ar) {
return Array.isArray(ar);
}
exports.isArray = isArray;
function isBoolean(arg) {
return typeof arg === 'boolean';
}
exports.isBoolean = isBoolean;
function isNull(arg) {
return arg === null;
}
exports.isNull = isNull;
function isNullOrUndefined(arg) {
return arg == null;
}
exports.isNullOrUndefined = isNullOrUndefined;
function isNumber(arg) {
return typeof arg === 'number';
}
exports.isNumber = isNumber;
function isString(arg) {
return typeof arg === 'string';
}
exports.isString = isString;
function isSymbol(arg) {
return typeof arg === 'symbol';
}
exports.isSymbol = isSymbol;
function isUndefined(arg) {
return arg === void 0;
}
exports.isUndefined = isUndefined;
function isRegExp(re) {
return isObject(re) && objectToString(re) === '[object RegExp]';
}
exports.isRegExp = isRegExp;
function isObject(arg) {
return typeof arg === 'object' && arg !== null;
}
exports.isObject = isObject;
function isDate(d) {
return isObject(d) && objectToString(d) === '[object Date]';
}
exports.isDate = isDate;
function isError(e) {
return isObject(e) &&
(objectToString(e) === '[object Error]' || e instanceof Error);
}
exports.isError = isError;
function isFunction(arg) {
return typeof arg === 'function';
}
exports.isFunction = isFunction;
function isPrimitive(arg) {
return arg === null ||
typeof arg === 'boolean' ||
typeof arg === 'number' ||
typeof arg === 'string' ||
typeof arg === 'symbol' || // ES6 symbol
typeof arg === 'undefined';
}
exports.isPrimitive = isPrimitive;
exports.isBuffer = isBufferBrowser;
function objectToString(o) {
return Object.prototype.toString.call(o);
}
function pad(n) {
return n < 10 ? '0' + n.toString(10) : n.toString(10);
}
var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
'Oct', 'Nov', 'Dec'];
// 26 Feb 16:19:34
function timestamp() {
var d = new Date();
var time = [pad(d.getHours()),
pad(d.getMinutes()),
pad(d.getSeconds())].join(':');
return [d.getDate(), months[d.getMonth()], time].join(' ');
}
// log is just a thin wrapper to console.log that prepends a timestamp
exports.log = function() {
console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments));
};
/**
* Inherit the prototype methods from one constructor into another.
*
* The Function.prototype.inherits from lang.js rewritten as a standalone
* function (not on Function.prototype). NOTE: If this file is to be loaded
* during bootstrapping this function needs to be rewritten using some native
* functions as prototype setup using normal JavaScript does not work as
* expected during bootstrapping (see mirror.js in r114903).
*
* @param {function} ctor Constructor function which needs to inherit the
* prototype.
* @param {function} superCtor Constructor function to inherit prototype from.
*/
exports.inherits = inherits_browserExports;
exports._extend = function(origin, add) {
// Don't do anything if add isn't an object
if (!add || !isObject(add)) return origin;
var keys = Object.keys(add);
var i = keys.length;
while (i--) {
origin[keys[i]] = add[keys[i]];
}
return origin;
};
function hasOwnProperty(obj, prop) {
return Object.prototype.hasOwnProperty.call(obj, prop);
}
} (util$2));
var util$1 = /*@__PURE__*/getDefaultExportFromCjs(util$2);
var assert_1 = assert$2.exports;
'use strict';
var objectAssign = objectAssign$1;
// compare and isBuffer taken from https://github.com/feross/buffer/blob/680e9e5e488f22aac27599a57dc844a6315928dd/index.js
// original notice:
/*!
* The buffer module from node.js, for the browser.
*
* @author Feross Aboukhadijeh <feross@feross.org> <http://feross.org>
* @license MIT
*/
function compare$1(a, b) {
if (a === b) {
return 0;
}
var x = a.length;
var y = b.length;
for (var i = 0, len = Math.min(x, y); i < len; ++i) {
if (a[i] !== b[i]) {
x = a[i];
y = b[i];
break;
}
}
if (x < y) {
return -1;
}
if (y < x) {
return 1;
}
return 0;
}
function isBuffer(b) {
if (global.Buffer && typeof global.Buffer.isBuffer === 'function') {
return global.Buffer.isBuffer(b);
}
return !!(b != null && b._isBuffer);
}
// based on node assert, original notice:
// NB: The URL to the CommonJS spec is kept just for tradition.
// node-assert has evolved a lot since then, both in API and behavior.
// http://wiki.commonjs.org/wiki/Unit_Testing/1.0
//
// THIS IS NOT TESTED NOR LIKELY TO WORK OUTSIDE V8!
//
// Originally from narwhal.js (http://narwhaljs.org)
// Copyright (c) 2009 Thomas Robinson <280north.com>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the 'Software'), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
var util = util$2;
var hasOwn = Object.prototype.hasOwnProperty;
var pSlice = Array.prototype.slice;
var functionsHaveNames = (function () {
return function foo() {}.name === 'foo';
}());
function pToString (obj) {
return Object.prototype.toString.call(obj);
}
function isView(arrbuf) {
if (isBuffer(arrbuf)) {
return false;
}
if (typeof global.ArrayBuffer !== 'function') {
return false;
}
if (typeof ArrayBuffer.isView === 'function') {
return ArrayBuffer.isView(arrbuf);
}
if (!arrbuf) {
return false;
}
if (arrbuf instanceof DataView) {
return true;
}
if (arrbuf.buffer && arrbuf.buffer instanceof ArrayBuffer) {
return true;
}
return false;
}
// 1. The assert module provides functions that throw
// AssertionError's when particular conditions are not met. The
// asser