Software: Apache/2.4.41 (Ubuntu). PHP/8.0.30 uname -a: Linux apirnd 5.4.0-204-generic #224-Ubuntu SMP Thu Dec 5 13:38:28 UTC 2024 x86_64 uid=33(www-data) gid=33(www-data) groups=33(www-data) Safe-mode: OFF (not secure) /var/www/html/node-red/node_modules/jshint/src/ drwxr-xr-x | |
| Viewing file: Select action/file-type: "use strict";
/**
* A note on `__proto__`:
*
* This file uses ordinary objects to track identifiers that are observed in
* the input source code. It creates these objects using `Object.create` so
* that the tracking objects have no prototype, allowing the `__proto__`
* property to be used to store a value *without* triggering the invocation of
* the built-in `Object.prototype.__proto__` accessor method. Some environments
* (e.g. PhantomJS) do not implement the correct semantics for property
* enumeration. In those environments, methods like `Object.keys` and Lodash's
* `values` do not include the property name. This file includes a number of
* branches which ensure that JSHint behaves consistently in those
* environments. The branches must be ignored by the test coverage verification
* system because the workaround is not necessary in the environment where
* coverage is verified (i.e. Node.js).
*/
var _ = require("lodash");
var events = require("events");
// Used to denote membership in lookup tables (a primitive value such as `true`
// would be silently rejected for the property name "__proto__" in some
// environments)
var marker = {};
/**
* A factory function for creating scope managers. A scope manager tracks
* bindings, detecting when variables are referenced (through "usages").
*
* @param {object} state - the global state object (see `state.js`)
* @param {Array} predefined - a set of binding names for built-in bindings
* provided by the environment
* @param {object} exported - a hash for binding names that are intended to be
* referenced in contexts beyond the current program
* code
* @param {object} declared - a hash for binding names that were defined as
* global bindings via linting configuration
*
* @returns {object} - a scope manager
*/
var scopeManager = function(state, predefined, exported, declared) {
var _current;
var _scopeStack = [];
function _newScope(type) {
_current = {
"(bindings)": Object.create(null),
"(usages)": Object.create(null),
"(labels)": Object.create(null),
"(parent)": _current,
"(type)": type,
"(params)": (type === "functionparams" || type === "catchparams") ? [] : null
};
_scopeStack.push(_current);
}
_newScope("global");
_current["(predefined)"] = predefined;
var _currentFunctBody = _current; // this is the block after the params = function
var usedPredefinedAndGlobals = Object.create(null);
var impliedGlobals = Object.create(null);
var unuseds = [];
var esModuleExports = [];
var emitter = new events.EventEmitter();
function warning(code, token) {
emitter.emit("warning", {
code: code,
token: token,
data: _.slice(arguments, 2)
});
}
function error(code, token) {
emitter.emit("warning", {
code: code,
token: token,
data: _.slice(arguments, 2)
});
}
function _setupUsages(bindingName) {
if (!_current["(usages)"][bindingName]) {
_current["(usages)"][bindingName] = {
"(modified)": [],
"(reassigned)": [],
"(tokens)": []
};
}
}
var _getUnusedOption = function(unused_opt) {
if (unused_opt === undefined) {
unused_opt = state.option.unused;
}
if (unused_opt === true) {
unused_opt = "last-param";
}
return unused_opt;
};
var _warnUnused = function(name, tkn, type, unused_opt) {
var line = tkn.line;
var chr = tkn.from;
var raw_name = tkn.raw_text || name;
unused_opt = _getUnusedOption(unused_opt);
var warnable_types = {
"vars": ["var"],
"last-param": ["var", "param"],
"strict": ["var", "param", "last-param"]
};
if (unused_opt) {
if (warnable_types[unused_opt] && warnable_types[unused_opt].indexOf(type) !== -1) {
warning("W098", { line: line, from: chr }, raw_name);
}
}
// inconsistent - see gh-1894
if (unused_opt || type === "var") {
unuseds.push({
name: name,
line: line,
character: chr
});
}
};
/**
* Check the current scope for unused identifiers
*/
function _checkForUnused() {
if (_current["(type)"] !== "functionparams") {
var currentBindings = _current["(bindings)"];
for (var bindingName in currentBindings) {
if (currentBindings[bindingName]["(type)"] !== "exception" &&
currentBindings[bindingName]["(unused)"]) {
_warnUnused(bindingName, currentBindings[bindingName]["(token)"], "var");
}
}
return;
}
// Check the current scope for unused parameters and issue warnings as
// necessary.
var params = _current["(params)"];
var param = params.pop();
var unused_opt;
while (param) {
var binding = _current["(bindings)"][param];
unused_opt = _getUnusedOption(state.funct["(unusedOption)"]);
// 'undefined' is a special case for the common pattern where `undefined`
// is used as a formal parameter name to defend against global
// re-assignment, e.g.
//
// (function(window, undefined) {
// })();
if (param === "undefined")
return;
if (binding["(unused)"]) {
_warnUnused(param, binding["(token)"], "param", state.funct["(unusedOption)"]);
} else if (unused_opt === "last-param") {
return;
}
param = params.pop();
}
}
/**
* Find the relevant binding's scope. The owning scope is located by first
* inspecting the current scope and then moving "downward" through the stack
* of scopes.
*
* @param {string} bindingName - the value of the identifier
*
* @returns {Object} - the scope in which the binding was found
*/
function _getBinding(bindingName) {
for (var i = _scopeStack.length - 1 ; i >= 0; --i) {
var scopeBindings = _scopeStack[i]["(bindings)"];
if (scopeBindings[bindingName]) {
return scopeBindings;
}
}
}
/**
* Determine if a given binding name has been referenced within the current
* function or any function defined within.
*
* @param {string} bindingName - the value of the identifier
*
* @returns {boolean}
*/
function usedSoFarInCurrentFunction(bindingName) {
for (var i = _scopeStack.length - 1; i >= 0; i--) {
var current = _scopeStack[i];
if (current["(usages)"][bindingName]) {
return current["(usages)"][bindingName];
}
if (current === _currentFunctBody) {
break;
}
}
return false;
}
function _checkOuterShadow(bindingName, token) {
// only check if shadow is outer
if (state.option.shadow !== "outer") {
return;
}
var isGlobal = _currentFunctBody["(type)"] === "global",
isNewFunction = _current["(type)"] === "functionparams";
var outsideCurrentFunction = !isGlobal;
for (var i = 0; i < _scopeStack.length; i++) {
var stackItem = _scopeStack[i];
if (!isNewFunction && _scopeStack[i + 1] === _currentFunctBody) {
outsideCurrentFunction = false;
}
if (outsideCurrentFunction && stackItem["(bindings)"][bindingName]) {
warning("W123", token, bindingName);
}
if (stackItem["(labels)"][bindingName]) {
warning("W123", token, bindingName);
}
}
}
function _latedefWarning(type, bindingName, token) {
var isFunction;
if (state.option.latedef) {
isFunction = type === "function" || type === "generator function" ||
type === "async function";
// if either latedef is strict and this is a function
// or this is not a function
if ((state.option.latedef === true && isFunction) || !isFunction) {
warning("W003", token, bindingName);
}
}
}
var scopeManagerInst = {
on: function(names, listener) {
names.split(" ").forEach(function(name) {
emitter.on(name, listener);
});
},
isPredefined: function(bindingName) {
return !this.has(bindingName) && _.has(_scopeStack[0]["(predefined)"], bindingName);
},
/**
* Create a new scope within the current scope. As the topmost value, the
* new scope will be interpreted as the current scope until it is
* exited--see the `unstack` method.
*
* @param {string} [type] - The type of the scope. Valid values are
* "functionparams", "catchparams" and
* "functionouter"
*/
stack: function(type) {
var previousScope = _current;
_newScope(type);
if (!type && previousScope["(type)"] === "functionparams") {
_current["(isFuncBody)"] = true;
_currentFunctBody = _current;
}
},
/**
* Valldate all binding references and declarations in the current scope
* and set the next scope on the stack as the active scope.
*/
unstack: function() {
// jshint proto: true
var subScope = _scopeStack.length > 1 ? _scopeStack[_scopeStack.length - 2] : null;
var isUnstackingFunctionBody = _current === _currentFunctBody,
isUnstackingFunctionParams = _current["(type)"] === "functionparams",
isUnstackingFunctionOuter = _current["(type)"] === "functionouter";
var i, j, isImmutable, isFunction;
var currentUsages = _current["(usages)"];
var currentBindings = _current["(bindings)"];
var usedBindingNameList = Object.keys(currentUsages);
// See comment, "A note on `__proto__`"
/* istanbul ignore if */
if (currentUsages.__proto__ && usedBindingNameList.indexOf("__proto__") === -1) {
usedBindingNameList.push("__proto__");
}
for (i = 0; i < usedBindingNameList.length; i++) {
var usedBindingName = usedBindingNameList[i];
var usage = currentUsages[usedBindingName];
var usedBinding = currentBindings[usedBindingName];
if (usedBinding) {
var usedBindingType = usedBinding["(type)"];
isImmutable = usedBindingType === "const" || usedBindingType === "import";
if (usedBinding["(useOutsideOfScope)"] && !state.option.funcscope) {
var usedTokens = usage["(tokens)"];
for (j = 0; j < usedTokens.length; j++) {
// Keep the consistency of https://github.com/jshint/jshint/issues/2409
if (usedBinding["(function)"] === usedTokens[j]["(function)"]) {
error("W038", usedTokens[j], usedBindingName);
}
}
}
// mark the binding used
_current["(bindings)"][usedBindingName]["(unused)"] = false;
// check for modifying a const
if (isImmutable && usage["(modified)"]) {
for (j = 0; j < usage["(modified)"].length; j++) {
error("E013", usage["(modified)"][j], usedBindingName);
}
}
isFunction = usedBindingType === "function" ||
usedBindingType === "generator function" ||
usedBindingType === "async function";
// check for re-assigning a function declaration
if ((isFunction || usedBindingType === "class") && usage["(reassigned)"]) {
for (j = 0; j < usage["(reassigned)"].length; j++) {
if (!usage["(reassigned)"][j].ignoreW021) {
warning("W021", usage["(reassigned)"][j], usedBindingName, usedBindingType);
}
}
}
continue;
}
if (subScope) {
var bindingType = this.bindingtype(usedBindingName);
isImmutable = bindingType === "const" ||
(bindingType === null && _scopeStack[0]["(predefined)"][usedBindingName] === false);
if (isUnstackingFunctionOuter && !isImmutable) {
if (!state.funct["(outerMutables)"]) {
state.funct["(outerMutables)"] = [];
}
state.funct["(outerMutables)"].push(usedBindingName);
}
// not exiting the global scope, so copy the usage down in case its an out of scope usage
if (!subScope["(usages)"][usedBindingName]) {
subScope["(usages)"][usedBindingName] = usage;
if (isUnstackingFunctionBody) {
subScope["(usages)"][usedBindingName]["(onlyUsedSubFunction)"] = true;
}
} else {
var subScopeUsage = subScope["(usages)"][usedBindingName];
subScopeUsage["(modified)"] = subScopeUsage["(modified)"].concat(usage["(modified)"]);
subScopeUsage["(tokens)"] = subScopeUsage["(tokens)"].concat(usage["(tokens)"]);
subScopeUsage["(reassigned)"] =
subScopeUsage["(reassigned)"].concat(usage["(reassigned)"]);
}
} else {
// this is exiting global scope, so we finalise everything here - we are at the end of the file
if (typeof _current["(predefined)"][usedBindingName] === "boolean") {
// remove the declared token, so we know it is used
delete declared[usedBindingName];
// note it as used so it can be reported
usedPredefinedAndGlobals[usedBindingName] = marker;
// check for re-assigning a read-only (set to false) predefined
if (_current["(predefined)"][usedBindingName] === false && usage["(reassigned)"]) {
for (j = 0; j < usage["(reassigned)"].length; j++) {
if (!usage["(reassigned)"][j].ignoreW020) {
warning("W020", usage["(reassigned)"][j]);
}
}
}
}
else {
// binding usage is not predefined and we have not found a declaration
// so report as undeclared
for (j = 0; j < usage["(tokens)"].length; j++) {
var undefinedToken = usage["(tokens)"][j];
// if its not a forgiven undefined (e.g. typof x)
if (!undefinedToken.forgiveUndef) {
// if undef is on and undef was on when the token was defined
if (state.option.undef && !undefinedToken.ignoreUndef) {
warning("W117", undefinedToken, usedBindingName);
}
if (impliedGlobals[usedBindingName]) {
impliedGlobals[usedBindingName].line.push(undefinedToken.line);
} else {
impliedGlobals[usedBindingName] = {
name: usedBindingName,
line: [undefinedToken.line]
};
}
}
}
}
}
}
// if exiting the global scope, we can warn about declared globals that haven't been used yet
if (!subScope) {
Object.keys(declared)
.forEach(function(bindingNotUsed) {
_warnUnused(bindingNotUsed, declared[bindingNotUsed], "var");
});
}
// If this is not a function boundary, transfer function-scoped bindings to
// the parent block (a rough simulation of variable hoisting). Previously
// existing bindings in the parent block should take precedence so that
// prior usages are not discarded.
if (subScope && !isUnstackingFunctionBody &&
!isUnstackingFunctionParams && !isUnstackingFunctionOuter) {
var bindingNames = Object.keys(currentBindings);
for (i = 0; i < bindingNames.length; i++) {
var defBindingName = bindingNames[i];
var defBinding = currentBindings[defBindingName];
if (!defBinding["(blockscoped)"] && defBinding["(type)"] !== "exception") {
var shadowed = subScope["(bindings)"][defBindingName];
// Do not overwrite a binding if it exists in the parent scope
// because it is shared by adjacent blocks. Copy the `unused`
// property so that any references found within the current block
// are counted toward that higher-level declaration.
if (shadowed) {
shadowed["(unused)"] &= defBinding["(unused)"];
// "Hoist" the variable to the parent block, decorating the binding
// so that future references, though technically valid, can be
// reported as "out-of-scope" in the absence of the `funcscope`
// option.
} else {
defBinding["(useOutsideOfScope)"] =
// Do not warn about out-of-scope usages in the global scope
_currentFunctBody["(type)"] !== "global" &&
// When a higher scope contains a binding for the binding, the
// binding is a re-declaration and should not prompt "used
// out-of-scope" warnings.
!this.funct.has(defBindingName, { excludeCurrent: true });
subScope["(bindings)"][defBindingName] = defBinding;
}
delete currentBindings[defBindingName];
}
}
}
_checkForUnused();
_scopeStack.pop();
if (isUnstackingFunctionBody) {
_currentFunctBody = _scopeStack[_.findLastIndex(_scopeStack, function(scope) {
// if function or if global (which is at the bottom so it will only return true if we call back)
return scope["(isFuncBody)"] || scope["(type)"] === "global";
})];
}
_current = subScope;
},
/**
* Add a function parameter to the current scope.
*
* @param {string} bindingName - the value of the identifier
* @param {Token} token
* @param {string} [type] - binding type; defaults to "param"
*/
addParam: function(bindingName, token, type) {
type = type || "param";
if (type === "exception") {
// if defined in the current function
var previouslyDefinedBindingType = this.funct.bindingtype(bindingName);
if (previouslyDefinedBindingType && previouslyDefinedBindingType !== "exception") {
// and has not been used yet in the current function scope
if (!state.option.node) {
warning("W002", state.tokens.next, bindingName);
}
}
if (state.isStrict() && (bindingName === "arguments" || bindingName === "eval")) {
warning("E008", token);
}
}
// The variable was declared in the current scope
if (_.has(_current["(bindings)"], bindingName)) {
_current["(bindings)"][bindingName].duplicated = true;
// The variable was declared in an outer scope
} else {
// if this scope has the variable defined, it's a re-definition error
_checkOuterShadow(bindingName, token);
_current["(bindings)"][bindingName] = {
"(type)" : type,
"(token)": token,
"(unused)": true };
_current["(params)"].push(bindingName);
}
if (_.has(_current["(usages)"], bindingName)) {
var usage = _current["(usages)"][bindingName];
// if its in a sub function it is not necessarily an error, just latedef
if (usage["(onlyUsedSubFunction)"]) {
_latedefWarning(type, bindingName, token);
} else {
// this is a clear illegal usage, but not a syntax error, so emit a
// warning and not an error
warning("W003", token, bindingName);
}
}
},
validateParams: function(isArrow) {
var isStrict = state.isStrict();
var currentFunctParamScope = _currentFunctBody["(parent)"];
// From ECMAScript 2017:
//
// > 14.1.2Static Semantics: Early Errors
// >
// > [...]
// > - It is a Syntax Error if IsSimpleParameterList of
// > FormalParameterList is false and BoundNames of FormalParameterList
// > contains any duplicate elements.
var isSimple = state.funct['(hasSimpleParams)'];
// Method definitions are defined in terms of UniqueFormalParameters, so
// they cannot support duplicate parameter names regardless of strict
// mode.
var isMethod = state.funct["(method)"];
if (!currentFunctParamScope["(params)"]) {
/* istanbul ignore next */
return;
}
currentFunctParamScope["(params)"].forEach(function(bindingName) {
var binding = currentFunctParamScope["(bindings)"][bindingName];
if (binding.duplicated) {
if (isStrict || isArrow || isMethod || !isSimple) {
warning("E011", binding["(token)"], bindingName);
} else if (state.option.shadow !== true) {
warning("W004", binding["(token)"], bindingName);
}
}
if (isStrict && (bindingName === "arguments" || bindingName === "eval")) {
warning("E008", binding["(token)"]);
}
});
},
getUsedOrDefinedGlobals: function() {
// jshint proto: true
var list = Object.keys(usedPredefinedAndGlobals);
// See comment, "A note on `__proto__`"
/* istanbul ignore if */
if (usedPredefinedAndGlobals.__proto__ === marker &&
list.indexOf("__proto__") === -1) {
list.push("__proto__");
}
return list;
},
/**
* Get an array of implied globals
*
* @returns {Array.<{ name: string, line: Array.<number>}>}
*/
getImpliedGlobals: function() {
// jshint proto: true
var values = _.values(impliedGlobals);
var hasProto = false;
// See comment, "A note on `__proto__`"
if (impliedGlobals.__proto__) {
hasProto = values.some(function(value) {
return value.name === "__proto__";
});
/* istanbul ignore if */
if (!hasProto) {
values.push(impliedGlobals.__proto__);
}
}
return values;
},
/**
* Get an array of objects describing unused bindings.
*
* @returns {Array<Object>}
*/
getUnuseds: function() {
return unuseds;
},
/**
* Determine if a given name has been defined in the current scope or any
* lower scope.
*
* @param {string} bindingName - the value of the identifier
*
* @return {boolean}
*/
has: function(bindingName) {
return Boolean(_getBinding(bindingName));
},
/**
* Retrieve binding described by `bindingName` or null
*
* @param {string} bindingName - the value of the identifier
*
* @returns {string|null} - the type of the binding or `null` if no such
* binding exists
*/
bindingtype: function(bindingName) {
var scopeBindings = _getBinding(bindingName);
if (scopeBindings) {
return scopeBindings[bindingName]["(type)"];
}
return null;
},
/**
* For the exported options, indicating a variable is used outside the file
*
* @param {string} bindingName - the value of the identifier
*/
addExported: function(bindingName) {
var globalBindings = _scopeStack[0]["(bindings)"];
if (_.has(declared, bindingName)) {
// remove the declared token, so we know it is used
delete declared[bindingName];
} else if (_.has(globalBindings, bindingName)) {
globalBindings[bindingName]["(unused)"] = false;
} else {
for (var i = 1; i < _scopeStack.length; i++) {
var scope = _scopeStack[i];
// if `scope.(type)` is not defined, it is a block scope
if (!scope["(type)"]) {
if (_.has(scope["(bindings)"], bindingName) &&
!scope["(bindings)"][bindingName]["(blockscoped)"]) {
scope["(bindings)"][bindingName]["(unused)"] = false;
return;
}
} else {
break;
}
}
exported[bindingName] = true;
}
},
/**
* Mark a binding as "exported" by an ES2015 module
*
* @param {string} bindingName - the value of the identifier
* @param {object} token
*/
setExported: function(localName, exportName) {
if (exportName) {
if (esModuleExports.indexOf(exportName.value) > -1) {
error("E069", exportName, exportName.value);
}
esModuleExports.push(exportName.value);
}
if (localName) {
this.block.use(localName.value, localName);
}
},
/**
* Mark a binding as "initialized." This is necessary to enforce the
* "temporal dead zone" (TDZ) of block-scoped bindings which are not
* hoisted.
*
* @param {string} bindingName - the value of the identifier
*/
initialize: function(bindingName) {
if (_current["(bindings)"][bindingName]) {
_current["(bindings)"][bindingName]["(initialized)"] = true;
}
},
/**
* Create a new binding and add it to the current scope. Delegates to the
* internal `block.add` or `func.add` methods depending on the type.
* Produces warnings and errors as necessary.
*
* @param {string} bindingName
* @param {Object} opts
* @param {String} opts.type - the type of the binding e.g. "param", "var",
* "let, "const", "import", "function",
* "generator function", "async function",
* "async generator function"
* @param {object} opts.token - the token pointing at the declaration
* @param {boolean} opts.initialized - whether the binding should be
* created in an "initialized" state.
*/
addbinding: function(bindingName, opts) {
var type = opts.type;
var token = opts.token;
var isblockscoped = type === "let" || type === "const" ||
type === "class" || type === "import" || type === "generator function" ||
type === "async function" || type === "async generator function";
var ishoisted = type === "function" || type === "generator function" ||
type === "async function" || type === "import";
var isexported = (isblockscoped ? _current : _currentFunctBody)["(type)"] === "global" &&
_.has(exported, bindingName);
// outer shadow check (inner is only on non-block scoped)
_checkOuterShadow(bindingName, token);
if (state.isStrict() && (bindingName === "arguments" || bindingName === "eval")) {
warning("E008", token);
}
if (isblockscoped) {
var declaredInCurrentScope = _current["(bindings)"][bindingName];
// for block scoped variables, params are seen in the current scope as the root function
// scope, so check these too.
if (!declaredInCurrentScope && _current === _currentFunctBody &&
_current["(type)"] !== "global") {
declaredInCurrentScope = !!_currentFunctBody["(parent)"]["(bindings)"][bindingName];
}
// if its not already defined (which is an error, so ignore) and is used in TDZ
if (!declaredInCurrentScope && _current["(usages)"][bindingName]) {
var usage = _current["(usages)"][bindingName];
// if its in a sub function it is not necessarily an error, just latedef
if (usage["(onlyUsedSubFunction)"] || ishoisted) {
_latedefWarning(type, bindingName, token);
} else if (!ishoisted) {
// this is a clear illegal usage for block scoped variables
warning("E056", token, bindingName, type);
}
}
// If this scope has already declared a binding with the same name,
// then this represents a redeclaration error if:
//
// 1. it is a "hoisted" block-scoped binding within a block. For
// instance: generator functions may be redeclared in the global
// scope but not within block statements
// 2. this is not a "hoisted" block-scoped binding
if (declaredInCurrentScope &&
(!ishoisted || (_current["(type)"] !== "global" || type === "import"))) {
warning("E011", token, bindingName);
}
else if (state.option.shadow === "outer") {
// if shadow is outer, for block scope we want to detect any shadowing within this function
if (scopeManagerInst.funct.has(bindingName)) {
warning("W004", token, bindingName);
}
}
scopeManagerInst.block.add(
bindingName, type, token, !isexported, opts.initialized
);
} else {
var declaredInCurrentFunctionScope = scopeManagerInst.funct.has(bindingName);
// check for late definition, ignore if already declared
if (!declaredInCurrentFunctionScope && usedSoFarInCurrentFunction(bindingName)) {
_latedefWarning(type, bindingName, token);
}
// defining with a var or a function when a block scope variable of the same name
// is in scope is an error
if (scopeManagerInst.funct.has(bindingName, { onlyBlockscoped: true })) {
warning("E011", token, bindingName);
} else if (state.option.shadow !== true) {
// now since we didn't get any block scope variables, test for var/function
// shadowing
if (declaredInCurrentFunctionScope && bindingName !== "__proto__") {
// see https://github.com/jshint/jshint/issues/2400
if (_currentFunctBody["(type)"] !== "global") {
warning("W004", token, bindingName);
}
}
}
scopeManagerInst.funct.add(bindingName, type, token, !isexported);
if (_currentFunctBody["(type)"] === "global" && !state.impliedClosure()) {
usedPredefinedAndGlobals[bindingName] = marker;
}
}
},
funct: {
/**
* Return the type of the provided binding given certain options
*
* @param {string} bindingName
* @param {Object=} [options]
* @param {boolean} [options.onlyBlockscoped] - only include block scoped
* bindings
* @param {boolean} [options.excludeParams] - exclude the param scope
* @param {boolean} [options.excludeCurrent] - exclude the current scope
*
* @returns {String}
*/
bindingtype: function(bindingName, options) {
var onlyBlockscoped = options && options.onlyBlockscoped;
var excludeParams = options && options.excludeParams;
var currentScopeIndex = _scopeStack.length - (options && options.excludeCurrent ? 2 : 1);
for (var i = currentScopeIndex; i >= 0; i--) {
var current = _scopeStack[i];
if (current["(bindings)"][bindingName] &&
(!onlyBlockscoped || current["(bindings)"][bindingName]["(blockscoped)"])) {
return current["(bindings)"][bindingName]["(type)"];
}
var scopeCheck = excludeParams ? _scopeStack[ i - 1 ] : current;
if (scopeCheck && scopeCheck["(type)"] === "functionparams") {
return null;
}
}
return null;
},
/**
* Determine whether a `break` statement label exists in the function
* scope.
*
* @param {string} labelName - the value of the identifier
*
* @returns {boolean}
*/
hasLabel: function(labelName) {
for (var i = _scopeStack.length - 1; i >= 0; i--) {
var current = _scopeStack[i];
if (current["(labels)"][labelName]) {
return true;
}
if (current["(type)"] === "functionparams") {
return false;
}
}
return false;
},
/**
* Determine if a given name has been defined in the current function
* scope.
*
* @param {string} bindingName - the value of the identifier
* @param {object} options - options as supported by the
* `funct.bindingtype` method
*
* @return {boolean}
*/
has: function(bindingName, options) {
return Boolean(this.bindingtype(bindingName, options));
},
/**
* Create a new function-scoped binding and add it to the current scope.
* See the `block.add` method for coresponding logic to create
* block-scoped bindings.
*
* @param {string} bindingName - the value of the identifier
* @param {string} type - the type of the binding; either "function" or
* "var"
* @param {object} tok - the token that triggered the definition
* @param {boolean} unused - `true` if the binding has not been
* referenced
*/
add: function(bindingName, type, tok, unused) {
_current["(bindings)"][bindingName] = {
"(type)" : type,
"(token)": tok,
"(blockscoped)": false,
"(function)": _currentFunctBody,
"(unused)": unused };
}
},
block: {
/**
* Determine whether the current block scope is the global scope.
*
* @returns Boolean
*/
isGlobal: function() {
return _current["(type)"] === "global";
},
/**
* Resolve a reference to a binding and mark the corresponding binding as
* "used."
*
* @param {string} bindingName - the value of the identifier
* @param {object} token - the token value that triggered the reference
*/
use: function(bindingName, token) {
// If the name resolves to a parameter of the current function, then do
// not store usage. This is because in cases such as the following:
//
// function(a) {
// var a;
// a = a;
// }
//
// the usage of `a` will resolve to the parameter, not to the unset
// variable binding.
var paramScope = _currentFunctBody["(parent)"];
if (paramScope && paramScope["(bindings)"][bindingName] &&
paramScope["(bindings)"][bindingName]["(type)"] === "param") {
// then check its not declared by a block scope variable
if (!scopeManagerInst.funct.has(bindingName,
{ excludeParams: true, onlyBlockscoped: true })) {
paramScope["(bindings)"][bindingName]["(unused)"] = false;
}
}
if (token && (state.ignored.W117 || state.option.undef === false)) {
token.ignoreUndef = true;
}
_setupUsages(bindingName);
_current["(usages)"][bindingName]["(onlyUsedSubFunction)"] = false;
if (token) {
token["(function)"] = _currentFunctBody;
_current["(usages)"][bindingName]["(tokens)"].push(token);
}
// Block-scoped bindings can't be used within their initializer due to
// "temporal dead zone" (TDZ) restrictions.
var binding = _current["(bindings)"][bindingName];
if (binding && binding["(blockscoped)"] && !binding["(initialized)"]) {
error("E056", token, bindingName, binding["(type)"]);
}
},
reassign: function(bindingName, token) {
token.ignoreW020 = state.ignored.W020;
token.ignoreW021 = state.ignored.W021;
this.modify(bindingName, token);
_current["(usages)"][bindingName]["(reassigned)"].push(token);
},
modify: function(bindingName, token) {
_setupUsages(bindingName);
_current["(usages)"][bindingName]["(onlyUsedSubFunction)"] = false;
_current["(usages)"][bindingName]["(modified)"].push(token);
},
/**
* Create a new block-scoped binding and add it to the current scope. See
* the `funct.add` method for coresponding logic to create
* function-scoped bindings.
*
* @param {string} bindingName - the value of the identifier
* @param {string} type - the type of the binding; one of "class",
* "const", "function", "import", or "let"
* @param {object} tok - the token that triggered the definition
* @param {boolean} unused - `true` if the binding has not been
* referenced
* @param {boolean} initialized - `true` if the binding has been
* initialized (as is the case with
* bindings created via `import`
* declarations)
*/
add: function(bindingName, type, tok, unused, initialized) {
_current["(bindings)"][bindingName] = {
"(type)" : type,
"(token)": tok,
"(initialized)": !!initialized,
"(blockscoped)": true,
"(unused)": unused };
},
addLabel: function(labelName, opts) {
var token = opts.token;
if (scopeManagerInst.funct.hasLabel(labelName)) {
warning("E011", token, labelName);
}
else if (state.option.shadow === "outer") {
if (scopeManagerInst.funct.has(labelName)) {
warning("W004", token, labelName);
} else {
_checkOuterShadow(labelName, token);
}
}
_current["(labels)"][labelName] = token;
}
}
};
return scopeManagerInst;
};
module.exports = scopeManager;
|
:: Command execute :: | |
--[ c99shell v. 2.5 [PHP 8 Update] [24.05.2025] | Generation time: 0.0049 ]-- |