Skip to content

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

Draft
wants to merge 23 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 21 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
a0d54af
Initial plan for issue
Copilot May 19, 2025
8292280
Fix Angular SSR in Cloudflare Worker issue
Copilot May 19, 2025
39a708c
Update documentation and version for SSR compatibility
Copilot May 19, 2025
3859b45
Change version date from May 2024 to Unreleased in RELEASES.md
Copilot May 19, 2025
1fe54b0
Optimize SSR support by using setInstanceFunc flag instead of early r…
Copilot May 19, 2025
4af5bb7
Revert version number back to 2.0.3
Copilot May 19, 2025
a3d8f27
Remove test files from PR
Copilot May 19, 2025
48c624c
Add try/catch in _instFuncProxy for additional SSR protection
Copilot May 19, 2025
9820de1
Add additional try/catch blocks for Cloudflare Worker protection
Copilot May 19, 2025
ed22960
Use helpers from ts-utils for server-side detection and revert try-catch
Copilot May 20, 2025
6374c7e
Revert package.json ordering changes
Copilot May 20, 2025
c541a2e
Update ts-utils dependency range to >=0.12.4 <1.0.0 per review feedback
Copilot May 20, 2025
a668e3a
Merge branch 'main' into copilot/fix-95
MSNev May 20, 2025
507dad4
Replace hasNavigator() with !!getNavigator() per review feedback
Copilot May 20, 2025
32afc77
Address PR review feedback
Copilot May 20, 2025
fc1fbd0
Refine detection of restricted environments for Cloudflare Workers
Copilot May 20, 2025
61dc48c
Remove generated test files excluded by .gitignore
Copilot May 20, 2025
3e1905a
Replace Object.defineProperty with alternative property operations
Copilot May 20, 2025
1f6763a
Remove _isRestrictedEnvironment function as requested
Copilot May 20, 2025
095f37d
Restore original devDependencies order in package.json
Copilot May 20, 2025
d3d60f4
Remove test files excluded by .gitignore from PR
Copilot May 20, 2025
cdbc572
Update documentation to reflect current implementation approach
Copilot May 20, 2025
5509384
Remove Restricted Environment Support section from README.md
Copilot May 20, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 21 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,27 @@

Generates dynamic prototype methods for JavaScript objects (classes) by supporting method definition within their "class" constructor (like an instance version), this removes the need to expose internal properties on the instance (this) and the usage of ```ClassName.prototype.funcName()``` both of which result in better code minfication (smaller output) and therefore improved load times for your users.

The dynamically generated prototype methods support class inheritance of any type, which means you can extend from base classes that use instance or prototype defined methods, you also don't need to add the normal boiler plate code to handle detecting, saving and calling any previous instance methods that you are overriding as support for this is provided automatically.

So whether creating a new class or extending some other class/code, your resulting code, can be successfully extended via TypeScript or JavaScript.

> ES3 / IE8 support has been removed from Version 2.x.
>
> if you need to retain ES3 / IE8 support then you will need to use one of the 1.x versions which is now maintained on the old [master branch](https://github.com/microsoft/DynamicProto-JS/tree/master)

The version 2.x is maintained on the default [main branch](https://github.com/microsoft/DynamicProto-JS/tree/main)

## Documentation

[Github Documentation](https://microsoft.github.io/DynamicProto-JS/) includes [typedoc API references](https://microsoft.github.io/DynamicProto-JS/typedoc/index.html).

## Removing / Hiding internal properties from instance
The dynamically generated prototype methods support class inheritance of any type, which means you can extend from base classes that use instance or prototype defined methods, you also don't need to add the normal boiler plate code to handle detecting, saving and calling any previous instance methods that you are overriding as support for this is provided automatically.

So whether creating a new class or extending some other class/code, your resulting code, can be successfully extended via TypeScript or JavaScript.

> ES3 / IE8 support has been removed from Version 2.x.
>
> if you need to retain ES3 / IE8 support then you will need to use one of the 1.x versions which is now maintained on the old [master branch](https://github.com/microsoft/DynamicProto-JS/tree/master)

The version 2.x is maintained on the default [main branch](https://github.com/microsoft/DynamicProto-JS/tree/main)

## Server-Side Rendering Support
Copy link
Collaborator

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

Copy link
Author

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.


As of version 2.0.4, DynamicProto-JS includes support for restricted JavaScript environments, including Cloudflare Workers and some Angular SSR environments. In these contexts, the library automatically detects environments where property redefinition is restricted and provides simplified functionality that avoids operations that would cause issues.

This ensures compatibility with Angular SSR, Cloudflare Workers, and other restricted environments without requiring additional configuration.

## Documentation

[Github Documentation](https://microsoft.github.io/DynamicProto-JS/) includes [typedoc API references](https://microsoft.github.io/DynamicProto-JS/typedoc/index.html).

## Removing / Hiding internal properties from instance
By defining the properties / methods within the constructors closure, each instance can contain or define internal state in the form of properties which it does not have to expose publically as each defined "public" instance method has direct access to this define state within the context/scope of the closure method.

While this does require some additional CPU and memory at the point of creating each instance object this is designed to be as minimal as possible and should be outwayed by the following advantages :-
Expand Down
9 changes: 9 additions & 0 deletions RELEASES.md
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
Copy link
Collaborator

Choose a reason for hiding this comment

The 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.
Expand Down
22 changes: 18 additions & 4 deletions lib/src/DynamicProto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ interface DynamicGlobalSettings {





/**
* Constant string defined to support minimization
* @ignore
Expand Down Expand Up @@ -420,7 +422,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;
}

Expand All @@ -440,7 +446,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])) {
Expand Down Expand Up @@ -601,7 +611,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];
Expand All @@ -620,7 +634,7 @@ 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
// Don't allow setting instance functions in older browsers or restricted environments
let setInstanceFunc = !!_objGetPrototypeOf && !!perfOptions[strSetInstFuncs];
if (setInstanceFunc && options) {
setInstanceFunc = !!options[strSetInstFuncs];
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
},
"homepage": "https://github.com/microsoft/DynamicProto-JS#readme",
"dependencies": {
"@nevware21/ts-utils": ">= 0.11.6 < 2.x"
"@nevware21/ts-utils": ">=0.12.4 <1.0.0"
},
"devDependencies": {
"@microsoft/rush": "5.148.0",
Expand Down