@dbux/common
Advanced tools
Comparing version 0.7.6 to 0.7.7-dev.1
{ | ||
"name": "@dbux/common", | ||
"version": "0.7.6", | ||
"version": "0.7.7-dev.1", | ||
"description": "", | ||
@@ -19,3 +19,3 @@ "module": "src/index.js", | ||
"_moduleAliases": {}, | ||
"gitHead": "8582bfcb6a0be083aed3cb1a8bb2f445a3b1ad9b" | ||
"gitHead": "275a70753f9de34187078d15a8f27963a42a991d" | ||
} |
@@ -18,5 +18,11 @@ /** | ||
} | ||
this.message = message; | ||
if (!cause) { | ||
// odd... | ||
cause = { message: '(no error object provided)', stack: undefined }; | ||
} | ||
// hackfix: we also nest `message`, because the custom `stack` is ignored in some environments (e.g. jest (i.e. vm2)) | ||
const nestedMsg = cause.message && `\n [Caused By] ${cause.message}` || ''; | ||
this.message = `${message}${nestedMsg}`; | ||
this.name = 'NestedError'; | ||
@@ -23,0 +29,0 @@ this.cause = cause; |
import Enum from '../../util/Enum'; | ||
// eslint-disable-next-line import/no-mutable-exports | ||
let DataNodeType = { | ||
let dataNodeTypeObj = { | ||
Write: 1, | ||
Read: 2, | ||
Delete: 3 | ||
Delete: 3, | ||
Compute: 4, | ||
// some special types: | ||
/** | ||
* Used for `UpdateExpression`. | ||
*/ | ||
ComputeWrite: 5, | ||
/** | ||
* Used for `pop`. | ||
*/ | ||
ReadAndDelete: 6 | ||
}; | ||
/** | ||
* @type {(Enum)} | ||
* @type {(Enum | typeof dataNodeTypeObj)} | ||
*/ | ||
DataNodeType = new Enum(DataNodeType); | ||
const DataNodeType = new Enum(dataNodeTypeObj); | ||
/** @typedef { typeof dataNodeTypeObj[keyof typeof dataNodeTypeObj] } DataNodeTypeValue */ | ||
export default DataNodeType; | ||
@@ -19,6 +35,36 @@ | ||
modifyTypes[DataNodeType.Write] = true; | ||
modifyTypes[DataNodeType.ComputeWrite] = true; | ||
modifyTypes[DataNodeType.Delete] = true; | ||
modifyTypes[DataNodeType.ReadAndDelete] = true; | ||
export function isDataNodeModifyType(dataNodeType) { | ||
return modifyTypes[dataNodeType] || false; | ||
} | ||
export function isDataNodeModifyType(dataNodeType) { | ||
return modifyTypes[dataNodeType]; | ||
} | ||
const modifyOrComputeTypes = [...modifyTypes]; | ||
modifyOrComputeTypes[DataNodeType.Compute] = true; | ||
export function isDataNodeModifyOrComputeType(dataNodeType) { | ||
return modifyOrComputeTypes[dataNodeType] || false; | ||
} | ||
const writeTypes = new Array(DataNodeType.getValueMaxIndex()).map(() => false); | ||
writeTypes[DataNodeType.Write] = true; | ||
writeTypes[DataNodeType.ComputeWrite] = true; | ||
export function isDataNodeWrite(dataNodeType) { | ||
return writeTypes[dataNodeType] || false; | ||
} | ||
const deleteTypes = new Array(DataNodeType.getValueMaxIndex()).map(() => false); | ||
deleteTypes[DataNodeType.Delete] = true; | ||
deleteTypes[DataNodeType.ReadAndDelete] = true; | ||
export function isDataNodeDelete(dataNodeType) { | ||
return deleteTypes[dataNodeType] || false; | ||
} | ||
const readTypes = new Array(DataNodeType.getValueMaxIndex()).map(() => false); | ||
readTypes[DataNodeType.Read] = true; | ||
readTypes[DataNodeType.ReadAndDelete] = true; | ||
export function isDataNodeRead(dataNodeType) { | ||
return readTypes[dataNodeType] || false; | ||
} |
import Enum from '../../util/Enum'; | ||
/** | ||
* Allows discerning between different call, apply, bind. | ||
* Allows discerning between call, apply, bind. | ||
*/ | ||
@@ -6,0 +6,0 @@ let specialCallType = { |
@@ -18,3 +18,3 @@ import Enum from "../../util/Enum"; | ||
/** | ||
* @type {Enum | typeof staticContextTypeObj} | ||
* @type {(Enum | typeof staticContextTypeObj)} | ||
*/ | ||
@@ -21,0 +21,0 @@ const StaticContextType = new Enum(staticContextTypeObj); |
@@ -8,3 +8,28 @@ import Enum from '../../util/Enum'; | ||
let tracePurposeObj = { | ||
Console: 1 | ||
Console: 1, | ||
/** | ||
* Generic compute call. | ||
* → Handled as a standard computation with (maybe multiple) inputs and single output. | ||
*/ | ||
Compute: 9, | ||
/** | ||
* Function call should as inputs take in all arguments as well as this (or `CalleeObject` as we call it below). | ||
*/ | ||
ComputeWithThis: 10, | ||
MathMax: 11, | ||
MathMin: 12, | ||
/** | ||
* Generally: CalleeObject = this. | ||
* Callee object of function call (e.g. `o` in `o.f()`) should be added as input to own DataNode. | ||
* Similar assumption to Compute: used on BCE with `createBCEOwnDataNode`. | ||
*/ | ||
CalleeObjectInput: 20, | ||
/** | ||
* hackfix: This is added to an input trace that is recorded after its target trace (because instrumentation is hard). | ||
*/ | ||
ReverseInput: 30, | ||
PatternDefaultValue: 31, | ||
NoData: 40 | ||
}; | ||
@@ -17,2 +42,13 @@ | ||
export default TracePurpose; | ||
const warnPurposes = new Array(TracePurpose.getValueMaxIndex()).map(() => false); | ||
warnPurposes[TracePurpose.PatternDefaultValue] = true; | ||
export function isWarnPurpose(purpose) { | ||
return warnPurposes[purpose]; | ||
} | ||
export function containsPurpose(purposes, purposeType) { | ||
return purposes?.some(p => p.type === purposeType) || false; | ||
} | ||
export default TracePurpose; |
@@ -20,15 +20,34 @@ import Enum from '../../util/Enum'; | ||
PushCallback: 11, | ||
PopCallback: 12, | ||
/** | ||
* A branch statement | ||
*/ | ||
BranchStatement: 9, | ||
BranchExpression: 10, | ||
/** | ||
* Dedicated branch push. | ||
* NOTE: Not all branches have one. Use `controlRole` for this. | ||
*/ | ||
BranchPush: 11, | ||
/** | ||
* Dedicated branch pop. | ||
* NOTE: Not all branches have one. Use `controlRole` for this. | ||
*/ | ||
BranchPop: 12, | ||
Statement: 13, | ||
BlockStart: 14, | ||
BlockEnd: 15, | ||
/** | ||
* Dedicated decision branch. | ||
* NOTE: Not all branches have one. Use `controlRole` for this. | ||
*/ | ||
BranchDecision: 13, | ||
Statement: 14, | ||
BlockStart: 15, | ||
BlockEnd: 16, | ||
// Return | ||
ReturnArgument: 16, | ||
ReturnNoArgument: 17, | ||
ReturnArgument: 17, | ||
ReturnNoArgument: 18, | ||
// Throw | ||
ThrowArgument: 18, | ||
ThrowArgument: 19, | ||
@@ -95,2 +114,13 @@ // Await | ||
ResumeGen: 51, | ||
PatternAssignment: 60, | ||
PatternWriteVar: 61, | ||
PatternWriteAndDeclareVar: 62, | ||
PatternWriteME: 63, | ||
/** | ||
* Meta trace type is used in some rare circumstances where we don't care about a StaticTrace itself, | ||
* but only about some data we associate with it. | ||
*/ | ||
Meta: 70 | ||
}; | ||
@@ -107,3 +137,2 @@ | ||
pushTypes[TraceType.Resume] = true; | ||
export function isTracePush(traceType) { | ||
@@ -131,3 +160,9 @@ return pushTypes[traceType]; | ||
const traceReturnOrBranchPopTypes = [...returnTraceTypes]; | ||
traceReturnOrBranchPopTypes[TraceType.BranchPop] = true; | ||
export function isTraceReturnOrBranchPop(traceType) { | ||
return traceReturnOrBranchPopTypes[traceType] || false; | ||
} | ||
const functionExitTypes = [...returnTraceTypes]; | ||
@@ -155,2 +190,3 @@ // functionExitTypes[TraceType.ThrowArgument] = true; | ||
expressionTypes[TraceType.ExpressionResult] = true; | ||
expressionTypes[TraceType.BranchExpression] = true; | ||
expressionTypes[TraceType.ExpressionValue] = true; | ||
@@ -162,2 +198,3 @@ expressionTypes[TraceType.CallExpressionResult] = true; | ||
expressionTypes[TraceType.ME] = true; | ||
expressionTypes[TraceType.PatternAssignment] = true; | ||
// expressionTypes[TraceType.ReturnArgument] = true; | ||
@@ -170,12 +207,3 @@ // expressionTypes[TraceType.ThrowArgument] = true; | ||
const callbackTypes = new Array(TraceType.getValueMaxIndex()).map(() => false); | ||
callbackTypes[TraceType.CallbackArgument] = true; | ||
callbackTypes[TraceType.PushCallback] = true; | ||
callbackTypes[TraceType.PopCallback] = true; | ||
export function isCallbackRelatedTrace(traceType) { | ||
return callbackTypes[traceType]; | ||
} | ||
const dataOnlyTypes = new Array(TraceType.getValueMaxIndex()).map(() => false); | ||
@@ -187,3 +215,4 @@ dataOnlyTypes[TraceType.ExpressionValue] = true; | ||
/** | ||
* Traces that are important for data flow analysis, but not important for control flow analysis | ||
* Expression types that were... to be skipped when navigating "over" traces(?) | ||
* NOTE: not very important | ||
*/ | ||
@@ -213,2 +242,4 @@ export function isDataOnlyTrace(traceType) { | ||
declarationTypes[TraceType.FunctionDeclaration] = true; | ||
// TODO: this messes things up with ClassMethod (→ breaks `class5.js` and friends) | ||
// declarationTypes[TraceType.FunctionDefinition] = true; | ||
declarationTypes[TraceType.ClassDeclaration] = true; | ||
@@ -218,2 +249,3 @@ declarationTypes[TraceType.DeclareAndWriteVar] = true; | ||
declarationTypes[TraceType.CatchParam] = true; | ||
declarationTypes[TraceType.PatternWriteAndDeclareVar] = true; | ||
@@ -220,0 +252,0 @@ export function isDeclarationTrace(traceType) { |
@@ -9,3 +9,3 @@ import isString from 'lodash/isString'; | ||
// eslint-disable-next-line import/no-mutable-exports | ||
let ValueTypeCategory = { | ||
let ValueTypeCategoryObj = { | ||
/** | ||
@@ -23,3 +23,3 @@ * Primitives have a small, fixed size, primarily: number, bool | ||
ValueTypeCategory = new Enum(ValueTypeCategory); | ||
const ValueTypeCategory = new Enum(ValueTypeCategoryObj); | ||
@@ -36,3 +36,6 @@ export function determineValueTypeCategory(value) { | ||
} | ||
if (isObject(value)) { | ||
if ( | ||
isObject(value) | ||
// !(typeof value === 'bigint') // hackfix | ||
) { | ||
return ValueTypeCategory.Object; | ||
@@ -86,3 +89,3 @@ } | ||
Normal: 0, | ||
Omitted: 1, | ||
Omitted: 1, // TODO: fix ordering → Omitted should be after Shortened | ||
Shortened: 2, | ||
@@ -95,4 +98,12 @@ ValueDisabled: 3, | ||
const okPruneStates = new Array(ValuePruneState.getValueMaxIndex()).map(() => false); | ||
okPruneStates[ValuePruneState.Normal] = true; | ||
okPruneStates[ValuePruneState.Shortened] = true; | ||
export function isPruneStateOk(pruneState) { | ||
return okPruneStates[pruneState] || false; | ||
} | ||
export { | ||
ValuePruneState | ||
}; |
@@ -80,3 +80,10 @@ /** | ||
/** | ||
* Array of `traceId`, representing incoming edges. | ||
* `nodeId` of the `DataNode` that this DataNode carried its value over from. | ||
* | ||
* @type {number} | ||
*/ | ||
valueFromId; | ||
/** | ||
* Array of `dataNodeId`, representing incoming edges. | ||
* @type {number[]} | ||
@@ -83,0 +90,0 @@ */ |
@@ -8,2 +8,7 @@ import StaticDataNode from './StaticDataNode'; | ||
/** | ||
* WARN: only available during instrumentation. | ||
*/ | ||
_traceId; | ||
/** | ||
* @type {number} | ||
@@ -36,2 +41,22 @@ */ | ||
/** | ||
* The branch decision staticTrace that controls this staticTrace. | ||
* | ||
* If controlId === staticTraceId (in Post): this itself is a decision trace. | ||
* | ||
* Runtime: `inProgramStaticTraceId` | ||
* Post: `staticTraceId` | ||
* | ||
* @type {number} | ||
*/ | ||
controlRole; | ||
/** | ||
* If this trace is a control statement's push trace, then `controlId` is the | ||
* statement's own `staticTraceId`. | ||
* | ||
* @type {number} | ||
*/ | ||
controlId; | ||
/** | ||
* Other data. | ||
@@ -38,0 +63,0 @@ * Currently used by: |
@@ -47,2 +47,4 @@ /** @typedef { import("./constants/SpecialIdentifierType").default } SpecialIdentifierType */ | ||
* | ||
* TODO: replace with `purpose` | ||
* | ||
* {@link SpecialIdentifierType} | ||
@@ -55,3 +57,5 @@ */ | ||
* | ||
* {@link SpecialTraceDynamicType} | ||
* TODO: replace with `purpose` | ||
* | ||
* {@link specialDynamicTraceType} | ||
*/ | ||
@@ -58,0 +62,0 @@ specialDynamicType; |
@@ -1,14 +0,9 @@ | ||
export default class ValueRef { | ||
/** | ||
* @type {number} | ||
*/ | ||
refId; | ||
/** | ||
* Id of `DataNode` that captured the first instance of this value. | ||
* @type {number} | ||
*/ | ||
nodeId; | ||
import RefSnapshot from './RefSnapshot'; | ||
import ValueTypeCategory from './constants/ValueTypeCategory'; | ||
/** @typedef { any } RawValue */ | ||
export default class ValueRef extends RefSnapshot { | ||
/** | ||
* {@link ValueTypeCategory} | ||
* @type {number} | ||
@@ -34,4 +29,13 @@ */ | ||
/** | ||
* NOTE: when stored in DataProvider, `serialized` is deleted | ||
* @type {boolean} | ||
*/ | ||
isError; | ||
/** ######################################## | ||
* value serialization | ||
* #######################################*/ | ||
/** | ||
* NOTE: when stored in DataProvider, `serialized` is deleted and replaced with `value` or `children` | ||
*/ | ||
serialized; | ||
@@ -42,3 +46,3 @@ | ||
*/ | ||
isError; | ||
} | ||
monkey; | ||
} |
@@ -6,4 +6,15 @@ import countBy from 'lodash/countBy'; | ||
import mergeWith from 'lodash/mergeWith'; | ||
import groupBy from 'lodash/groupBy'; | ||
import isString from 'lodash/isString'; | ||
import EmptyArray from './EmptyArray'; | ||
/** | ||
* @param {[]]} arr | ||
*/ | ||
export function makeUnique(arr) { | ||
return Array.from(new Set(arr)); | ||
} | ||
/** | ||
* @see https://stackoverflow.com/questions/29951293/using-lodash-to-compare-arrays-items-existence-without-order | ||
@@ -82,2 +93,3 @@ */ | ||
// ########################################################################### | ||
@@ -106,2 +118,18 @@ // binary search | ||
return null; | ||
} | ||
} | ||
export function groupBySorted(arr, prop) { | ||
if (!arr.length) { | ||
return EmptyArray; | ||
} | ||
const cmp = isString(arr[0][prop]) ? | ||
(a, b) => a.localeCompare(b) : | ||
(a, b) => a - b; | ||
return Object.values(groupBy(arr, prop),) | ||
.sort((groupA, groupB) => { | ||
const a = groupA[0][prop]; | ||
const b = groupB[0][prop]; | ||
return cmp(a, b); | ||
}); | ||
} |
@@ -142,3 +142,2 @@ /** | ||
if (value === undefined) { | ||
debugger; | ||
throw new Error(`Invalid name or value: ${nameOrValue} (enum = ${JSON.stringify(this.valuesByNames)})`); | ||
@@ -145,0 +144,0 @@ } |
@@ -65,3 +65,7 @@ /** | ||
export function pathSafe(fpath) { | ||
/** | ||
* Somewhat safe-ish (safer than not doing this) path. | ||
* This is not actually safe, but it can help sometimes. | ||
*/ | ||
export function pathSafeSegment(fpath) { | ||
return fpath.replace(/[:\\/]+/g, '-'); | ||
@@ -68,0 +72,0 @@ } |
@@ -12,3 +12,3 @@ import { newLogger } from '../log/logger'; | ||
*/ | ||
export function throttle(cb, ms = 300) { | ||
export function throttle(cb, ms = 100) { | ||
let p, args; | ||
@@ -30,3 +30,3 @@ | ||
catch (err) { | ||
// logError('Error when executing callback', cb.name?.trim() || '(anonymous callback)', '-', err); | ||
logError(`Error i throttled call ${cb.name?.trim() || '(anonymous callback)'} - ${err}`); | ||
reject(err); | ||
@@ -33,0 +33,0 @@ } |
@@ -13,4 +13,6 @@ import truncate from 'lodash/truncate'; | ||
const ShortenMaxLength = 100; | ||
const ShortenCfg = { length: ShortenMaxLength }; | ||
const DefaultMaxLength = 100; | ||
const DefaultTruncateCfg = { length: DefaultMaxLength }; | ||
const ShortMaxLength = 30; | ||
const ShortTruncateCfg = { length: ShortMaxLength }; | ||
@@ -20,4 +22,10 @@ /** | ||
*/ | ||
export function truncateStringDefault(s, cfg = ShortenCfg) { | ||
export function truncateStringDefault(s, cfg = DefaultTruncateCfg) { | ||
return truncate(s.replace(/\s+/g, ' '), cfg); | ||
} | ||
/** | ||
* @param {string} s | ||
*/ | ||
export function truncateStringShort(s, cfg = ShortTruncateCfg) { | ||
return truncate(s.replace(/\s+/g, ' '), cfg); | ||
} |
@@ -59,3 +59,3 @@ import { performance } from './universalLib'; | ||
print(printFun, msg) { | ||
printFun(`[perf] ${msg}: ${this}`); | ||
(printFun || console.debug)(`[perf] ${msg}: ${this}`); | ||
} | ||
@@ -62,0 +62,0 @@ |
@@ -9,5 +9,10 @@ /** | ||
import isString from 'lodash/isString'; | ||
import requireDynamic from './requireDynamic'; | ||
const Global = this || globalThis; | ||
/** | ||
* A little hackfix tool to get globals that are not available the same way in different | ||
* environments | ||
*/ | ||
export default function universalLib(globalName, fallbackNameOrCb) { | ||
@@ -25,3 +30,3 @@ if (globalName && globalName in Global) { | ||
// name | ||
return _require(fallbackNameOrCb); | ||
return requireDynamic(fallbackNameOrCb); | ||
} | ||
@@ -48,31 +53,6 @@ } | ||
/** | ||
* Custom require function to make webpack "happy". | ||
*/ | ||
let __r; | ||
export function _require(name) { | ||
// eslint-disable-next-line no-eval | ||
const _r = __r || (__r = eval(` | ||
((typeof __non_webpack_require__ !== 'undefined' && __non_webpack_require__) || | ||
(typeof require !== 'undefined' && require)) | ||
`)) || null; | ||
if (!_r) { | ||
return null; | ||
} | ||
let m = _r(name); | ||
const Module = _r('module'); | ||
if (m instanceof Module) { | ||
/** | ||
* Require might return a module object, rather than its exported content in an ESM context. | ||
* @see https://nodejs.org/api/module.html#the-module-object | ||
*/ | ||
m = m.default; | ||
} | ||
return m; | ||
} | ||
/** | ||
* @example `performance.now()` | ||
*/ | ||
export const performance = universalLib('performance', () => { | ||
const lib = _require('perf_hooks'); | ||
const lib = requireDynamic('perf_hooks'); | ||
return lib.performance; | ||
@@ -79,0 +59,0 @@ }); |
Uses eval
Supply chain riskPackage uses dynamic code execution (e.g., eval()), which is a dangerous practice. This can prevent the code from running in certain environments and increases the risk that the code may contain exploits or malicious behavior.
Found 1 instance in 1 package
127512
91
3787
0