-
Notifications
You must be signed in to change notification settings - Fork 12
Fix Angular SSR in Cloudflare Worker environments #96
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 16 commits
a0d54af
8292280
39a708c
3859b45
1fe54b0
4af5bb7
a3d8f27
48c624c
9820de1
ed22960
6374c7e
c541a2e
a668e3a
507dad4
32afc77
fc1fbd0
61dc48c
3e1905a
1f6763a
095f37d
d3d60f4
cdbc572
5509384
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,14 @@ | ||
# Releases | ||
|
||
## 2.0.4 (Unreleased) | ||
|
||
### Changes | ||
|
||
- #95 [BUG] AppInsights breaks Angular SSR in Cloudflare Worker | ||
- Added support for restricted JavaScript environments, including Cloudflare Workers | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Update |
||
- Modified the `dynamicProto` function to detect environments where property redefinition is restricted | ||
- This ensures compatibility with Angular SSR, Cloudflare Workers, and other restricted environments | ||
|
||
## 2.0.3 (Jan 11th, 2024) | ||
|
||
Blocks a medium level prototype pollution vulnerability. | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -18,6 +18,36 @@ interface DynamicGlobalSettings { | |
|
||
|
||
|
||
/** | ||
* Helper to check if we're running in a restricted environment that doesn't support | ||
* property redefinition, like Cloudflare Workers. This is primarily used to avoid | ||
* operations that would cause issues in these environments. | ||
* @ignore | ||
*/ | ||
function _isRestrictedEnvironment(): boolean { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. remove and don't use this There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I've removed the |
||
try { | ||
// Test if we can perform property definition/redefinition | ||
// This specifically targets restricted environments like Cloudflare Workers | ||
// where property redefinition causes errors | ||
let testObj = {}; | ||
let testProp = "testProperty"; | ||
Object.defineProperty(testObj, testProp, { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As this library doesn't use Object.defineProperty don't use this function, use an alternate method There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I've replaced the Object.defineProperty detection with an alternative approach in 3e1905a. The new implementation tests property operations similar to what the library actually does:
This provides reliable detection of restricted environments like Cloudflare Workers without using Object.defineProperty, while still testing operations crucial to the library's function. |
||
configurable: true, | ||
value: 1 | ||
}); | ||
Object.defineProperty(testObj, testProp, { | ||
configurable: true, | ||
value: 2 | ||
}); | ||
|
||
// If we can redefine properties, not a restricted environment | ||
return false; | ||
} catch (e) { | ||
// If property redefinition fails, we're in a restricted environment | ||
return true; | ||
} | ||
} | ||
|
||
/** | ||
* Constant string defined to support minimization | ||
* @ignore | ||
|
@@ -420,7 +450,11 @@ function _populatePrototype(proto:any, className:string, target:any, baseInstFun | |
|
||
// Tag this function as a proxy to support replacing dynamic proxy elements (primary use case is for unit testing | ||
// via which can dynamically replace the prototype function reference) | ||
(dynProtoProxy as any)[DynProxyTag] = 1; | ||
try { | ||
(dynProtoProxy as any)[DynProxyTag] = 1; | ||
} catch (e) { | ||
// Ignore errors in restricted environments like Cloudflare Workers | ||
} | ||
return dynProtoProxy; | ||
} | ||
|
||
|
@@ -440,7 +474,11 @@ function _populatePrototype(proto:any, className:string, target:any, baseInstFun | |
if (_isDynamicCandidate(target, name, false) && target[name] !== baseInstFuncs[name] ) { | ||
// Save the instance Function to the lookup table and remove it from the instance as it's not a dynamic proto function | ||
instFuncs[name] = target[name]; | ||
delete target[name]; | ||
try { | ||
delete target[name]; | ||
} catch (e) { | ||
// Ignore errors in restricted environments like Cloudflare Workers | ||
} | ||
|
||
// Add a dynamic proto if one doesn't exist or if a prototype function exists and it's not a dynamic one | ||
if (!objHasOwnProperty(proto, name) || (proto[name] && !proto[name][DynProxyTag])) { | ||
|
@@ -601,7 +639,11 @@ export default function dynamicProto<DPType, DPCls>(theClass:DPCls, target:DPTyp | |
// function table lookup. | ||
className = DynClassNamePrefix + _getObjName(theClass, "_") + "$" + _gblInst.n ; | ||
_gblInst.n++; | ||
classProto[DynClassName] = className; | ||
try { | ||
classProto[DynClassName] = className; | ||
} catch (e) { | ||
// Ignore errors in restricted environments like Cloudflare Workers | ||
} | ||
} | ||
|
||
let perfOptions = dynamicProto[DynProtoDefaultOptions]; | ||
|
@@ -620,8 +662,8 @@ export default function dynamicProto<DPType, DPCls>(theClass:DPCls, target:DPTyp | |
// Note casting the same type as we don't actually have the base class here and this will provide some intellisense support | ||
delegateFunc(target, baseFuncs as DPType); | ||
|
||
// Don't allow setting instance functions for older IE instances | ||
let setInstanceFunc = !!_objGetPrototypeOf && !!perfOptions[strSetInstFuncs]; | ||
// Don't allow setting instance functions in older browsers or restricted environments | ||
let setInstanceFunc = !!_objGetPrototypeOf && !!perfOptions[strSetInstFuncs] && !_isRestrictedEnvironment(); | ||
if (setInstanceFunc && options) { | ||
setInstanceFunc = !!options[strSetInstFuncs]; | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Update this documentation as it's not explicitly doing this anymore
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've updated the documentation in cdbc572. Changed the section title to "Restricted Environment Support" and updated the description to accurately reflect the current implementation that handles potential property manipulation errors in restricted environments rather than explicitly detecting server-side rendering.