@microsoft/applicationinsights-core-js
Version:
Microsoft Application Insights Core Javascript SDK
245 lines (243 loc) • 10 kB
JavaScript
/*
* Application Insights JavaScript SDK - Core, 3.3.6
* Copyright (c) Microsoft and contributors. All rights reserved.
*/
import { strShimFunction, strShimPrototype } from "@microsoft/applicationinsights-shims";
import { getInst, objHasOwnProperty } from "@nevware21/ts-utils";
import { _DYN_APPLY, _DYN_LENGTH, _DYN_PUSH, _DYN_SPLICE } from "../__DynamicConstants";
import { _getObjProto } from "./HelperFuncs";
var aiInstrumentHooks = "_aiHooks";
var cbNames = [
"req", "rsp", "hkErr", "fnErr"
];
/** @ignore */
function _arrLoop(arr, fn) {
if (arr) {
for (var lp = 0; lp < arr[_DYN_LENGTH /* @min:%2elength */]; lp++) {
if (fn(arr[lp], lp)) {
break;
}
}
}
}
/** @ignore */
function _doCallbacks(hooks, callDetails, cbArgs, hookCtx, type) {
if (type >= 0 /* CallbackType.Request */ && type <= 2 /* CallbackType.HookError */) {
_arrLoop(hooks, function (hook, idx) {
var cbks = hook.cbks;
var cb = cbks[cbNames[type]];
if (cb) {
// Set the specific hook context implementation using a lazy creation pattern
callDetails.ctx = function () {
var ctx = hookCtx[idx] = (hookCtx[idx] || {});
return ctx;
};
try {
cb[_DYN_APPLY /* @min:%2eapply */](callDetails.inst, cbArgs);
}
catch (err) {
var orgEx = callDetails.err;
try {
// Report Hook error via the callback
var hookErrorCb = cbks[cbNames[2 /* CallbackType.HookError */]];
if (hookErrorCb) {
callDetails.err = err;
hookErrorCb[_DYN_APPLY /* @min:%2eapply */](callDetails.inst, cbArgs);
}
}
catch (e) {
// Not much we can do here -- swallowing the exception to avoid crashing the hosting app
}
finally {
// restore the original exception (if any)
callDetails.err = orgEx;
}
}
}
});
}
}
/** @ignore */
function _createFunctionHook(aiHook) {
// Define a temporary method that queues-up a the real method call
return function () {
var funcThis = this;
// Capture the original arguments passed to the method
var orgArgs = arguments;
var hooks = aiHook.h;
var funcArgs = {
name: aiHook.n,
inst: funcThis,
ctx: null,
set: _replaceArg
};
var hookCtx = [];
var cbArgs = _createArgs([funcArgs], orgArgs);
funcArgs.evt = getInst("event");
function _createArgs(target, theArgs) {
_arrLoop(theArgs, function (arg) {
target[_DYN_PUSH /* @min:%2epush */](arg);
});
return target;
}
function _replaceArg(idx, value) {
orgArgs = _createArgs([], orgArgs);
orgArgs[idx] = value;
cbArgs = _createArgs([funcArgs], orgArgs);
}
// Call the pre-request hooks
_doCallbacks(hooks, funcArgs, cbArgs, hookCtx, 0 /* CallbackType.Request */);
// Call the original function was called
var theFunc = aiHook.f;
if (theFunc) {
try {
funcArgs.rslt = theFunc[_DYN_APPLY /* @min:%2eapply */](funcThis, orgArgs);
}
catch (err) {
// Report the request callback
funcArgs.err = err;
_doCallbacks(hooks, funcArgs, cbArgs, hookCtx, 3 /* CallbackType.FunctionError */);
// rethrow the original exception so anyone listening for it can catch the exception
throw err;
}
}
// Call the post-request hooks
_doCallbacks(hooks, funcArgs, cbArgs, hookCtx, 1 /* CallbackType.Response */);
return funcArgs.rslt;
};
}
/** @ignore */
function _getOwner(target, name, checkPrototype, checkParentProto) {
var owner = null;
if (target) {
if (objHasOwnProperty(target, name)) {
owner = target;
}
else if (checkPrototype) {
owner = _getOwner(_getObjProto(target), name, checkParentProto, false);
}
}
return owner;
}
/**
* Intercept the named prototype functions for the target class / object
* @param target - The target object
* @param funcName - The function name
* @param callbacks - The callbacks to configure and call whenever the function is called
*/
export function InstrumentProto(target, funcName, callbacks) {
if (target) {
return InstrumentFunc(target[strShimPrototype], funcName, callbacks, false);
}
return null;
}
/**
* Intercept the named prototype functions for the target class / object
* @param target - The target object
* @param funcNames - The function names to intercept and call
* @param callbacks - The callbacks to configure and call whenever the function is called
*/
export function InstrumentProtos(target, funcNames, callbacks) {
if (target) {
return InstrumentFuncs(target[strShimPrototype], funcNames, callbacks, false);
}
return null;
}
function _createInstrumentHook(owner, funcName, fn, callbacks) {
var aiHook = fn && fn[aiInstrumentHooks];
if (!aiHook) {
// Only hook the function once
aiHook = {
i: 0,
n: funcName,
f: fn,
h: []
};
// Override (hook) the original function
var newFunc = _createFunctionHook(aiHook);
newFunc[aiInstrumentHooks] = aiHook; // Tag and store the function hooks
owner[funcName] = newFunc;
}
var theHook = {
// tslint:disable:object-literal-shorthand
id: aiHook.i,
cbks: callbacks,
rm: function () {
// DO NOT Use () => { shorthand for the function as the this gets replaced
// with the outer this and not the this for theHook instance.
var id = this.id;
_arrLoop(aiHook.h, function (hook, idx) {
if (hook.id === id) {
aiHook.h[_DYN_SPLICE /* @min:%2esplice */](idx, 1);
return 1;
}
});
}
// tslint:enable:object-literal-shorthand
};
aiHook.i++;
aiHook.h[_DYN_PUSH /* @min:%2epush */](theHook);
return theHook;
}
/**
* Intercept the named prototype functions for the target class / object
* @param target - The target object
* @param funcName - The function name
* @param callbacks - The callbacks to configure and call whenever the function is called
* @param checkPrototype - If the function doesn't exist on the target should it attempt to hook the prototype function
* @param checkParentProto - If the function doesn't exist on the target or it's prototype should it attempt to hook the parent's prototype
*/
export function InstrumentFunc(target, funcName, callbacks, checkPrototype, checkParentProto) {
if (checkPrototype === void 0) { checkPrototype = true; }
if (target && funcName && callbacks) {
var owner = _getOwner(target, funcName, checkPrototype, checkParentProto);
if (owner) {
var fn = owner[funcName];
if (typeof fn === strShimFunction) {
return _createInstrumentHook(owner, funcName, fn, callbacks);
}
}
}
return null;
}
/**
* Intercept the named functions for the target class / object
* @param target - The target object
* @param funcNames - The function names to intercept and call
* @param callbacks - The callbacks to configure and call whenever the function is called
* @param checkPrototype - If the function doesn't exist on the target should it attempt to hook the prototype function
* @param checkParentProto - If the function doesn't exist on the target or it's prototype should it attempt to hook the parent's prototype
*/
export function InstrumentFuncs(target, funcNames, callbacks, checkPrototype, checkParentProto) {
if (checkPrototype === void 0) { checkPrototype = true; }
var hooks = null;
_arrLoop(funcNames, function (funcName) {
var hook = InstrumentFunc(target, funcName, callbacks, checkPrototype, checkParentProto);
if (hook) {
if (!hooks) {
hooks = [];
}
hooks[_DYN_PUSH /* @min:%2epush */](hook);
}
});
return hooks;
}
/**
* Add an instrumentation hook to the provided named "event" for the target class / object, this doesn't check whether the
* named "event" is in fact a function and just assigns the instrumentation hook to the target[evtName]
* @param target - The target object
* @param evtName - The name of the event
* @param callbacks - The callbacks to configure and call whenever the function is called
* @param checkPrototype - If the function doesn't exist on the target should it attempt to hook the prototype function
* @param checkParentProto - If the function doesn't exist on the target or it's prototype should it attempt to hook the parent's prototype
*/
export function InstrumentEvent(target, evtName, callbacks, checkPrototype, checkParentProto) {
if (target && evtName && callbacks) {
var owner = _getOwner(target, evtName, checkPrototype, checkParentProto) || target;
if (owner) {
return _createInstrumentHook(owner, evtName, owner[evtName], callbacks);
}
}
return null;
}
//# sourceMappingURL=InstrumentHooks.js.map