summaryrefslogtreecommitdiff
path: root/platform/node/index.js
blob: 6f6b33058ac84541c347e637437283153941093b (plain)
1
2
3
4
5
6
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
47
48
49
50
51
"use strict";

// Shim to wrap req.respond while preserving callback-passing API

var mbgl = require('../../lib/mbgl-node.abi-' + process.versions.modules);
var constructor = mbgl.Map.prototype.constructor;

var Map = function(options) {
    if (!(options instanceof Object)) {
        throw TypeError("Requires an options object as first argument");
    }

    if (!options.hasOwnProperty('request') || !(options.request instanceof Function)) {
        throw TypeError("Options object must have a 'request' method");
    }

    var request = options.request;

    return new constructor(Object.assign(options, {
        request: function(req) {
            // Protect against `request` implementations that call the callback synchronously,
            // call it multiple times, or throw exceptions.
            // http://blog.izs.me/post/59142742143/designing-apis-for-asynchrony

            var responded = false;
            var callback = function() {
                var args = arguments;
                if (!responded) {
                    responded = true;
                    process.nextTick(function() {
                        req.respond.apply(req, args);
                    });
                } else {
                    console.warn('request function responded multiple times; it should call the callback only once');
                }
            };

            try {
                request(req, callback);
            } catch (e) {
                console.warn('request function threw an exception; it should call the callback with an error instead');
                callback(e);
            }
        }
    }));
};

Map.prototype = mbgl.Map.prototype;
Map.prototype.constructor = Map;

module.exports = Object.assign(mbgl, { Map: Map });