-
Notifications
You must be signed in to change notification settings - Fork 1
/
has.js
134 lines (124 loc) · 3.99 KB
/
has.js
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
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
define([ 'require' ], function (require) {
/*jshint node:true */
var has = require.has;
if (!has) {
has = (function () {
var hasCache = Object.create(null),
global = this,
document = global.document,
element = document && document.createElement('DIV');
/**
* A standard API for retrieving feature test results and configuration data that may be
* used to remove code at build time. See {@link has.add} for information on adding new
* tests.
*
* @param name
* The name of the feature to test.
*
* @returns The value of the given has-flag.
*
* @example
* if (has('host-node')) {
* // Node.js-specific code which can be optimized out
* // for browser-specific builds
* }
*/
function has(/**string*/ name) {
return typeof hasCache[name] === 'function' ? (hasCache[name] = hasCache[name](global, document, element)) : hasCache[name];
}
/**
* Registers a new feature test or configuration value for use by {@link has}.
*
* @param name
* The name of the feature to register.
*
* @param {*|function(global:Global, document:HTMLDocument=, element:HTMLElement=):*} test
* A value or test function to register. If a function is passed, it will be called once
* the first time its value is requested and the return value cached.
*
* @param now
* If `test` is a function, passing a truthy value will cause it to be invoked
* immediately. By default, a test function is not executed until the value is actually
* used for the first time.
*
* @param force
* If `name` is already registered, passing a truthy value will cause its value to be
* replaced with the new value. By default, re-registering a test that already exists is
* a no-op.
*/
has.add = function (/**string*/ name, test, /**boolean=*/ now, /**boolean=*/ force) {
(!(name in hasCache) || force) && (hasCache[name] = test);
now && has(name);
};
return has;
})();
}
has.add('host-browser', typeof document !== 'undefined' && typeof location !== 'undefined');
has.add('host-node', typeof process === 'object' && process.versions && process.versions.node);
/**
* Resolves a conditional module ID into a real module ID based on a possibly-nested tenary
* expression that branches on has-flags. See {@link has.load} for details on the syntax.
*
* @param id
* The conditional module ID.
*
* @param toAbsMid
* A function that converts a relative module ID into the correct absolute module ID.
*/
has.normalize = function (/**string*/ id, /**Function*/ normalize) {
var tokens = id.match(/[\?:]|[^:\?]*/g),
i = 0,
get = function (skip) {
var term = tokens[i++];
if (term === ':') {
// empty string module name, resolves to 0
return 0;
}
else {
// postfixed with a ? means it is a feature to branch on, the term is the name of the feature
if (tokens[i++] === '?') {
if (!skip && has(term)) {
// matched the feature, get the first value from the options
return get();
}
else {
// did not match, get the second value, passing over the first
get(true);
return get(skip);
}
}
// a module
return term || 0;
}
};
id = get();
return id && normalize(id);
};
/**
* Conditionally loads AMD modules based on the value of has-flags.
*
* @param id
* The module ID to load. The correct module ID to load is determined by the code in `has.normalize`.
*
* @param parentRequire
* The loader require function with respect to the module that contained the plugin resource in its dependency
* list.
*
* @param loaded
* Callback to loader that consumes result of plugin demand.
*
* @example
* define([
* 'dojo/has!test-foo?module/foo:test-bar?module/bar:module/baz'
* ], ...);
*/
has.load = function (/**string*/ id, /**Function*/ parentRequire, /**Function*/ load) {
if (id) {
parentRequire([ id ], load);
}
else {
load();
}
};
return has;
});