mirror of
https://github.com/github/codeql.git
synced 2026-04-30 11:15:13 +02:00
Merge remote-tracking branch 'upstream/master'
This commit is contained in:
@@ -77,8 +77,8 @@ import com.semmle.util.trap.TrapWriter;
|
||||
* <li><code>LGTM_INDEX_EXCLUDE</code>: a newline-separated list of paths to exclude
|
||||
* <li><code>LGTM_REPOSITORY_FOLDERS_CSV</code>: the path of a CSV file containing file
|
||||
* classifications
|
||||
* <li><code>LGTM_INDEX_FILTERS</code>: a newline-separated list of {@link ProjectLayout}-style
|
||||
* patterns that can be used to refine the list of files to include and exclude
|
||||
* <li><code>LGTM_INDEX_FILTERS</code>: a newline-separated list of strings of form "include:PATTERN"
|
||||
* or "exclude:PATTERN" that can be used to refine the list of files to include and exclude.
|
||||
* <li><code>LGTM_INDEX_TYPESCRIPT</code>: whether to extract TypeScript
|
||||
* <li><code>LGTM_INDEX_FILETYPES</code>: a newline-separated list of ".extension:filetype" pairs
|
||||
* specifying which {@link FileType} to use for the given extension; the additional file type
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
- description: Security-and-quality queries for JavaScript
|
||||
- qlpack: codeql-javascript
|
||||
- apply: security-and-quality-selectors.yml
|
||||
from: codeql-suite-helpers
|
||||
@@ -0,0 +1,4 @@
|
||||
- description: Security-extended queries for JavaScript
|
||||
- qlpack: codeql-javascript
|
||||
- apply: security-extended-selectors.yml
|
||||
from: codeql-suite-helpers
|
||||
@@ -1,5 +1,6 @@
|
||||
import javascript
|
||||
private import semmle.javascript.dataflow.InferredTypes
|
||||
private import semmle.javascript.dataflow.internal.PreCallGraphStep
|
||||
|
||||
/**
|
||||
* Classes and predicates for modelling TaintTracking steps for arrays.
|
||||
@@ -222,29 +223,32 @@ private module ArrayDataFlow {
|
||||
*
|
||||
* And the second parameter in the callback is the array ifself, so there is a `loadStoreStep` from the array to that second parameter.
|
||||
*/
|
||||
private class ArrayIteration extends DataFlow::AdditionalFlowStep, DataFlow::MethodCallNode {
|
||||
ArrayIteration() {
|
||||
this.getMethodName() = "map" or
|
||||
this.getMethodName() = "forEach"
|
||||
}
|
||||
|
||||
private class ArrayIteration extends PreCallGraphStep {
|
||||
override predicate loadStep(DataFlow::Node obj, DataFlow::Node element, string prop) {
|
||||
prop = arrayElement() and
|
||||
obj = this.getReceiver() and
|
||||
element = getCallback(0).getParameter(0)
|
||||
exists(DataFlow::MethodCallNode call |
|
||||
call.getMethodName() = ["map", "forEach"] and
|
||||
prop = arrayElement() and
|
||||
obj = call.getReceiver() and
|
||||
element = call.getCallback(0).getParameter(0)
|
||||
)
|
||||
}
|
||||
|
||||
override predicate storeStep(DataFlow::Node element, DataFlow::SourceNode obj, string prop) {
|
||||
this.getMethodName() = "map" and
|
||||
prop = arrayElement() and
|
||||
element = this.getCallback(0).getAReturn() and
|
||||
obj = this
|
||||
exists(DataFlow::MethodCallNode call |
|
||||
call.getMethodName() = "map" and
|
||||
prop = arrayElement() and
|
||||
element = call.getCallback(0).getAReturn() and
|
||||
obj = call
|
||||
)
|
||||
}
|
||||
|
||||
override predicate loadStoreStep(DataFlow::Node pred, DataFlow::Node succ, string prop) {
|
||||
prop = arrayElement() and
|
||||
pred = this.getReceiver() and
|
||||
succ = getCallback(0).getParameter(2)
|
||||
override predicate loadStoreStep(DataFlow::Node pred, DataFlow::SourceNode succ, string prop) {
|
||||
exists(DataFlow::MethodCallNode call |
|
||||
call.getMethodName() = ["map", "forEach"] and
|
||||
prop = arrayElement() and
|
||||
pred = call.getReceiver() and
|
||||
succ = call.getCallback(0).getParameter(2)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -311,16 +315,13 @@ private module ArrayDataFlow {
|
||||
/**
|
||||
* A step for modelling `for of` iteration on arrays.
|
||||
*/
|
||||
private class ForOfStep extends DataFlow::AdditionalFlowStep, DataFlow::ValueNode {
|
||||
ForOfStmt forOf;
|
||||
DataFlow::Node element;
|
||||
|
||||
ForOfStep() { this.asExpr() = forOf.getIterationDomain() }
|
||||
|
||||
private class ForOfStep extends PreCallGraphStep {
|
||||
override predicate loadStep(DataFlow::Node obj, DataFlow::Node e, string prop) {
|
||||
obj = this and
|
||||
e = DataFlow::lvalueNode(forOf.getLValue()) and
|
||||
prop = arrayElement()
|
||||
exists(ForOfStmt forOf |
|
||||
obj = forOf.getIterationDomain().flow() and
|
||||
e = DataFlow::lvalueNode(forOf.getLValue()) and
|
||||
prop = arrayElement()
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ private class PseudoProperty extends TypeTrackingPseudoProperty {
|
||||
* `load`/`store`/`loadStore` can be used in the `CollectionsTypeTracking` module.
|
||||
* (Thereby avoiding naming conflicts with a "cousin" `AdditionalFlowStep` implementation.)
|
||||
*/
|
||||
abstract private class CollectionFlowStep extends DataFlow::AdditionalFlowStep {
|
||||
abstract class CollectionFlowStep extends DataFlow::AdditionalFlowStep {
|
||||
final override predicate step(DataFlow::Node pred, DataFlow::Node succ) { none() }
|
||||
|
||||
final override predicate step(
|
||||
|
||||
@@ -33,7 +33,7 @@ deprecated module GlobalAccessPath {
|
||||
/**
|
||||
* Provides predicates for associating access paths with data flow nodes.
|
||||
*
|
||||
* For example, `AccessPath.getAReferenceTo(x)` can be used to obtain the global access path
|
||||
* For example, `AccessPath::getAReferenceTo(x)` can be used to obtain the global access path
|
||||
* that `x` refers to, as in the following sample:
|
||||
* ```
|
||||
* function f() {
|
||||
@@ -240,7 +240,7 @@ module AccessPath {
|
||||
* ```
|
||||
* function f(x) {
|
||||
* x.foo.bar = class {};
|
||||
* x.foo = { bar: class() };
|
||||
* x.foo = { bar: class {} };
|
||||
* let alias = x;
|
||||
* alias.foo.bar = class {};
|
||||
* }
|
||||
@@ -338,7 +338,7 @@ module AccessPath {
|
||||
* ```
|
||||
* function f(x) {
|
||||
* x.foo.bar = class {};
|
||||
* x.foo = { bar: class() };
|
||||
* x.foo = { bar: class {} };
|
||||
* let alias = x;
|
||||
* alias.foo.bar = class {};
|
||||
* }
|
||||
@@ -355,7 +355,7 @@ module AccessPath {
|
||||
* Only gets the immediate right-hand side of an assignment or property or a global declaration,
|
||||
* not nodes that transitively flow there.
|
||||
*
|
||||
* For example, the class nodes below are all assignmetns to `foo.bar`:
|
||||
* For example, the class nodes below are all assignments to `foo.bar`:
|
||||
* ```
|
||||
* foo.bar = class {};
|
||||
* foo = { bar: class {} };
|
||||
|
||||
@@ -23,6 +23,7 @@ private import internal.CallGraphs
|
||||
private import internal.FlowSteps as FlowSteps
|
||||
private import internal.DataFlowNode
|
||||
private import internal.AnalyzedParameters
|
||||
private import internal.PreCallGraphStep
|
||||
|
||||
module DataFlow {
|
||||
/**
|
||||
|
||||
@@ -335,5 +335,20 @@ abstract class AdditionalTypeTrackingStep extends DataFlow::Node {
|
||||
/**
|
||||
* Holds if type-tracking should step from `pred` to `succ`.
|
||||
*/
|
||||
abstract predicate step(DataFlow::Node pred, DataFlow::Node succ);
|
||||
predicate step(DataFlow::Node pred, DataFlow::Node succ) { none() }
|
||||
|
||||
/**
|
||||
* Holds if type-tracking should step from `pred` into the `prop` property of `succ`.
|
||||
*/
|
||||
predicate storeStep(DataFlow::Node pred, DataFlow::SourceNode succ, string prop) { none() }
|
||||
|
||||
/**
|
||||
* Holds if type-tracking should step from the `prop` property of `pred` to `succ`.
|
||||
*/
|
||||
predicate loadStep(DataFlow::Node pred, DataFlow::Node succ, string prop) { none() }
|
||||
|
||||
/**
|
||||
* Holds if type-tracking should step from the `prop` property of `pred` to the same property in `succ`.
|
||||
*/
|
||||
predicate loadStoreStep(DataFlow::Node pred, DataFlow::SourceNode succ, string prop) { none() }
|
||||
}
|
||||
|
||||
@@ -61,6 +61,19 @@ module CallGraph {
|
||||
function = cls.getConstructor() and
|
||||
cls.getAClassReference(t.continue()).flowsTo(result)
|
||||
)
|
||||
or
|
||||
imprecision = 0 and
|
||||
exists(DataFlow::FunctionNode outer |
|
||||
result = getAFunctionReference(outer, 0, t.continue()).getAnInvocation() and
|
||||
locallyReturnedFunction(outer, function)
|
||||
)
|
||||
}
|
||||
|
||||
cached
|
||||
private predicate locallyReturnedFunction(
|
||||
DataFlow::FunctionNode outer, DataFlow::FunctionNode inner
|
||||
) {
|
||||
inner.flowsTo(outer.getAReturn())
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,134 @@
|
||||
/**
|
||||
* Provides an extension point for contributing flow edges prior
|
||||
* to call graph construction and type tracking.
|
||||
*/
|
||||
|
||||
private import javascript
|
||||
|
||||
private newtype TUnit = MkUnit()
|
||||
|
||||
private class Unit extends TUnit {
|
||||
string toString() { result = "unit" }
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal extension point for adding flow edges prior to call graph construction
|
||||
* and type tracking.
|
||||
*
|
||||
* Steps added here will be added to both `AdditionalFlowStep` and `AdditionalTypeTrackingStep`.
|
||||
*
|
||||
* Contributing steps that rely on type tracking will lead to negative recursion.
|
||||
*/
|
||||
class PreCallGraphStep extends Unit {
|
||||
/**
|
||||
* Holds if there is a step from `pred` to `succ`.
|
||||
*/
|
||||
predicate step(DataFlow::Node pred, DataFlow::Node succ) { none() }
|
||||
|
||||
/**
|
||||
* Holds if there is a step from `pred` into the `prop` property of `succ`.
|
||||
*/
|
||||
predicate storeStep(DataFlow::Node pred, DataFlow::SourceNode succ, string prop) { none() }
|
||||
|
||||
/**
|
||||
* Holds if there is a step from the `prop` property of `pred` to `succ`.
|
||||
*/
|
||||
predicate loadStep(DataFlow::Node pred, DataFlow::Node succ, string prop) { none() }
|
||||
|
||||
/**
|
||||
* Holds if there is a step from the `prop` property of `pred` to the same property in `succ`.
|
||||
*/
|
||||
predicate loadStoreStep(DataFlow::Node pred, DataFlow::SourceNode succ, string prop) { none() }
|
||||
}
|
||||
|
||||
module PreCallGraphStep {
|
||||
/**
|
||||
* Holds if there is a step from `pred` to `succ`.
|
||||
*/
|
||||
cached
|
||||
predicate step(DataFlow::Node pred, DataFlow::Node succ) {
|
||||
any(PreCallGraphStep s).step(pred, succ)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if there is a step from `pred` into the `prop` property of `succ`.
|
||||
*/
|
||||
cached
|
||||
predicate storeStep(DataFlow::Node pred, DataFlow::SourceNode succ, string prop) {
|
||||
any(PreCallGraphStep s).storeStep(pred, succ, prop)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if there is a step from the `prop` property of `pred` to `succ`.
|
||||
*/
|
||||
cached
|
||||
predicate loadStep(DataFlow::Node pred, DataFlow::Node succ, string prop) {
|
||||
any(PreCallGraphStep s).loadStep(pred, succ, prop)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if there is a step from the `prop` property of `pred` to the same property in `succ`.
|
||||
*/
|
||||
cached
|
||||
predicate loadStoreStep(DataFlow::Node pred, DataFlow::SourceNode succ, string prop) {
|
||||
any(PreCallGraphStep s).loadStoreStep(pred, succ, prop)
|
||||
}
|
||||
}
|
||||
|
||||
private class NodeWithPreCallGraphStep extends DataFlow::Node {
|
||||
NodeWithPreCallGraphStep() {
|
||||
PreCallGraphStep::step(this, _)
|
||||
or
|
||||
PreCallGraphStep::storeStep(this, _, _)
|
||||
or
|
||||
PreCallGraphStep::loadStep(this, _, _)
|
||||
or
|
||||
PreCallGraphStep::loadStoreStep(this, _, _)
|
||||
}
|
||||
}
|
||||
|
||||
private class AdditionalFlowStepFromPreCallGraph extends NodeWithPreCallGraphStep,
|
||||
DataFlow::AdditionalFlowStep {
|
||||
override predicate step(DataFlow::Node pred, DataFlow::Node succ) {
|
||||
pred = this and
|
||||
PreCallGraphStep::step(this, succ)
|
||||
}
|
||||
|
||||
override predicate storeStep(DataFlow::Node pred, DataFlow::SourceNode succ, string prop) {
|
||||
pred = this and
|
||||
PreCallGraphStep::storeStep(this, succ, prop)
|
||||
}
|
||||
|
||||
override predicate loadStep(DataFlow::Node pred, DataFlow::Node succ, string prop) {
|
||||
pred = this and
|
||||
PreCallGraphStep::loadStep(this, succ, prop)
|
||||
}
|
||||
|
||||
override predicate loadStoreStep(DataFlow::Node pred, DataFlow::Node succ, string prop) {
|
||||
pred = this and
|
||||
PreCallGraphStep::loadStoreStep(this, succ, prop)
|
||||
}
|
||||
}
|
||||
|
||||
private class AdditionalTypeTrackingStepFromPreCallGraph extends NodeWithPreCallGraphStep,
|
||||
DataFlow::AdditionalTypeTrackingStep {
|
||||
override predicate step(DataFlow::Node pred, DataFlow::Node succ) {
|
||||
pred = this and
|
||||
PreCallGraphStep::step(this, succ)
|
||||
}
|
||||
|
||||
override predicate storeStep(DataFlow::Node pred, DataFlow::SourceNode succ, string prop) {
|
||||
pred = this and
|
||||
PreCallGraphStep::storeStep(this, succ, prop)
|
||||
}
|
||||
|
||||
override predicate loadStep(DataFlow::Node pred, DataFlow::Node succ, string prop) {
|
||||
pred = this and
|
||||
PreCallGraphStep::loadStep(this, succ, prop)
|
||||
}
|
||||
|
||||
override predicate loadStoreStep(DataFlow::Node pred, DataFlow::SourceNode succ, string prop) {
|
||||
pred = this and
|
||||
PreCallGraphStep::loadStoreStep(this, succ, prop)
|
||||
}
|
||||
}
|
||||
@@ -110,6 +110,15 @@ module StepSummary {
|
||||
or
|
||||
basicLoadStep(pred, succ, prop) and
|
||||
summary = LoadStep(prop)
|
||||
or
|
||||
any(AdditionalTypeTrackingStep st).storeStep(pred, succ, prop) and
|
||||
summary = StoreStep(prop)
|
||||
or
|
||||
any(AdditionalTypeTrackingStep st).loadStep(pred, succ, prop) and
|
||||
summary = LoadStep(prop)
|
||||
or
|
||||
any(AdditionalTypeTrackingStep st).loadStoreStep(pred, succ, prop) and
|
||||
summary = CopyStep(prop)
|
||||
)
|
||||
or
|
||||
any(AdditionalTypeTrackingStep st).step(pred, succ) and
|
||||
|
||||
@@ -119,7 +119,14 @@ module Express {
|
||||
t.start() and
|
||||
result = getARouteHandlerExpr().flow().getALocalSource()
|
||||
or
|
||||
exists(DataFlow::TypeBackTracker t2 | result = getARouteHandler(t2).backtrack(t2, t))
|
||||
exists(DataFlow::TypeBackTracker t2, DataFlow::SourceNode succ | succ = getARouteHandler(t2) |
|
||||
result = succ.backtrack(t2, t)
|
||||
or
|
||||
exists(HTTP::RouteHandlerCandidateContainer container |
|
||||
result = container.getRouteHandler(succ)
|
||||
) and
|
||||
t = t2
|
||||
)
|
||||
}
|
||||
|
||||
override Expr getServer() { result.(Application).getARouteHandler() = getARouteHandler() }
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
*/
|
||||
|
||||
import javascript
|
||||
private import semmle.javascript.DynamicPropertyAccess
|
||||
private import semmle.javascript.dataflow.internal.StepSummary
|
||||
|
||||
module HTTP {
|
||||
/**
|
||||
@@ -496,4 +498,111 @@ module HTTP {
|
||||
class CookieCryptographicKey extends CryptographicKey {
|
||||
CookieCryptographicKey() { this = any(CookieMiddlewareInstance instance).getASecretKey() }
|
||||
}
|
||||
|
||||
/**
|
||||
* An object that contains one or more potential route handlers.
|
||||
*/
|
||||
class RouteHandlerCandidateContainer extends DataFlow::Node {
|
||||
RouteHandlerCandidateContainer::Range self;
|
||||
|
||||
RouteHandlerCandidateContainer() { this = self }
|
||||
|
||||
/**
|
||||
* Gets the route handler in this container that is accessed at `access`.
|
||||
*/
|
||||
DataFlow::SourceNode getRouteHandler(DataFlow::SourceNode access) {
|
||||
result = self.getRouteHandler(access)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides classes for working with objects that may contain one or more route handlers.
|
||||
*/
|
||||
module RouteHandlerCandidateContainer {
|
||||
private DataFlow::SourceNode ref(DataFlow::TypeTracker t, RouteHandlerCandidateContainer c) {
|
||||
t.start() and result = c
|
||||
or
|
||||
exists(DataFlow::TypeTracker t2 | result = ref(t2, c).track(t2, t))
|
||||
}
|
||||
|
||||
private DataFlow::SourceNode ref(RouteHandlerCandidateContainer c) {
|
||||
result = ref(DataFlow::TypeTracker::end(), c)
|
||||
}
|
||||
|
||||
/**
|
||||
* A container for one or more potential route handlers.
|
||||
*
|
||||
* Extend this class and implement its abstract member predicates to model additional
|
||||
* containers.
|
||||
*/
|
||||
abstract class Range extends DataFlow::SourceNode {
|
||||
/**
|
||||
* Gets the route handler in this container that is accessed at `access`.
|
||||
*/
|
||||
abstract DataFlow::SourceNode getRouteHandler(DataFlow::SourceNode access);
|
||||
}
|
||||
|
||||
/**
|
||||
* An object that contains one or more potential route handlers.
|
||||
*/
|
||||
private class ContainerObject extends Range {
|
||||
ContainerObject() {
|
||||
(
|
||||
this instanceof DataFlow::ObjectLiteralNode
|
||||
or
|
||||
exists(DataFlow::CallNode create | this = create |
|
||||
create = DataFlow::globalVarRef("Object").getAMemberCall("create") and
|
||||
create.getArgument(0).asExpr() instanceof NullLiteral
|
||||
)
|
||||
) and
|
||||
exists(RouteHandlerCandidate candidate | candidate.flowsTo(getAPropertyWrite().getRhs()))
|
||||
}
|
||||
|
||||
override DataFlow::SourceNode getRouteHandler(DataFlow::SourceNode access) {
|
||||
result instanceof RouteHandlerCandidate and
|
||||
exists(DataFlow::PropWrite write, DataFlow::PropRead read |
|
||||
access = read and
|
||||
ref(this).getAPropertyRead() = read and
|
||||
result.flowsTo(write.getRhs()) and
|
||||
write = this.getAPropertyWrite()
|
||||
|
|
||||
write.getPropertyName() = read.getPropertyName()
|
||||
or
|
||||
exists(EnumeratedPropName prop | access = prop.getASourceProp())
|
||||
or
|
||||
read = DataFlow::lvalueNode(any(ForOfStmt stmt).getLValue())
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A collection that contains one or more route potential handlers.
|
||||
*/
|
||||
private class ContainerCollection extends HTTP::RouteHandlerCandidateContainer::Range {
|
||||
ContainerCollection() {
|
||||
this = DataFlow::globalVarRef("Map").getAnInstantiation() and // restrict to Map for now
|
||||
exists(
|
||||
CollectionFlowStep store, DataFlow::Node storeTo, DataFlow::Node input,
|
||||
RouteHandlerCandidate candidate
|
||||
|
|
||||
this.flowsTo(storeTo) and
|
||||
store.store(input, storeTo, _) and
|
||||
candidate.flowsTo(input)
|
||||
)
|
||||
}
|
||||
|
||||
override DataFlow::SourceNode getRouteHandler(DataFlow::SourceNode access) {
|
||||
exists(
|
||||
DataFlow::Node input, TypeTrackingPseudoProperty key, CollectionFlowStep store,
|
||||
CollectionFlowStep load, DataFlow::Node storeTo, DataFlow::Node loadFrom
|
||||
|
|
||||
this.flowsTo(storeTo) and
|
||||
store.store(input, storeTo, key) and
|
||||
result.(RouteHandlerCandidate).flowsTo(input) and
|
||||
ref(this).flowsTo(loadFrom) and
|
||||
load.load(loadFrom, access, key)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,7 +66,8 @@ query predicate missingCallee(AnnotatedCall call, AnnotatedFunction target, int
|
||||
|
||||
query predicate badAnnotation(string name) {
|
||||
name = any(AnnotatedCall cl).getCallTargetName() and
|
||||
not name = any(AnnotatedFunction cl).getCalleeName()
|
||||
not name = any(AnnotatedFunction cl).getCalleeName() and
|
||||
name != "NONE"
|
||||
or
|
||||
not name = any(AnnotatedCall cl).getCallTargetName() and
|
||||
name = any(AnnotatedFunction cl).getCalleeName()
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
import 'dummy';
|
||||
|
||||
/** name:curry1 */
|
||||
function curry1() {
|
||||
/** name:curry2 */
|
||||
function curry2(x) {
|
||||
/** name:curry3 */
|
||||
function curry3(y) {
|
||||
|
||||
}
|
||||
return curry3;
|
||||
}
|
||||
return curry2;
|
||||
};
|
||||
|
||||
/** calls:curry1 */
|
||||
let r1 = curry1();
|
||||
|
||||
/** calls:curry2 */
|
||||
let r2 = r1();
|
||||
|
||||
/** calls:curry3 */
|
||||
r2();
|
||||
|
||||
function callback(f) {
|
||||
// Call graph should not include callback invocations.
|
||||
/** calls:NONE */
|
||||
f();
|
||||
}
|
||||
|
||||
let w1 = callback(curry1);
|
||||
callback(() => {});
|
||||
@@ -0,0 +1,8 @@
|
||||
import javascript
|
||||
|
||||
query predicate getRouteHandlerContainerStep(
|
||||
HTTP::RouteHandlerCandidateContainer container, DataFlow::SourceNode handler,
|
||||
DataFlow::SourceNode access
|
||||
) {
|
||||
handler = container.getRouteHandler(access)
|
||||
}
|
||||
@@ -0,0 +1,163 @@
|
||||
var express = require("express");
|
||||
var app = express();
|
||||
|
||||
// registration of route handlers in bulk
|
||||
let routes0 = {
|
||||
a: (req, res) => console.log(req),
|
||||
b: (req, res) => console.log(req)
|
||||
};
|
||||
for (const p in routes0) {
|
||||
app.get(p, routes0[p]);
|
||||
}
|
||||
|
||||
// registration of route handlers in bulk
|
||||
let routes1 = {
|
||||
a: (req, res) => console.log(req),
|
||||
b: (req, res) => console.log(req)
|
||||
};
|
||||
for (const handler of routes1) {
|
||||
app.use(handler);
|
||||
}
|
||||
|
||||
// registration of route handlers in bulk, with indirection
|
||||
let routes2 = {
|
||||
a: (req, res) => console.log(req),
|
||||
b: (req, res) => console.log(req)
|
||||
};
|
||||
for (const p of Object.keys(routes2)) {
|
||||
app.get(p, routes2[p]);
|
||||
}
|
||||
|
||||
// registration of route handlers in bulk, with indirection
|
||||
let routes3 = {
|
||||
a: (req, res) => console.log(req),
|
||||
b: (req, res) => console.log(req)
|
||||
};
|
||||
for (const h of Object.values(routes3)) {
|
||||
app.use(h);
|
||||
}
|
||||
|
||||
// custom router indirection for all requests
|
||||
let myRouter1 = {
|
||||
handlers: {},
|
||||
add: function(n, h) {
|
||||
this.handlers[n] = h;
|
||||
},
|
||||
handle: function(req, res, target) {
|
||||
this.handlers[target](req, res);
|
||||
}
|
||||
};
|
||||
myRouter1.add("whatever", (req, res) => console.log(req));
|
||||
app.use((req, res) => myRouter1.handle(req, res, "whatever"));
|
||||
|
||||
// simpler custom router indirection for all requests
|
||||
let mySimpleRouter = {
|
||||
handler: undefined,
|
||||
add: function(h) {
|
||||
this.handler = h;
|
||||
},
|
||||
handle: function(req, res) {
|
||||
this.handler(req, res);
|
||||
}
|
||||
};
|
||||
mySimpleRouter.add((req, res) => console.log(req));
|
||||
app.use((req, res) => mySimpleRouter.handle(req, res));
|
||||
|
||||
// simplest custom router indirection for all requests
|
||||
let mySimplestRouter = {
|
||||
handler: (req, res) => console.log(req),
|
||||
handle: function(req, res) {
|
||||
this.handler(req, res);
|
||||
}
|
||||
};
|
||||
app.use((req, res) => mySimplestRouter.handle(req, res));
|
||||
|
||||
// a combination of bulk registration and indirection through a custom router
|
||||
let myRouter3 = {
|
||||
handlers: {},
|
||||
add: function(n, h) {
|
||||
this.handlers[n] = h;
|
||||
},
|
||||
handle: function(req, res, target) {
|
||||
this.handlers[target](req, res);
|
||||
}
|
||||
};
|
||||
let routes3 = {
|
||||
a: (req, res) => console.log(req),
|
||||
b: (req, res) => console.log(req)
|
||||
};
|
||||
for (const p of Object.keys(routes3)) {
|
||||
myRouter3.add(p, routes3[p]);
|
||||
}
|
||||
app.use((req, res) => myRouter3.handle(req, res, "whatever"));
|
||||
|
||||
// a combination of bulk registration and indirection through a custom router. Using a map instead of an object.
|
||||
let myRouter4 = {
|
||||
handlers: new Map(),
|
||||
add: function(n, h) {
|
||||
this.handlers.set(n, h);
|
||||
},
|
||||
handle: function(req, res, target) {
|
||||
this.handlers.get(target)(req, res);
|
||||
}
|
||||
};
|
||||
let routes4 = {
|
||||
a: (req, res) => console.log(req),
|
||||
b: (req, res) => console.log(req)
|
||||
};
|
||||
for (const p of Object.keys(routes4)) {
|
||||
myRouter4.add(p, routes4[p]);
|
||||
}
|
||||
app.use((req, res) => myRouter4.handle(req, res, "whatever"));
|
||||
|
||||
// registration of imported route handlers in bulk
|
||||
let importedRoutes = require("./route-collection").routes;
|
||||
for (const p in importedRoutes) {
|
||||
app.get(p, importedRoutes[p]);
|
||||
}
|
||||
app.get("a", importedRoutes.a);
|
||||
app.get("b", importedRoutes.b);
|
||||
|
||||
// registration of imported route handlers in a map
|
||||
let routesMap = new Map();
|
||||
routesMap.set("a", (req, res) => console.log(req));
|
||||
routesMap.set("b", (req, res) => console.log(req));
|
||||
routesMap.forEach((v, k) => app.get(k, v));
|
||||
app.get("a", routesMap.get("a"));
|
||||
app.get("b", routesMap.get("b"));
|
||||
|
||||
let method = "GET";
|
||||
app[method.toLowerCase()](path, (req, res) => undefined);
|
||||
|
||||
let names = ["handler-in-dynamic-require"];
|
||||
names.forEach(name => {
|
||||
let dynamicRequire = require("./controllers/" + name);
|
||||
app.get(dynamicRequire.path, dynamicRequire.handler);
|
||||
});
|
||||
|
||||
let bulkRequire = require("./controllers");
|
||||
app.get(bulkRequire.bulky.path, bulkRequire.bulky.handler);
|
||||
|
||||
let options = { app: app };
|
||||
let args = [];
|
||||
args.push((req, res) => undefined);
|
||||
app.use.apply(options.app, args);
|
||||
|
||||
let handlers = { handlerA: (req, res) => undefined};
|
||||
app.use(handlers.handlerA.bind(data));
|
||||
|
||||
for ([k, v] of routesMap) {
|
||||
app.get(k, v) // not supported - requires one too many heap steps
|
||||
}
|
||||
|
||||
app.get("b", routesMap.get("NOT_A_KEY!")); // unknown route handler
|
||||
|
||||
let routesMap2 = new Map();
|
||||
routesMap2.set("c", (req, res) => console.log(req));
|
||||
routesMap2.set(unknown(), (req, res) => console.log(req));
|
||||
routesMap2.set("e", (req, res) => console.log(req));
|
||||
|
||||
app.get("c", routesMap2.get("c"));
|
||||
app.get("d", routesMap2.get(unknown()));
|
||||
app.get("e", unknown());
|
||||
app.get("d", routesMap2.get("f"));
|
||||
@@ -0,0 +1 @@
|
||||
module.exports = { path: "bulky", handler: (req, res) => undefined };
|
||||
@@ -0,0 +1 @@
|
||||
module.exports = { path: "/A", handler: (req, res) => undefined };
|
||||
@@ -0,0 +1,4 @@
|
||||
let bulky = require("./handler-in-bulk-require");
|
||||
module.exports = {
|
||||
bulky: bulky
|
||||
};
|
||||
@@ -0,0 +1,4 @@
|
||||
exports.routes = {
|
||||
a: (req, res) => console.log(req),
|
||||
b: (req, res) => console.log(req)
|
||||
};
|
||||
File diff suppressed because it is too large
Load Diff
@@ -46,3 +46,4 @@ import RequestExpr
|
||||
import RouteHandlerExpr_getAsSubRouter
|
||||
import Credentials
|
||||
import RouteHandler_getARequestExpr
|
||||
import RouteHandlerContainer
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
| src/handler-in-property.js:12:18:12:37 | function(req, res){} |
|
||||
| src/middleware-attacher-getter.js:4:17:4:36 | function(req, res){} |
|
||||
| src/middleware-attacher-getter.js:19:19:19:38 | function(req, res){} |
|
||||
| src/middleware-attacher-getter.js:29:32:29:51 | function(req, res){} |
|
||||
| src/middleware-attacher.js:3:13:3:32 | function(req, res){} |
|
||||
| src/nodejs.js:3:19:3:38 | function(req, res){} |
|
||||
| src/nodejs.js:8:14:8:33 | function(req, res){} |
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
| src/bound-handler.js:9:12:9:31 | function(req, res){} | A `RouteHandlerCandidate` that did not get promoted to `RouteHandler`, and it is not used in a `RouteSetupCandidate`. |
|
||||
| src/hapi.js:1:1:1:30 | functio ... t, h){} | A `RouteHandlerCandidate` that did not get promoted to `RouteHandler`, and it is not used in a `RouteSetupCandidate`. |
|
||||
| src/iterated-handlers.js:4:2:4:22 | functio ... res){} | A `RouteHandlerCandidate` that did not get promoted to `RouteHandler`, and it is not used in a `RouteSetupCandidate`. |
|
||||
| src/middleware-attacher-getter.js:29:32:29:51 | function(req, res){} | A `RouteHandlerCandidate` that did not get promoted to `RouteHandler`, and it is not used in a `RouteSetupCandidate`. |
|
||||
| src/route-objects.js:7:19:7:38 | function(req, res){} | A `RouteHandlerCandidate` that did not get promoted to `RouteHandler`, and it is not used in a `RouteSetupCandidate`. |
|
||||
| src/route-objects.js:8:12:10:5 | (req, res) {\\n\\n } | A `RouteHandlerCandidate` that did not get promoted to `RouteHandler`, and it is not used in a `RouteSetupCandidate`. |
|
||||
| src/route-objects.js:20:16:22:9 | (req, r ... } | A `RouteHandlerCandidate` that did not get promoted to `RouteHandler`, and it is not used in a `RouteSetupCandidate`. |
|
||||
|
||||
@@ -41,4 +41,5 @@
|
||||
| spanner.js:19:23:19:32 | "SQL code" |
|
||||
| spannerImport.js:4:8:4:17 | "SQL code" |
|
||||
| sqlite.js:7:8:7:45 | "UPDATE ... id = ?" |
|
||||
| sqliteArray.js:6:12:6:49 | "UPDATE ... id = ?" |
|
||||
| sqliteImport.js:2:8:2:44 | "UPDATE ... id = ?" |
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
var sqlite = require('sqlite3');
|
||||
|
||||
let databaseNames = [":memory:", ":foo:"];
|
||||
let databases = databaseNames.map(name => new sqlite.Database(name));
|
||||
for (let db of databases) {
|
||||
db.run("UPDATE tbl SET name = ? WHERE id = ?", "bar", 2);
|
||||
}
|
||||
Reference in New Issue
Block a user