From 8401776a0392f5f6683fd04a9c9ab05ea820fe00 Mon Sep 17 00:00:00 2001 From: Cody Bennett Date: Sat, 5 Apr 2025 07:55:57 -0500 Subject: [PATCH] fix(lottie-web): remove expressions eval --- src/libs/lottie.js | 399 +-------------------------------------------- 1 file changed, 7 insertions(+), 392 deletions(-) diff --git a/src/libs/lottie.js b/src/libs/lottie.js index fecc85a5..54fefc0f 100644 --- a/src/libs/lottie.js +++ b/src/libs/lottie.js @@ -7933,7 +7933,6 @@ const lottie = /* @__PURE__ */ (() => { if (stringValue !== _prevValue) { elem.textProperty.currentData.t = _prevValue _sourceText = new String(stringValue) // eslint-disable-line no-new-wrappers - // If stringValue is an empty string, eval returns undefined, so it has to be returned as a String primitive _sourceText.value = stringValue || new String(stringValue) // eslint-disable-line no-new-wrappers } return _sourceText @@ -14869,398 +14868,14 @@ This method searches for multiple shapes that affect a single element and one of return path } + // https://github.com/airbnb/lottie-web/issues/2828 + // https://github.com/airbnb/lottie-web/pull/2833 + // Bail out if we don't want expressions + function noOp(_value) { + return _value + } function initiateExpression(elem, data, property) { - var val = data.x - var needsVelocity = /velocity(?![\w\d])/.test(val) - var _needsRandom = val.indexOf('random') !== -1 - var elemType = elem.data.ty - var transform - var $bm_transform - var content - var effect - var thisProperty = property - thisProperty.valueAtTime = thisProperty.getValueAtTime - Object.defineProperty(thisProperty, 'value', { - get: function () { - return thisProperty.v - }, - }) - elem.comp.frameDuration = 1 / elem.comp.globalData.frameRate - elem.comp.displayStartTime = 0 - var inPoint = elem.data.ip / elem.comp.globalData.frameRate - var outPoint = elem.data.op / elem.comp.globalData.frameRate - var width = elem.data.sw ? elem.data.sw : 0 - var height = elem.data.sh ? elem.data.sh : 0 - var name = elem.data.nm - var loopIn - var loop_in - var loopOut - var loop_out - var smooth - var toWorld - var fromWorld - var fromComp - var toComp - var fromCompToSurface - var position - var rotation - var anchorPoint - var scale - var thisLayer - var thisComp - var mask - var valueAtTime - var velocityAtTime - - var scoped_bm_rt - // val = val.replace(/(\\?"|')((http)(s)?(:\/))?\/.*?(\\?"|')/g, "\"\""); // deter potential network calls - var expression_function = eval('[function _expression_function(){' + val + ';scoped_bm_rt=$bm_rt}]')[0] // eslint-disable-line no-eval - var numKeys = property.kf ? data.k.length : 0 - - var active = !this.data || this.data.hd !== true - - var wiggle = function wiggle(freq, amp) { - var iWiggle - var j - var lenWiggle = this.pv.length ? this.pv.length : 1 - var addedAmps = createTypedArray('float32', lenWiggle) - freq = 5 - var iterations = Math.floor(time * freq) - iWiggle = 0 - j = 0 - while (iWiggle < iterations) { - // var rnd = BMMath.random(); - for (j = 0; j < lenWiggle; j += 1) { - addedAmps[j] += -amp + amp * 2 * BMMath.random() - // addedAmps[j] += -amp + amp*2*rnd; - } - iWiggle += 1 - } - // var rnd2 = BMMath.random(); - var periods = time * freq - var perc = periods - Math.floor(periods) - var arr = createTypedArray('float32', lenWiggle) - if (lenWiggle > 1) { - for (j = 0; j < lenWiggle; j += 1) { - arr[j] = this.pv[j] + addedAmps[j] + (-amp + amp * 2 * BMMath.random()) * perc - // arr[j] = this.pv[j] + addedAmps[j] + (-amp + amp*2*rnd)*perc; - // arr[i] = this.pv[i] + addedAmp + amp1*perc + amp2*(1-perc); - } - return arr - } - return this.pv + addedAmps[0] + (-amp + amp * 2 * BMMath.random()) * perc - }.bind(this) - - if (thisProperty.loopIn) { - loopIn = thisProperty.loopIn.bind(thisProperty) - loop_in = loopIn - } - - if (thisProperty.loopOut) { - loopOut = thisProperty.loopOut.bind(thisProperty) - loop_out = loopOut - } - - if (thisProperty.smooth) { - smooth = thisProperty.smooth.bind(thisProperty) - } - - function loopInDuration(type, duration) { - return loopIn(type, duration, true) - } - - function loopOutDuration(type, duration) { - return loopOut(type, duration, true) - } - - if (this.getValueAtTime) { - valueAtTime = this.getValueAtTime.bind(this) - } - - if (this.getVelocityAtTime) { - velocityAtTime = this.getVelocityAtTime.bind(this) - } - - var comp = elem.comp.globalData.projectInterface.bind(elem.comp.globalData.projectInterface) - - function lookAt(elem1, elem2) { - var fVec = [elem2[0] - elem1[0], elem2[1] - elem1[1], elem2[2] - elem1[2]] - var pitch = Math.atan2(fVec[0], Math.sqrt(fVec[1] * fVec[1] + fVec[2] * fVec[2])) / degToRads - var yaw = -Math.atan2(fVec[1], fVec[2]) / degToRads - return [yaw, pitch, 0] - } - - function easeOut(t, tMin, tMax, val1, val2) { - return applyEase(easeOutBez, t, tMin, tMax, val1, val2) - } - - function easeIn(t, tMin, tMax, val1, val2) { - return applyEase(easeInBez, t, tMin, tMax, val1, val2) - } - - function ease(t, tMin, tMax, val1, val2) { - return applyEase(easeInOutBez, t, tMin, tMax, val1, val2) - } - - function applyEase(fn, t, tMin, tMax, val1, val2) { - if (val1 === undefined) { - val1 = tMin - val2 = tMax - } else { - t = (t - tMin) / (tMax - tMin) - } - if (t > 1) { - t = 1 - } else if (t < 0) { - t = 0 - } - var mult = fn(t) - if ($bm_isInstanceOfArray(val1)) { - var iKey - var lenKey = val1.length - var arr = createTypedArray('float32', lenKey) - for (iKey = 0; iKey < lenKey; iKey += 1) { - arr[iKey] = (val2[iKey] - val1[iKey]) * mult + val1[iKey] - } - return arr - } - return (val2 - val1) * mult + val1 - } - - function nearestKey(time) { - var iKey - var lenKey = data.k.length - var index - var keyTime - if (!data.k.length || typeof data.k[0] === 'number') { - index = 0 - keyTime = 0 - } else { - index = -1 - time *= elem.comp.globalData.frameRate - if (time < data.k[0].t) { - index = 1 - keyTime = data.k[0].t - } else { - for (iKey = 0; iKey < lenKey - 1; iKey += 1) { - if (time === data.k[iKey].t) { - index = iKey + 1 - keyTime = data.k[iKey].t - break - } else if (time > data.k[iKey].t && time < data.k[iKey + 1].t) { - if (time - data.k[iKey].t > data.k[iKey + 1].t - time) { - index = iKey + 2 - keyTime = data.k[iKey + 1].t - } else { - index = iKey + 1 - keyTime = data.k[iKey].t - } - break - } - } - if (index === -1) { - index = iKey + 1 - keyTime = data.k[iKey].t - } - } - } - var obKey = {} - obKey.index = index - obKey.time = keyTime / elem.comp.globalData.frameRate - return obKey - } - - function key(ind) { - var obKey - var iKey - var lenKey - if (!data.k.length || typeof data.k[0] === 'number') { - throw new Error('The property has no keyframe at index ' + ind) - } - ind -= 1 - obKey = { - time: data.k[ind].t / elem.comp.globalData.frameRate, - value: [], - } - var arr = Object.prototype.hasOwnProperty.call(data.k[ind], 's') ? data.k[ind].s : data.k[ind - 1].e - - lenKey = arr.length - for (iKey = 0; iKey < lenKey; iKey += 1) { - obKey[iKey] = arr[iKey] - obKey.value[iKey] = arr[iKey] - } - return obKey - } - - function framesToTime(fr, fps) { - if (!fps) { - fps = elem.comp.globalData.frameRate - } - return fr / fps - } - - function timeToFrames(t, fps) { - if (!t && t !== 0) { - t = time - } - if (!fps) { - fps = elem.comp.globalData.frameRate - } - return t * fps - } - - function seedRandom(seed) { - BMMath.seedrandom(randSeed + seed) - } - - function sourceRectAtTime() { - return elem.sourceRectAtTime() - } - - function substring(init, end) { - if (typeof value === 'string') { - if (end === undefined) { - return value.substring(init) - } - return value.substring(init, end) - } - return '' - } - - function substr(init, end) { - if (typeof value === 'string') { - if (end === undefined) { - return value.substr(init) - } - return value.substr(init, end) - } - return '' - } - - function posterizeTime(framesPerSecond) { - time = framesPerSecond === 0 ? 0 : Math.floor(time * framesPerSecond) / framesPerSecond - value = valueAtTime(time) - } - - var time - var velocity - var value - var text - var textIndex - var textTotal - var selectorValue - var index = elem.data.ind - var hasParent = !!(elem.hierarchy && elem.hierarchy.length) - var parent - var randSeed = Math.floor(Math.random() * 1000000) - var globalData = elem.globalData - function executeExpression(_value) { - // globalData.pushExpression(); - value = _value - if (this.frameExpressionId === elem.globalData.frameId && this.propType !== 'textSelector') { - return value - } - if (this.propType === 'textSelector') { - textIndex = this.textIndex - textTotal = this.textTotal - selectorValue = this.selectorValue - } - if (!thisLayer) { - text = elem.layerInterface.text - thisLayer = elem.layerInterface - thisComp = elem.comp.compInterface - toWorld = thisLayer.toWorld.bind(thisLayer) - fromWorld = thisLayer.fromWorld.bind(thisLayer) - fromComp = thisLayer.fromComp.bind(thisLayer) - toComp = thisLayer.toComp.bind(thisLayer) - mask = thisLayer.mask ? thisLayer.mask.bind(thisLayer) : null - fromCompToSurface = fromComp - } - if (!transform) { - transform = elem.layerInterface('ADBE Transform Group') - $bm_transform = transform - if (transform) { - anchorPoint = transform.anchorPoint - /* position = transform.position; - rotation = transform.rotation; - scale = transform.scale; */ - } - } - - if (elemType === 4 && !content) { - content = thisLayer('ADBE Root Vectors Group') - } - if (!effect) { - effect = thisLayer(4) - } - hasParent = !!(elem.hierarchy && elem.hierarchy.length) - if (hasParent && !parent) { - parent = elem.hierarchy[0].layerInterface - } - time = this.comp.renderedFrame / this.comp.globalData.frameRate - if (_needsRandom) { - seedRandom(randSeed + time) - } - if (needsVelocity) { - velocity = velocityAtTime(time) - } - expression_function() - this.frameExpressionId = elem.globalData.frameId - - // TODO: Check if it's possible to return on ShapeInterface the .v value - // Changed this to a ternary operation because Rollup failed compiling it correctly - scoped_bm_rt = scoped_bm_rt.propType === propTypes.SHAPE ? scoped_bm_rt.v : scoped_bm_rt - return scoped_bm_rt - } - // Bundlers will see these as dead code and unless we reference them - executeExpression.__preventDeadCodeRemoval = [ - $bm_transform, - anchorPoint, - time, - velocity, - inPoint, - outPoint, - width, - height, - name, - loop_in, - loop_out, - smooth, - toComp, - fromCompToSurface, - toWorld, - fromWorld, - mask, - position, - rotation, - scale, - thisComp, - numKeys, - active, - wiggle, - loopInDuration, - loopOutDuration, - comp, - lookAt, - easeOut, - easeIn, - ease, - nearestKey, - key, - text, - textIndex, - textTotal, - selectorValue, - framesToTime, - timeToFrames, - sourceRectAtTime, - substring, - substr, - posterizeTime, - index, - globalData, - ] - return executeExpression + return noOp } ob.initiateExpression = initiateExpression