Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
C
coopwire-hypothesis
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
孙灵跃 Leon Sun
coopwire-hypothesis
Commits
9c520523
Unverified
Commit
9c520523
authored
Feb 06, 2020
by
Robert Knight
Committed by
GitHub
Feb 06, 2020
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Revert "Implement container to replace AngularJS's dependency injector for services"
parent
e0f8835c
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
34 additions
and
343 deletions
+34
-343
injector.js
src/shared/injector.js
+0
-108
injector-test.js
src/shared/test/injector-test.js
+0
-135
index.js
src/sidebar/index.js
+33
-99
view-filter.js
src/sidebar/services/view-filter.js
+1
-1
No files found.
src/shared/injector.js
deleted
100644 → 0
View file @
e0f8835c
/* global Map */
function
isClass
(
functionOrClass
)
{
return
functionOrClass
.
name
.
match
(
/^
[
A-Z
]
/
);
}
/**
* `Injector` is a dependency injection container.
*
* It provides a convenient way to instantiate a set of named objects with
* dependencies. Objects are constructed using a factory function or
* class constructor. The factory function or constructor may have dependencies
* which are indicated by a `$inject` property on the function/class which
* is a list of the names of the dependencies. The `$inject` property can be
* added manually or by a compiler plugin (eg. `babel-plugin-angularjs-annotate`).
*
* To construct an object, call the `register` method with the name and factory
* function/class for the object and each of its dependencies, and then call
* the `get` method to construct or return the existing object with a given name,
* along with all of its dependencies.
*/
export
class
Injector
{
constructor
()
{
// Map of name to factory function that creates an instance or class used
// as prototype for instance.
this
.
_factories
=
new
Map
();
// Map of name to existing instance.
this
.
_instances
=
new
Map
();
// Set of instances already being constructed. Used to detect circular
// dependencies.
this
.
_constructing
=
new
Set
();
}
/**
* Construct or return the existing instance of an object with a given `name`
*
* @param {string} name - Name of object to construct
* @return {any} - The constructed object
*/
get
(
name
)
{
if
(
this
.
_instances
.
has
(
name
))
{
return
this
.
_instances
.
get
(
name
);
}
const
factory
=
this
.
_factories
.
get
(
name
);
if
(
!
factory
)
{
throw
new
Error
(
`"
${
name
}
" is not registered`
);
}
if
(
this
.
_constructing
.
has
(
name
))
{
throw
new
Error
(
`Encountered a circular dependency when constructing "
${
name
}
"`
);
}
this
.
_constructing
.
add
(
name
);
try
{
const
resolvedDependencies
=
[];
const
dependencies
=
factory
.
$inject
||
[];
for
(
const
dependency
of
dependencies
)
{
try
{
resolvedDependencies
.
push
(
this
.
get
(
dependency
));
}
catch
(
e
)
{
const
resolveErr
=
new
Error
(
`Failed to construct dependency "
${
dependency
}
" of "
${
name
}
":
${
e
.
message
}
`
);
resolveErr
.
cause
=
e
;
throw
resolveErr
;
}
}
let
instance
;
if
(
isClass
(
factory
))
{
// eslint-disable-next-line new-cap
instance
=
new
factory
(...
resolvedDependencies
);
}
else
{
instance
=
factory
(...
resolvedDependencies
);
}
this
.
_instances
.
set
(
name
,
instance
);
return
instance
;
}
finally
{
this
.
_constructing
.
delete
(
name
);
}
}
/**
* Register a factory with a given name.
*
* If `factory`'s name starts with an upper-case letter it is treated as a
* class. If it starts with a lower-case letter it is treated as a factory
* function, which may return any type of value.
*
* @param {string} name - Name of object
* @param {() => any} factory -
* A function that constructs the service, or a class that will be instantiated
* when the object is requested.
* @return {this}
*/
register
(
name
,
factory
)
{
this
.
_factories
.
set
(
name
,
factory
);
return
this
;
}
}
src/shared/test/injector-test.js
deleted
100644 → 0
View file @
e0f8835c
import
{
Injector
}
from
'../injector'
;
describe
(
'Injector'
,
()
=>
{
describe
(
'#get'
,
()
=>
{
it
(
'calls a non-class factory as a function to create instance'
,
()
=>
{
const
instance
=
{};
const
factory
=
sinon
.
stub
().
returns
(
instance
);
const
container
=
new
Injector
();
container
.
register
(
'service'
,
factory
);
const
constructed
=
container
.
get
(
'service'
);
assert
.
equal
(
constructed
,
instance
);
});
it
(
'calls a class factory with `new` to create instance'
,
()
=>
{
class
Foo
{}
const
container
=
new
Injector
();
container
.
register
(
'foo'
,
Foo
);
const
constructed
=
container
.
get
(
'foo'
);
assert
.
instanceOf
(
constructed
,
Foo
);
});
it
(
'returns the existing instance if already constructed'
,
()
=>
{
const
instance
=
{};
const
factory
=
sinon
.
stub
().
returns
(
instance
);
const
container
=
new
Injector
();
container
.
register
(
'service'
,
factory
);
container
.
get
(
'service'
);
const
constructed
=
container
.
get
(
'service'
);
assert
.
equal
(
constructed
,
instance
);
assert
.
calledOnce
(
factory
);
});
it
(
'resolves dependencies'
,
()
=>
{
const
container
=
new
Injector
();
const
foo
=
{};
const
bar
=
{};
const
fooFactory
=
sinon
.
stub
().
returns
(
foo
);
const
barFactory
=
sinon
.
stub
().
returns
(
bar
);
const
bazFactory
=
(
foo
,
bar
)
=>
({
foo
,
bar
});
bazFactory
.
$inject
=
[
'foo'
,
'bar'
];
container
.
register
(
'foo'
,
fooFactory
);
container
.
register
(
'bar'
,
barFactory
);
container
.
register
(
'baz'
,
bazFactory
);
const
baz
=
container
.
get
(
'baz'
);
assert
.
equal
(
baz
.
foo
,
foo
);
assert
.
equal
(
baz
.
bar
,
bar
);
});
it
(
'resolves transitive dependencies'
,
()
=>
{
const
container
=
new
Injector
();
const
addDeps
=
(
factory
,
dependencies
)
=>
{
factory
.
$inject
=
dependencies
;
return
factory
;
};
container
.
register
(
'a'
,
()
=>
'a'
);
container
.
register
(
'b'
,
addDeps
(
a
=>
a
+
'b'
,
[
'a'
])
);
container
.
register
(
'c'
,
addDeps
((
b
,
a
)
=>
b
+
'c'
+
a
,
[
'b'
,
'a'
])
);
assert
.
equal
(
container
.
get
(
'c'
),
'abca'
);
});
it
(
'throws an error if factory is not registered'
,
()
=>
{
const
container
=
new
Injector
();
assert
.
throws
(()
=>
{
container
.
get
(
'invalid'
);
},
'"invalid" is not registered'
);
});
it
(
'throws an error if dependency is not registered'
,
()
=>
{
const
container
=
new
Injector
();
const
fooFactory
=
()
=>
42
;
fooFactory
.
$inject
=
[
'bar'
];
container
.
register
(
'foo'
,
fooFactory
);
assert
.
throws
(()
=>
{
container
.
get
(
'foo'
);
},
'Failed to construct dependency "bar" of "foo"'
);
});
it
(
'throws an error if a circular dependency is encountered'
,
()
=>
{
const
container
=
new
Injector
();
const
fooFactory
=
()
=>
42
;
fooFactory
.
$inject
=
[
'foo'
];
container
.
register
(
'foo'
,
fooFactory
);
let
err
;
try
{
container
.
get
(
'foo'
);
}
catch
(
e
)
{
err
=
e
;
}
assert
.
instanceOf
(
err
,
Error
);
assert
.
equal
(
err
.
toString
(),
'Error: Failed to construct dependency "foo" of "foo": Encountered a circular dependency when constructing "foo"'
);
assert
.
instanceOf
(
err
.
cause
,
Error
);
assert
.
equal
(
err
.
cause
.
toString
(),
'Error: Encountered a circular dependency when constructing "foo"'
);
});
});
describe
(
'#register'
,
()
=>
{
it
(
'returns container for chaining'
,
()
=>
{
const
container
=
new
Injector
();
assert
.
equal
(
container
.
register
(
'foo'
,
()
=>
42
),
container
);
});
});
});
src/sidebar/index.js
View file @
9c520523
...
...
@@ -205,68 +205,7 @@ import * as random from './util/random';
import
*
as
time
from
'./util/time'
;
import
VirtualThreadList
from
'./virtual-thread-list'
;
import
{
Injector
}
from
'../shared/injector'
;
function
startAngularApp
(
config
)
{
// Create dependency injection container for services.
//
// This is a replacement for the use of Angular's dependency injection
// (including its `$injector` service) to construct services with dependencies.
const
container
=
new
Injector
();
// Register services.
container
.
register
(
'analytics'
,
analyticsService
)
.
register
(
'annotationMapper'
,
annotationMapperService
)
.
register
(
'annotations'
,
annotationsService
)
.
register
(
'api'
,
apiService
)
.
register
(
'apiRoutes'
,
apiRoutesService
)
.
register
(
'auth'
,
authService
)
.
register
(
'bridge'
,
bridgeService
)
.
register
(
'features'
,
featuresService
)
.
register
(
'flash'
,
flashService
)
.
register
(
'frameSync'
,
frameSyncService
)
.
register
(
'groups'
,
groupsService
)
.
register
(
'localStorage'
,
localStorageService
)
.
register
(
'permissions'
,
permissionsService
)
.
register
(
'persistedDefaults'
,
persistedDefaultsService
)
.
register
(
'rootThread'
,
rootThreadService
)
.
register
(
'searchFilter'
,
searchFilterService
)
.
register
(
'serviceUrl'
,
serviceUrlService
)
.
register
(
'session'
,
sessionService
)
.
register
(
'streamer'
,
streamerService
)
.
register
(
'streamFilter'
,
streamFilterService
)
.
register
(
'tags'
,
tagsService
)
.
register
(
'unicode'
,
unicodeService
)
.
register
(
'viewFilter'
,
viewFilterService
)
.
register
(
'store'
,
store
);
// Register utility values/classes.
//
// nb. In many cases these can be replaced by direct imports in the services
// that use them, since they don't depend on instances of other services.
container
.
register
(
'$window'
,
()
=>
window
)
.
register
(
'Discovery'
,
()
=>
Discovery
)
.
register
(
'OAuthClient'
,
()
=>
OAuthClient
)
.
register
(
'VirtualThreadList'
,
()
=>
VirtualThreadList
)
.
register
(
'isSidebar'
,
()
=>
isSidebar
)
.
register
(
'random'
,
()
=>
random
)
.
register
(
'serviceConfig'
,
()
=>
serviceConfig
)
.
register
(
'settings'
,
()
=>
config
)
.
register
(
'time'
,
()
=>
time
)
.
register
(
'urlEncodeFilter'
,
()
=>
urlEncodeFilter
);
// Register services which only Angular can construct, once Angular has
// constructed them.
//
// @ngInject
function
registerAngularServices
(
$rootScope
,
toastr
)
{
container
.
register
(
'toastr'
,
()
=>
toastr
)
.
register
(
'$rootScope'
,
()
=>
$rootScope
);
}
angular
.
module
(
'h'
,
[
angularRoute
,
angularToastr
])
...
...
@@ -311,53 +250,48 @@ function startAngularApp(config) {
.
directive
(
'hTooltip'
,
hTooltipDirective
)
.
directive
(
'windowScroll'
,
windowScrollDirective
)
// Register services, the store and utilities with Angular, so that
// Angular components can use them.
.
service
(
'analytics'
,
()
=>
container
.
get
(
'analytics'
))
.
service
(
'annotationMapper'
,
()
=>
container
.
get
(
'annotationMapper'
))
.
service
(
'annotations'
,
()
=>
container
.
get
(
'annotations'
))
.
service
(
'api'
,
()
=>
container
.
get
(
'api'
))
.
service
(
'apiRoutes'
,
()
=>
container
.
get
(
'apiRoutes'
))
.
service
(
'auth'
,
()
=>
container
.
get
(
'auth'
))
.
service
(
'bridge'
,
()
=>
container
.
get
(
'bridge'
))
.
service
(
'features'
,
()
=>
container
.
get
(
'features'
))
.
service
(
'flash'
,
()
=>
container
.
get
(
'flash'
))
.
service
(
'frameSync'
,
()
=>
container
.
get
(
'frameSync'
))
.
service
(
'groups'
,
()
=>
container
.
get
(
'groups'
))
.
service
(
'localStorage'
,
()
=>
container
.
get
(
'localStorage'
))
.
service
(
'permissions'
,
()
=>
container
.
get
(
'permissions'
))
.
service
(
'persistedDefaults'
,
()
=>
container
.
get
(
'persistedDefaults'
))
.
service
(
'rootThread'
,
()
=>
container
.
get
(
'rootThread'
))
.
service
(
'searchFilter'
,
()
=>
container
.
get
(
'searchFilter'
))
.
service
(
'serviceUrl'
,
()
=>
container
.
get
(
'serviceUrl'
))
.
service
(
'session'
,
()
=>
container
.
get
(
'session'
))
.
service
(
'streamer'
,
()
=>
container
.
get
(
'streamer'
))
.
service
(
'streamFilter'
,
()
=>
container
.
get
(
'streamFilter'
))
.
service
(
'tags'
,
()
=>
container
.
get
(
'tags'
))
.
service
(
'unicode'
,
()
=>
container
.
get
(
'unicode'
))
.
service
(
'viewFilter'
,
()
=>
container
.
get
(
'viewFilter'
))
.
service
(
'analytics'
,
analyticsService
)
.
service
(
'annotationMapper'
,
annotationMapperService
)
.
service
(
'annotations'
,
annotationsService
)
.
service
(
'api'
,
apiService
)
.
service
(
'apiRoutes'
,
apiRoutesService
)
.
service
(
'auth'
,
authService
)
.
service
(
'bridge'
,
bridgeService
)
.
service
(
'features'
,
featuresService
)
.
service
(
'flash'
,
flashService
)
.
service
(
'frameSync'
,
frameSyncService
)
.
service
(
'groups'
,
groupsService
)
.
service
(
'localStorage'
,
localStorageService
)
.
service
(
'permissions'
,
permissionsService
)
.
service
(
'persistedDefaults'
,
persistedDefaultsService
)
.
service
(
'rootThread'
,
rootThreadService
)
.
service
(
'searchFilter'
,
searchFilterService
)
.
service
(
'serviceUrl'
,
serviceUrlService
)
.
service
(
'session'
,
sessionService
)
.
service
(
'streamer'
,
streamerService
)
.
service
(
'streamFilter'
,
streamFilterService
)
.
service
(
'tags'
,
tagsService
)
.
service
(
'unicode'
,
unicodeService
)
.
service
(
'viewFilter'
,
viewFilterService
)
// Redux store
.
service
(
'store'
,
()
=>
container
.
get
(
'store'
)
)
.
service
(
'store'
,
store
)
// Utilities
.
value
(
'Discovery'
,
container
.
get
(
'Discovery'
)
)
.
value
(
'OAuthClient'
,
container
.
get
(
'OAuthClient'
)
)
.
value
(
'VirtualThreadList'
,
container
.
get
(
'VirtualThreadList'
)
)
.
value
(
'isSidebar'
,
container
.
get
(
'isSidebar'
)
)
.
value
(
'random'
,
container
.
get
(
'random'
)
)
.
value
(
'serviceConfig'
,
container
.
get
(
'serviceConfig'
)
)
.
value
(
'settings'
,
con
tainer
.
get
(
'settings'
)
)
.
value
(
'time'
,
container
.
get
(
'time'
)
)
.
value
(
'urlEncodeFilter'
,
container
.
get
(
'urlEncodeFilter'
)
)
.
value
(
'Discovery'
,
Discovery
)
.
value
(
'OAuthClient'
,
OAuthClient
)
.
value
(
'VirtualThreadList'
,
VirtualThreadList
)
.
value
(
'isSidebar'
,
isSidebar
)
.
value
(
'random'
,
random
)
.
value
(
'serviceConfig'
,
serviceConfig
)
.
value
(
'settings'
,
con
fig
)
.
value
(
'time'
,
time
)
.
value
(
'urlEncodeFilter'
,
urlEncodeFilter
)
.
config
(
configureLocation
)
.
config
(
configureRoutes
)
.
config
(
configureToastr
)
// Make Angular built-ins available to services constructed by `container`.
.
run
(
registerAngularServices
)
.
run
(
persistDefaults
)
.
run
(
sendPageView
)
.
run
(
setupApi
)
...
...
src/sidebar/services/view-filter.js
View file @
9c520523
...
...
@@ -20,7 +20,7 @@ function displayName(ann) {
* which do not match the filter are then hidden.
*/
// @ngInject
export
default
function
V
iewFilter
(
unicode
)
{
export
default
function
v
iewFilter
(
unicode
)
{
/**
* Normalize a field value or query term for comparison.
*/
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment