Skip to content

Commit

Permalink
ko.applyBindings requires a valid 2nd parameter if given
Browse files Browse the repository at this point in the history
  • Loading branch information
mbest committed Jun 5, 2018
1 parent 28fc51a commit 965de2d
Show file tree
Hide file tree
Showing 5 changed files with 28 additions and 8 deletions.
3 changes: 2 additions & 1 deletion build/types/knockout.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -287,7 +287,8 @@ export interface BindingContext<T = any> {
createChildContext<X>(accessor: () => T | Observable<T>, dataItemAlias?: string, extendCallback?: BindingContextExtendCallback<X>): BindingContext<X>;
}

export function applyBindings<T = any>(bindingContext: T | BindingContext<T>, rootNode?: Node | null, extendCallback?: BindingContextExtendCallback<T>): void;
export function applyBindings<T = any>(bindingContext: T | BindingContext<T>): void;
export function applyBindings<T = any>(bindingContext: T | BindingContext<T>, rootNode: Node | null, extendCallback?: BindingContextExtendCallback<T>): void;
export function applyBindingsToDescendants<T = any>(bindingContext: T | BindingContext<T>, rootNode?: Node): void;
export function applyBindingsToNode<T = any>(node: Node, bindings: object | (() => object), viewModel: T | BindingContext<T>): void;
export function applyBindingAccessorsToNode<T = any>(node: Node, bindings: BindingAccessors | (() => BindingAccessors), viewModel: T | BindingContext<T>): void;
Expand Down
17 changes: 17 additions & 0 deletions spec/bindingAttributeBehaviors.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,23 @@ describe('Binding attribute syntax', function() {
expect(didInit).toEqual(true);
});

var exceptionMessage = "second parameter should be a DOM node";
ko.utils.arrayForEach([
undefined,
null,
"",
"A Node",
123,
{},
[]
], function (testValue) {
it('applyBindings should throw an error if called with a non-node value: '+ jasmine.pp(testValue), function () {
expect(function () {
ko.applyBindings({}, testValue);
}).toThrowContaining(exceptionMessage);
});
});

it('applyBindings should accept three parameters and use the third parameter as a callback for modifying the root context', function() {
var didInit = false;
ko.bindingHandlers.test = {
Expand Down
1 change: 1 addition & 0 deletions spec/types/global/test-global.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ function test_creatingVMs() {
};

ko.applyBindings(myViewModel);
ko.applyBindings(myViewModel, document.body, (ctx) => { ctx.x = "test"; });
ko.applyBindings(myViewModel, document.getElementById('someElementId'));

myViewModel.personName();
Expand Down
1 change: 1 addition & 0 deletions spec/types/module/test-module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ function test_creatingVMs() {
};

ko.applyBindings(myViewModel);
ko.applyBindings(myViewModel, document.body, (ctx) => { ctx.x = "test"; });
ko.applyBindings(myViewModel, document.getElementById('someElementId'));

myViewModel.personName();
Expand Down
14 changes: 7 additions & 7 deletions src/binding/bindingAttributeSyntax.js
Original file line number Diff line number Diff line change
Expand Up @@ -529,7 +529,7 @@
ko.applyBindingAccessorsToNode = function (node, bindings, viewModelOrBindingContext) {
if (node.nodeType === 1) // If it's an element, workaround IE <= 8 HTML parsing weirdness
ko.virtualElements.normaliseVirtualElementDomStructure(node);
return applyBindingsToNodeInternal(node, bindings, getBindingContext(viewModelOrBindingContext), true);
return applyBindingsToNodeInternal(node, bindings, getBindingContext(viewModelOrBindingContext));
};

ko.applyBindingsToNode = function (node, bindings, viewModelOrBindingContext) {
Expand All @@ -539,26 +539,26 @@

ko.applyBindingsToDescendants = function(viewModelOrBindingContext, rootNode) {
if (rootNode.nodeType === 1 || rootNode.nodeType === 8)
applyBindingsToDescendantsInternal(getBindingContext(viewModelOrBindingContext), rootNode, true);
applyBindingsToDescendantsInternal(getBindingContext(viewModelOrBindingContext), rootNode);
};

ko.applyBindings = function (viewModelOrBindingContext, rootNode, extendContextCallback) {
ko.applyBindings = function (viewModelOrBindingContext, rootNodeArg, extendContextCallback) {
// If jQuery is loaded after Knockout, we won't initially have access to it. So save it here.
if (!jQueryInstance && window['jQuery']) {
jQueryInstance = window['jQuery'];
}

// rootNode is optional
if (!rootNode) {
var rootNode = rootNodeArg;
if (!rootNode && arguments.length < 2) {
rootNode = window.document.body;
if (!rootNode) {
throw Error("ko.applyBindings: could not find window.document.body; has the document been loaded?");
}
} else if (rootNode.nodeType !== 1 && rootNode.nodeType !== 8) {
} else if (!rootNode || (rootNode.nodeType !== 1 && rootNode.nodeType !== 8)) {
throw Error("ko.applyBindings: first parameter should be your view model; second parameter should be a DOM node");
}

applyBindingsToNodeAndDescendantsInternal(getBindingContext(viewModelOrBindingContext, extendContextCallback), rootNode, true);
applyBindingsToNodeAndDescendantsInternal(getBindingContext(viewModelOrBindingContext, extendContextCallback), rootNode);
};

// Retrieving binding context from arbitrary nodes
Expand Down

0 comments on commit 965de2d

Please sign in to comment.